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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [fs/] [jffs2/] [gc.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * JFFS2 -- Journalling Flash File System, Version 2.
3
 *
4
 * Copyright (C) 2001 Red Hat, Inc.
5
 *
6
 * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
7
 *
8
 * The original JFFS, from which the design for JFFS2 was derived,
9
 * was designed and implemented by Axis Communications AB.
10
 *
11
 * The contents of this file are subject to the Red Hat eCos Public
12
 * License Version 1.1 (the "Licence"); you may not use this file
13
 * except in compliance with the Licence.  You may obtain a copy of
14
 * the Licence at http://www.redhat.com/
15
 *
16
 * Software distributed under the Licence is distributed on an "AS IS"
17
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
18
 * See the Licence for the specific language governing rights and
19
 * limitations under the Licence.
20
 *
21
 * The Original Code is JFFS2 - Journalling Flash File System, version 2
22
 *
23
 * Alternatively, the contents of this file may be used under the
24
 * terms of the GNU General Public License version 2 (the "GPL"), in
25
 * which case the provisions of the GPL are applicable instead of the
26
 * above.  If you wish to allow the use of your version of this file
27
 * only under the terms of the GPL and not to allow others to use your
28
 * version of this file under the RHEPL, indicate your decision by
29
 * deleting the provisions above and replace them with the notice and
30
 * other provisions required by the GPL.  If you do not delete the
31
 * provisions above, a recipient may use your version of this file
32
 * under either the RHEPL or the GPL.
33
 *
34
 * $Id: gc.c,v 1.1.1.1 2004-04-15 01:11:00 phoenix Exp $
35
 *
36
 */
37
 
38
#include <linux/kernel.h>
39
#include <linux/mtd/mtd.h>
40
#include <linux/slab.h>
41
#include <linux/jffs2.h>
42
#include <linux/sched.h>
43
#include <linux/interrupt.h>
44
#include <linux/pagemap.h>
45
#include "nodelist.h"
46
#include <linux/crc32.h>
47
 
48
static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
49
                                        struct inode *inode, struct jffs2_full_dnode *fd);
50
static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
51
                                        struct inode *inode, struct jffs2_full_dirent *fd);
52
static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
53
                                        struct inode *inode, struct jffs2_full_dirent *fd);
54
static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
55
                                      struct inode *indeo, struct jffs2_full_dnode *fn,
56
                                      __u32 start, __u32 end);
57
static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
58
                                       struct inode *inode, struct jffs2_full_dnode *fn,
59
                                       __u32 start, __u32 end);
60
 
61
/* Called with erase_completion_lock held */
62
static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c)
63
{
64
        struct jffs2_eraseblock *ret;
65
        struct list_head *nextlist = NULL;
66
 
67
        /* Pick an eraseblock to garbage collect next. This is where we'll
68
           put the clever wear-levelling algorithms. Eventually.  */
69
        if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > JFFS2_RESERVED_BLOCKS_GCBAD) {
70
                D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n"));
71
                nextlist = &c->bad_used_list;
72
        } else if (jiffies % 100 && !list_empty(&c->dirty_list)) {
73
                /* Most of the time, pick one off the dirty list */
74
                D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n"));
75
                nextlist = &c->dirty_list;
76
        } else if (!list_empty(&c->clean_list)) {
77
                D1(printk(KERN_DEBUG "Picking block from clean_list to GC next\n"));
78
                nextlist = &c->clean_list;
79
        } else if (!list_empty(&c->dirty_list)) {
80
                D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n"));
81
 
82
                nextlist = &c->dirty_list;
83
        } else {
84
                /* Eep. Both were empty */
85
                printk(KERN_NOTICE "jffs2: No clean _or_ dirty blocks to GC from! Where are they all?\n");
86
                return NULL;
87
        }
88
 
89
        ret = list_entry(nextlist->next, struct jffs2_eraseblock, list);
90
        list_del(&ret->list);
91
        c->gcblock = ret;
92
        ret->gc_node = ret->first_node;
93
        if (!ret->gc_node) {
94
                printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset);
95
                BUG();
96
        }
97
        return ret;
98
}
99
 
100
/* jffs2_garbage_collect_pass
101
 * Make a single attempt to progress GC. Move one node, and possibly
102
 * start erasing one eraseblock.
103
 */
