Commit 20fed049 authored by David Woodhouse's avatar David Woodhouse

Merge [acm]time nanosecond support from 2.5.48.

parents 65b5db50 f662cf7a
...@@ -531,8 +531,8 @@ config JFFS2_FS ...@@ -531,8 +531,8 @@ config JFFS2_FS
levelling, compression and support for hard links. You cannot use levelling, compression and support for hard links. You cannot use
this on normal block devices, only on 'MTD' devices. this on normal block devices, only on 'MTD' devices.
Further information should be made available soon at Further information on the design and implementation of JFFS2 is
<http://sources.redhat.com/jffs2/>. available at <http://sources.redhat.com/jffs2/>.
config JFFS2_FS_DEBUG config JFFS2_FS_DEBUG
int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)" int "JFFS2 debugging verbosity (0 = quiet, 2 = noisy)"
...@@ -554,6 +554,19 @@ config JFFS2_FS_DEBUG ...@@ -554,6 +554,19 @@ config JFFS2_FS_DEBUG
config JFFS2_FS_NAND config JFFS2_FS_NAND
bool "JFFS2 support for NAND flash (EXPERIMENTAL)" bool "JFFS2 support for NAND flash (EXPERIMENTAL)"
depends on JFFS2_FS && EXPERIMENTAL depends on JFFS2_FS && EXPERIMENTAL
default n
---help---
This enables the experimental support for NAND flash in JFFS2. NAND
is a newer type of flash chip design than the traditional NOR flash,
with higher density but a handful of characteristics which make it
more interesting for the file system to use. Support for NAND flash
is not yet complete and may corrupt data. For further information,
including a link to the mailing list where details of the remaining
work to be completed for NAND flash support can be found, see the
JFFS2 web site at <http://sources.redhat.com/jffs2>.
Say 'N' unless you have NAND flash and you are willing to test and
develop JFFS2 support for it.
config CRAMFS config CRAMFS
tristate "Compressed ROM file system support" tristate "Compressed ROM file system support"
......
$Id: TODO,v 1.9 2002/07/11 10:39:04 dwmw2 Exp $ $Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $
- disable compression in commit_write()? - disable compression in commit_write()?
- fine-tune the allocation / GC thresholds - fine-tune the allocation / GC thresholds
...@@ -23,22 +23,18 @@ $Id: TODO,v 1.9 2002/07/11 10:39:04 dwmw2 Exp $ ...@@ -23,22 +23,18 @@ $Id: TODO,v 1.9 2002/07/11 10:39:04 dwmw2 Exp $
- Optimisations: - Optimisations:
- Stop GC from decompressing and immediately recompressing nodes which could - Stop GC from decompressing and immediately recompressing nodes which could
just be copied intact. just be copied intact. (We now keep track of REF_PRISTINE flag. Easy now.)
- Furthermore, in the case where it could be copied intact we don't even need - Furthermore, in the case where it could be copied intact we don't even need
to call iget() for it -- if we use (raw_node_raw->flash_offset & 2) as a flag to call iget() for it -- if we use (raw_node_raw->flash_offset & 2) as a flag
to show a node can be copied intact and it's _not_ in icache, we could just do to show a node can be copied intact and it's _not_ in icache, we could just do
it, fix up the next_in_ino list and move on. We would need a way to find out it, fix up the next_in_ino list and move on. We would need a way to find out
_whether_ it's in icache though -- if it's in icache we also need to do the _whether_ it's in icache though -- if it's in icache we also need to do the
fragment lists, etc. P'raps a flag or pointer in the jffs2_inode_cache could fragment lists, etc. P'raps a flag or pointer in the jffs2_inode_cache could
help. help. (We have half of this now.)
- Stop keeping name in-core with struct jffs2_full_dirent. If we keep the hash in - Stop keeping name in-core with struct jffs2_full_dirent. If we keep the hash in
the full dirent, we only need to go to the flash in lookup() when we think we've the full dirent, we only need to go to the flash in lookup() when we think we've
got a match, and in readdir(). got a match, and in readdir().
- Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately? - Doubly-linked next_in_ino list to allow us to free obsoleted raw_node_refs immediately?
- Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into
jffs2_mark_node_obsolete(). Can all callers work it out? jffs2_mark_node_obsolete(). Can all callers work it out?
- Don't check data CRC on node scan during mount. We don't really need to know - Remove size from jffs2_raw_node_frag.
yet. This means we can't build up node fragment lists, and hence can't
build accurate clean/dirty information. But we don't _need_ that for reading,
only for writing. And in fact we don't even need it for writing until we
start to need GC.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: background.c,v 1.29 2002/06/07 10:04:28 dwmw2 Exp $ * $Id: background.c,v 1.33 2002/11/12 09:44:30 dwmw2 Exp $
* *
*/ */
...@@ -83,6 +83,7 @@ static int jffs2_garbage_collect_thread(void *_c) ...@@ -83,6 +83,7 @@ static int jffs2_garbage_collect_thread(void *_c)
struct jffs2_sb_info *c = _c; struct jffs2_sb_info *c = _c;
daemonize(); daemonize();
c->gc_task = current; c->gc_task = current;
up(&c->gc_thread_start); up(&c->gc_thread_start);
...@@ -91,10 +92,10 @@ static int jffs2_garbage_collect_thread(void *_c) ...@@ -91,10 +92,10 @@ static int jffs2_garbage_collect_thread(void *_c)
set_user_nice(current, 10); set_user_nice(current, 10);
for (;;) { for (;;) {
spin_lock_irq(&current->sig->siglock); spin_lock_irq(&current_sig_lock);
siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); siginitsetinv (&current->blocked, sigmask(SIGHUP) | sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sig->siglock); spin_unlock_irq(&current_sig_lock);
if (!thread_should_wake(c)) { if (!thread_should_wake(c)) {
set_current_state (TASK_INTERRUPTIBLE); set_current_state (TASK_INTERRUPTIBLE);
...@@ -112,11 +113,11 @@ static int jffs2_garbage_collect_thread(void *_c) ...@@ -112,11 +113,11 @@ static int jffs2_garbage_collect_thread(void *_c)
*/ */
while (signal_pending(current)) { while (signal_pending(current)) {
siginfo_t info; siginfo_t info;
unsigned long signr = 0 ; unsigned long signr;
spin_lock_irq(&current->sig->siglock); spin_lock_irq(&current_sig_lock);
signr = dequeue_signal(&current->blocked, &info); signr = dequeue_signal(&current->blocked, &info);
spin_unlock_irq(&current->sig->siglock); spin_unlock_irq(&current_sig_lock);
switch(signr) { switch(signr) {
case SIGSTOP: case SIGSTOP:
...@@ -137,14 +138,13 @@ static int jffs2_garbage_collect_thread(void *_c) ...@@ -137,14 +138,13 @@ static int jffs2_garbage_collect_thread(void *_c)
break; break;
default: default:
D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): signal %ld received\n", signr)); D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): signal %ld received\n", signr));
} }
} }
/* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */ /* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */
spin_lock_irq(&current->sig->siglock); spin_lock_irq(&current_sig_lock);
siginitsetinv (&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT)); siginitsetinv (&current->blocked, sigmask(SIGKILL) | sigmask(SIGSTOP) | sigmask(SIGCONT));
recalc_sigpending(); recalc_sigpending();
spin_unlock_irq(&current->sig->siglock); spin_unlock_irq(&current_sig_lock);
D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n")); D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n"));
jffs2_garbage_collect_pass(c); jffs2_garbage_collect_pass(c);
...@@ -153,23 +153,20 @@ static int jffs2_garbage_collect_thread(void *_c) ...@@ -153,23 +153,20 @@ static int jffs2_garbage_collect_thread(void *_c)
static int thread_should_wake(struct jffs2_sb_info *c) static int thread_should_wake(struct jffs2_sb_info *c)
{ {
uint32_t gcnodeofs = 0; int ret = 0;
int ret;
/* Don't count any progress we've already made through the gcblock if (c->unchecked_size) {
as dirty space, for the purposes of this calculation */ D1(printk(KERN_DEBUG "thread_should_wake(): unchecked_size %d, checked_ino #%d\n",
if (c->gcblock && c->gcblock->gc_node) c->unchecked_size, c->checked_ino));
gcnodeofs = c->gcblock->gc_node->flash_offset & ~3 & (c->sector_size-1); return 1;
}
if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER && if (c->nr_free_blocks + c->nr_erasing_blocks < JFFS2_RESERVED_BLOCKS_GCTRIGGER &&
(c->dirty_size - gcnodeofs) > c->sector_size) (c->dirty_size > c->sector_size))
ret = 1; ret = 1;
else
ret = 0;
D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x (mod 0x%x): %s\n", D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n",
c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no"));
c->dirty_size - gcnodeofs, ret?"yes":"no"));
return ret; return ret;
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: build.c,v 1.35 2002/05/20 14:56:37 dwmw2 Exp $ * $Id: build.c,v 1.42 2002/09/09 16:29:08 dwmw2 Exp $
* *
*/ */
...@@ -43,8 +43,9 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) ...@@ -43,8 +43,9 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
return ret; return ret;
D1(printk(KERN_DEBUG "Scanned flash completely\n")); D1(printk(KERN_DEBUG "Scanned flash completely\n"));
/* Now build the data map for each inode, marking obsoleted nodes D1(jffs2_dump_block_lists(c));
as such, and also increase nlink of any children. */
/* Now scan the directory tree, increasing nlink according to every dirent found. */
for_each_inode(i, c, ic) { for_each_inode(i, c, ic) {
D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino)); D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino));
ret = jffs2_build_inode_pass1(c, ic); ret = jffs2_build_inode_pass1(c, ic);
...@@ -52,8 +53,10 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) ...@@ -52,8 +53,10 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
D1(printk(KERN_WARNING "Eep. jffs2_build_inode_pass1 for ino %d returned %d\n", ic->ino, ret)); D1(printk(KERN_WARNING "Eep. jffs2_build_inode_pass1 for ino %d returned %d\n", ic->ino, ret));
return ret; return ret;
} }
cond_resched();
} }
D1(printk(KERN_DEBUG "Pass 1 complete\n")); D1(printk(KERN_DEBUG "Pass 1 complete\n"));
D1(jffs2_dump_block_lists(c));
/* Next, scan for inodes with nlink == 0 and remove them. If /* Next, scan for inodes with nlink == 0 and remove them. If
they were directories, then decrement the nlink of their they were directories, then decrement the nlink of their
...@@ -68,6 +71,8 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) ...@@ -68,6 +71,8 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
if (ic->nlink) if (ic->nlink)
continue; continue;
/* XXX: Can get high latency here. Move the cond_resched() from the end of the loop? */
ret = jffs2_build_remove_unlinked_inode(c, ic); ret = jffs2_build_remove_unlinked_inode(c, ic);
if (ret) if (ret)
break; break;
...@@ -75,30 +80,29 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) ...@@ -75,30 +80,29 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
and furthermore that it had children and their nlink has now and furthermore that it had children and their nlink has now
gone to zero too. So we have to restart the scan. */ gone to zero too. So we have to restart the scan. */
} }
D1(jffs2_dump_block_lists(c));
cond_resched();
} while(ret == -EAGAIN); } while(ret == -EAGAIN);
D1(printk(KERN_DEBUG "Pass 2 complete\n")); D1(printk(KERN_DEBUG "Pass 2 complete\n"));
/* Finally, we can scan again and free the dirent nodes and scan_info structs */ /* Finally, we can scan again and free the dirent nodes and scan_info structs */
for_each_inode(i, c, ic) { for_each_inode(i, c, ic) {
struct jffs2_scan_info *scan = ic->scan;
struct jffs2_full_dirent *fd; struct jffs2_full_dirent *fd;
D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes)); D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes));
if (!scan) {
if (ic->nlink) { while(ic->scan_dents) {
D1(printk(KERN_WARNING "Why no scan struct for ino #%u which has nlink %d?\n", ic->ino, ic->nlink)); fd = ic->scan_dents;
} ic->scan_dents = fd->next;
continue;
}
ic->scan = NULL;
while(scan->dents) {
fd = scan->dents;
scan->dents = fd->next;
jffs2_free_full_dirent(fd); jffs2_free_full_dirent(fd);
} }
kfree(scan); ic->scan_dents = NULL;
cond_resched();
} }
D1(printk(KERN_DEBUG "Pass 3 complete\n")); D1(printk(KERN_DEBUG "Pass 3 complete\n"));
D1(jffs2_dump_block_lists(c));
/* Rotate the lists by some number to ensure wear levelling */ /* Rotate the lists by some number to ensure wear levelling */
jffs2_rotate_lists(c); jffs2_rotate_lists(c);
...@@ -108,83 +112,21 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) ...@@ -108,83 +112,21 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) int jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic)
{ {
struct jffs2_tmp_dnode_info *tn;
struct jffs2_full_dirent *fd; struct jffs2_full_dirent *fd;
struct jffs2_node_frag *fraglist = NULL;
struct jffs2_tmp_dnode_info *metadata = NULL;
D1(printk(KERN_DEBUG "jffs2_build_inode building inode #%u\n", ic->ino)); D1(printk(KERN_DEBUG "jffs2_build_inode building inode #%u\n", ic->ino));
if (ic->ino > c->highest_ino) if (ic->ino > c->highest_ino)
c->highest_ino = ic->ino; c->highest_ino = ic->ino;
if (!ic->scan->tmpnodes && ic->ino != 1) { /* For each child, increase nlink */
D1(printk(KERN_DEBUG "jffs2_build_inode: ino #%u has no data nodes!\n", ic->ino)); for(fd=ic->scan_dents; fd; fd = fd->next) {
}
/* Build the list to make sure any obsolete nodes are marked as such */
while(ic->scan->tmpnodes) {
tn = ic->scan->tmpnodes;
ic->scan->tmpnodes = tn->next;
if (metadata && tn->version > metadata->version) {
D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring old metadata at 0x%08x\n",
metadata->fn->raw->flash_offset &~3));
jffs2_mark_node_obsolete(c, metadata->fn->raw);
jffs2_free_full_dnode(metadata->fn);
jffs2_free_tmp_dnode_info(metadata);
metadata = NULL;
}
if (tn->fn->size) {
jffs2_add_full_dnode_to_fraglist (c, &fraglist, tn->fn);
jffs2_free_tmp_dnode_info(tn);
} else {
if (!metadata) {
metadata = tn;
} else {
/* This will only happen if it has the _same_ version
number as the existing metadata node. */
D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 ignoring new metadata at 0x%08x\n",
tn->fn->raw->flash_offset &~3));
jffs2_mark_node_obsolete(c, tn->fn->raw);
jffs2_free_full_dnode(tn->fn);
jffs2_free_tmp_dnode_info(tn);
}
}
}
if (ic->scan->version) {
/* It's a regular file, so truncate it to the last known
i_size, if necessary */
D1(printk(KERN_DEBUG "jffs2_build_inode_pass1 truncating fraglist to 0x%08x\n", ic->scan->isize));
jffs2_truncate_fraglist(c, &fraglist, ic->scan->isize);
}
/* OK. Now clear up */
if (metadata) {
jffs2_free_full_dnode(metadata->fn);
jffs2_free_tmp_dnode_info(metadata);
}
metadata = NULL;
while (fraglist) {
struct jffs2_node_frag *frag;
frag = fraglist;
fraglist = fraglist->next;
if (frag->node && !(--frag->node->frags)) {
jffs2_free_full_dnode(frag->node);
}
jffs2_free_node_frag(frag);
}
/* Now for each child, increase nlink */
for(fd=ic->scan->dents; fd; fd = fd->next) {
struct jffs2_inode_cache *child_ic; struct jffs2_inode_cache *child_ic;
if (!fd->ino) if (!fd->ino)
continue; continue;
/* XXX: Can get high latency here with huge directories */
child_ic = jffs2_get_ino_cache(c, fd->ino); child_ic = jffs2_get_ino_cache(c, fd->ino);
if (!child_ic) { if (!child_ic) {
printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n",
...@@ -212,26 +154,33 @@ int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inod ...@@ -212,26 +154,33 @@ int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inod
struct jffs2_full_dirent *fd; struct jffs2_full_dirent *fd;
int ret = 0; int ret = 0;
if(!ic->scan) {
D1(printk(KERN_DEBUG "ino #%u was already removed\n", ic->ino));
return 0;
}
D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino));
for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) { for (raw = ic->nodes; raw != (void *)ic; raw = raw->next_in_ino) {
D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", raw->flash_offset&~3)); D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", ref_offset(raw)));
jffs2_mark_node_obsolete(c, raw); jffs2_mark_node_obsolete(c, raw);
} }
if (ic->scan->dents) { if (ic->scan_dents) {
printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); int whinged = 0;
D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino));
while(ic->scan->dents) { while(ic->scan_dents) {
struct jffs2_inode_cache *child_ic; struct jffs2_inode_cache *child_ic;
fd = ic->scan->dents; fd = ic->scan_dents;
ic->scan->dents = fd->next; ic->scan_dents = fd->next;
if (!fd->ino) {
/* It's a deletion dirent. Ignore it */
D1(printk(KERN_DEBUG "Child \"%s\" is a deletion dirent, skipping...\n", fd->name));
jffs2_free_full_dirent(fd);
continue;
}
if (!whinged) {
whinged = 1;
printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino);
}
D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n",
fd->name, fd->ino)); fd->name, fd->ino));
...@@ -239,6 +188,7 @@ int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inod ...@@ -239,6 +188,7 @@ int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inod
child_ic = jffs2_get_ino_cache(c, fd->ino); child_ic = jffs2_get_ino_cache(c, fd->ino);
if (!child_ic) { if (!child_ic) {
printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino);
jffs2_free_full_dirent(fd);
continue; continue;
} }
jffs2_free_full_dirent(fd); jffs2_free_full_dirent(fd);
...@@ -246,8 +196,6 @@ int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inod ...@@ -246,8 +196,6 @@ int jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inod
} }
ret = -EAGAIN; ret = -EAGAIN;
} }
kfree(ic->scan);
ic->scan = NULL;
/* /*
We don't delete the inocache from the hash list and free it yet. We don't delete the inocache from the hash list and free it yet.
...@@ -271,6 +219,8 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) ...@@ -271,6 +219,8 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
c->blocks[i].offset = i * c->sector_size; c->blocks[i].offset = i * c->sector_size;
c->blocks[i].free_size = c->sector_size; c->blocks[i].free_size = c->sector_size;
c->blocks[i].dirty_size = 0; c->blocks[i].dirty_size = 0;
c->blocks[i].wasted_size = 0;
c->blocks[i].unchecked_size = 0;
c->blocks[i].used_size = 0; c->blocks[i].used_size = 0;
c->blocks[i].first_node = NULL; c->blocks[i].first_node = NULL;
c->blocks[i].last_node = NULL; c->blocks[i].last_node = NULL;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: dir.c,v 1.71 2002/07/23 17:00:45 dwmw2 Exp $ * $Id: dir.c,v 1.73 2002/08/26 15:00:51 dwmw2 Exp $
* *
*/ */
...@@ -211,7 +211,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode) ...@@ -211,7 +211,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode)
return ret; return ret;
} }
dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = ri->ctime; dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = je32_to_cpu(ri->ctime);
dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0; dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0;
jffs2_free_raw_inode(ri); jffs2_free_raw_inode(ri);
...@@ -234,6 +234,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) ...@@ -234,6 +234,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry)
ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name,
dentry->d_name.len, dead_f); dentry->d_name.len, dead_f);
if (dead_f->inocache)
dentry->d_inode->i_nlink = dead_f->inocache->nlink; dentry->d_inode->i_nlink = dead_f->inocache->nlink;
return ret; return ret;
} }
...@@ -248,6 +249,10 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de ...@@ -248,6 +249,10 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de
int ret; int ret;
uint8_t type; uint8_t type;
/* Don't let people make hard links to bad inodes. */
if (!f->inocache)
return -EIO;
if (S_ISDIR(old_dentry->d_inode->i_mode)) if (S_ISDIR(old_dentry->d_inode->i_mode))
return -EPERM; return -EPERM;
...@@ -318,13 +323,14 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char ...@@ -318,13 +323,14 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
f = JFFS2_INODE_INFO(inode); f = JFFS2_INODE_INFO(inode);
inode->i_size = ri->isize = ri->dsize = ri->csize = strlen(target); inode->i_size = strlen(target);
ri->totlen = sizeof(*ri) + ri->dsize; ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size);
ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size);
ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
ri->compr = JFFS2_COMPR_NONE; ri->compr = JFFS2_COMPR_NONE;
ri->data_crc = crc32(0, target, strlen(target)); ri->data_crc = cpu_to_je32(crc32(0, target, strlen(target)));
ri->node_crc = crc32(0, ri, sizeof(*ri)-8); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
fn = jffs2_write_dnode(c, f, ri, target, strlen(target), phys_ofs, &writtenlen); fn = jffs2_write_dnode(c, f, ri, target, strlen(target), phys_ofs, &writtenlen);
...@@ -370,19 +376,19 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char ...@@ -370,19 +376,19 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
dir_f = JFFS2_INODE_INFO(dir_i); dir_f = JFFS2_INODE_INFO(dir_i);
down(&dir_f->sem); down(&dir_f->sem);
rd->magic = JFFS2_MAGIC_BITMASK; rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
rd->nodetype = JFFS2_NODETYPE_DIRENT; rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
rd->totlen = sizeof(*rd) + namelen; rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
rd->pino = dir_i->i_ino; rd->pino = cpu_to_je32(dir_i->i_ino);
rd->version = ++dir_f->highest_version; rd->version = cpu_to_je32(++dir_f->highest_version);
rd->ino = inode->i_ino; rd->ino = cpu_to_je32(inode->i_ino);
rd->mctime = get_seconds(); rd->mctime = cpu_to_je32(get_seconds());
rd->nsize = namelen; rd->nsize = namelen;
rd->type = DT_LNK; rd->type = DT_LNK;
rd->node_crc = crc32(0, rd, sizeof(*rd)-8); rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
rd->name_crc = crc32(0, dentry->d_name.name, namelen); rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
...@@ -396,7 +402,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char ...@@ -396,7 +402,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
return PTR_ERR(fd); return PTR_ERR(fd);
} }
dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = rd->mctime; dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = je32_to_cpu(rd->mctime);
dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0; dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0;
jffs2_free_raw_dirent(rd); jffs2_free_raw_dirent(rd);
...@@ -461,8 +467,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ...@@ -461,8 +467,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
f = JFFS2_INODE_INFO(inode); f = JFFS2_INODE_INFO(inode);
ri->data_crc = 0; ri->data_crc = cpu_to_je32(0);
ri->node_crc = crc32(0, ri, sizeof(*ri)-8); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, &writtenlen); fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, &writtenlen);
...@@ -508,19 +514,19 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ...@@ -508,19 +514,19 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
dir_f = JFFS2_INODE_INFO(dir_i); dir_f = JFFS2_INODE_INFO(dir_i);
down(&dir_f->sem); down(&dir_f->sem);
rd->magic = JFFS2_MAGIC_BITMASK; rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
rd->nodetype = JFFS2_NODETYPE_DIRENT; rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
rd->totlen = sizeof(*rd) + namelen; rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
rd->pino = dir_i->i_ino; rd->pino = cpu_to_je32(dir_i->i_ino);
rd->version = ++dir_f->highest_version; rd->version = cpu_to_je32(++dir_f->highest_version);
rd->ino = inode->i_ino; rd->ino = cpu_to_je32(inode->i_ino);
rd->mctime = get_seconds(); rd->mctime = cpu_to_je32(get_seconds());
rd->nsize = namelen; rd->nsize = namelen;
rd->type = DT_DIR; rd->type = DT_DIR;
rd->node_crc = crc32(0, rd, sizeof(*rd)-8); rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
rd->name_crc = crc32(0, dentry->d_name.name, namelen); rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
...@@ -534,7 +540,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ...@@ -534,7 +540,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode)
return PTR_ERR(fd); return PTR_ERR(fd);
} }
dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = rd->mctime; dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = je32_to_cpu(rd->mctime);
dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0; dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0;
dir_i->i_nlink++; dir_i->i_nlink++;
...@@ -617,13 +623,13 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in ...@@ -617,13 +623,13 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in
f = JFFS2_INODE_INFO(inode); f = JFFS2_INODE_INFO(inode);
ri->dsize = ri->csize = devlen; ri->dsize = ri->csize = cpu_to_je32(devlen);
ri->totlen = sizeof(*ri) + ri->csize; ri->totlen = cpu_to_je32(sizeof(*ri) + devlen);
ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
ri->compr = JFFS2_COMPR_NONE; ri->compr = JFFS2_COMPR_NONE;
ri->data_crc = crc32(0, &dev, devlen); ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen));
ri->node_crc = crc32(0, ri, sizeof(*ri)-8); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, &writtenlen); fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, &writtenlen);
...@@ -669,22 +675,22 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in ...@@ -669,22 +675,22 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in
dir_f = JFFS2_INODE_INFO(dir_i); dir_f = JFFS2_INODE_INFO(dir_i);
down(&dir_f->sem); down(&dir_f->sem);
rd->magic = JFFS2_MAGIC_BITMASK; rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
rd->nodetype = JFFS2_NODETYPE_DIRENT; rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
rd->totlen = sizeof(*rd) + namelen; rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
rd->hdr_crc = crc32(0, rd, sizeof(struct jffs2_unknown_node)-4); rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
rd->pino = dir_i->i_ino; rd->pino = cpu_to_je32(dir_i->i_ino);
rd->version = ++dir_f->highest_version; rd->version = cpu_to_je32(++dir_f->highest_version);
rd->ino = inode->i_ino; rd->ino = cpu_to_je32(inode->i_ino);
rd->mctime = get_seconds(); rd->mctime = cpu_to_je32(get_seconds());
rd->nsize = namelen; rd->nsize = namelen;
/* XXX: This is ugly. */ /* XXX: This is ugly. */
rd->type = (mode & S_IFMT) >> 12; rd->type = (mode & S_IFMT) >> 12;
rd->node_crc = crc32(0, rd, sizeof(*rd)-8); rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
rd->name_crc = crc32(0, dentry->d_name.name, namelen); rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen));
fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, &writtenlen);
...@@ -698,7 +704,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in ...@@ -698,7 +704,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, in
return PTR_ERR(fd); return PTR_ERR(fd);
} }
dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = rd->mctime; dir_i->i_mtime.tv_sec = dir_i->i_ctime.tv_sec = je32_to_cpu(rd->mctime);
dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0; dir_i->i_mtime.tv_nsec = dir_i->i_ctime.tv_nsec = 0;
jffs2_free_raw_dirent(rd); jffs2_free_raw_dirent(rd);
...@@ -790,6 +796,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, ...@@ -790,6 +796,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode);
down(&f->sem); down(&f->sem);
old_dentry->d_inode->i_nlink++; old_dentry->d_inode->i_nlink++;
if (f->inocache)
f->inocache->nlink++; f->inocache->nlink++;
up(&f->sem); up(&f->sem);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: erase.c,v 1.39 2002/07/23 17:00:45 dwmw2 Exp $ * $Id: erase.c,v 1.45 2002/10/09 08:27:08 dwmw2 Exp $
* *
*/ */
...@@ -27,6 +27,7 @@ struct erase_priv_struct { ...@@ -27,6 +27,7 @@ struct erase_priv_struct {
static void jffs2_erase_callback(struct erase_info *); static void jffs2_erase_callback(struct erase_info *);
static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
{ {
...@@ -81,12 +82,18 @@ void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) ...@@ -81,12 +82,18 @@ void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
else else
printk(KERN_WARNING "Erase at 0x%08x failed immediately: errno %d\n", jeb->offset, ret); printk(KERN_WARNING "Erase at 0x%08x failed immediately: errno %d\n", jeb->offset, ret);
/* Note: This is almost identical to jffs2_erase_failed() except
for the fact that we used spin_lock_bh() not spin_lock(). If
we could use spin_lock_bh() from a BH, we could merge them.
Or if we abandon the idea that MTD drivers may call the erase
callback from a BH, I suppose :)
*/
spin_lock_bh(&c->erase_completion_lock); spin_lock_bh(&c->erase_completion_lock);
c->erasing_size -= c->sector_size;
c->bad_size += c->sector_size;
list_del(&jeb->list); list_del(&jeb->list);
list_add(&jeb->list, &c->bad_list); list_add(&jeb->list, &c->bad_list);
c->nr_erasing_blocks--; c->nr_erasing_blocks--;
c->bad_size += c->sector_size;
c->erasing_size -= c->sector_size;
spin_unlock_bh(&c->erase_completion_lock); spin_unlock_bh(&c->erase_completion_lock);
wake_up(&c->erase_wait); wake_up(&c->erase_wait);
} }
...@@ -98,12 +105,19 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c) ...@@ -98,12 +105,19 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c)
down(&c->erase_free_sem); down(&c->erase_free_sem);
spin_lock_bh(&c->erase_completion_lock); spin_lock_bh(&c->erase_completion_lock);
while (!list_empty(&c->erase_pending_list)) {
jeb = list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list); while (!list_empty(&c->erase_complete_list) ||
!list_empty(&c->erase_pending_list)) {
D1(printk(KERN_DEBUG "Starting erase of pending block 0x%08x\n", jeb->offset)); if (!list_empty(&c->erase_complete_list)) {
jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
list_del(&jeb->list);
spin_unlock_bh(&c->erase_completion_lock);
jffs2_mark_erased_block(c, jeb);
} else if (!list_empty(&c->erase_pending_list)) {
jeb = list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list);
D1(printk(KERN_DEBUG "Starting erase of pending block 0x%08x\n", jeb->offset));
list_del(&jeb->list); list_del(&jeb->list);
c->erasing_size += c->sector_size; c->erasing_size += c->sector_size;
c->free_size -= jeb->free_size; c->free_size -= jeb->free_size;
...@@ -116,18 +130,21 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c) ...@@ -116,18 +130,21 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c)
jffs2_erase_block(c, jeb); jffs2_erase_block(c, jeb);
} else {
BUG();
}
/* Be nice */ /* Be nice */
cond_resched(); cond_resched();
spin_lock_bh(&c->erase_completion_lock); spin_lock_bh(&c->erase_completion_lock);
} }
spin_unlock_bh(&c->erase_completion_lock); spin_unlock_bh(&c->erase_completion_lock);
D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n")); D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n"));
up(&c->erase_free_sem); up(&c->erase_free_sem);
} }
static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
{ {
D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset)); D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset));
...@@ -135,6 +152,8 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblo ...@@ -135,6 +152,8 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblo
list_del(&jeb->list); list_del(&jeb->list);
list_add_tail(&jeb->list, &c->erase_complete_list); list_add_tail(&jeb->list, &c->erase_complete_list);
spin_unlock(&c->erase_completion_lock); spin_unlock(&c->erase_completion_lock);
/* Ensure that kupdated calls us again to mark them clean */
jffs2_erase_pending_trigger(c);
} }
...@@ -160,8 +179,6 @@ static void jffs2_erase_callback(struct erase_info *instr) ...@@ -160,8 +179,6 @@ static void jffs2_erase_callback(struct erase_info *instr)
} else { } else {
jffs2_erase_succeeded(priv->c, priv->jeb); jffs2_erase_succeeded(priv->c, priv->jeb);
} }
/* Make sure someone picks up the block off the erase_complete list */
OFNI_BS_2SFFJ(priv->c)->s_dirt = 1;
kfree(instr); kfree(instr);
} }
...@@ -220,7 +237,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, ...@@ -220,7 +237,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c,
this = ic->nodes; this = ic->nodes;
while(this) { while(this) {
printk( "0x%08x(%d)->", this->flash_offset & ~3, this->flash_offset &3); printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this));
if (++i == 5) { if (++i == 5) {
printk("\n" KERN_DEBUG); printk("\n" KERN_DEBUG);
i=0; i=0;
...@@ -260,26 +277,22 @@ void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) ...@@ -260,26 +277,22 @@ void jffs2_erase_pending_trigger(struct jffs2_sb_info *c)
OFNI_BS_2SFFJ(c)->s_dirt = 1; OFNI_BS_2SFFJ(c)->s_dirt = 1;
} }
void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb)
{ {
struct jffs2_eraseblock *jeb;
struct jffs2_raw_node_ref *marker_ref = NULL; struct jffs2_raw_node_ref *marker_ref = NULL;
unsigned char *ebuf; unsigned char *ebuf;
size_t retlen; size_t retlen;
int ret; int ret;
spin_lock_bh(&c->erase_completion_lock);
while (!list_empty(&c->erase_complete_list)) {
jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
list_del(&jeb->list);
spin_unlock_bh(&c->erase_completion_lock);
if (!jffs2_cleanmarker_oob(c)) { if (!jffs2_cleanmarker_oob(c)) {
marker_ref = jffs2_alloc_raw_node_ref(); marker_ref = jffs2_alloc_raw_node_ref();
if (!marker_ref) { if (!marker_ref) {
printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n"); printk(KERN_WARNING "Failed to allocate raw node ref for clean marker\n");
/* Come back later */ /* Stick it back on the list from whence it came and come back later */
jffs2_erase_pending_trigger(c); jffs2_erase_pending_trigger(c);
spin_lock_bh(&c->erase_completion_lock);
list_add(&jeb->list, &c->erase_complete_list);
spin_unlock_bh(&c->erase_completion_lock);
return; return;
} }
} }
...@@ -344,37 +357,39 @@ void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) ...@@ -344,37 +357,39 @@ void jffs2_mark_erased_blocks(struct jffs2_sb_info *c)
jeb->free_size = c->sector_size; jeb->free_size = c->sector_size;
jeb->used_size = 0; jeb->used_size = 0;
jeb->dirty_size = 0; jeb->dirty_size = 0;
jeb->wasted_size = 0;
} else { } else {
struct jffs2_unknown_node marker = { struct jffs2_unknown_node marker = {
.magic = JFFS2_MAGIC_BITMASK, .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK),
.nodetype = JFFS2_NODETYPE_CLEANMARKER, .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER),
.totlen = c->cleanmarker_size .totlen = cpu_to_je32(c->cleanmarker_size)
}; };
marker.hdr_crc = crc32(0, &marker, marker.totlen - 4); marker.hdr_crc = cpu_to_je32(crc32(0, &marker, je32_to_cpu(marker.totlen) - 4));
ret = jffs2_flash_write(c, jeb->offset, marker.totlen, &retlen, (char *)&marker); ret = jffs2_flash_write(c, jeb->offset, je32_to_cpu(marker.totlen), &retlen, (char *)&marker);
if (ret) { if (ret) {
printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n",
jeb->offset, ret); jeb->offset, ret);
goto bad2; goto bad2;
} }
if (retlen != marker.totlen) { if (retlen != je32_to_cpu(marker.totlen)) {
printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %d\n", printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %d, got %d\n",
jeb->offset, marker.totlen, retlen); jeb->offset, je32_to_cpu(marker.totlen), retlen);
goto bad2; goto bad2;
} }
marker_ref->next_in_ino = NULL; marker_ref->next_in_ino = NULL;
marker_ref->next_phys = NULL; marker_ref->next_phys = NULL;
marker_ref->flash_offset = jeb->offset; marker_ref->flash_offset = jeb->offset | REF_NORMAL;
marker_ref->totlen = PAD(marker.totlen); marker_ref->totlen = PAD(je32_to_cpu(marker.totlen));
jeb->first_node = jeb->last_node = marker_ref; jeb->first_node = jeb->last_node = marker_ref;
jeb->free_size = c->sector_size - marker_ref->totlen; jeb->free_size = c->sector_size - marker_ref->totlen;
jeb->used_size = marker_ref->totlen; jeb->used_size = marker_ref->totlen;
jeb->dirty_size = 0; jeb->dirty_size = 0;
jeb->wasted_size = 0;
} }
spin_lock_bh(&c->erase_completion_lock); spin_lock_bh(&c->erase_completion_lock);
...@@ -383,12 +398,12 @@ void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) ...@@ -383,12 +398,12 @@ void jffs2_mark_erased_blocks(struct jffs2_sb_info *c)
c->used_size += jeb->used_size; c->used_size += jeb->used_size;
ACCT_SANITY_CHECK(c,jeb); ACCT_SANITY_CHECK(c,jeb);
ACCT_PARANOIA_CHECK(jeb); D1(ACCT_PARANOIA_CHECK(jeb));
list_add_tail(&jeb->list, &c->free_list); list_add_tail(&jeb->list, &c->free_list);
c->nr_erasing_blocks--; c->nr_erasing_blocks--;
c->nr_free_blocks++; c->nr_free_blocks++;
wake_up(&c->erase_wait);
}
spin_unlock_bh(&c->erase_completion_lock); spin_unlock_bh(&c->erase_completion_lock);
wake_up(&c->erase_wait);
} }
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: file.c,v 1.76 2002/07/29 08:25:35 dwmw2 Exp $ * $Id: file.c,v 1.81 2002/11/12 09:46:22 dwmw2 Exp $
* *
*/ */
...@@ -139,41 +139,43 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ...@@ -139,41 +139,43 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
down(&f->sem); down(&f->sem);
ivalid = iattr->ia_valid; ivalid = iattr->ia_valid;
ri->magic = JFFS2_MAGIC_BITMASK; ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
ri->nodetype = JFFS2_NODETYPE_INODE; ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
ri->totlen = sizeof(*ri) + mdatalen; ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen);
ri->hdr_crc = crc32(0, ri, sizeof(struct jffs2_unknown_node)-4); ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
ri->ino = inode->i_ino; ri->ino = cpu_to_je32(inode->i_ino);
ri->version = ++f->highest_version; ri->version = cpu_to_je32(++f->highest_version);
ri->mode = (ivalid & ATTR_MODE)?iattr->ia_mode:inode->i_mode; ri->uid = cpu_to_je16((ivalid & ATTR_UID)?iattr->ia_uid:inode->i_uid);
ri->uid = (ivalid & ATTR_UID)?iattr->ia_uid:inode->i_uid; ri->gid = cpu_to_je16((ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid);
ri->gid = (ivalid & ATTR_GID)?iattr->ia_gid:inode->i_gid;
if (ivalid & ATTR_MODE && ri->mode & S_ISGID && if (ivalid & ATTR_MODE)
!in_group_p(ri->gid) && !capable(CAP_FSETID)) if (iattr->ia_mode & S_ISGID &&
ri->mode &= ~S_ISGID; !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID))
ri->mode = cpu_to_je32(iattr->ia_mode & ~S_ISGID);
else
ri->mode = cpu_to_je32(iattr->ia_mode);
else
ri->mode = cpu_to_je32(inode->i_mode);
ri->isize = (ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size;
ri->atime = (ivalid & ATTR_ATIME)?iattr->ia_atime.tv_sec:inode->i_atime.tv_sec;
ri->mtime = (ivalid & ATTR_MTIME)?iattr->ia_mtime.tv_sec:inode->i_mtime.tv_sec;
ri->ctime = (ivalid & ATTR_CTIME)?iattr->ia_ctime.tv_sec:inode->i_ctime.tv_sec;
ri->offset = 0; ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size);
ri->csize = ri->dsize = mdatalen; ri->atime = cpu_to_je32((ivalid & ATTR_ATIME)?iattr->ia_atime.tv_sec:inode->i_atime.tv_sec);
ri->mtime = cpu_to_je32((ivalid & ATTR_MTIME)?iattr->ia_mtime.tv_sec:inode->i_mtime.tv_sec);
ri->ctime = cpu_to_je32((ivalid & ATTR_CTIME)?iattr->ia_ctime.tv_sec:inode->i_ctime.tv_sec);
ri->compr = JFFS2_COMPR_NONE; ri->compr = JFFS2_COMPR_NONE;
if (inode->i_size < ri->isize) { if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
/* It's an extension. Make it a hole node */ /* It's an extension. Make it a hole node */
ri->compr = JFFS2_COMPR_ZERO; ri->compr = JFFS2_COMPR_ZERO;
ri->dsize = ri->isize - inode->i_size; ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
ri->offset = inode->i_size; ri->offset = cpu_to_je32(inode->i_size);
} }
ri->node_crc = crc32(0, ri, sizeof(*ri)-8); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
if (mdatalen) if (mdatalen)
ri->data_crc = crc32(0, mdata, mdatalen); ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));
else else
ri->data_crc = 0; ri->data_crc = cpu_to_je32(0);
new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, NULL); new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, NULL);
if (S_ISLNK(inode->i_mode)) if (S_ISLNK(inode->i_mode))
...@@ -186,27 +188,27 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ...@@ -186,27 +188,27 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
return PTR_ERR(new_metadata); return PTR_ERR(new_metadata);
} }
/* It worked. Update the inode */ /* It worked. Update the inode */
inode->i_atime.tv_sec = ri->atime; inode->i_atime = je32_to_cpu(ri->atime.tv_sec);
inode->i_ctime.tv_sec = ri->ctime; inode->i_ctime = je32_to_cpu(ri->ctime.tv_sec);
inode->i_mtime.tv_sec = ri->mtime; inode->i_mtime = je32_to_cpu(ri->mtime.tv_sec);
inode->i_atime.tv_nsec = inode->i_atime.tv_nsec =
inode->i_ctime.tv_nsec = inode->i_ctime.tv_nsec =
inode->i_mtime.tv_nsec = 0; inode->i_mtime.tv_nsec = 0;
inode->i_mode = ri->mode; inode->i_mode = je32_to_cpu(ri->mode);
inode->i_uid = ri->uid; inode->i_uid = je16_to_cpu(ri->uid);
inode->i_gid = ri->gid; inode->i_gid = je16_to_cpu(ri->gid);
old_metadata = f->metadata; old_metadata = f->metadata;
if (inode->i_size > ri->isize) { if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
vmtruncate(inode, ri->isize); vmtruncate(inode, iattr->ia_size);
jffs2_truncate_fraglist (c, &f->fraglist, ri->isize); jffs2_truncate_fraglist (c, &f->fragtree, iattr->ia_size);
} }
if (inode->i_size < ri->isize) { if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
jffs2_add_full_dnode_to_inode(c, f, new_metadata); jffs2_add_full_dnode_to_inode(c, f, new_metadata);
inode->i_size = ri->isize; inode->i_size = iattr->ia_size;
f->metadata = NULL; f->metadata = NULL;
} else { } else {
f->metadata = new_metadata; f->metadata = new_metadata;
...@@ -281,7 +283,6 @@ int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, uns ...@@ -281,7 +283,6 @@ int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, uns
uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT; uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT;
int ret = 0; int ret = 0;
down(&f->sem);
D1(printk(KERN_DEBUG "jffs2_prepare_write()\n")); D1(printk(KERN_DEBUG "jffs2_prepare_write()\n"));
if (pageofs > inode->i_size) { if (pageofs > inode->i_size) {
...@@ -295,30 +296,30 @@ int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, uns ...@@ -295,30 +296,30 @@ int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, uns
(unsigned int)inode->i_size, pageofs)); (unsigned int)inode->i_size, pageofs));
ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, ALLOC_NORMAL); ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, ALLOC_NORMAL);
if (ret) { if (ret)
up(&f->sem);
return ret; return ret;
}
down(&f->sem);
memset(&ri, 0, sizeof(ri)); memset(&ri, 0, sizeof(ri));
ri.magic = JFFS2_MAGIC_BITMASK; ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
ri.nodetype = JFFS2_NODETYPE_INODE; ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
ri.totlen = sizeof(ri); ri.totlen = cpu_to_je32(sizeof(ri));
ri.hdr_crc = crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4); ri.hdr_crc = cpu_to_je32(crc32(0, &ri, sizeof(struct jffs2_unknown_node)-4));
ri.ino = f->inocache->ino; ri.ino = cpu_to_je32(f->inocache->ino);
ri.version = ++f->highest_version; ri.version = cpu_to_je32(++f->highest_version);
ri.mode = inode->i_mode; ri.mode = cpu_to_je32(inode->i_mode);
ri.uid = inode->i_uid; ri.uid = cpu_to_je16(inode->i_uid);
ri.gid = inode->i_gid; ri.gid = cpu_to_je16(inode->i_gid);
ri.isize = max((uint32_t)inode->i_size, pageofs); ri.isize = cpu_to_je32(max((uint32_t)inode->i_size, pageofs));
ri.atime = ri.ctime = ri.mtime = get_seconds(); ri.atime = ri.ctime = ri.mtime = cpu_to_je32(get_seconds());
ri.offset = inode->i_size; ri.offset = cpu_to_je32(inode->i_size);
ri.dsize = pageofs - inode->i_size; ri.dsize = cpu_to_je32(pageofs - inode->i_size);
ri.csize = 0; ri.csize = cpu_to_je32(0);
ri.compr = JFFS2_COMPR_ZERO; ri.compr = JFFS2_COMPR_ZERO;
ri.node_crc = crc32(0, &ri, sizeof(ri)-8); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8));
ri.data_crc = 0; ri.data_crc = cpu_to_je32(0);
fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, NULL); fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, NULL);
...@@ -344,14 +345,16 @@ int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, uns ...@@ -344,14 +345,16 @@ int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, uns
} }
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
inode->i_size = pageofs; inode->i_size = pageofs;
up(&f->sem);
} }
/* Read in the page if it wasn't already present, unless it's a whole page */
/* Read in the page if it wasn't already present */ if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) {
if (!PageUptodate(pg) && (start || end < PAGE_SIZE)) down(&f->sem);
ret = jffs2_do_readpage_nolock(inode, pg); ret = jffs2_do_readpage_nolock(inode, pg);
D1(printk(KERN_DEBUG "end prepare_write()\n"));
up(&f->sem); up(&f->sem);
}
D1(printk(KERN_DEBUG "end prepare_write(). pg->flags %lx\n", pg->flags));
return ret; return ret;
} }
...@@ -367,8 +370,16 @@ int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsi ...@@ -367,8 +370,16 @@ int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsi
int ret = 0; int ret = 0;
uint32_t writtenlen = 0; uint32_t writtenlen = 0;
D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d\n", D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n",
inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end)); inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags));
if (!start && end == PAGE_CACHE_SIZE) {
/* We need to avoid deadlock with page_cache_read() in
jffs2_garbage_collect_pass(). So we have to mark the
page up to date, to prevent page_cache_read() from
trying to re-lock it. */
SetPageUptodate(pg);
}
ri = jffs2_alloc_raw_inode(); ri = jffs2_alloc_raw_inode();
...@@ -378,16 +389,21 @@ int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsi ...@@ -378,16 +389,21 @@ int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsi
} }
/* Set the fields that the generic jffs2_write_inode_range() code can't find */ /* Set the fields that the generic jffs2_write_inode_range() code can't find */
ri->ino = inode->i_ino; ri->ino = cpu_to_je32(inode->i_ino);
ri->mode = inode->i_mode; ri->mode = cpu_to_je32(inode->i_mode);
ri->uid = inode->i_uid; ri->uid = cpu_to_je16(inode->i_uid);
ri->gid = inode->i_gid; ri->gid = cpu_to_je16(inode->i_gid);
ri->isize = (uint32_t)inode->i_size; ri->isize = cpu_to_je32((uint32_t)inode->i_size);
ri->atime = ri->ctime = ri->mtime = get_seconds(); ri->atime = ri->ctime = ri->mtime = cpu_to_je32(get_seconds());
/* In 2.4, it was already kmapped by generic_file_write(). Doesn't
hurt to do it again. The alternative is ifdefs, which are ugly. */
kmap(pg); kmap(pg);
ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start, ret = jffs2_write_inode_range(c, f, ri, page_address(pg) + start,
(pg->index << PAGE_CACHE_SHIFT) + start, end - start, &writtenlen); (pg->index << PAGE_CACHE_SHIFT) + start,
end - start, &writtenlen);
kunmap(pg); kunmap(pg);
if (ret) { if (ret) {
...@@ -400,7 +416,7 @@ int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsi ...@@ -400,7 +416,7 @@ int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsi
inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen;
inode->i_blocks = (inode->i_size + 511) >> 9; inode->i_blocks = (inode->i_size + 511) >> 9;
inode->i_ctime.tv_sec = inode->i_mtime.tv_sec = ri->ctime; inode->i_ctime.tv_sec = inode->i_mtime.tv_sec = je32_to_cpu(ri->ctime);
inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0; inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
} }
} }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: fs.c,v 1.13 2002/07/02 22:48:24 dwmw2 Exp $ * $Id: fs.c,v 1.19 2002/11/12 09:53:40 dwmw2 Exp $
* *
*/ */
...@@ -86,13 +86,13 @@ void jffs2_read_inode (struct inode *inode) ...@@ -86,13 +86,13 @@ void jffs2_read_inode (struct inode *inode)
up(&f->sem); up(&f->sem);
return; return;
} }
inode->i_mode = latest_node.mode; inode->i_mode = je32_to_cpu(latest_node.mode);
inode->i_uid = latest_node.uid; inode->i_uid = je16_to_cpu(latest_node.uid);
inode->i_gid = latest_node.gid; inode->i_gid = je16_to_cpu(latest_node.gid);
inode->i_size = latest_node.isize; inode->i_size = je32_to_cpu(latest_node.isize);
inode->i_atime.tv_sec = latest_node.atime; inode->i_atime = je32_to_cpu(latest_node.atime);
inode->i_mtime.tv_sec = latest_node.mtime; inode->i_mtime = je32_to_cpu(latest_node.mtime);
inode->i_ctime.tv_sec = latest_node.ctime; inode->i_ctime = je32_to_cpu(latest_node.ctime);
inode->i_atime.tv_nsec = inode->i_atime.tv_nsec =
inode->i_mtime.tv_nsec = inode->i_mtime.tv_nsec =
inode->i_ctime.tv_nsec = 0; inode->i_ctime.tv_nsec = 0;
...@@ -192,19 +192,9 @@ void jffs2_write_super (struct super_block *sb) ...@@ -192,19 +192,9 @@ void jffs2_write_super (struct super_block *sb)
if (sb->s_flags & MS_RDONLY) if (sb->s_flags & MS_RDONLY)
return; return;
D1(printk(KERN_DEBUG "jffs2_write_super(): flush_wbuf before gc-trigger\n")); D1(printk(KERN_DEBUG "jffs2_write_super()\n"));
jffs2_garbage_collect_trigger(c); jffs2_garbage_collect_trigger(c);
jffs2_erase_pending_blocks(c); jffs2_erase_pending_blocks(c);
jffs2_mark_erased_blocks(c);
/* Eep. If we lock this here, we deadlock with jffs2_reserve_space() when
* it locks the alloc_sem and jffs2_do_reserve_space() waits for erases
* to happen. I think the erases and/or the flush_wbuf want doing from
*
*/
if (!down_trylock(&c->alloc_sem)) {
jffs2_flush_wbuf(c, 2);
up(&c->alloc_sem);
} // else it stays dirty. FIXME.
} }
...@@ -232,16 +222,16 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i ...@@ -232,16 +222,16 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
memset(ri, 0, sizeof(*ri)); memset(ri, 0, sizeof(*ri));
/* Set OS-specific defaults for new inodes */ /* Set OS-specific defaults for new inodes */
ri->uid = current->fsuid; ri->uid = cpu_to_je16(current->fsuid);
if (dir_i->i_mode & S_ISGID) { if (dir_i->i_mode & S_ISGID) {
ri->gid = dir_i->i_gid; ri->gid = cpu_to_je16(dir_i->i_gid);
if (S_ISDIR(mode)) if (S_ISDIR(mode))
ri->mode |= S_ISGID; mode |= S_ISGID;
} else { } else {
ri->gid = current->fsgid; ri->gid = cpu_to_je16(current->fsgid);
} }
ri->mode = mode; ri->mode = cpu_to_je32(mode);
ret = jffs2_do_new_inode (c, f, mode, ri); ret = jffs2_do_new_inode (c, f, mode, ri);
if (ret) { if (ret) {
make_bad_inode(inode); make_bad_inode(inode);
...@@ -249,12 +239,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i ...@@ -249,12 +239,14 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i
return ERR_PTR(ret); return ERR_PTR(ret);
} }
inode->i_nlink = 1; inode->i_nlink = 1;
inode->i_ino = ri->ino; inode->i_ino = je32_to_cpu(ri->ino);
inode->i_mode = ri->mode; inode->i_mode = je32_to_cpu(ri->mode);
inode->i_gid = ri->gid; inode->i_gid = je16_to_cpu(ri->gid);
inode->i_uid = ri->uid; inode->i_uid = je16_to_cpu(ri->uid);
inode->i_atime = inode->i_ctime = inode->i_mtime = inode->i_atime.tv_nsec = inode->i_ctime.tv_nsec = inode->i_mtime.tv_nsec = 0;
ri->atime = ri->mtime = ri->ctime = get_seconds(); inode->i_atime.tv_sec = inode->i_ctime.tv_sec = inode->i_mtime.tv_sec = get_seconds();
ri->atime = ri->mtime = ri->ctime = cpu_to_je32(inode->i_mtime.tv_sec);
inode->i_blksize = PAGE_SIZE; inode->i_blksize = PAGE_SIZE;
inode->i_blocks = 0; inode->i_blocks = 0;
inode->i_size = 0; inode->i_size = 0;
...@@ -305,9 +297,10 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) ...@@ -305,9 +297,10 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
if (!c->wbuf) if (!c->wbuf)
return -ENOMEM; return -ENOMEM;
/* Initialize process for timed wbuf flush */ /* Initialise process for timed wbuf flush */
INIT_WORK(&c->wbuf_task,(void*) jffs2_wbuf_process, (void *)c); INIT_WORK(&c->wbuf_task,(void*) jffs2_wbuf_process, (void *)c);
/* Initialize timer for timed wbuf flush */
/* Initialise timer for timed wbuf flush */
init_timer(&c->wbuf_timer); init_timer(&c->wbuf_timer);
c->wbuf_timer.function = jffs2_wbuf_timeout; c->wbuf_timer.function = jffs2_wbuf_timeout;
c->wbuf_timer.data = (unsigned long) c; c->wbuf_timer.data = (unsigned long) c;
......
This diff is collapsed.
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: nodelist.h,v 1.74 2002/06/26 01:20:43 dwmw2 Exp $ * $Id: nodelist.h,v 1.87 2002/11/12 13:36:18 dwmw2 Exp $
* *
*/ */
...@@ -53,16 +53,22 @@ struct jffs2_raw_node_ref ...@@ -53,16 +53,22 @@ struct jffs2_raw_node_ref
for this inode instead. The inode_cache will have NULL in the first for this inode instead. The inode_cache will have NULL in the first
word so you know when you've got there :) */ word so you know when you've got there :) */
struct jffs2_raw_node_ref *next_phys; struct jffs2_raw_node_ref *next_phys;
// uint32_t ino;
uint32_t flash_offset; uint32_t flash_offset;
uint32_t totlen; uint32_t totlen;
// uint16_t nodetype;
/* flash_offset & 3 always has to be zero, because nodes are /* flash_offset & 3 always has to be zero, because nodes are
always aligned at 4 bytes. So we have a couple of extra bits always aligned at 4 bytes. So we have a couple of extra bits
to play with. So we set the least significant bit to 1 to to play with. So we set the least significant bit to 1 to
signify that the node is obsoleted by later nodes. signify that the node is obsoleted by later nodes.
*/ */
#define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */
#define REF_OBSOLETE 1 /* Obsolete, can be completely ignored */
#define REF_PRISTINE 2 /* Completely clean. GC without looking */
#define REF_NORMAL 3 /* Possibly overlapped. Read the page and write again on GC */
#define ref_flags(ref) ((ref)->flash_offset & 3)
#define ref_offset(ref) ((ref)->flash_offset & ~3)
#define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE)
#define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0)
}; };
/* /*
...@@ -83,14 +89,20 @@ struct jffs2_raw_node_ref_list { ...@@ -83,14 +89,20 @@ struct jffs2_raw_node_ref_list {
a pointer to the first physical node which is part of this inode, too. a pointer to the first physical node which is part of this inode, too.
*/ */
struct jffs2_inode_cache { struct jffs2_inode_cache {
struct jffs2_scan_info *scan; /* Used during scan to hold struct jffs2_full_dirent *scan_dents; /* Used during scan to hold
temporary lists of nodes, and later must be set to temporary lists of dirents, and later must be set to
NULL to mark the end of the raw_node_ref->next_in_ino NULL to mark the end of the raw_node_ref->next_in_ino
chain. */ chain. */
struct jffs2_inode_cache *next; struct jffs2_inode_cache *next;
struct jffs2_raw_node_ref *nodes; struct jffs2_raw_node_ref *nodes;
uint32_t ino; uint32_t ino;
int nlink; int nlink;
int state;
#define INO_STATE_UNCHECKED 0
#define INO_STATE_CHECKING 1
#define INO_STATE_CHECKEDABSENT 2
#define INO_STATE_READINGINODE 3
#define INO_STATE_PRESENT 5
}; };
#define INOCACHE_HASHSIZE 128 #define INOCACHE_HASHSIZE 128
...@@ -146,7 +158,7 @@ struct jffs2_full_dirent ...@@ -146,7 +158,7 @@ struct jffs2_full_dirent
*/ */
struct jffs2_node_frag struct jffs2_node_frag
{ {
struct jffs2_node_frag *next; struct rb_node rb;
struct jffs2_full_dnode *node; /* NULL for holes */ struct jffs2_full_dnode *node; /* NULL for holes */
uint32_t size; uint32_t size;
uint32_t ofs; /* Don't really need this, but optimisation */ uint32_t ofs; /* Don't really need this, but optimisation */
...@@ -158,8 +170,10 @@ struct jffs2_eraseblock ...@@ -158,8 +170,10 @@ struct jffs2_eraseblock
int bad_count; int bad_count;
uint32_t offset; /* of this block in the MTD */ uint32_t offset; /* of this block in the MTD */
uint32_t unchecked_size;
uint32_t used_size; uint32_t used_size;
uint32_t dirty_size; uint32_t dirty_size;
uint32_t wasted_size;
uint32_t free_size; /* Note that sector_size - free_size uint32_t free_size; /* Note that sector_size - free_size
is the address of the first free space */ is the address of the first free space */
struct jffs2_raw_node_ref *first_node; struct jffs2_raw_node_ref *first_node;
...@@ -177,25 +191,28 @@ struct jffs2_eraseblock ...@@ -177,25 +191,28 @@ struct jffs2_eraseblock
}; };
#define ACCT_SANITY_CHECK(c, jeb) do { \ #define ACCT_SANITY_CHECK(c, jeb) do { \
if (jeb->used_size + jeb->dirty_size + jeb->free_size != c->sector_size) { \ if (jeb->used_size + jeb->dirty_size + jeb->free_size + jeb->wasted_size + jeb->unchecked_size != c->sector_size) { \
printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); \ printk(KERN_NOTICE "Eeep. Space accounting for block at 0x%08x is screwed\n", jeb->offset); \
printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x != total %08x\n", \ printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + wasted %08x + unchecked %08x != total %08x\n", \
jeb->free_size, jeb->dirty_size, jeb->used_size, c->sector_size); \ jeb->free_size, jeb->dirty_size, jeb->used_size, jeb->wasted_size, jeb->unchecked_size, c->sector_size); \
BUG(); \ BUG(); \
} \ } \
if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size != c->flash_size) { \ if (c->used_size + c->dirty_size + c->free_size + c->erasing_size + c->bad_size + c->wasted_size + c->unchecked_size != c->flash_size) { \
printk(KERN_NOTICE "Eeep. Space accounting superblock info is screwed\n"); \ printk(KERN_NOTICE "Eeep. Space accounting superblock info is screwed\n"); \
printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x != total %08x\n", \ printk(KERN_NOTICE "free 0x%08x + dirty 0x%08x + used %08x + erasing %08x + bad %08x + wasted %08x + unchecked %08x != total %08x\n", \
c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->flash_size); \ c->free_size, c->dirty_size, c->used_size, c->erasing_size, c->bad_size, c->wasted_size, c->unchecked_size, c->flash_size); \
BUG(); \ BUG(); \
} \ } \
} while(0) } while(0)
#define ACCT_PARANOIA_CHECK(jeb) do { \ #define ACCT_PARANOIA_CHECK(jeb) do { \
uint32_t my_used_size = 0; \ uint32_t my_used_size = 0; \
uint32_t my_unchecked_size = 0; \
struct jffs2_raw_node_ref *ref2 = jeb->first_node; \ struct jffs2_raw_node_ref *ref2 = jeb->first_node; \
while (ref2) { \ while (ref2) { \
if (!(ref2->flash_offset & 1)) \ if (ref_flags(ref2) == REF_UNCHECKED) \
my_unchecked_size += ref2->totlen; \
else if (!ref_obsolete(ref2)) \
my_used_size += ref2->totlen; \ my_used_size += ref2->totlen; \
ref2 = ref2->next_phys; \ ref2 = ref2->next_phys; \
} \ } \
...@@ -203,6 +220,10 @@ struct jffs2_eraseblock ...@@ -203,6 +220,10 @@ struct jffs2_eraseblock
printk(KERN_NOTICE "Calculated used size %08x != stored used size %08x\n", my_used_size, jeb->used_size); \ printk(KERN_NOTICE "Calculated used size %08x != stored used size %08x\n", my_used_size, jeb->used_size); \
BUG(); \ BUG(); \
} \ } \
if (my_unchecked_size != jeb->unchecked_size) { \
printk(KERN_NOTICE "Calculated unchecked size %08x != stored unchecked size %08x\n", my_unchecked_size, jeb->unchecked_size); \
BUG(); \
} \
} while(0) } while(0)
#define ALLOC_NORMAL 0 /* Normal allocation */ #define ALLOC_NORMAL 0 /* Normal allocation */
...@@ -211,7 +232,7 @@ struct jffs2_eraseblock ...@@ -211,7 +232,7 @@ struct jffs2_eraseblock
#define JFFS2_RESERVED_BLOCKS_BASE 3 /* Number of free blocks there must be before we... */ #define JFFS2_RESERVED_BLOCKS_BASE 3 /* Number of free blocks there must be before we... */
#define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 2) /* ... allow a normal filesystem write */ #define JFFS2_RESERVED_BLOCKS_WRITE (JFFS2_RESERVED_BLOCKS_BASE + 2) /* ... allow a normal filesystem write */
#define JFFS2_RESERVED_BLOCKS_DELETION (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... allow a normal filesystem deletion */ #define JFFS2_RESERVED_BLOCKS_DELETION (JFFS2_RESERVED_BLOCKS_BASE) /* ... allow a normal filesystem deletion */
#define JFFS2_RESERVED_BLOCKS_GCTRIGGER (JFFS2_RESERVED_BLOCKS_BASE + 3) /* ... wake up the GC thread */ #define JFFS2_RESERVED_BLOCKS_GCTRIGGER (JFFS2_RESERVED_BLOCKS_BASE + 3) /* ... wake up the GC thread */
#define JFFS2_RESERVED_BLOCKS_GCBAD (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... pick a block from the bad_list to GC */ #define JFFS2_RESERVED_BLOCKS_GCBAD (JFFS2_RESERVED_BLOCKS_BASE + 1) /* ... pick a block from the bad_list to GC */
#define JFFS2_RESERVED_BLOCKS_GCMERGE (JFFS2_RESERVED_BLOCKS_BASE) /* ... merge pages when garbage collecting */ #define JFFS2_RESERVED_BLOCKS_GCMERGE (JFFS2_RESERVED_BLOCKS_BASE) /* ... merge pages when garbage collecting */
...@@ -220,6 +241,9 @@ struct jffs2_eraseblock ...@@ -220,6 +241,9 @@ struct jffs2_eraseblock
/* How much dirty space before it goes on the very_dirty_list */ /* How much dirty space before it goes on the very_dirty_list */
#define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) #define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2))
/* check if dirty space is more than 255 Byte */
#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN)
#define PAD(x) (((x)+3)&~3) #define PAD(x) (((x)+3)&~3)
static inline int jffs2_raw_ref_to_inum(struct jffs2_raw_node_ref *raw) static inline int jffs2_raw_ref_to_inum(struct jffs2_raw_node_ref *raw)
...@@ -231,6 +255,24 @@ static inline int jffs2_raw_ref_to_inum(struct jffs2_raw_node_ref *raw) ...@@ -231,6 +255,24 @@ static inline int jffs2_raw_ref_to_inum(struct jffs2_raw_node_ref *raw)
return ((struct jffs2_inode_cache *)raw)->ino; return ((struct jffs2_inode_cache *)raw)->ino;
} }
static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
{
struct rb_node *node = root->rb_node;
if (!node)
return NULL;
while(node->rb_left)
node = node->rb_left;
return rb_entry(node, struct jffs2_node_frag, rb);
}
#define rb_parent(rb) ((rb)->rb_parent)
#define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb)
#define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb)
#define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb)
#define frag_left(frag) rb_entry((frag)->rb.rb_left, struct jffs2_node_frag, rb)
#define frag_right(frag) rb_entry((frag)->rb.rb_right, struct jffs2_node_frag, rb)
#define frag_erase(frag, list) rb_erase(&frag->rb, list);
/* nodelist.c */ /* nodelist.c */
D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)); D1(void jffs2_print_frag_list(struct jffs2_inode_info *f));
void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list);
...@@ -244,11 +286,17 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new ...@@ -244,11 +286,17 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new
void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old); void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old);
void jffs2_free_ino_caches(struct jffs2_sb_info *c); void jffs2_free_ino_caches(struct jffs2_sb_info *c);
void jffs2_free_raw_node_refs(struct jffs2_sb_info *c); void jffs2_free_raw_node_refs(struct jffs2_sb_info *c);
struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset);
void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c_delete);
void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_node_frag *base);
struct rb_node *rb_next(struct rb_node *);
struct rb_node *rb_prev(struct rb_node *);
void rb_replace_node(struct rb_node *victim, struct rb_node *new, struct rb_root *root);
/* nodemgmt.c */ /* nodemgmt.c */
int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio); int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio);
int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len);
int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new, uint32_t len, int dirty); int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new);
void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_complete_reservation(struct jffs2_sb_info *c);
void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw);
void jffs2_dump_block_lists(struct jffs2_sb_info *c); void jffs2_dump_block_lists(struct jffs2_sb_info *c);
...@@ -266,8 +314,8 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint ...@@ -266,8 +314,8 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint
/* readinode.c */ /* readinode.c */
void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct jffs2_node_frag **list, uint32_t size); void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size);
int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct jffs2_node_frag **list, struct jffs2_full_dnode *fn); int jffs2_add_full_dnode_to_fraglist(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_full_dnode *fn);
int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn);
int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
uint32_t ino, struct jffs2_raw_inode *latest_node); uint32_t ino, struct jffs2_raw_inode *latest_node);
...@@ -320,7 +368,6 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c); ...@@ -320,7 +368,6 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c);
/* erase.c */ /* erase.c */
void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); void jffs2_erase_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
void jffs2_erase_pending_blocks(struct jffs2_sb_info *c); void jffs2_erase_pending_blocks(struct jffs2_sb_info *c);
void jffs2_mark_erased_blocks(struct jffs2_sb_info *c);
void jffs2_erase_pending_trigger(struct jffs2_sb_info *c); void jffs2_erase_pending_trigger(struct jffs2_sb_info *c);
#ifdef CONFIG_JFFS2_FS_NAND #ifdef CONFIG_JFFS2_FS_NAND
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: os-linux.h,v 1.19 2002/05/20 14:56:38 dwmw2 Exp $ * $Id: os-linux.h,v 1.21 2002/11/12 09:44:30 dwmw2 Exp $
* *
*/ */
...@@ -49,11 +49,19 @@ ...@@ -49,11 +49,19 @@
#define JFFS2_F_I_RDEV_MAJ(f) (MAJOR(to_kdev_t(OFNI_EDONI_2SFFJ(f)->i_rdev))) #define JFFS2_F_I_RDEV_MAJ(f) (MAJOR(to_kdev_t(OFNI_EDONI_2SFFJ(f)->i_rdev)))
#endif #endif
/* Hmmm. P'raps generic code should only ever see versions of signal
functions which do the locking automatically? */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,40)
#define current_sig_lock current->sigmask_lock
#else
#define current_sig_lock current->sig->siglock
#endif
static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
{ {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2)
f->highest_version = 0; f->highest_version = 0;
f->fraglist = NULL; f->fragtree = RB_ROOT;
f->metadata = NULL; f->metadata = NULL;
f->dents = NULL; f->dents = NULL;
f->flags = 0; f->flags = 0;
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: read.c,v 1.23 2002/05/20 14:56:38 dwmw2 Exp $ * $Id: read.c,v 1.29 2002/11/12 09:51:22 dwmw2 Exp $
* *
*/ */
...@@ -31,35 +31,41 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsig ...@@ -31,35 +31,41 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsig
if (!ri) if (!ri)
return -ENOMEM; return -ENOMEM;
ret = jffs2_flash_read(c, fd->raw->flash_offset & ~3, sizeof(*ri), &readlen, (char *)ri); ret = jffs2_flash_read(c, ref_offset(fd->raw), sizeof(*ri), &readlen, (char *)ri);
if (ret) { if (ret) {
jffs2_free_raw_inode(ri); jffs2_free_raw_inode(ri);
printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", fd->raw->flash_offset & ~3, ret); printk(KERN_WARNING "Error reading node from 0x%08x: %d\n", ref_offset(fd->raw), ret);
return ret; return ret;
} }
if (readlen != sizeof(*ri)) { if (readlen != sizeof(*ri)) {
jffs2_free_raw_inode(ri); jffs2_free_raw_inode(ri);
printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%x bytes, got 0x%x\n", printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%x bytes, got 0x%x\n",
fd->raw->flash_offset & ~3, sizeof(*ri), readlen); ref_offset(fd->raw), sizeof(*ri), readlen);
return -EIO; return -EIO;
} }
crc = crc32(0, ri, sizeof(*ri)-8); crc = crc32(0, ri, sizeof(*ri)-8);
D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n", fd->raw->flash_offset & ~3, ri->node_crc, crc, ri->dsize, ri->csize, ri->offset, buf)); D1(printk(KERN_DEBUG "Node read from %08x: node_crc %08x, calculated CRC %08x. dsize %x, csize %x, offset %x, buf %p\n",
if (crc != ri->node_crc) { ref_offset(fd->raw), je32_to_cpu(ri->node_crc),
printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n", ri->node_crc, crc, fd->raw->flash_offset & ~3); crc, je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize),
je32_to_cpu(ri->offset), buf));
if (crc != je32_to_cpu(ri->node_crc)) {
printk(KERN_WARNING "Node CRC %08x != calculated CRC %08x for node at %08x\n",
je32_to_cpu(ri->node_crc), crc, ref_offset(fd->raw));
ret = -EIO; ret = -EIO;
goto out_ri; goto out_ri;
} }
/* There was a bug where we wrote hole nodes out with csize/dsize /* There was a bug where we wrote hole nodes out with csize/dsize
swapped. Deal with it */ swapped. Deal with it */
if (ri->compr == JFFS2_COMPR_ZERO && !ri->dsize && ri->csize) { if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) &&
je32_to_cpu(ri->csize)) {
ri->dsize = ri->csize; ri->dsize = ri->csize;
ri->csize = 0; ri->csize = cpu_to_je32(0);
} }
D1(if(ofs + len > ri->dsize) { D1(if(ofs + len > je32_to_cpu(ri->dsize)) {
printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n", len, ofs, ri->dsize); printk(KERN_WARNING "jffs2_read_dnode() asked for %d bytes at %d from %d-byte node\n",
len, ofs, je32_to_cpu(ri->dsize));
ret = -EINVAL; ret = -EINVAL;
goto out_ri; goto out_ri;
}); });
...@@ -76,18 +82,18 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsig ...@@ -76,18 +82,18 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsig
Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy
Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy
*/ */
if (ri->compr == JFFS2_COMPR_NONE && len == ri->dsize) { if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) {
readbuf = buf; readbuf = buf;
} else { } else {
readbuf = kmalloc(ri->csize, GFP_KERNEL); readbuf = kmalloc(je32_to_cpu(ri->csize), GFP_KERNEL);
if (!readbuf) { if (!readbuf) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_ri; goto out_ri;
} }
} }
if (ri->compr != JFFS2_COMPR_NONE) { if (ri->compr != JFFS2_COMPR_NONE) {
if (len < ri->dsize) { if (len < je32_to_cpu(ri->dsize)) {
decomprbuf = kmalloc(ri->dsize, GFP_KERNEL); decomprbuf = kmalloc(je32_to_cpu(ri->dsize), GFP_KERNEL);
if (!decomprbuf) { if (!decomprbuf) {
ret = -ENOMEM; ret = -ENOMEM;
goto out_readbuf; goto out_readbuf;
...@@ -99,31 +105,35 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsig ...@@ -99,31 +105,35 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_full_dnode *fd, unsig
decomprbuf = readbuf; decomprbuf = readbuf;
} }
D2(printk(KERN_DEBUG "Read %d bytes to %p\n", ri->csize, readbuf)); D2(printk(KERN_DEBUG "Read %d bytes to %p\n", je32_to_cpu(ri->csize),
ret = jffs2_flash_read(c, (fd->raw->flash_offset &~3) + sizeof(*ri), ri->csize, &readlen, readbuf); readbuf));
ret = jffs2_flash_read(c, (ref_offset(fd->raw)) + sizeof(*ri),
je32_to_cpu(ri->csize), &readlen, readbuf);
if (!ret && readlen != ri->csize) if (!ret && readlen != je32_to_cpu(ri->csize))
ret = -EIO; ret = -EIO;
if (ret) if (ret)
goto out_decomprbuf; goto out_decomprbuf;
crc = crc32(0, readbuf, ri->csize); crc = crc32(0, readbuf, je32_to_cpu(ri->csize));
if (crc != ri->data_crc) { if (crc != je32_to_cpu(ri->data_crc)) {
printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n", ri->data_crc, crc, fd->raw->flash_offset & ~3); printk(KERN_WARNING "Data CRC %08x != calculated CRC %08x for node at %08x\n",
je32_to_cpu(ri->data_crc), crc, ref_offset(fd->raw));
ret = -EIO; ret = -EIO;
goto out_decomprbuf; goto out_decomprbuf;
} }
D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc)); D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc));
if (ri->compr != JFFS2_COMPR_NONE) { if (ri->compr != JFFS2_COMPR_NONE) {
D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", ri->csize, readbuf, ri->dsize, decomprbuf)); D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n",
ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, ri->csize, ri->dsize); je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf));
ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize));
if (ret) { if (ret) {
printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret); printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret);
goto out_decomprbuf; goto out_decomprbuf;
} }
} }
if (len < ri->dsize) { if (len < je32_to_cpu(ri->dsize)) {
memcpy(buf, decomprbuf+ofs, len); memcpy(buf, decomprbuf+ofs, len);
} }
out_decomprbuf: out_decomprbuf:
...@@ -142,16 +152,14 @@ int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, ...@@ -142,16 +152,14 @@ int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
unsigned char *buf, uint32_t offset, uint32_t len) unsigned char *buf, uint32_t offset, uint32_t len)
{ {
uint32_t end = offset + len; uint32_t end = offset + len;
struct jffs2_node_frag *frag = f->fraglist; struct jffs2_node_frag *frag;
int ret; int ret;
D1(printk(KERN_DEBUG "jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n", D1(printk(KERN_DEBUG "jffs2_read_inode_range: ino #%u, range 0x%08x-0x%08x\n",
f->inocache->ino, offset, offset+len)); f->inocache->ino, offset, offset+len));
while(frag && frag->ofs + frag->size <= offset) { frag = jffs2_lookup_node_frag(&f->fragtree, offset);
D2(printk(KERN_DEBUG "skipping frag %d-%d; before the region we care about\n", frag->ofs, frag->ofs + frag->size));
frag = frag->next;
}
/* XXX FIXME: Where a single physical node actually shows up in two /* XXX FIXME: Where a single physical node actually shows up in two
frags, we read it twice. Don't do that. */ frags, we read it twice. Don't do that. */
/* Now we're pointing at the first frag which overlaps our page */ /* Now we're pointing at the first frag which overlaps our page */
...@@ -181,25 +189,29 @@ int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, ...@@ -181,25 +189,29 @@ int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
memset(buf, 0, holeend - offset); memset(buf, 0, holeend - offset);
buf += holeend - offset; buf += holeend - offset;
offset = holeend; offset = holeend;
frag = frag->next; frag = frag_next(frag);
continue; continue;
} else { } else {
uint32_t readlen; uint32_t readlen;
readlen = min(frag->size, end - offset); uint32_t fragofs; /* offset within the frag to start reading */
D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%x\n", frag->ofs, frag->ofs+readlen, frag->node->raw->flash_offset & ~3));
ret = jffs2_read_dnode(c, frag->node, buf, frag->ofs - frag->node->ofs, readlen); fragofs = offset - frag->ofs;
readlen = min(frag->size - fragofs, end - offset);
D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%x\n", frag->ofs+fragofs, frag->ofs+fragofs+readlen,
ref_offset(frag->node->raw)));
ret = jffs2_read_dnode(c, frag->node, buf, fragofs + frag->ofs - frag->node->ofs, readlen);
D2(printk(KERN_DEBUG "node read done\n")); D2(printk(KERN_DEBUG "node read done\n"));
if (ret) { if (ret) {
D1(printk(KERN_DEBUG"jffs2_read_inode_range error %d\n",ret)); D1(printk(KERN_DEBUG"jffs2_read_inode_range error %d\n",ret));
memset(buf, 0, frag->size); memset(buf, 0, readlen);
return ret; return ret;
} }
} buf += readlen;
buf += frag->size; offset += readlen;
offset += frag->size; frag = frag_next(frag);
frag = frag->next;
D2(printk(KERN_DEBUG "node read was OK. Looping\n")); D2(printk(KERN_DEBUG "node read was OK. Looping\n"));
} }
}
return 0; return 0;
} }
......
This diff is collapsed.
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: super.c,v 1.73 2002/07/23 17:00:45 dwmw2 Exp $ * $Id: super.c,v 1.74 2002/11/12 09:37:39 dwmw2 Exp $
* *
*/ */
......
...@@ -7,8 +7,9 @@ ...@@ -7,8 +7,9 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: wbuf.c,v 1.12 2002/05/20 14:56:39 dwmw2 Exp $ * $Id: wbuf.c,v 1.20 2002/11/12 11:33:02 dwmw2 Exp $
* -- with the NAND definitions added back pending MTD update for 2.5. * + some of the dependencies on later MTD NAND code temporarily reverted.
*
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -16,17 +17,22 @@ ...@@ -16,17 +17,22 @@
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/mtd/nand.h>
#include "nodelist.h" #include "nodelist.h"
/* FIXME duplicated defines in wbuf.c and nand.c /* FIXME duplicated defines in wbuf.c and nand.c
* Constants for out of band layout * Constants for out of band layout
*/ */
#ifndef NAND_BADBLOCK_POS
#define NAND_BADBLOCK_POS 5
#endif
#ifndef NAND_JFFS2_OOB_BADBPOS
#define NAND_JFFS2_OOB_BADBPOS 5 #define NAND_JFFS2_OOB_BADBPOS 5
#define NAND_JFFS2_OOB8_FSDAPOS 6 #define NAND_JFFS2_OOB8_FSDAPOS 6
#define NAND_JFFS2_OOB16_FSDAPOS 8 #define NAND_JFFS2_OOB16_FSDAPOS 8
#define NAND_JFFS2_OOB8_FSDALEN 2 #define NAND_JFFS2_OOB8_FSDALEN 2
#define NAND_JFFS2_OOB16_FSDALEN 8 #define NAND_JFFS2_OOB16_FSDALEN 8
#endif
/* max. erase failures before we mark a block bad */ /* max. erase failures before we mark a block bad */
#define MAX_ERASE_FAILURES 5 #define MAX_ERASE_FAILURES 5
...@@ -89,17 +95,39 @@ void jffs2_wbuf_process (void *data) ...@@ -89,17 +95,39 @@ void jffs2_wbuf_process (void *data)
D1(printk(KERN_DEBUG "jffs2_wbuf_process() entered\n")); D1(printk(KERN_DEBUG "jffs2_wbuf_process() entered\n"));
if (!down_trylock(&c->alloc_sem)) { /* Check, if the timer is active again */
if (timer_pending (&c->wbuf_timer)) {
D1(printk (KERN_DEBUG "Nothing to do, timer is active again\n"));
return;
}
if (down_trylock(&c->alloc_sem)) {
/* If someone else has the alloc_sem, they're about to
write anyway. So no need to waste space by
padding */
D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem already occupied\n"));
return;
}
D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem got\n")); D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem got\n"));
if(!c->nextblock || (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len))) if (!c->nextblock) {
jffs2_flush_wbuf(c, 1); /* pad only */ D1(printk(KERN_DEBUG "jffs2_wbuf_process(): nextblock NULL, nothing to do\n"));
else if (c->wbuf_len) {
jffs2_flush_wbuf(c, 2); /* pad and adjust nextblock */ printk(KERN_WARNING "jffs2_wbuf_process(): c->wbuf_len is 0x%03x but nextblock is NULL!\n", c->wbuf_len);
up(&c->alloc_sem); up(&c->alloc_sem);
} else { BUG();
D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem already occupied\n")); }
return;
} }
/* if !c->nextblock then the tail will have got flushed from
jffs2_do_reserve_space() anyway. */
if(c->nextblock)
jffs2_flush_wbuf(c, 2); /* pad and adjust nextblock */
up(&c->alloc_sem);
} }
...@@ -113,6 +141,11 @@ int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) ...@@ -113,6 +141,11 @@ int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
int ret; int ret;
size_t retlen; size_t retlen;
/* Nothing to do if not NAND flash. In particular, we shouldn't
del_timer() the timer we never initialised. */
if (jffs2_can_mark_obsolete(c))
return 0;
if (!down_trylock(&c->alloc_sem)) { if (!down_trylock(&c->alloc_sem)) {
up(&c->alloc_sem); up(&c->alloc_sem);
printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n"); printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
...@@ -136,10 +169,10 @@ int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) ...@@ -136,10 +169,10 @@ int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) {
struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len);
padnode->magic = JFFS2_MAGIC_BITMASK; padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
padnode->nodetype = JFFS2_NODETYPE_PADDING; padnode->nodetype = cpu_to_je16(JFFS2_NODETYPE_PADDING);
padnode->totlen = c->wbuf_pagesize - c->wbuf_len; padnode->totlen = cpu_to_je32(c->wbuf_pagesize - c->wbuf_len);
padnode->hdr_crc = crc32(0, padnode, sizeof(*padnode)-4); padnode->hdr_crc = cpu_to_je32(crc32(0, padnode, sizeof(*padnode)-4));
} }
} }
/* else jffs2_flash_writev has actually filled in the rest of the /* else jffs2_flash_writev has actually filled in the rest of the
...@@ -175,10 +208,20 @@ int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) ...@@ -175,10 +208,20 @@ int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
spin_lock_bh(&c->erase_completion_lock); spin_lock_bh(&c->erase_completion_lock);
if (!c->nextblock) if (!c->nextblock)
BUG(); BUG();
if (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len)) /* wbuf_pagesize - wbuf_len is the amount of space that's to be
padded. If there is less free space in the block than that,
something screwed up */
if (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len)) {
printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n",
c->wbuf_ofs, c->wbuf_len, c->wbuf_pagesize-c->wbuf_len);
printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n",
c->nextblock->offset, c->nextblock->free_size);
BUG(); BUG();
}
c->nextblock->free_size -= (c->wbuf_pagesize - c->wbuf_len); c->nextblock->free_size -= (c->wbuf_pagesize - c->wbuf_len);
c->nextblock->dirty_size += (c->wbuf_pagesize - c->wbuf_len); c->free_size -= (c->wbuf_pagesize - c->wbuf_len);
c->nextblock->wasted_size += (c->wbuf_pagesize - c->wbuf_len);
c->wasted_size += (c->wbuf_pagesize - c->wbuf_len);
spin_unlock_bh(&c->erase_completion_lock); spin_unlock_bh(&c->erase_completion_lock);
} }
...@@ -415,9 +458,10 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re ...@@ -415,9 +458,10 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re
int ret; int ret;
/* Read flash */ /* Read flash */
if (!jffs2_can_mark_obsolete(c)) {
ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); ret = c->mtd->read(c->mtd, ofs, len, retlen, buf);
if (!jffs2_can_mark_obsolete(c) && (ret == -EIO) && (*retlen == len) ) { if ( (ret == -EIO) && (*retlen == len) ) {
printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%llx) returned ECC error\n", len, ofs); printk(KERN_WARNING "mtd->read(0x%x bytes from 0x%llx) returned ECC error\n", len, ofs);
/* /*
* We have the raw data without ECC correction in the buffer, maybe * We have the raw data without ECC correction in the buffer, maybe
...@@ -431,12 +475,13 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re ...@@ -431,12 +475,13 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re
*/ */
ret = 0; ret = 0;
} }
} else
return c->mtd->read(c->mtd, ofs, len, retlen, buf);
/* if no writebuffer available or write buffer empty, return */ /* if no writebuffer available or write buffer empty, return */
if (!c->wbuf_pagesize || !c->wbuf_len) if (!c->wbuf_pagesize || !c->wbuf_len)
return ret; return ret;
/* if we read in a different block, return */ /* if we read in a different block, return */
if ( (ofs & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) ) if ( (ofs & ~(c->sector_size-1)) != (c->wbuf_ofs & ~(c->sector_size-1)) )
return ret; return ret;
...@@ -478,7 +523,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ...@@ -478,7 +523,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
switch(c->mtd->ecctype) { switch(c->mtd->ecctype) {
case MTD_ECC_SW: case MTD_ECC_SW:
fsdata_pos = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDAPOS : NAND_JFFS2_OOB16_FSDAPOS; fsdata_pos = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDAPOS : NAND_JFFS2_OOB16_FSDAPOS;
badblock_pos = NAND_JFFS2_OOB_BADBPOS; badblock_pos = NAND_BADBLOCK_POS;
break; break;
default: default:
D1(printk(KERN_WARNING "jffs2_write_oob_empty(): Invalid ECC type\n")); D1(printk(KERN_WARNING "jffs2_write_oob_empty(): Invalid ECC type\n"));
...@@ -486,7 +531,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ...@@ -486,7 +531,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
} }
/* allocate a buffer for all oob data in this sector */ /* allocate a buffer for all oob data in this sector */
len = oob_size * (c->sector_size/c->mtd->oobblock); len = 4 * oob_size;
buf = kmalloc(len, GFP_KERNEL); buf = kmalloc(len, GFP_KERNEL);
if (!buf) { if (!buf) {
printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n");
...@@ -510,7 +555,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb ...@@ -510,7 +555,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb
} }
/* Special check for first two pages */ /* Special check for first two pages */
for (page = 0; page < 2; page += oob_size) { for (page = 0; page < 2 * oob_size; page += oob_size) {
/* Check for bad block marker */ /* Check for bad block marker */
if (buf[page+badblock_pos] != 0xff) { if (buf[page+badblock_pos] != 0xff) {
D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Bad or failed block at %08x\n",jeb->offset)); D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Bad or failed block at %08x\n",jeb->offset));
...@@ -563,7 +608,7 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -563,7 +608,7 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc
case MTD_ECC_SW: case MTD_ECC_SW:
fsdata_pos = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDAPOS : NAND_JFFS2_OOB16_FSDAPOS; fsdata_pos = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDAPOS : NAND_JFFS2_OOB16_FSDAPOS;
fsdata_len = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDALEN : NAND_JFFS2_OOB16_FSDALEN; fsdata_len = (c->wbuf_pagesize == 256) ? NAND_JFFS2_OOB8_FSDALEN : NAND_JFFS2_OOB16_FSDALEN;
badblock_pos = NAND_JFFS2_OOB_BADBPOS; badblock_pos = NAND_BADBLOCK_POS;
break; break;
default: default:
D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Invalid ECC type\n")); D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Invalid ECC type\n"));
...@@ -598,9 +643,9 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -598,9 +643,9 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc
return 3; return 3;
} }
n.magic = JFFS2_MAGIC_BITMASK; n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
n.nodetype = JFFS2_NODETYPE_CLEANMARKER; n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
n.totlen = 8; n.totlen = cpu_to_je32(8);
p = (unsigned char *) &n; p = (unsigned char *) &n;
for (i = 0; i < fsdata_len; i++) { for (i = 0; i < fsdata_len; i++) {
...@@ -630,9 +675,9 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -630,9 +675,9 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc
return -EINVAL; return -EINVAL;
} }
n.magic = JFFS2_MAGIC_BITMASK; n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
n.nodetype = JFFS2_NODETYPE_CLEANMARKER; n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER);
n.totlen = 8; n.totlen = cpu_to_je32(8);
ret = jffs2_flash_write_oob(c, jeb->offset + fsdata_pos, fsdata_len, &retlen, (unsigned char *)&n); ret = jffs2_flash_write_oob(c, jeb->offset + fsdata_pos, fsdata_len, &retlen, (unsigned char *)&n);
...@@ -661,7 +706,7 @@ int jffs2_nand_read_failcnt(struct jffs2_sb_info *c, struct jffs2_eraseblock *je ...@@ -661,7 +706,7 @@ int jffs2_nand_read_failcnt(struct jffs2_sb_info *c, struct jffs2_eraseblock *je
switch(c->mtd->ecctype) { switch(c->mtd->ecctype) {
case MTD_ECC_SW: case MTD_ECC_SW:
badblock_pos = NAND_JFFS2_OOB_BADBPOS; badblock_pos = NAND_BADBLOCK_POS;
break; break;
default: default:
D1(printk(KERN_WARNING "jffs2_nand_read_failcnt(): Invalid ECC type\n")); D1(printk(KERN_WARNING "jffs2_nand_read_failcnt(): Invalid ECC type\n"));
...@@ -702,7 +747,7 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock * ...@@ -702,7 +747,7 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
switch(c->mtd->ecctype) { switch(c->mtd->ecctype) {
case MTD_ECC_SW: case MTD_ECC_SW:
pos = NAND_JFFS2_OOB_BADBPOS; pos = NAND_BADBLOCK_POS;
break; break;
default: default:
D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Invalid ECC type\n")); D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Invalid ECC type\n"));
......
This diff is collapsed.
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* *
* For licensing information, see the file 'LICENCE' in this directory. * For licensing information, see the file 'LICENCE' in this directory.
* *
* $Id: writev.c,v 1.2 2002/05/20 14:56:39 dwmw2 Exp $ * $Id: writev.c,v 1.3 2002/08/08 08:35:21 dwmw2 Exp $
* *
*/ */
...@@ -28,7 +28,7 @@ static inline int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs ...@@ -28,7 +28,7 @@ static inline int mtd_fake_writev(struct mtd_info *mtd, const struct iovec *vecs
for (i=0; i<count; i++) { for (i=0; i<count; i++) {
if (!vecs[i].iov_len) if (!vecs[i].iov_len)
continue; continue;
mtd->write(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base); ret = mtd->write(mtd, to, vecs[i].iov_len, &thislen, vecs[i].iov_base);
totlen += thislen; totlen += thislen;
if (ret || thislen != vecs[i].iov_len) if (ret || thislen != vecs[i].iov_len)
break; break;
......
This diff is collapsed.
/* $Id: jffs2_fs_i.h,v 1.12 2002/03/06 13:59:21 dwmw2 Exp $ */ /* $Id: jffs2_fs_i.h,v 1.15 2002/11/12 09:42:49 dwmw2 Exp $ */
#ifndef _JFFS2_FS_I #ifndef _JFFS2_FS_I
#define _JFFS2_FS_I #define _JFFS2_FS_I
#include <linux/version.h> #include <linux/version.h>
#include <linux/rbtree.h>
struct jffs2_inode_info { struct jffs2_inode_info {
/* We need an internal semaphore similar to inode->i_sem. /* We need an internal semaphore similar to inode->i_sem.
...@@ -18,7 +19,7 @@ struct jffs2_inode_info { ...@@ -18,7 +19,7 @@ struct jffs2_inode_info {
uint32_t highest_version; uint32_t highest_version;
/* List of data fragments which make up the file */ /* List of data fragments which make up the file */
struct jffs2_node_frag *fraglist; struct rb_root fragtree;
/* There may be one datanode which isn't referenced by any of the /* There may be one datanode which isn't referenced by any of the
above fragments, if it contains a metadata update but no actual above fragments, if it contains a metadata update but no actual
......
/* $Id: jffs2_fs_sb.h,v 1.32 2002/07/23 14:35:34 dwmw2 Exp $ */ /* $Id: jffs2_fs_sb.h,v 1.35 2002/11/12 09:42:18 dwmw2 Exp $ */
#ifndef _JFFS2_FS_SB #ifndef _JFFS2_FS_SB
#define _JFFS2_FS_SB #define _JFFS2_FS_SB
...@@ -21,6 +21,8 @@ struct jffs2_sb_info { ...@@ -21,6 +21,8 @@ struct jffs2_sb_info {
struct mtd_info *mtd; struct mtd_info *mtd;
uint32_t highest_ino; uint32_t highest_ino;
uint32_t checked_ino;
unsigned int flags; unsigned int flags;
struct task_struct *gc_task; /* GC task struct */ struct task_struct *gc_task; /* GC task struct */
...@@ -38,10 +40,12 @@ struct jffs2_sb_info { ...@@ -38,10 +40,12 @@ struct jffs2_sb_info {
uint32_t flash_size; uint32_t flash_size;
uint32_t used_size; uint32_t used_size;
uint32_t dirty_size; uint32_t dirty_size;
uint32_t wasted_size;
uint32_t free_size; uint32_t free_size;
uint32_t erasing_size; uint32_t erasing_size;
uint32_t bad_size; uint32_t bad_size;
uint32_t sector_size; uint32_t sector_size;
uint32_t unchecked_size;
uint32_t nr_free_blocks; uint32_t nr_free_blocks;
uint32_t nr_erasing_blocks; uint32_t nr_erasing_blocks;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment