embox

Форк
0
/
write.c 
741 строка · 20.8 Кб
1
/*
2
 * JFFS2 -- Journalling Flash File System, Version 2.
3
 *
4
 * Copyright (C) 2001-2003 Red Hat, Inc.
5
 *
6
 * Created by David Woodhouse <dwmw2@infradead.org>
7
 *
8
 * For licensing information, see the file 'LICENCE' in this directory.
9
 *
10
 * $Id: write.c,v 1.94 2005/07/20 15:50:51 dedekind Exp $
11
 *
12
 */
13

14
#include <dirent.h>
15
#include <stddef.h>
16
#include <errno.h>
17
#include <stdint.h>
18
#include <string.h>
19

20
#include <linux/kernel.h>
21
#include <linux/fs.h>
22
#include <linux/crc32.h>
23
#include <linux/slab.h>
24
#include <linux/pagemap.h>
25
#include <linux/mtd/mtd.h>
26
#include "nodelist.h"
27
#include "compr.h"
28

29

30
int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
31
								uint32_t mode, struct jffs2_raw_inode *ri) {
32
	struct jffs2_inode_cache *ic;
33

34
	ic = jffs2_alloc_inode_cache();
35
	if (!ic) {
36
		return -ENOMEM;
37
	}
38

39
	memset(ic, 0, sizeof(*ic));
40

41
	f->inocache = ic;
42
	f->inocache->nlink = 1;
43
	f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
44
	f->inocache->state = INO_STATE_PRESENT;
45

46

47
	jffs2_add_ino_cache(c, f->inocache);
48
	D1(printk( "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));
49
	ri->ino = cpu_to_je32(f->inocache->ino);
50

51
	ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
52
	ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
53
	ri->totlen = cpu_to_je32(PAD(sizeof(*ri)));
54
	ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
55
	ri->mode = cpu_to_jemode(mode);
56

57
	f->highest_version = 1;
58
	ri->version = cpu_to_je32(f->highest_version);
59

60
	return 0;
61
}
62

63
/**
64
 * jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it,
65
 * write it to the flash, link it into the existing inode/fragment list
66
 */
67
struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c,
68
		struct jffs2_inode_info *f, struct jffs2_raw_inode *ri,
69
		const unsigned char *data,
70
				uint32_t datalen, uint32_t flash_ofs, int alloc_mode) {
71
	struct jffs2_raw_node_ref *raw;
72
	struct jffs2_full_dnode *fn;
73
	size_t retlen;
74
	struct iovec vecs[2];
75
	int ret;
76
	uint32_t dummy;
77
	struct jffs2_eraseblock *jeb;
78
	int retried = 0;
79
	unsigned long cnt = 2;
80

81
	D1(
82
	if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) {
83
		printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dnode()\n");
84
		BUG();
85
	}
86
	);
87
	vecs[0].iov_base = ri;
88
	vecs[0].iov_len = sizeof(*ri);
89
	vecs[1].iov_base = (unsigned char *)data;
90
	vecs[1].iov_len = datalen;
91

92
	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs,
93
			vecs[0].iov_len + vecs[1].iov_len);
94

95
	if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
96
		printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen);
97
	}
98
	raw = jffs2_alloc_raw_node_ref();
99
	if (!raw) {
100
		return ERR_PTR(-ENOMEM);
101
	}
102

103
	fn = jffs2_alloc_full_dnode();
104
	if (!fn) {
105
		jffs2_free_raw_node_ref(raw);
106
		return ERR_PTR(-ENOMEM);
107
	}
108

109
	fn->ofs = je32_to_cpu(ri->offset);
110
	fn->size = je32_to_cpu(ri->dsize);
111
	fn->frags = 0;
112

113
	/* check number of valid vecs */
114
	if (!datalen || !data) {
115
		cnt = 1;
116
	}
117
 retry:
118
	fn->raw = raw;
119

120
	raw->flash_offset = flash_ofs;
121
	raw->__totlen = PAD(sizeof(*ri)+datalen);
122
	raw->next_phys = NULL;
123

124
	if ((alloc_mode!=ALLOC_GC) &&
125
			(je32_to_cpu(ri->version) < f->highest_version)) {
126
		BUG_ON(!retried);
127
		D1(printk( "jffs2_write_dnode : dnode_version %d, "
128
				"highest version %d -> updating dnode\n",
129
				je32_to_cpu(ri->version), f->highest_version));
130
		ri->version = cpu_to_je32(++f->highest_version);
131
		ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
132
	}
133

134
	ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen,
135
				 (alloc_mode==ALLOC_GC)?0:f->inocache->ino);
136

137
	if (ret || (retlen != sizeof(*ri) + datalen)) {
138
		printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
139
		       sizeof(*ri)+datalen, flash_ofs, ret, retlen);
140

141
		/* Mark the space as dirtied */
142
		if (retlen) {
143
			/* Doesn't belong to any inode */
144
			raw->next_in_ino = NULL;
145

146
			/* Don't change raw->size to match retlen. We may have
147
			 * written the node header already, and only the data will
148
			 * seem corrupted, in which case the scan would skip over
149
			 * any node we write before the original intended end of
150
			 * this node
151
			 */
152
			raw->flash_offset |= REF_OBSOLETE;
153
			jffs2_add_physical_node_ref(c, raw);
154
			jffs2_mark_node_obsolete(c, raw);
155
		} else {
156
			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
157
			jffs2_free_raw_node_ref(raw);
158
		}
159
		if (!retried && alloc_mode != ALLOC_NORETRY &&
160
				(raw = jffs2_alloc_raw_node_ref())) {
161
			/* Try to reallocate space and retry */
162
			jeb = &c->blocks[flash_ofs / c->sector_size];
163

164
			retried = 1;
165

166
			D1(printk( "Retrying failed write.\n"));
167

168
			jffs2_dbg_acct_sanity_check(c,jeb);
169
			jffs2_dbg_acct_paranoia_check(c, jeb);
170

171
			if (alloc_mode == ALLOC_GC) {
172
				ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy);
173
			} else {
174
				/* Locking pain */
175
				up(&f->sem);
176
				jffs2_complete_reservation(c);
177

178
				ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode);
179
				down(&f->sem);
180
			}
181

182
			if (!ret) {
183
				D1(printk( "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
184

185
				jffs2_dbg_acct_sanity_check(c,jeb);
186
				jffs2_dbg_acct_paranoia_check(c, jeb);
187

188
				goto retry;
189
			}
190
			D1(printk( "Failed to allocate space to retry failed write: %d!\n", ret));
191
			jffs2_free_raw_node_ref(raw);
192
		}
193
		/* Release the full_dnode which is now useless, and return */
194
		jffs2_free_full_dnode(fn);
195
		return ERR_PTR(ret?ret:-EIO);
196
	}
197
	/* Mark the space used */
198
	/* If node covers at least a whole page, or if it starts at the
199
	   beginning of a page and runs to the end of the file, or if
200
	   it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
201
	*/
202
	if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) ||
203
	    ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) &&
204
	      (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) ==  je32_to_cpu(ri->isize)))) {
205
		raw->flash_offset |= REF_PRISTINE;
206
	} else {
207
		raw->flash_offset |= REF_NORMAL;
208
	}
209
	jffs2_add_physical_node_ref(c, raw);
210

211
	/* Link into per-inode list */
212
	spin_lock(&c->erase_completion_lock);
213
	raw->next_in_ino = f->inocache->nodes;
214
	f->inocache->nodes = raw;
215
	spin_unlock(&c->erase_completion_lock);
216

217
	D1(printk( "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n",
218
		  flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize),
219
		  je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
220
		  je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)));
221

222
	if (retried) {
223
		jffs2_dbg_acct_sanity_check(c,NULL);
224
	}
225

226
	return fn;
227
}
228

229
struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode)
230
{
231
	struct jffs2_raw_node_ref *raw;
232
	struct jffs2_full_dirent *fd;
233
	size_t retlen;
234
	struct iovec vecs[2];
235
	int retried = 0;
236
	int ret;
237

238
	D1(printk( "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n",
239
		  je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino),
240
		  je32_to_cpu(rd->name_crc)));
241

242
	D1(
243
	if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
244
		printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n");
245
		BUG();
246
	}
247
	);
248

249
	vecs[0].iov_base = rd;
250
	vecs[0].iov_len = sizeof(*rd);
251
	vecs[1].iov_base = (unsigned char *)name;
252
	vecs[1].iov_len = namelen;
253

254
	jffs2_dbg_prewrite_paranoia_check(c, flash_ofs,
255
					vecs[0].iov_len + vecs[1].iov_len);
256

257
	raw = jffs2_alloc_raw_node_ref();
258

259
	if (!raw) {
260
		return ERR_PTR(-ENOMEM);
261
	}
262

263
	fd = jffs2_alloc_full_dirent(namelen+1);
264
	if (!fd) {
265
		jffs2_free_raw_node_ref(raw);
266
		return ERR_PTR(-ENOMEM);
267
	}
268

269
	fd->version = je32_to_cpu(rd->version);
270
	fd->ino = je32_to_cpu(rd->ino);
271
	fd->nhash = full_name_hash(name, strlen((const char *) name));
272
	fd->type = rd->type;
273
	memcpy(fd->name, name, namelen);
274
	fd->name[namelen]=0;
275

276
 retry:
277
	fd->raw = raw;
278

279
	raw->flash_offset = flash_ofs;
280
	raw->__totlen = PAD(sizeof(*rd)+namelen);
281
	raw->next_phys = NULL;
282

283
	if ((alloc_mode!=ALLOC_GC) &&
284
			(je32_to_cpu(rd->version) < f->highest_version)) {
285
		BUG_ON(!retried);
286
		D1(printk( "jffs2_write_dirent : dirent_version %d, "
287
				     "highest version %d -> updating dirent\n",
288
				     je32_to_cpu(rd->version), f->highest_version));
289
		rd->version = cpu_to_je32(++f->highest_version);
290
		fd->version = je32_to_cpu(rd->version);
291
		rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
292
	}
293

294
	ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen,
295
				 (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino));
296
	if (ret || (retlen != sizeof(*rd) + namelen)) {
297
		printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
298
			       sizeof(*rd)+namelen, flash_ofs, ret, retlen);
299
		/* Mark the space as dirtied */
300
		if (retlen) {
301
			raw->next_in_ino = NULL;
302
			raw->flash_offset |= REF_OBSOLETE;
303
			jffs2_add_physical_node_ref(c, raw);
304
			jffs2_mark_node_obsolete(c, raw);
305
		} else {
306
			printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
307
			jffs2_free_raw_node_ref(raw);
308
		}
309
		if (!retried && (raw = jffs2_alloc_raw_node_ref())) {
310
			/* Try to reallocate space and retry */
311
			uint32_t dummy;
312
			struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
313

314
			retried = 1;
315

316
			D1(printk( "Retrying failed write.\n"));
317

318
			jffs2_dbg_acct_sanity_check(c,jeb);
319
			jffs2_dbg_acct_paranoia_check(c, jeb);
320

321
			if (alloc_mode == ALLOC_GC) {
322
				ret = jffs2_reserve_space_gc(c,
323
						sizeof(*rd) + namelen, &flash_ofs, &dummy);
324
			} else {
325
				/* Locking pain */
326
				up(&f->sem);
327
				jffs2_complete_reservation(c);
328

329
				ret = jffs2_reserve_space(c,
330
						sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode);
331
				down(&f->sem);
332
			}
333

334
			if (!ret) {
335
				D1(printk( "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
336
				jffs2_dbg_acct_sanity_check(c,jeb);
337
				jffs2_dbg_acct_paranoia_check(c, jeb);
338
				goto retry;
339
			}
340
			D1(printk( "Failed to allocate space to retry failed write: %d!\n", ret));
341
			jffs2_free_raw_node_ref(raw);
342
		}
343
		/* Release the full_dnode which is now useless, and return */
344
		jffs2_free_full_dirent(fd);
345
		return ERR_PTR(ret?ret:-EIO);
346
	}
347
	/* Mark the space used */
348
	raw->flash_offset |= REF_PRISTINE;
349
	jffs2_add_physical_node_ref(c, raw);
350

351
	spin_lock(&c->erase_completion_lock);
352
	raw->next_in_ino = f->inocache->nodes;
353
	f->inocache->nodes = raw;
354
	spin_unlock(&c->erase_completion_lock);
355

356
	if (retried) {
357
		jffs2_dbg_acct_sanity_check(c,NULL);
358
	}
359

360
	return fd;
361
}
362

363
/**
364
 * The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that
365
 * we don't have to go digging in struct inode or its equivalent. It should set:
366
 * mode, uid, gid, (starting)isize, atime, ctime, mtime
367
 */