104
int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
105
{
106
        struct jffs2_eraseblock *jeb;
107
        struct jffs2_inode_info *f;
108
        struct jffs2_raw_node_ref *raw;
109
        struct jffs2_node_frag *frag;
110
        struct jffs2_full_dnode *fn = NULL;
111
        struct jffs2_full_dirent *fd;
112
        struct jffs2_inode_cache *ic;
113
        __u32 start = 0, end = 0, nrfrags = 0;
114
        struct inode *inode;
115
        int ret = 0;
116
 
117
        if (down_interruptible(&c->alloc_sem))
118
                return -EINTR;
119
 
120
        spin_lock_bh(&c->erase_completion_lock);
121
 
122
        /* First, work out which block we're garbage-collecting */
123
        jeb = c->gcblock;
124
 
125
        if (!jeb)
126
                jeb = jffs2_find_gc_block(c);
127
 
128
        if (!jeb) {
129
                printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n");
130
                spin_unlock_bh(&c->erase_completion_lock);
131
                up(&c->alloc_sem);
132
                return -EIO;
133
        }
134
 
135
        D1(printk(KERN_DEBUG "garbage collect from block at phys 0x%08x\n", jeb->offset));
136
 
137
        if (!jeb->used_size) {
138
                up(&c->alloc_sem);
139
                goto eraseit;
140
        }
141
 
142
        raw = jeb->gc_node;
143
 
144
        while(raw->flash_offset & 1) {
145
                D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", raw->flash_offset &~3));
146
                jeb->gc_node = raw = raw->next_phys;
147
                if (!raw) {
148
                        printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n");
149
                        printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n",
150
                               jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size);
151
                        spin_unlock_bh(&c->erase_completion_lock);
152
                        up(&c->alloc_sem);
153
                        BUG();
154
                }
155
        }
156
        D1(printk(KERN_DEBUG "Going to garbage collect node at 0x%08x\n", raw->flash_offset &~3));
157
        if (!raw->next_in_ino) {
158
                /* Inode-less node. Clean marker, snapshot or something like that */
159
                spin_unlock_bh(&c->erase_completion_lock);
160
                jffs2_mark_node_obsolete(c, raw);
161
                up(&c->alloc_sem);
162
                goto eraseit_lock;
163
        }
164
 
165
        ic = jffs2_raw_ref_to_ic(raw);
166
        D1(printk(KERN_DEBUG "Inode number is #%u\n", ic->ino));
167
 
168
        spin_unlock_bh(&c->erase_completion_lock);
169
 
170
        D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass collecting from block @0x%08x. Node @0x%08x, ino #%u\n", jeb->offset, raw->flash_offset&~3, ic->ino));
171
        if (!ic->nlink) {
172
                /* The inode has zero nlink but its nodes weren't yet marked
173
                   obsolete. This has to be because we're still waiting for
174
                   the final (close() and) iput() to happen.
175
 
176
                   There's a possibility that the final iput() could have
177
                   happened while we were contemplating. In order to ensure
178
                   that we don't cause a new read_inode() (which would fail)
179
                   for the inode in question, we use ilookup() in this case
180
                   instead of iget().
181
 
182
                   The nlink can't _become_ zero at this point because we're
183
                   holding the alloc_sem, and jffs2_do_unlink() would also
184
                   need that while decrementing nlink on any inode.
185
                */
186
                inode = ilookup(OFNI_BS_2SFFJ(c), ic->ino);
187
                if (!inode) {
188
                        D1(printk(KERN_DEBUG "ilookup() failed for ino #%u; inode is probably deleted.\n",
189
                                  ic->ino));
190
                        up(&c->alloc_sem);
191
                        return 0;
192
                }
193
        } else {
194
                /* Inode has links to it still; they're not going away because
195
                   jffs2_do_unlink() would need the alloc_sem and we have it.
196
                   Just iget() it, and if read_inode() is necessary that's OK.
197
                */
198
                inode = iget(OFNI_BS_2SFFJ(c), ic->ino);
199
                if (!inode) {
200
                        up(&c->alloc_sem);
201
                        return -ENOMEM;
202
                }
203
        }
204
        if (is_bad_inode(inode)) {
205
                printk(KERN_NOTICE "Eep. read_inode() failed for ino #%u\n", ic->ino);
206
                /* NB. This will happen again. We need to do something appropriate here. */
207
                up(&c->alloc_sem);
208
                iput(inode);
209
                return -EIO;
210
        }
