blob: 0a194759bbbdc9a34e0f50d1e1310c0a7c416630 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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 *
Artem B. Bityutskiy3a69e0c2005-08-17 14:46:26 +010010 * $Id: write.c,v 1.95 2005/08/17 13:46:23 dedekind Exp $
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 *
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;
Linus Torvalds1da177e2005-04-16 15:20:36 -070038 f->inocache->state = INO_STATE_PRESENT;
39
Linus Torvalds1da177e2005-04-16 15:20:36 -070040
Linus Torvalds1da177e2005-04-16 15:20:36 -070041 jffs2_add_ino_cache(c, f->inocache);
David Woodhouse7d200962005-04-13 14:22:38 +010042 D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));
43 ri->ino = cpu_to_je32(f->inocache->ino);
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
45 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
46 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
47 ri->totlen = cpu_to_je32(PAD(sizeof(*ri)));
48 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
49 ri->mode = cpu_to_jemode(mode);
50
51 f->highest_version = 1;
52 ri->version = cpu_to_je32(f->highest_version);
53
54 return 0;
55}
56
Linus Torvalds1da177e2005-04-16 15:20:36 -070057/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it,
58 write it to the flash, link it into the existing inode/fragment list */
59
60struct 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)
61
62{
63 struct jffs2_raw_node_ref *raw;
64 struct jffs2_full_dnode *fn;
65 size_t retlen;
66 struct kvec vecs[2];
67 int ret;
68 int retried = 0;
69 unsigned long cnt = 2;
70
71 D1(if(je32_to_cpu(ri->hdr_crc) != crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)) {
72 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dnode()\n");
73 BUG();
74 }
75 );
76 vecs[0].iov_base = ri;
77 vecs[0].iov_len = sizeof(*ri);
78 vecs[1].iov_base = (unsigned char *)data;
79 vecs[1].iov_len = datalen;
80
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +010081 jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -070082
83 if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) {
84 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);
85 }
86 raw = jffs2_alloc_raw_node_ref();
87 if (!raw)
88 return ERR_PTR(-ENOMEM);
89
90 fn = jffs2_alloc_full_dnode();
91 if (!fn) {
92 jffs2_free_raw_node_ref(raw);
93 return ERR_PTR(-ENOMEM);
94 }
95
96 fn->ofs = je32_to_cpu(ri->offset);
97 fn->size = je32_to_cpu(ri->dsize);
98 fn->frags = 0;
99
100 /* check number of valid vecs */
101 if (!datalen || !data)
102 cnt = 1;
103 retry:
104 fn->raw = raw;
105
106 raw->flash_offset = flash_ofs;
107 raw->__totlen = PAD(sizeof(*ri)+datalen);
108 raw->next_phys = NULL;
109
Estelle Hammache9b88f472005-01-28 18:53:05 +0000110 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) {
111 BUG_ON(!retried);
112 D1(printk(KERN_DEBUG "jffs2_write_dnode : dnode_version %d, "
113 "highest version %d -> updating dnode\n",
114 je32_to_cpu(ri->version), f->highest_version));
115 ri->version = cpu_to_je32(++f->highest_version);
116 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
Estelle Hammachee4803c32005-01-24 21:13:42 +0000117 }
118
Linus Torvalds1da177e2005-04-16 15:20:36 -0700119 ret = jffs2_flash_writev(c, vecs, cnt, flash_ofs, &retlen,
120 (alloc_mode==ALLOC_GC)?0:f->inocache->ino);
121
122 if (ret || (retlen != sizeof(*ri) + datalen)) {
123 printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
124 sizeof(*ri)+datalen, flash_ofs, ret, retlen);
125
126 /* Mark the space as dirtied */
127 if (retlen) {
128 /* Doesn't belong to any inode */
129 raw->next_in_ino = NULL;
130
131 /* Don't change raw->size to match retlen. We may have
132 written the node header already, and only the data will
133 seem corrupted, in which case the scan would skip over
134 any node we write before the original intended end of
135 this node */
136 raw->flash_offset |= REF_OBSOLETE;
137 jffs2_add_physical_node_ref(c, raw);
138 jffs2_mark_node_obsolete(c, raw);
139 } else {
140 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
141 jffs2_free_raw_node_ref(raw);
142 }
143 if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) {
144 /* Try to reallocate space and retry */
145 uint32_t dummy;
146 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
147
148 retried = 1;
149
150 D1(printk(KERN_DEBUG "Retrying failed write.\n"));
151
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100152 jffs2_dbg_acct_sanity_check(c,jeb);
153 jffs2_dbg_acct_paranoia_check(c, jeb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
155 if (alloc_mode == ALLOC_GC) {
156 ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy);
157 } else {
158 /* Locking pain */
159 up(&f->sem);
160 jffs2_complete_reservation(c);
161
162 ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode);
163 down(&f->sem);
164 }
165
166 if (!ret) {
167 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
168
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100169 jffs2_dbg_acct_sanity_check(c,jeb);
170 jffs2_dbg_acct_paranoia_check(c, jeb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700171
172 goto retry;
173 }
174 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
175 jffs2_free_raw_node_ref(raw);
176 }
177 /* Release the full_dnode which is now useless, and return */
178 jffs2_free_full_dnode(fn);
179 return ERR_PTR(ret?ret:-EIO);
180 }
181 /* Mark the space used */
182 /* If node covers at least a whole page, or if it starts at the
183 beginning of a page and runs to the end of the file, or if
184 it's a hole node, mark it REF_PRISTINE, else REF_NORMAL.
185 */
186 if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) ||
187 ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) &&
188 (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) {
189 raw->flash_offset |= REF_PRISTINE;
190 } else {
191 raw->flash_offset |= REF_NORMAL;
192 }
193 jffs2_add_physical_node_ref(c, raw);
194
195 /* Link into per-inode list */
196 spin_lock(&c->erase_completion_lock);
197 raw->next_in_ino = f->inocache->nodes;
198 f->inocache->nodes = raw;
199 spin_unlock(&c->erase_completion_lock);
200
201 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",
202 flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize),
203 je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc),
204 je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen)));
205
206 if (retried) {
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100207 jffs2_dbg_acct_sanity_check(c,NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208 }
209
210 return fn;
211}
212
213struct 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)
214{
215 struct jffs2_raw_node_ref *raw;
216 struct jffs2_full_dirent *fd;
217 size_t retlen;
218 struct kvec vecs[2];
219 int retried = 0;
220 int ret;
221
222 D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n",
223 je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino),
224 je32_to_cpu(rd->name_crc)));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100225
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226 D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) {
227 printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n");
228 BUG();
229 }
230 );
231
232 vecs[0].iov_base = rd;
233 vecs[0].iov_len = sizeof(*rd);
234 vecs[1].iov_base = (unsigned char *)name;
235 vecs[1].iov_len = namelen;
236
Artem B. Bityutskiye0c8e422005-07-24 16:14:17 +0100237 jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
238
Linus Torvalds1da177e2005-04-16 15:20:36 -0700239 raw = jffs2_alloc_raw_node_ref();
240
241 if (!raw)
242 return ERR_PTR(-ENOMEM);
243
244 fd = jffs2_alloc_full_dirent(namelen+1);
245 if (!fd) {
246 jffs2_free_raw_node_ref(raw);
247 return ERR_PTR(-ENOMEM);
248 }
249
250 fd->version = je32_to_cpu(rd->version);
251 fd->ino = je32_to_cpu(rd->ino);
252 fd->nhash = full_name_hash(name, strlen(name));
253 fd->type = rd->type;
254 memcpy(fd->name, name, namelen);
255 fd->name[namelen]=0;
256
257 retry:
258 fd->raw = raw;
259
260 raw->flash_offset = flash_ofs;
261 raw->__totlen = PAD(sizeof(*rd)+namelen);
262 raw->next_phys = NULL;
263
Estelle Hammache9b88f472005-01-28 18:53:05 +0000264 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) {
265 BUG_ON(!retried);
266 D1(printk(KERN_DEBUG "jffs2_write_dirent : dirent_version %d, "
267 "highest version %d -> updating dirent\n",
268 je32_to_cpu(rd->version), f->highest_version));
269 rd->version = cpu_to_je32(++f->highest_version);
270 fd->version = je32_to_cpu(rd->version);
271 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
Estelle Hammachee4803c32005-01-24 21:13:42 +0000272 }
273
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen,
275 (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino));
276 if (ret || (retlen != sizeof(*rd) + namelen)) {
277 printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n",
278 sizeof(*rd)+namelen, flash_ofs, ret, retlen);
279 /* Mark the space as dirtied */
280 if (retlen) {
281 raw->next_in_ino = NULL;
282 raw->flash_offset |= REF_OBSOLETE;
283 jffs2_add_physical_node_ref(c, raw);
284 jffs2_mark_node_obsolete(c, raw);
285 } else {
286 printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset);
287 jffs2_free_raw_node_ref(raw);
288 }
289 if (!retried && (raw = jffs2_alloc_raw_node_ref())) {
290 /* Try to reallocate space and retry */
291 uint32_t dummy;
292 struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size];
293
294 retried = 1;
295
296 D1(printk(KERN_DEBUG "Retrying failed write.\n"));
297
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100298 jffs2_dbg_acct_sanity_check(c,jeb);
299 jffs2_dbg_acct_paranoia_check(c, jeb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700300
301 if (alloc_mode == ALLOC_GC) {
302 ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy);
303 } else {
304 /* Locking pain */
305 up(&f->sem);
306 jffs2_complete_reservation(c);
307
308 ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode);
309 down(&f->sem);
310 }
311
312 if (!ret) {
313 D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs));
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100314 jffs2_dbg_acct_sanity_check(c,jeb);
315 jffs2_dbg_acct_paranoia_check(c, jeb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 goto retry;
317 }
318 D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret));
319 jffs2_free_raw_node_ref(raw);
320 }
321 /* Release the full_dnode which is now useless, and return */
322 jffs2_free_full_dirent(fd);
323 return ERR_PTR(ret?ret:-EIO);
324 }
325 /* Mark the space used */
326 raw->flash_offset |= REF_PRISTINE;
327 jffs2_add_physical_node_ref(c, raw);
328
329 spin_lock(&c->erase_completion_lock);
330 raw->next_in_ino = f->inocache->nodes;
331 f->inocache->nodes = raw;
332 spin_unlock(&c->erase_completion_lock);
333
334 if (retried) {
Artem B. Bityutskiy730554d2005-07-17 07:56:26 +0100335 jffs2_dbg_acct_sanity_check(c,NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 }
337
338 return fd;
339}
340
341/* The OS-specific code fills in the metadata in the jffs2_raw_inode for us, so that
342 we don't have to go digging in struct inode or its equivalent. It should set:
343 mode, uid, gid, (starting)isize, atime, ctime, mtime */
344int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
345 struct jffs2_raw_inode *ri, unsigned char *buf,
346 uint32_t offset, uint32_t writelen, uint32_t *retlen)
347{
348 int ret = 0;
349 uint32_t writtenlen = 0;
350
351 D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n",
352 f->inocache->ino, offset, writelen));
353
354 while(writelen) {
355 struct jffs2_full_dnode *fn;
356 unsigned char *comprbuf = NULL;
357 uint16_t comprtype = JFFS2_COMPR_NONE;
358 uint32_t phys_ofs, alloclen;
359 uint32_t datalen, cdatalen;
360 int retried = 0;
361
362 retry:
363 D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset));
364
365 ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL);
366 if (ret) {
367 D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret));
368 break;
369 }
370 down(&f->sem);
371 datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1)));
372 cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen);
373
374 comprtype = jffs2_compress(c, f, buf, &comprbuf, &datalen, &cdatalen);
375
376 ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
377 ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
378 ri->totlen = cpu_to_je32(sizeof(*ri) + cdatalen);
379 ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
380
381 ri->ino = cpu_to_je32(f->inocache->ino);
382 ri->version = cpu_to_je32(++f->highest_version);
383 ri->isize = cpu_to_je32(max(je32_to_cpu(ri->isize), offset + datalen));
384 ri->offset = cpu_to_je32(offset);
385 ri->csize = cpu_to_je32(cdatalen);
386 ri->dsize = cpu_to_je32(datalen);
387 ri->compr = comprtype & 0xff;
388 ri->usercompr = (comprtype >> 8 ) & 0xff;
389 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
390 ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen));
391
392 fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY);
393
394 jffs2_free_comprbuf(comprbuf, buf);
395
396 if (IS_ERR(fn)) {
397 ret = PTR_ERR(fn);
398 up(&f->sem);
399 jffs2_complete_reservation(c);
400 if (!retried) {
401 /* Write error to be retried */
402 retried = 1;
403 D1(printk(KERN_DEBUG "Retrying node write in jffs2_write_inode_range()\n"));
404 goto retry;
405 }
406 break;
407 }
408 ret = jffs2_add_full_dnode_to_inode(c, f, fn);
409 if (f->metadata) {
410 jffs2_mark_node_obsolete(c, f->metadata->raw);
411 jffs2_free_full_dnode(f->metadata);
412 f->metadata = NULL;
413 }
414 if (ret) {
415 /* Eep */
416 D1(printk(KERN_DEBUG "Eep. add_full_dnode_to_inode() failed in commit_write, returned %d\n", ret));
417 jffs2_mark_node_obsolete(c, fn->raw);
418 jffs2_free_full_dnode(fn);
419
420 up(&f->sem);
421 jffs2_complete_reservation(c);
422 break;
423 }
424 up(&f->sem);
425 jffs2_complete_reservation(c);
426 if (!datalen) {
427 printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n");
428 ret = -EIO;
429 break;
430 }
431 D1(printk(KERN_DEBUG "increasing writtenlen by %d\n", datalen));
432 writtenlen += datalen;
433 offset += datalen;
434 writelen -= datalen;
435 buf += datalen;
436 }
437 *retlen = writtenlen;
438 return ret;
439}
440
441int 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)
442{
443 struct jffs2_raw_dirent *rd;
444 struct jffs2_full_dnode *fn;
445 struct jffs2_full_dirent *fd;
446 uint32_t alloclen, phys_ofs;
447 int ret;
448
449 /* Try to reserve enough space for both node and dirent.
450 * Just the node will do for now, though
451 */
452 ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
453 D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
454 if (ret) {
455 up(&f->sem);
456 return ret;
457 }
458
459 ri->data_crc = cpu_to_je32(0);
460 ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
461
462 fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
463
464 D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n",
465 jemode_to_cpu(ri->mode)));
466
467 if (IS_ERR(fn)) {
468 D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n"));
469 /* Eeek. Wave bye bye */
470 up(&f->sem);
471 jffs2_complete_reservation(c);
472 return PTR_ERR(fn);
473 }
474 /* No data here. Only a metadata node, which will be
475 obsoleted by the first data write
476 */
477 f->metadata = fn;
478
479 up(&f->sem);
480 jffs2_complete_reservation(c);
481 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
482
483 if (ret) {
484 /* Eep. */
485 D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n"));
486 return ret;
487 }
488
489 rd = jffs2_alloc_raw_dirent();
490 if (!rd) {
491 /* Argh. Now we treat it like a normal delete */
492 jffs2_complete_reservation(c);
493 return -ENOMEM;
494 }
495
496 down(&dir_f->sem);
497
498 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
499 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
500 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
501 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
502
503 rd->pino = cpu_to_je32(dir_f->inocache->ino);
504 rd->version = cpu_to_je32(++dir_f->highest_version);
505 rd->ino = ri->ino;
506 rd->mctime = ri->ctime;
507 rd->nsize = namelen;
508 rd->type = DT_REG;
509 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
510 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
511
512 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
513
514 jffs2_free_raw_dirent(rd);
515
516 if (IS_ERR(fd)) {
517 /* dirent failed to write. Delete the inode normally
518 as if it were the final unlink() */
519 jffs2_complete_reservation(c);
520 up(&dir_f->sem);
521 return PTR_ERR(fd);
522 }
523
524 /* Link the fd into the inode's list, obsoleting an old
525 one if necessary. */
526 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
527
528 jffs2_complete_reservation(c);
529 up(&dir_f->sem);
530
531 return 0;
532}
533
534
535int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
Artem B. Bityutskiy3a69e0c2005-08-17 14:46:26 +0100536 const char *name, int namelen, struct jffs2_inode_info *dead_f,
537 uint32_t time)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538{
539 struct jffs2_raw_dirent *rd;
540 struct jffs2_full_dirent *fd;
541 uint32_t alloclen, phys_ofs;
542 int ret;
543
544 if (1 /* alternative branch needs testing */ ||
545 !jffs2_can_mark_obsolete(c)) {
546 /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */
547
548 rd = jffs2_alloc_raw_dirent();
549 if (!rd)
550 return -ENOMEM;
551
552 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION);
553 if (ret) {
554 jffs2_free_raw_dirent(rd);
555 return ret;
556 }
557
558 down(&dir_f->sem);
559
560 /* Build a deletion node */
561 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
562 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
563 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
564 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
565
566 rd->pino = cpu_to_je32(dir_f->inocache->ino);
567 rd->version = cpu_to_je32(++dir_f->highest_version);
568 rd->ino = cpu_to_je32(0);
Artem B. Bityutskiy3a69e0c2005-08-17 14:46:26 +0100569 rd->mctime = cpu_to_je32(time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570 rd->nsize = namelen;
571 rd->type = DT_UNKNOWN;
572 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
573 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
574
575 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION);
576
577 jffs2_free_raw_dirent(rd);
578
579 if (IS_ERR(fd)) {
580 jffs2_complete_reservation(c);
581 up(&dir_f->sem);
582 return PTR_ERR(fd);
583 }
584
585 /* File it. This will mark the old one obsolete. */
586 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
587 up(&dir_f->sem);
588 } else {
589 struct jffs2_full_dirent **prev = &dir_f->dents;
590 uint32_t nhash = full_name_hash(name, namelen);
591
592 down(&dir_f->sem);
593
594 while ((*prev) && (*prev)->nhash <= nhash) {
595 if ((*prev)->nhash == nhash &&
596 !memcmp((*prev)->name, name, namelen) &&
597 !(*prev)->name[namelen]) {
598 struct jffs2_full_dirent *this = *prev;
599
600 D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n",
601 this->ino, ref_offset(this->raw)));
602
603 *prev = this->next;
604 jffs2_mark_node_obsolete(c, (this->raw));
605 jffs2_free_full_dirent(this);
606 break;
607 }
608 prev = &((*prev)->next);
609 }
610 up(&dir_f->sem);
611 }
612
613 /* dead_f is NULL if this was a rename not a real unlink */
614 /* Also catch the !f->inocache case, where there was a dirent
615 pointing to an inode which didn't exist. */
616 if (dead_f && dead_f->inocache) {
617
618 down(&dead_f->sem);
619
Artem B. Bityuckiy32f1a952005-03-01 10:50:52 +0000620 if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {
621 while (dead_f->dents) {
622 /* There can be only deleted ones */
623 fd = dead_f->dents;
624
625 dead_f->dents = fd->next;
626
627 if (fd->ino) {
628 printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n",
629 dead_f->inocache->ino, fd->name, fd->ino);
630 } else {
631 D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n",
632 fd->name, dead_f->inocache->ino));
633 }
634 jffs2_mark_node_obsolete(c, fd->raw);
635 jffs2_free_full_dirent(fd);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 }
638
639 dead_f->inocache->nlink--;
640 /* NB: Caller must set inode nlink if appropriate */
641 up(&dead_f->sem);
642 }
643
644 jffs2_complete_reservation(c);
645
646 return 0;
647}
648
649
Artem B. Bityutskiy3a69e0c2005-08-17 14:46:26 +0100650int 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, uint32_t time)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651{
652 struct jffs2_raw_dirent *rd;
653 struct jffs2_full_dirent *fd;
654 uint32_t alloclen, phys_ofs;
655 int ret;
656
657 rd = jffs2_alloc_raw_dirent();
658 if (!rd)
659 return -ENOMEM;
660
661 ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
662 if (ret) {
663 jffs2_free_raw_dirent(rd);
664 return ret;
665 }
666
667 down(&dir_f->sem);
668
669 /* Build a deletion node */
670 rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
671 rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
672 rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
673 rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
674
675 rd->pino = cpu_to_je32(dir_f->inocache->ino);
676 rd->version = cpu_to_je32(++dir_f->highest_version);
677 rd->ino = cpu_to_je32(ino);
Artem B. Bityutskiy3a69e0c2005-08-17 14:46:26 +0100678 rd->mctime = cpu_to_je32(time);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679 rd->nsize = namelen;
680
681 rd->type = type;
682
683 rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
684 rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
685
686 fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
687
688 jffs2_free_raw_dirent(rd);
689
690 if (IS_ERR(fd)) {
691 jffs2_complete_reservation(c);
692 up(&dir_f->sem);
693 return PTR_ERR(fd);
694 }
695
696 /* File it. This will mark the old one obsolete. */
697 jffs2_add_fd_to_list(c, fd, &dir_f->dents);
698
699 jffs2_complete_reservation(c);
700 up(&dir_f->sem);
701
702 return 0;
703}