368
int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
369
			    struct jffs2_raw_inode *ri, unsigned char *buf,
370
			    uint32_t offset, uint32_t writelen, uint32_t *retlen) {
371
	int ret = 0;
372
	uint32_t writtenlen = 0;
373

374
       	D1(printk( "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n",
375
		  f->inocache->ino, offset, writelen));
376

377
	while(writelen) {
378
		struct jffs2_full_dnode *fn;
379
		unsigned char *comprbuf = NULL;
380
		uint16_t comprtype = JFFS2_COMPR_NONE;
381
		uint32_t phys_ofs, alloclen;
382
		uint32_t datalen, cdatalen;
383
		int retried = 0;
384

385
	retry:
386
		D2(printk( "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset));
387

388
		ret = jffs2_reserve_space(c, sizeof(*ri) +
389
				JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL);
390
		if (ret) {
391
			D1(printk( "jffs2_reserve_space returned %d\n", ret));
392
			break;
393
		}
394
		down(&f->sem);
395
		datalen = min_t(uint32_t, writelen,
396
				PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1)));
397
		cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);
398

399
		comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen);
400

401
		ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
402
		ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
403
		ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen);
404
		ri->hdr_crc = cpu_to_je32(crc32(0, ri,
405
				sizeof(struct jffs2_unknown_node)-4));
406

407
		ri->ino = cpu_to_je32(f->inocache->ino);
408
		ri->version = cpu_to_je32(++f->highest_version);
409
		ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen));
410
		ri->offset = cpu_to_je32(offset);
411
		ri->csize = cpu_to_je32(cdatalen);
412
		ri->dsize = cpu_to_je32(datalen);
413
		ri->compr = comprtype & 0xff;
414
		ri->usercompr = (comprtype >> 8 ) & 0xff;
415
		ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
416
		ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
417

418
		fn = jffs2_write_dnode(c, f, ri,
419
				comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY);
420

421
		jffs2_free_comprbuf(comprbuf, buf);
422

423
		if (IS_ERR(fn)) {
424
			ret = PTR_ERR(fn);
425
			up(&f->sem);
426
			jffs2_complete_reservation(c);
427
			if (!retried) {
428
				/* Write error to be retried */
429
				retried = 1;
430
				D1(printk( "Retrying node write in jffs2_write_inode_range()\n"));
431
				goto retry;
432
			}
433
			break;
434
		}
435
		ret = jffs2_add_full_dnode_to_inode(c, f, fn);
436
		if (f->metadata) {
437
			jffs2_mark_node_obsolete(c, f->metadata->raw);
438
			jffs2_free_full_dnode(f->metadata);
439
			f->metadata = NULL;
440
		}
441
		if (ret) {
442
			/* Eep */
443
			D1(printk( "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret));
444
			jffs2_mark_node_obsolete(c, fn->raw);
445
			jffs2_free_full_dnode(fn);
446

447
			up(&f->sem);
448
			jffs2_complete_reservation(c);
449
			break;
450
		}
451
		up(&f->sem);
452
		jffs2_complete_reservation(c);
453
		if (!datalen) {
454
			printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n");
455
			ret = -EIO;
456
			break;
457
		}
458
		D1(printk( "increasing writtenlen by %d\n", datalen));
459
		writtenlen += datalen;
460
		offset += datalen;
461
		writelen -= datalen;
462
		buf += datalen;
463
	}
464
	*retlen = writtenlen;
465
	return ret;
466
}
467

468
int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
469
						struct jffs2_inode_info *f,
470
						struct jffs2_raw_inode *ri,