211
 
212
        f = JFFS2_INODE_INFO(inode);
213
        down(&f->sem);
214
        /* Now we have the lock for this inode. Check that it's still the one at the head
215
           of the list. */
216
 
217
        if (raw->flash_offset & 1) {
218
                D1(printk(KERN_DEBUG "node to be GC'd was obsoleted in the meantime.\n"));
219
                /* They'll call again */
220
                goto upnout;
221
        }
222
        /* OK. Looks safe. And nobody can get us now because we have the semaphore. Move the block */
223
        if (f->metadata && f->metadata->raw == raw) {
224
                fn = f->metadata;
225
                ret = jffs2_garbage_collect_metadata(c, jeb, inode, fn);
226
                goto upnout;
227
        }
228
 
229
        for (frag = f->fraglist; frag; frag = frag->next) {
230
                if (frag->node && frag->node->raw == raw) {
231
                        fn = frag->node;
232
                        end = frag->ofs + frag->size;
233
                        if (!nrfrags++)
234
                                start = frag->ofs;
235
                        if (nrfrags == frag->node->frags)
236
                                break; /* We've found them all */
237
                }
238
        }
239
        if (fn) {
240
                /* We found a datanode. Do the GC */
241
                if((start >> PAGE_CACHE_SHIFT) < ((end-1) >> PAGE_CACHE_SHIFT)) {
242
                        /* It crosses a page boundary. Therefore, it must be a hole. */
243
                        ret = jffs2_garbage_collect_hole(c, jeb, inode, fn, start, end);
244
                } else {
245
                        /* It could still be a hole. But we GC the page this way anyway */
246
                        ret = jffs2_garbage_collect_dnode(c, jeb, inode, fn, start, end);
247
                }
248
                goto upnout;
249
        }
250
 
251
        /* Wasn't a dnode. Try dirent */
252
        for (fd = f->dents; fd; fd=fd->next) {
253
                if (fd->raw == raw)
254
                        break;
255
        }
256
 
257
        if (fd && fd->ino) {
258
                ret = jffs2_garbage_collect_dirent(c, jeb, inode, fd);
259
        } else if (fd) {
260
                ret = jffs2_garbage_collect_deletion_dirent(c, jeb, inode, fd);
261
        } else {
262
                printk(KERN_WARNING "Raw node at 0x%08x wasn't in node lists for ino #%lu\n", raw->flash_offset&~3, inode->i_ino);
263
                if (raw->flash_offset & 1) {
264
                        printk(KERN_WARNING "But it's obsolete so we don't mind too much\n");
265
                } else {
266
                        ret = -EIO;
267
                }
268
        }
269
 upnout:
270
        up(&f->sem);
271
        up(&c->alloc_sem);
272
        iput(inode);
273
 
274
 eraseit_lock:
275
        /* If we've finished this block, start it erasing */
276
        spin_lock_bh(&c->erase_completion_lock);
277
 
278
 eraseit:
279
        if (c->gcblock && !c->gcblock->used_size) {
280
                D1(printk(KERN_DEBUG "Block at 0x%08x completely obsoleted by GC. Moving to erase_pending_list\n", c->gcblock->offset));
281
                /* We're GC'ing an empty block? */
282
                list_add_tail(&c->gcblock->list, &c->erase_pending_list);
283
                c->gcblock = NULL;
284
                c->nr_erasing_blocks++;
285
                jffs2_erase_pending_trigger(c);
286
        }
287
        spin_unlock_bh(&c->erase_completion_lock);
288
 
289
        return ret;
290
}
291
 
292
static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
293
                                        struct inode *inode, struct jffs2_full_dnode *fn)
294
{
295
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
296
        struct jffs2_full_dnode *new_fn;
297
        struct jffs2_raw_inode ri;
298
        unsigned short dev;
299
        char *mdata = NULL, mdatalen = 0;
300
        __u32 alloclen, phys_ofs;
301
        int ret;
302
 
303
        if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
304
                /* For these, we don't actually need to read the old node */
305
                dev =  (MAJOR(to_kdev_t(inode->i_rdev)) << 8) |
306
                        MINOR(to_kdev_t(inode->i_rdev));
307
                mdata = (char *)&dev;
308
                mdatalen = sizeof(dev);
309
                D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen));
310
        } else if (S_ISLNK(inode->i_mode)) {
311
                mdatalen = fn->size;
312
                mdata = kmalloc(fn->size, GFP_KERNEL);
313
                if (!mdata) {
314
                        printk(KERN_WARNING "kmalloc of mdata failed in jffs2_garbage_collect_metadata()\n");
315
                        return -ENOMEM;
316
                }
317
                ret = jffs2_read_dnode(c, fn, mdata, 0, mdatalen);
318
                if (ret) {
319
                        printk(KERN_WARNING "read of old metadata failed in jffs2_garbage_collect_metadata(): %d\n", ret);
320
                        kfree(mdata);
321
                        return ret;
322
                }
323
                D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bites of symlink target\n", mdatalen));
324
 
325
        }
326
 
327
        ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen);
328
        if (ret) {
329
                printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_metadata failed: %d\n",
330
                       sizeof(ri)+ mdatalen, ret);
331
                goto out;
332
        }
333
 
334
        memset(&ri, 0, sizeof(ri));
335
        ri.magic = JFFS2_MAGIC_BITMASK;
336
        ri.nodetype = JFFS2_NODETYPE_INODE;
337
        ri.totlen = sizeof(ri) + mdatalen;
338
        ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4);
339
 
340
        ri.ino = inode->i_ino;
341
        ri.version = ++f->highest_version;
342
        ri.mode = inode->i_mode;
343
        ri.uid = inode->i_uid;
344
        ri.gid = inode->i_gid;
345
        ri.isize = inode->i_size;
346
        ri.atime = inode->i_atime;
347
        ri.ctime = inode->i_ctime;
348
        ri.mtime = inode->i_mtime;
349
        ri.offset = 0;
350
        ri.csize = mdatalen;
351
        ri.dsize = mdatalen;
352
        ri.compr = JFFS2_COMPR_NONE;
353
        ri.node_crc = crc32(0, &ri, sizeof(ri)-8);
354
        ri.data_crc = crc32(0, mdata, mdatalen);
355
 
356
        new_fn = jffs2_write_dnode(inode, &ri, mdata, mdatalen, phys_ofs, NULL);
357
 
358
        if (IS_ERR(new_fn)) {
359
                printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn));
360
                ret = PTR_ERR(new_fn);
361
                goto out;
362
        }
363
        jffs2_mark_node_obsolete(c, fn->raw);
364
        jffs2_free_full_dnode(fn);
365
        f->metadata = new_fn;
366
 out:
367
        if (S_ISLNK(inode->i_mode))
368
                kfree(mdata);
369
        return ret;
370
}
371
 
372
static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
373
                                        struct inode *inode, struct jffs2_full_dirent *fd)
374
{
375
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
376
        struct jffs2_full_dirent *new_fd;
377
        struct jffs2_raw_dirent rd;
378
        __u32 alloclen, phys_ofs;
379
        int ret;
380
 
381
        rd.magic = JFFS2_MAGIC_BITMASK;
382
        rd.nodetype = JFFS2_NODETYPE_DIRENT;
383
        rd.nsize = strlen(fd->name);
384
        rd.totlen = sizeof(rd) + rd.nsize;
385
        rd.hdr_crc = crc32(0, &rd, sizeof(struct jffs2_unknown_node)-4);
386
 
387
        rd.pino = inode->i_ino;
388
        rd.version = ++f->highest_version;
389
        rd.ino = fd->ino;
390
        rd.mctime = max(inode->i_mtime, inode->i_ctime);
391
        rd.type = fd->type;
392
        rd.node_crc = crc32(0, &rd, sizeof(rd)-8);
393
        rd.name_crc = crc32(0, fd->name, rd.nsize);
394
 
395
        ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen);
396
        if (ret) {
397
                printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_dirent failed: %d\n",
398
                       sizeof(rd)+rd.nsize, ret);
399
                return ret;
400
        }
401
        new_fd = jffs2_write_dirent(inode, &rd, fd->name, rd.nsize, phys_ofs, NULL);
402
 
403
        if (IS_ERR(new_fd)) {
404
                printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd));
405
                return PTR_ERR(new_fd);
406
        }
407
        jffs2_add_fd_to_list(c, new_fd, &f->dents);
