OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [fs/] [jffs2/] [current/] [src/] [write.c] - Blame information for rev 786

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 786 skrzyp
/*
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 <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
 
24
int 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->state = INO_STATE_PRESENT;
39
 
40
 
41
        jffs2_add_ino_cache(c, f->inocache);
42
        D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino));
43
        ri->ino = cpu_to_je32(f->inocache->ino);
44
 
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
 
57
/* 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
 
60
struct 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
 
81
        jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
82
 
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
 
110
        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));
117
        }
118
 
119
        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
 
152
                        jffs2_dbg_acct_sanity_check(c,jeb);
153
                        jffs2_dbg_acct_paranoia_check(c, jeb);
154
 
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
 
169
                                jffs2_dbg_acct_sanity_check(c,jeb);
170
                                jffs2_dbg_acct_paranoia_check(c, jeb);
171
 
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) {
207
                jffs2_dbg_acct_sanity_check(c,NULL);
208
        }
209
 
210
        return fn;
211
}
212
 
213
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)
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)));
225
 
226
        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
 
237
        jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len);
238
 
239
        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
 
264
        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));
272
        }
273
 
274
        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
 
298
                        jffs2_dbg_acct_sanity_check(c,jeb);
299
                        jffs2_dbg_acct_paranoia_check(c, jeb);
300
 
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));
314
                                jffs2_dbg_acct_sanity_check(c,jeb);
315
                                jffs2_dbg_acct_paranoia_check(c, jeb);
316
                                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) {
335
                jffs2_dbg_acct_sanity_check(c,NULL);
336
        }
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 */
344
int 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
 
441
int 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
 
535
int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
536
                    const char *name, int namelen, struct jffs2_inode_info *dead_f)
537
{
538
        struct jffs2_raw_dirent *rd;
539
        struct jffs2_full_dirent *fd;
540
        uint32_t alloclen, phys_ofs;
541
        int ret;
542
 
543
        if (1 /* alternative branch needs testing */ ||
544
            !jffs2_can_mark_obsolete(c)) {
545
                /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */
546
 
547
                rd = jffs2_alloc_raw_dirent();
548
                if (!rd)
549
                        return -ENOMEM;
550
 
551
                ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION);
552
                if (ret) {
553
                        jffs2_free_raw_dirent(rd);
554
                        return ret;
555
                }
556
 
557
                down(&dir_f->sem);
558
 
559
                /* Build a deletion node */
560
                rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
561
                rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
562
                rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
563
                rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
564
 
565
                rd->pino = cpu_to_je32(dir_f->inocache->ino);
566
                rd->version = cpu_to_je32(++dir_f->highest_version);
567
                rd->ino = cpu_to_je32(0);
568
                rd->mctime = cpu_to_je32(get_seconds());
569
                rd->nsize = namelen;
570
                rd->type = DT_UNKNOWN;
571
                rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
572
                rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
573
 
574
                fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION);
575
 
576
                jffs2_free_raw_dirent(rd);
577
 
578
                if (IS_ERR(fd)) {
579
                        jffs2_complete_reservation(c);
580
                        up(&dir_f->sem);
581
                        return PTR_ERR(fd);
582
                }
583
 
584
                /* File it. This will mark the old one obsolete. */
585
                jffs2_add_fd_to_list(c, fd, &dir_f->dents);
586
                up(&dir_f->sem);
587
        } else {
588
                struct jffs2_full_dirent **prev = &dir_f->dents;
589
                uint32_t nhash = full_name_hash(name, namelen);
590
 
591
                down(&dir_f->sem);
592
 
593
                while ((*prev) && (*prev)->nhash <= nhash) {
594
                        if ((*prev)->nhash == nhash &&
595
                            !memcmp((*prev)->name, name, namelen) &&
596
                            !(*prev)->name[namelen]) {
597
                                struct jffs2_full_dirent *this = *prev;
598
 
599
                                D1(printk(KERN_DEBUG "Marking old dirent node (ino #%u) @%08x obsolete\n",
600
                                          this->ino, ref_offset(this->raw)));
601
 
602
                                *prev = this->next;
603
                                jffs2_mark_node_obsolete(c, (this->raw));
604
                                jffs2_free_full_dirent(this);
605
                                break;
606
                        }
607
                        prev = &((*prev)->next);
608
                }
609
                up(&dir_f->sem);
610
        }
611
 
612
        /* dead_f is NULL if this was a rename not a real unlink */
613
        /* Also catch the !f->inocache case, where there was a dirent
614
           pointing to an inode which didn't exist. */
615
        if (dead_f && dead_f->inocache) {
616
 
617
                down(&dead_f->sem);
618
 
619
                if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) {
620
                        while (dead_f->dents) {
621
                                /* There can be only deleted ones */
622
                                fd = dead_f->dents;
623
 
624
                                dead_f->dents = fd->next;
625
 
626
                                if (fd->ino) {
627
                                        printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n",
628
                                               dead_f->inocache->ino, fd->name, fd->ino);
629
                                } else {
630
                                        D1(printk(KERN_DEBUG "Removing deletion dirent for \"%s\" from dir ino #%u\n",
631
                                                fd->name, dead_f->inocache->ino));
632
                                }
633
                                jffs2_mark_node_obsolete(c, fd->raw);
634
                                jffs2_free_full_dirent(fd);
635
                        }
636
                }
637
 
638
                dead_f->inocache->nlink--;
639
                /* NB: Caller must set inode nlink if appropriate */
640
                up(&dead_f->sem);
641
        }
642
 
643
        jffs2_complete_reservation(c);
644
 
645
        return 0;
646
}
647
 
648
 
649
int 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)
650
{
651
        struct jffs2_raw_dirent *rd;
652
        struct jffs2_full_dirent *fd;
653
        uint32_t alloclen, phys_ofs;
654
        int ret;
655
 
656
        rd = jffs2_alloc_raw_dirent();
657
        if (!rd)
658
                return -ENOMEM;
659
 
660
        ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
661
        if (ret) {
662
                jffs2_free_raw_dirent(rd);
663
                return ret;
664
        }
665
 
666
        down(&dir_f->sem);
667
 
668
        /* Build a deletion node */
669
        rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
670
        rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
671
        rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
672
        rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
673
 
674
        rd->pino = cpu_to_je32(dir_f->inocache->ino);
675
        rd->version = cpu_to_je32(++dir_f->highest_version);
676
        rd->ino = cpu_to_je32(ino);
677
        rd->mctime = cpu_to_je32(get_seconds());
678
        rd->nsize = namelen;
679
 
680
        rd->type = type;
681
 
682
        rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
683
        rd->name_crc = cpu_to_je32(crc32(0, name, namelen));
684
 
685
        fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL);
686
 
687
        jffs2_free_raw_dirent(rd);
688
 
689
        if (IS_ERR(fd)) {
690
                jffs2_complete_reservation(c);
691
                up(&dir_f->sem);
692
                return PTR_ERR(fd);
693
        }
694
 
695
        /* File it. This will mark the old one obsolete. */
696
        jffs2_add_fd_to_list(c, fd, &dir_f->dents);
697
 
698
        jffs2_complete_reservation(c);
699
        up(&dir_f->sem);
700
 
701
        return 0;
702
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.