471
						const char *name, int namelen) {
472
	struct jffs2_raw_dirent *rd;
473
	struct jffs2_full_dnode *fn;
474
	struct jffs2_full_dirent *fd;
475
	uint32_t alloclen, phys_ofs;
476
	int ret;
477

478
	/* Try to reserve enough space for both node and dirent.
479
	 * Just the node will do for now, though
480
	 */
481
	ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
482
	D1(printk( "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
483
	if (ret) {
484
		up(&f->sem);
485
		return ret;
486
	}
487

488
	ri->data_crc = cpu_to_je32(0);
489
	ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
490

491
	fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
492

493
	D1(printk( "jffs2_do_create created file with mode 0x%x\n",
494
		  jemode_to_cpu(ri->mode)));
495

496
	if (IS_ERR(fn)) {
497
		D1(printk( "jffs2_write_dnode() failed\n"));
498
		/* Eeek. Wave bye bye */
499
		up(&f->sem);
500
		jffs2_complete_reservation(c);
501
		return PTR_ERR(fn);
502
	}
503
	/* No data here. Only a metadata node, which will be
504
	 * obsoleted by the first data write
505
	 */
506
	f->metadata = fn;
507

508
	up(&f->sem);
509
	jffs2_complete_reservation(c);
510
	ret = jffs2_reserve_space(c,
511
			sizeof(*rd) + namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
512

513
	if (ret) {
514
		/* Eep. */
515
		D1(printk( "jffs2_reserve_space() for dirent failed\n"));
516
		return ret;
517
	}
518

519
	rd = jffs2_alloc_raw_dirent();
520
	if (!rd) {
521
		/* Argh. Now we treat it like a normal delete */
522
		jffs2_complete_reservation(c);
523
		return -ENOMEM;
524
	}
525

526
	down(&dir_f->sem);
527

528
	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
529
	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
530
	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
531
	rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
532

533
	rd->pino = cpu_to_je32(dir_f->inocache->ino);
534
	rd->version = cpu_to_je32(++dir_f->highest_version);
535
	rd->ino = ri->ino;
536
	rd->mctime = ri->ctime;
537
	rd->nsize = namelen;
538
	rd->type = DT_REG;
539
	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
540
	rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
541

542
	fd = jffs2_write_dirent(c, dir_f, rd,
543
			(const unsigned char *) name, namelen, phys_ofs, ALLOC_NORMAL);
544

545
	jffs2_free_raw_dirent(rd);
546

547
	if (IS_ERR(fd)) {
548
		/* dirent failed to write. Delete the inode normally
549
		 * as if it were the final unlink()
550
		 */
551
		jffs2_complete_reservation(c);
552
		up(&dir_f->sem);
553
		return PTR_ERR(fd);
554
	}
555

556
	/* Link the fd into the inode's list, obsoleting an old
557
	   one if necessary. */
558
	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
559

560
	jffs2_complete_reservation(c);
561
	up(&dir_f->sem);
562

563
	return 0;
564
}
565

566

567
int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
568
		    const char *name, int namelen, struct jffs2_inode_info *dead_f) {
569
	struct jffs2_raw_dirent *rd;
570
	struct jffs2_full_dirent *fd;
571
	uint32_t alloclen, phys_ofs;
572
	int ret;
573

574
	if (1 /* alternative branch needs testing */ ||
575
	    !jffs2_can_mark_obsolete(c)) {
576
		/* We can't mark stuff obsolete on the medium.
577
		 * We need to write a deletion dirent
578
		 */
579
		rd = jffs2_alloc_raw_dirent();
580
		if (!rd) {
581
			return -ENOMEM;
582
		}
583

584
		ret = jffs2_reserve_space(c,
585
				sizeof(*rd) + namelen, &phys_ofs, &alloclen, ALLOC_DELETION);
586
		if (ret) {
587
			jffs2_free_raw_dirent(rd);
588
			return ret;
589
		}
590

591
		down(&dir_f->sem);
592

593
		/* Build a deletion node */
594
		rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
595
		rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
596
		rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
597
		rd->hdr_crc = cpu_to_je32(crc32(0, rd,
598
				sizeof(struct jffs2_unknown_node)-4));
599

600
		rd->pino = cpu_to_je32(dir_f->inocache->ino);
601
		rd->version = cpu_to_je32(++dir_f->highest_version);
602
		rd->ino = cpu_to_je32(0);
603
		rd->mctime = cpu_to_je32(get_seconds());
604
		rd->nsize = namelen;
605
		rd->type = DT_UNKNOWN;
606
		rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
607
		rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
608

609
		fd = jffs2_write_dirent(c, dir_f, rd, (const unsigned char *) name,
610
											namelen, phys_ofs, ALLOC_DELETION);
611

612
		jffs2_free_raw_dirent(rd);
613

614
		if (IS_ERR(fd)) {
615
			jffs2_complete_reservation(c);
616
			up(&dir_f->sem);
617
			return PTR_ERR(fd);
618
		}
619

620
		/* File it. This will mark the old one obsolete. */
621
		jffs2_add_fd_to_list(c, fd, &dir_f->dents);
622
		up(&dir_f->sem);
623
	} else {
624
		struct jffs2_full_dirent **prev = &dir_f->dents;
625
		uint32_t nhash = full_name_hash((const unsigned char *) name, namelen);
626

627
		down(&dir_f->sem);
628

629
		while ((*prev) && (*prev)->nhash <= nhash) {
630
			if ((*prev)->nhash == nhash &&
631
			    !memcmp((*prev)->name, name, namelen) &&
632
			    !(*prev)->name[namelen]) {
633
				struct jffs2_full_dirent *this = *prev;
634

635
				D1(printk( "Marking old dirent node (ino #%u) @%08x obsolete\n",
636
					  this->ino, ref_offset(this->raw)));
637

638
				*prev = this->next;
639
				jffs2_mark_node_obsolete(c, (this->raw));
640
				jffs2_free_full_dirent(this);
641
				break;
642
			}
643
			prev = &((*prev)->next);
644
		}
645
		up(&dir_f->sem);
646
	}
647

648
	/* dead_f is NULL if this was a rename not a real unlink */
649
	/* Also catch the !f->inocache case, where there was a dirent
650
	   pointing to an inode which didn't exist. */
651
	if (dead_f && dead_f->inocache) {
652

653
		down(&dead_f->sem);
654

655
		if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {
656
			while (dead_f->dents) {
657
				/* There can be only deleted ones */
658
				fd = dead_f->dents;
659

660
				dead_f->dents = fd->next;
661

662
				if (fd->ino) {
663
					printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n",
664
					       dead_f->inocache->ino, fd->name, fd->ino);
665
				} else {
666
					D1(printk( "Removing deletion dirent for \"%s\" from dir ino #%u\n",
667
						fd->name, dead_f->inocache->ino));
668
				}
669
				jffs2_mark_node_obsolete(c, fd->raw);
670
				jffs2_free_full_dirent(fd);
671
			}
672
		}
673

674
		dead_f->inocache->nlink--;
675
		/* NB: Caller must set inode nlink if appropriate */
676
		up(&dead_f->sem);
677
	}
678

679
	jffs2_complete_reservation(c);
680

681
	return 0;
682
}
683

684
int jffs2_do_link (struct jffs2_sb_info *c,
685
		struct jffs2_inode_info *dir_f, uint32_t ino,
686
		uint8_t type, const char *name, int namelen) {
687
	struct jffs2_raw_dirent *rd;
688
	struct jffs2_full_dirent *fd;
689
	uint32_t alloclen, phys_ofs;
690
	int ret;
691

692
	rd = jffs2_alloc_raw_dirent();
693
	if (!rd)
694
		return -ENOMEM;
695

696
	ret = jffs2_reserve_space(c,
697
			sizeof(*rd) + namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
698
	if (ret) {
699
		jffs2_free_raw_dirent(rd);
700
		return ret;
701
	}
702

703
	down(&dir_f->sem);
704

705
	/* Build a deletion node */
706
	rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
707
	rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
708
	rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
709
	rd->hdr_crc = cpu_to_je32(crc32(0, rd,
710
			sizeof(struct jffs2_unknown_node) - 4));
711

712
	rd->pino = cpu_to_je32(dir_f->inocache->ino);
713
	rd->version = cpu_to_je32(++dir_f->highest_version);
714
	rd->ino = cpu_to_je32(ino);
715
	rd->mctime = cpu_to_je32(get_seconds());
716
	rd->nsize = namelen;
717

718
	rd->type = type;
719

720
	rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
721
	rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
722

723
	fd = jffs2_write_dirent(c, dir_f, rd,
724
			(const unsigned char *) name, namelen, phys_ofs, ALLOC_NORMAL);
725

726
	jffs2_free_raw_dirent(rd);
727

728
	if (IS_ERR(fd)) {
729
		jffs2_complete_reservation(c);
730
		up(&dir_f->sem);
731
		return PTR_ERR(fd);
732
	}
733

734
	/* File it. This will mark the old one obsolete. */
735
	jffs2_add_fd_to_list(c, fd, &dir_f->dents);
736

737
	jffs2_complete_reservation(c);
738
	up(&dir_f->sem);
739

740
	return 0;
741
}
742

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.