408
        return 0;
409
}
410
 
411
static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
412
                                        struct inode *inode, struct jffs2_full_dirent *fd)
413
{
414
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
415
        struct jffs2_full_dirent **fdp = &f->dents;
416
        int found = 0;
417
 
418
        /* FIXME: When we run on NAND flash, we need to work out whether
419
           this deletion dirent is still needed to actively delete a
420
           'real' dirent with the same name that's still somewhere else
421
           on the flash. For now, we know that we've actually obliterated
422
           all the older dirents when they became obsolete, so we didn't
423
           really need to write the deletion to flash in the first place.
424
        */
425
        while (*fdp) {
426
                if ((*fdp) == fd) {
427
                        found = 1;
428
                        *fdp = fd->next;
429
                        break;
430
                }
431
                fdp = &(*fdp)->next;
432
        }
433
        if (!found) {
434
                printk(KERN_WARNING "Deletion dirent \"%s\" not found in list for ino #%lu\n", fd->name, inode->i_ino);
435
        }
436
        jffs2_mark_node_obsolete(c, fd->raw);
437
        jffs2_free_full_dirent(fd);
438
        return 0;
439
}
440
 
441
static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
442
                                      struct inode *inode, struct jffs2_full_dnode *fn,
443
                                      __u32 start, __u32 end)
444
{
445
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
446
        struct jffs2_raw_inode ri;
447
        struct jffs2_node_frag *frag;
448
        struct jffs2_full_dnode *new_fn;
449
        __u32 alloclen, phys_ofs;
450
        int ret;
451
 
452
        D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%lu from offset 0x%x to 0x%x\n",
453
                  inode->i_ino, start, end));
454
 
455
        memset(&ri, 0, sizeof(ri));
456
 
457
        if(fn->frags > 1) {
458
                size_t readlen;
459
                __u32 crc;
460
                /* It's partially obsoleted by a later write. So we have to
461
                   write it out again with the _same_ version as before */
462
                ret = c->mtd->read(c->mtd, fn->raw->flash_offset & ~3, sizeof(ri), &readlen, (char *)&ri);
463
                if (readlen != sizeof(ri) || ret) {
464
                        printk(KERN_WARNING "Node read failed in jffs2_garbage_collect_hole. Ret %d, retlen %d. Data will be lost by writing new hold node\n", ret, readlen);
465
                        goto fill;
466
                }
467
                if (ri.nodetype != JFFS2_NODETYPE_INODE) {
468
                        printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had node type 0x%04x instead of JFFS2_NODETYPE_INODE(0x%04x)\n",
469
                               fn->raw->flash_offset & ~3, ri.nodetype, JFFS2_NODETYPE_INODE);
470
                        return -EIO;
471
                }
472
                if (ri.totlen != sizeof(ri)) {
473
                        printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had totlen 0x%x instead of expected 0x%x\n",
474
                               fn->raw->flash_offset & ~3, ri.totlen, sizeof(ri));
475
                        return -EIO;
476
                }
477
                crc = crc32(0, &ri, sizeof(ri)-8);
478
                if (crc != ri.node_crc) {
479
                        printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n",
480
                               fn->raw->flash_offset & ~3, ri.node_crc, crc);
481
                        /* FIXME: We could possibly deal with this by writing new holes for each frag */
482
                        printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%lu will be lost\n",
483
                               start, end, inode->i_ino);
484
                        goto fill;
485
                }
486
                if (ri.compr != JFFS2_COMPR_ZERO) {
487
                        printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", fn->raw->flash_offset & ~3);
488
                        printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%lu will be lost\n",
489
                               start, end, inode->i_ino);
490
                        goto fill;
491
                }
492
        } else {
493
        fill:
494
                ri.magic = JFFS2_MAGIC_BITMASK;
495
                ri.nodetype = JFFS2_NODETYPE_INODE;
496
                ri.totlen = sizeof(ri);
497
                ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4);
498
 
499
                ri.ino = inode->i_ino;
500
                ri.version = ++f->highest_version;
501
                ri.offset = start;
502
                ri.dsize = end - start;
503
                ri.csize = 0;
504
                ri.compr = JFFS2_COMPR_ZERO;
505
        }
506
        ri.mode = inode->i_mode;
507
        ri.uid = inode->i_uid;
