aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jffs2/write.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/jffs2/write.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'fs/jffs2/write.c')
-rw-r--r--fs/jffs2/write.c708
1 files changed, 708 insertions, 0 deletions
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c
new file mode 100644
index 000000000000..80a5db542629
--- /dev/null
+++ b/fs/jffs2/write.c
@@ -0,0 +1,708 @@
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.87 2004/11/16 20:36:12 dwmw2 Exp $
11 *
12 */
13
14#include <linux/kernel.h>
15#include <linux/fs.h>
16#include <linux/crc32.h>
17#include <linux/slab.h>
18#include <linux/pagemap.h>
19#include <linux/mtd/mtd.h>
20#include "nodelist.h"
21#include "compr.h"
22
23
24int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri)
25{
26 struct jffs2_inode_cache *ic;
27
28 ic = jffs2_alloc_inode_cache();
29 if (!ic) {
30 return -ENOMEM;
31 }
32
33 memset(ic, 0, sizeof(*ic));
34
35 f->inocache = ic;
36 f->inocache->nlink = 1;
37 f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache;
38 f->inocache->ino = ++c->highest_ino;
39 f->inocache->state = INO_STATE_PRESENT;
40
41 ri->ino = cpu_to_je32(f->inocache->ino);
42
43 D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));
44 jffs2_add_ino_cache(c, f->inocache);
45
46 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
47 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
48 ri->totlen = cpu_to_je32(PAD(sizeof(*ri)));
49 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
50 ri->mode = cpu_to_jemode(mode);
51
52 f->highest_version = 1;
53 ri->version = cpu_to_je32(f->highest_version);
54
55 return 0;
56}
57
58#if CONFIG_JFFS2_FS_DEBUG > 0
59static void writecheck(struct jffs2_sb_info *c, uint32_t ofs)
60{
61 unsigned char buf[16];
62 size_t retlen;
63 int ret, i;
64
65 ret = jffs2_flash_read(c, ofs, 16, &retlen, buf);
66 if (ret || (retlen != 16)) {
67 D1(printk(KERN_DEBUG "read failed or short in writecheck(). ret %d, retlen %zd\n", ret, retlen));
68 return;
69 }
70 ret = 0;
71 for (i=0; i<16; i++) {
72 if (buf[i] != 0xff)
73 ret = 1;
74 }
75 if (ret) {
76 printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there are data already there:\n", ofs);
77 printk(KERN_WARNING "0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
78 ofs,
79 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
80 buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
81 }
82}
83#endif
84
85
86/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it,
87 write it to the flash, link it into the existing inode/fragment list */
88
89struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode)
90
91{
92 struct jffs2_raw_node_ref *raw;
93 struct jffs2_full_dnode *fn;
94 size_t retlen;
95 struct kvec vecs[2];
96 int ret;
97 int retried = 0;
98 unsigned long cnt = 2;
99
100 D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) {
101 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dnode()\n");
102 BUG();
103 }
104 );
105 vecs[0].iov_base = ri;
106 vecs[0].iov_len = sizeof(*ri);
107 vecs[1].iov_base = (unsigned char *)data;
108 vecs[1].iov_len = datalen;
109
110 D1(writecheck(c, flash_ofs));
111
112 if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
113 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);
114 }
115 raw = jffs2_alloc_raw_node_ref();
116 if (!raw)
117 return ERR_PTR(-ENOMEM);
118
119 fn = jffs2_alloc_full_dnode();
120 if (!fn) {
121 jffs2_free_raw_node_ref(raw);
122 return ERR_PTR(-ENOMEM);
123 }
124
125 fn->ofs = je32_to_cpu(ri->offset);
126 fn->size = je32_to_cpu(ri->dsize);
127 fn->frags = 0;
128
129 /* check number of valid vecs */
130 if (!datalen || !data)
131 cnt = 1;
132 retry:
133 fn->raw = raw;
134
135 raw->flash_offset = flash_ofs;
136 raw->__totlen = PAD(sizeof(*ri)+datalen);
137 raw->next_phys = NULL;
138
139 ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen,
140 (alloc_mode==ALLOC_GC)?0:f->inocache->ino);
141
142 if (ret || (retlen != sizeof(*ri) + datalen)) {
143 printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
144 sizeof(*ri)+datalen, flash_ofs, ret, retlen);
145
146 /* Mark the space as dirtied */
147 if (retlen) {
148 /* Doesn't belong to any inode */
149 raw->next_in_ino = NULL;
150
151 /* Don't change raw->size to match retlen. We may have
152 written the node header already, and only the data will
153 seem corrupted, in which case the scan would skip over
154 any node we write before the original intended end of
155 this node */
156 raw->flash_offset |= REF_OBSOLETE;
157 jffs2_add_physical_node_ref(c, raw);
158 jffs2_mark_node_obsolete(c, raw);
159 } else {
160 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
161 jffs2_free_raw_node_ref(raw);
162 }
163 if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) {
164 /* Try to reallocate space and retry */
165 uint32_t dummy;
166 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
167
168 retried = 1;
169
170 D1(printk(KERN_DEBUG "Retrying failed write.\n"));
171
172 ACCT_SANITY_CHECK(c,jeb);
173 D1(ACCT_PARANOIA_CHECK(jeb));
174
175 if (alloc_mode == ALLOC_GC) {
176 ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy);
177 } else {
178 /* Locking pain */
179 up(&f->sem);
180 jffs2_complete_reservation(c);
181
182 ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode);
183 down(&f->sem);
184 }
185
186 if (!ret) {
187 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
188
189 ACCT_SANITY_CHECK(c,jeb);
190 D1(ACCT_PARANOIA_CHECK(jeb));
191
192 goto retry;
193 }
194 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
195 jffs2_free_raw_node_ref(raw);
196 }
197 /* Release the full_dnode which is now useless, and return */
198 jffs2_free_full_dnode(fn);
199 return ERR_PTR(ret?ret:-EIO);
200 }
201 /* Mark the space used */
202 /* If node covers at least a whole page, or if it starts at the
203 beginning of a page and runs to the end of the file, or if
204 it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
205 */
206 if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) ||
207 ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) &&
208 (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) {
209 raw->flash_offset |= REF_PRISTINE;
210 } else {
211 raw->flash_offset |= REF_NORMAL;
212 }
213 jffs2_add_physical_node_ref(c, raw);
214
215 /* Link into per-inode list */
216 spin_lock(&c->erase_completion_lock);
217 raw->next_in_ino = f->inocache->nodes;
218 f->inocache->nodes = raw;
219 spin_unlock(&c->erase_completion_lock);
220
221 D1(printk(KERN_DEBUG "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",
222 flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize),
223 je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
224 je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)));
225
226 if (retried) {
227 ACCT_SANITY_CHECK(c,NULL);
228 }
229
230 return fn;
231}
232
233struct 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)
234{
235 struct jffs2_raw_node_ref *raw;
236 struct jffs2_full_dirent *fd;
237 size_t retlen;
238 struct kvec vecs[2];
239 int retried = 0;
240 int ret;
241
242 D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n",
243 je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino),
244 je32_to_cpu(rd->name_crc)));
245 D1(writecheck(c, flash_ofs));
246
247 D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
248 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n");
249 BUG();
250 }
251 );
252
253 vecs[0].iov_base = rd;
254 vecs[0].iov_len = sizeof(*rd);
255 vecs[1].iov_base = (unsigned char *)name;
256 vecs[1].iov_len = namelen;
257
258 raw = jffs2_alloc_raw_node_ref();
259
260 if (!raw)
261 return ERR_PTR(-ENOMEM);
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(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 ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen,
284 (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino));
285 if (ret || (retlen != sizeof(*rd) + namelen)) {
286 printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
287 sizeof(*rd)+namelen, flash_ofs, ret, retlen);
288 /* Mark the space as dirtied */
289 if (retlen) {
290 raw->next_in_ino = NULL;
291 raw->flash_offset |= REF_OBSOLETE;
292 jffs2_add_physical_node_ref(c, raw);
293 jffs2_mark_node_obsolete(c, raw);
294 } else {
295 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
296 jffs2_free_raw_node_ref(raw);
297 }
298 if (!retried && (raw = jffs2_alloc_raw_node_ref())) {
299 /* Try to reallocate space and retry */
300 uint32_t dummy;
301 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
302
303 retried = 1;
304
305 D1(printk(KERN_DEBUG "Retrying failed write.\n"));
306
307 ACCT_SANITY_CHECK(c,jeb);
308 D1(ACCT_PARANOIA_CHECK(jeb));
309
310 if (alloc_mode == ALLOC_GC) {
311 ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy);
312 } else {
313 /* Locking pain */
314 up(&f->sem);
315 jffs2_complete_reservation(c);
316
317 ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode);
318 down(&f->sem);
319 }
320
321 if (!ret) {
322 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
323 ACCT_SANITY_CHECK(c,jeb);
324 D1(ACCT_PARANOIA_CHECK(jeb));
325 goto retry;
326 }
327 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
328 jffs2_free_raw_node_ref(raw);
329 }
330 /* Release the full_dnode which is now useless, and return */
331 jffs2_free_full_dirent(fd);
332 return ERR_PTR(ret?ret:-EIO);
333 }
334 /* Mark the space used */
335 raw->flash_offset |= REF_PRISTINE;
336 jffs2_add_physical_node_ref(c, raw);
337
338 spin_lock(&c->erase_completion_lock);
339 raw->next_in_ino = f->inocache->nodes;
340 f->inocache->nodes = raw;
341 spin_unlock(&c->erase_completion_lock);
342
343 if (retried) {
344 ACCT_SANITY_CHECK(c,NULL);
345 }
346
347 return fd;
348}
349
350/* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that
351 we don't have to go digging in struct inode or its equivalent. It should set:
352 mode, uid, gid, (starting)isize, atime, ctime, mtime */
353int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
354 struct jffs2_raw_inode *ri, unsigned char *buf,
355 uint32_t offset, uint32_t writelen, uint32_t *retlen)
356{
357 int ret = 0;
358 uint32_t writtenlen = 0;
359
360 D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n",
361 f->inocache->ino, offset, writelen));
362
363 while(writelen) {
364 struct jffs2_full_dnode *fn;
365 unsigned char *comprbuf = NULL;
366 uint16_t comprtype = JFFS2_COMPR_NONE;
367 uint32_t phys_ofs, alloclen;
368 uint32_t datalen, cdatalen;
369 int retried = 0;
370
371 retry:
372 D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset));
373
374 ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL);
375 if (ret) {
376 D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
377 break;
378 }
379 down(&f->sem);
380 datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1)));
381 cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);
382
383 comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen);
384
385 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
386 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
387 ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen);
388 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
389
390 ri->ino = cpu_to_je32(f->inocache->ino);
391 ri->version = cpu_to_je32(++f->highest_version);
392 ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen));
393 ri->offset = cpu_to_je32(offset);
394 ri->csize = cpu_to_je32(cdatalen);
395 ri->dsize = cpu_to_je32(datalen);
396 ri->compr = comprtype & 0xff;
397 ri->usercompr = (comprtype >> 8 ) & 0xff;
398 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
399 ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
400
401 fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY);
402
403 jffs2_free_comprbuf(comprbuf, buf);
404
405 if (IS_ERR(fn)) {
406 ret = PTR_ERR(fn);
407 up(&f->sem);
408 jffs2_complete_reservation(c);
409 if (!retried) {
410 /* Write error to be retried */
411 retried = 1;
412 D1(printk(KERN_DEBUG "Retrying node write in jffs2_write_inode_range()\n"));
413 goto retry;
414 }
415 break;
416 }
417 ret = jffs2_add_full_dnode_to_inode(c, f, fn);
418 if (f->metadata) {
419 jffs2_mark_node_obsolete(c, f->metadata->raw);
420 jffs2_free_full_dnode(f->metadata);
421 f->metadata = NULL;
422 }
423 if (ret) {
424 /* Eep */
425 D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret));
426 jffs2_mark_node_obsolete(c, fn->raw);
427 jffs2_free_full_dnode(fn);
428
429 up(&f->sem);
430 jffs2_complete_reservation(c);
431 break;
432 }
433 up(&f->sem);
434 jffs2_complete_reservation(c);
435 if (!datalen) {
436 printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n");
437 ret = -EIO;
438 break;
439 }
440 D1(printk(KERN_DEBUG "increasing writtenlen by %d\n", datalen));
441 writtenlen += datalen;
442 offset += datalen;
443 writelen -= datalen;
444 buf += datalen;
445 }
446 *retlen = writtenlen;
447 return ret;
448}
449
450int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen)
451{
452 struct jffs2_raw_dirent *rd;
453 struct jffs2_full_dnode *fn;
454 struct jffs2_full_dirent *fd;
455 uint32_t alloclen, phys_ofs;
456 int ret;
457
458 /* Try to reserve enough space for both node and dirent.
459 * Just the node will do for now, though
460 */
461 ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
462 D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
463 if (ret) {
464 up(&f->sem);
465 return ret;
466 }
467
468 ri->data_crc = cpu_to_je32(0);
469 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
470
471 fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
472
473 D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n",
474 jemode_to_cpu(ri->mode)));
475
476 if (IS_ERR(fn)) {
477 D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n"));
478 /* Eeek. Wave bye bye */
479 up(&f->sem);
480 jffs2_complete_reservation(c);
481 return PTR_ERR(fn);
482 }
483 /* No data here. Only a metadata node, which will be
484 obsoleted by the first data write
485 */
486 f->metadata = fn;
487
488 up(&f->sem);
489 jffs2_complete_reservation(c);
490 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
491
492 if (ret) {
493 /* Eep. */
494 D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n"));
495 return ret;
496 }
497
498 rd = jffs2_alloc_raw_dirent();
499 if (!rd) {
500 /* Argh. Now we treat it like a normal delete */
501 jffs2_complete_reservation(c);
502 return -ENOMEM;
503 }
504
505 down(&dir_f->sem);
506
507 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
508 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
509 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
510 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
511
512 rd->pino = cpu_to_je32(dir_f->inocache->ino);
513 rd->version = cpu_to_je32(++dir_f->highest_version);
514 rd->ino = ri->ino;
515 rd->mctime = ri->ctime;
516 rd->nsize = namelen;
517 rd->type = DT_REG;
518 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
519 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
520
521 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
522
523 jffs2_free_raw_dirent(rd);
524
525 if (IS_ERR(fd)) {
526 /* dirent failed to write. Delete the inode normally
527 as if it were the final unlink() */
528 jffs2_complete_reservation(c);
529 up(&dir_f->sem);
530 return PTR_ERR(fd);
531 }
532
533 /* Link the fd into the inode's list, obsoleting an old
534 one if necessary. */
535 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
536
537 jffs2_complete_reservation(c);
538 up(&dir_f->sem);
539
540 return 0;
541}
542
543
544int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
545 const char *name, int namelen, struct jffs2_inode_info *dead_f)
546{
547 struct jffs2_raw_dirent *rd;
548 struct jffs2_full_dirent *fd;
549 uint32_t alloclen, phys_ofs;
550 int ret;
551
552 if (1 /* alternative branch needs testing */ ||
553 !jffs2_can_mark_obsolete(c)) {
554 /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */
555
556 rd = jffs2_alloc_raw_dirent();
557 if (!rd)
558 return -ENOMEM;
559
560 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION);
561 if (ret) {
562 jffs2_free_raw_dirent(rd);
563 return ret;
564 }
565
566 down(&dir_f->sem);
567
568 /* Build a deletion node */
569 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
570 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
571 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
572 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
573
574 rd->pino = cpu_to_je32(dir_f->inocache->ino);
575 rd->version = cpu_to_je32(++dir_f->highest_version);
576 rd->ino = cpu_to_je32(0);
577 rd->mctime = cpu_to_je32(get_seconds());
578 rd->nsize = namelen;
579 rd->type = DT_UNKNOWN;
580 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
581 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
582
583 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION);
584
585 jffs2_free_raw_dirent(rd);
586
587 if (IS_ERR(fd)) {
588 jffs2_complete_reservation(c);
589 up(&dir_f->sem);
590 return PTR_ERR(fd);
591 }
592
593 /* File it. This will mark the old one obsolete. */
594 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
595 up(&dir_f->sem);
596 } else {
597 struct jffs2_full_dirent **prev = &dir_f->dents;
598 uint32_t nhash = full_name_hash(name, namelen);
599
600 down(&dir_f->sem);
601
602 while ((*prev) && (*prev)->nhash <= nhash) {
603 if ((*prev)->nhash == nhash &&
604 !memcmp((*prev)->name, name, namelen) &&
605 !(*prev)->name[namelen]) {
606 struct jffs2_full_dirent *this = *prev;
607
608 D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n",
609 this->ino, ref_offset(this->raw)));
610
611 *prev = this->next;
612 jffs2_mark_node_obsolete(c, (this->raw));
613 jffs2_free_full_dirent(this);
614 break;
615 }
616 prev = &((*prev)->next);
617 }
618 up(&dir_f->sem);
619 }
620
621 /* dead_f is NULL if this was a rename not a real unlink */
622 /* Also catch the !f->inocache case, where there was a dirent
623 pointing to an inode which didn't exist. */
624 if (dead_f && dead_f->inocache) {
625
626 down(&dead_f->sem);
627
628 while (dead_f->dents) {
629 /* There can be only deleted ones */
630 fd = dead_f->dents;
631
632 dead_f->dents = fd->next;
633
634 if (fd->ino) {
635 printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n",
636 dead_f->inocache->ino, fd->name, fd->ino);
637 } else {
638 D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n", fd->name, dead_f->inocache->ino));
639 }
640 jffs2_mark_node_obsolete(c, fd->raw);
641 jffs2_free_full_dirent(fd);
642 }
643
644 dead_f->inocache->nlink--;
645 /* NB: Caller must set inode nlink if appropriate */
646 up(&dead_f->sem);
647 }
648
649 jffs2_complete_reservation(c);
650
651 return 0;
652}
653
654
655int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen)
656{
657 struct jffs2_raw_dirent *rd;
658 struct jffs2_full_dirent *fd;
659 uint32_t alloclen, phys_ofs;
660 int ret;
661
662 rd = jffs2_alloc_raw_dirent();
663 if (!rd)
664 return -ENOMEM;
665
666 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
667 if (ret) {
668 jffs2_free_raw_dirent(rd);
669 return ret;
670 }
671
672 down(&dir_f->sem);
673
674 /* Build a deletion node */
675 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
676 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
677 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
678 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
679
680 rd->pino = cpu_to_je32(dir_f->inocache->ino);
681 rd->version = cpu_to_je32(++dir_f->highest_version);
682 rd->ino = cpu_to_je32(ino);
683 rd->mctime = cpu_to_je32(get_seconds());
684 rd->nsize = namelen;
685
686 rd->type = type;
687
688 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
689 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
690
691 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
692
693 jffs2_free_raw_dirent(rd);
694
695 if (IS_ERR(fd)) {
696 jffs2_complete_reservation(c);
697 up(&dir_f->sem);
698 return PTR_ERR(fd);
699 }
700
701 /* File it. This will mark the old one obsolete. */
702 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
703
704 jffs2_complete_reservation(c);
705 up(&dir_f->sem);
706
707 return 0;
708}