508
        ri.gid = inode->i_gid;
509
        ri.isize = inode->i_size;
510
        ri.atime = inode->i_atime;
511
        ri.ctime = inode->i_ctime;
512
        ri.mtime = inode->i_mtime;
513
        ri.data_crc = 0;
514
        ri.node_crc = crc32(0, &ri, sizeof(ri)-8);
515
 
516
        ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen);
517
        if (ret) {
518
                printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_hole failed: %d\n",
519
                       sizeof(ri), ret);
520
                return ret;
521
        }
522
        new_fn = jffs2_write_dnode(inode, &ri, NULL, 0, phys_ofs, NULL);
523
 
524
        if (IS_ERR(new_fn)) {
525
                printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn));
526
                return PTR_ERR(new_fn);
527
        }
528
        if (ri.version == f->highest_version) {
529
                jffs2_add_full_dnode_to_inode(c, f, new_fn);
530
                if (f->metadata) {
531
                        jffs2_mark_node_obsolete(c, f->metadata->raw);
532
                        jffs2_free_full_dnode(f->metadata);
533
                        f->metadata = NULL;
534
                }
535
                return 0;
536
        }
537
 
538
        /*
539
         * We should only get here in the case where the node we are
540
         * replacing had more than one frag, so we kept the same version
541
         * number as before. (Except in case of error -- see 'goto fill;'
542
         * above.)
543
         */
544
        D1(if(fn->frags <= 1) {
545
                printk(KERN_WARNING "jffs2_garbage_collect_hole: Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n",
546
                       fn->frags, ri.version, f->highest_version, ri.ino);
547
        });
548
 
549
        for (frag = f->fraglist; frag; frag = frag->next) {
550
                if (frag->ofs > fn->size + fn->ofs)
551
                        break;
552
                if (frag->node == fn) {
553
                        frag->node = new_fn;
554
                        new_fn->frags++;
555
                        fn->frags--;
556
                }
557
        }
558
        if (fn->frags) {
559
                printk(KERN_WARNING "jffs2_garbage_collect_hole: Old node still has frags!\n");
560
                BUG();
561
        }
562
        if (!new_fn->frags) {
563
                printk(KERN_WARNING "jffs2_garbage_collect_hole: New node has no frags!\n");
564
                BUG();
565
        }
566
 
567
        jffs2_mark_node_obsolete(c, fn->raw);
568
        jffs2_free_full_dnode(fn);
569
 
570
        return 0;
571
}
572
 
573
static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
574
                                       struct inode *inode, struct jffs2_full_dnode *fn,
575
                                       __u32 start, __u32 end)
576
{
577
        struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
578
        struct jffs2_full_dnode *new_fn;
579
        struct jffs2_raw_inode ri;
580
        __u32 alloclen, phys_ofs, offset, orig_end;
581
        int ret = 0;
582
        unsigned char *comprbuf = NULL, *writebuf;
583
        struct page *pg;
584
        unsigned char *pg_ptr;
585
 
586
 
587
        memset(&ri, 0, sizeof(ri));
588
 
589
        D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%lu from offset 0x%x to 0x%x\n",
590
                  inode->i_ino, start, end));
591
 
592
        orig_end = end;
593
 
594
 
595
        /* If we're looking at the last node in the block we're
596
           garbage-collecting, we allow ourselves to merge as if the
597
           block was already erasing. We're likely to be GC'ing a
598
           partial page, and the next block we GC is likely to have
599
           the other half of this page right at the beginning, which
600
           means we'd expand it _then_, as nr_erasing_blocks would have
601
           increased since we checked, and in doing so would obsolete
602
           the partial node which we'd have written here. Meaning that
603
           the GC would churn and churn, and just leave dirty blocks in
604
           it's wake.
605
        */
606
        if(c->nr_free_blocks + c->nr_erasing_blocks > JFFS2_RESERVED_BLOCKS_GCMERGE - (fn->raw->next_phys?0:1)) {
607
                /* Shitloads of space */
608
                /* FIXME: Integrate this properly with GC calculations */
609
                start &= ~(PAGE_CACHE_SIZE-1);
610
                end = min_t(__u32, start + PAGE_CACHE_SIZE, inode->i_size);
611
                D1(printk(KERN_DEBUG "Plenty of free space, so expanding to write from offset 0x%x to 0x%x\n",
612
                          start, end));
613
                if (end < orig_end) {
614
                        printk(KERN_WARNING "Eep. jffs2_garbage_collect_dnode extended node to write, but it got smaller: start 0x%x, orig_end 0x%x, end 0x%x\n", start, orig_end, end);
615
                        end = orig_end;
616
                }
617
        }
618
 
619
        /* First, use readpage() to read the appropriate page into the page cache */
620
        /* Q: What happens if we actually try to GC the _same_ page for which commit_write()
621
         *    triggered garbage collection in the first place?
622
         * A: I _think_ it's OK. read_cache_page shouldn't deadlock, we'll write out the
623
         *    page OK. We'll actually write it out again in commit_write, which is a little
624
         *    suboptimal, but at least we're correct.
625
         */
626
        pg = read_cache_page(inode->i_mapping, start >> PAGE_CACHE_SHIFT, (void *)jffs2_do_readpage_unlock, inode);
627
 
628
        if (IS_ERR(pg)) {
629
                printk(KERN_WARNING "read_cache_page() returned error: %ld\n", PTR_ERR(pg));
630
                return PTR_ERR(pg);
631
        }
632
        pg_ptr = (char *)kmap(pg);
633
        comprbuf = kmalloc(end - start, GFP_KERNEL);
634
 
635
        offset = start;
636
        while(offset < orig_end) {
637
                __u32 datalen;
638
                __u32 cdatalen;
639
                char comprtype = JFFS2_COMPR_NONE;
640
 
641
                ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen);
642
 
643
                if (ret) {
644
                        printk(KERN_WARNING "jffs2_reserve_space_gc of %d bytes for garbage_collect_dnode failed: %d\n",
645
                               sizeof(ri)+ JFFS2_MIN_DATA_LEN, ret);
646
                        break;
647
                }
648
                cdatalen = min(alloclen - sizeof(ri), end - offset);
649
                datalen = end - offset;
650
 
651
                writebuf = pg_ptr + (offset & (PAGE_CACHE_SIZE -1));
652
 
653
                if (comprbuf) {
654
                        comprtype = jffs2_compress(writebuf, comprbuf, &datalen, &cdatalen);
655
                }
656
                if (comprtype) {
657
                        writebuf = comprbuf;
658
                } else {
659
                        datalen = cdatalen;
660
                }
661
                ri.magic = JFFS2_MAGIC_BITMASK;
662
                ri.nodetype = JFFS2_NODETYPE_INODE;
663
                ri.totlen = sizeof(ri) + cdatalen;
664
                ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4);
665
 
666
                ri.ino = inode->i_ino;
667
                ri.version = ++f->highest_version;
668
                ri.mode = inode->i_mode;
669
                ri.uid = inode->i_uid;
670
                ri.gid = inode->i_gid;
671
                ri.isize = inode->i_size;
672
                ri.atime = inode->i_atime;
673
                ri.ctime = inode->i_ctime;
674
                ri.mtime = inode->i_mtime;
675
                ri.offset = offset;
676
                ri.csize = cdatalen;
677
                ri.dsize = datalen;
678
                ri.compr = comprtype;
679
                ri.node_crc = crc32(0, &ri, sizeof(ri)-8);
680
                ri.data_crc = crc32(0, writebuf, cdatalen);
681
 
682
                new_fn = jffs2_write_dnode(inode, &ri, writebuf, cdatalen, phys_ofs, NULL);
683
 
684
                if (IS_ERR(new_fn)) {
685
                        printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn));
686
                        ret = PTR_ERR(new_fn);
687
                        break;
688
                }
689
                ret = jffs2_add_full_dnode_to_inode(c, f, new_fn);
690
                offset += datalen;
691
                if (f->metadata) {
692
                        jffs2_mark_node_obsolete(c, f->metadata->raw);
693
                        jffs2_free_full_dnode(f->metadata);
694
                        f->metadata = NULL;
695
                }
696
        }
697
        if (comprbuf) kfree(comprbuf);
698
 
699
        kunmap(pg);
700
        /* XXX: Does the page get freed automatically? */
701
        /* AAA: Judging by the unmount getting stuck in __wait_on_page, nope. */
702
        page_cache_release(pg);
703
        return ret;
704
}
705
 

powered by: WebSVN 2.1.0

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