Commit 1a4c1b9e authored by David Woodhouse's avatar David Woodhouse

Merge hch's addition of generic_file_sendfile into jffs2_file_operations.

parents ff42067b 70d06792
The files in this directory and elsewhere which refer to this LICENCE
file are part of JFFS2, the Journalling Flash File System v2.
Copyright (C) 2001, 2002 Red Hat, Inc.
JFFS2 is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2 or (at your option) any later
version.
JFFS2 is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with JFFS2; if not, write to the Free Software Foundation, Inc.,
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
As a special exception, if other files instantiate templates or use
macros or inline functions from these files, or you compile these
files and link them with other works to produce a work based on these
files, these files do not by themselves cause the resulting work to be
covered by the GNU General Public License. However the source code for
these files must still be made available in accordance with section (3)
of the GNU General Public License.
This exception does not invalidate any other reasons why a work based on
this file might be covered by the GNU General Public License.
For information on obtaining alternative licences for JFFS2, see
http://sources.redhat.com/jffs2/jffs2-licence.html
$Id: LICENCE,v 1.1 2002/05/20 14:56:37 dwmw2 Exp $
$Id: TODO,v 1.7 2002/03/11 12:36:59 dwmw2 Exp $ $Id: TODO,v 1.9 2002/07/11 10:39:04 dwmw2 Exp $
- Locking audit. Even more so now 2.5 took away the BKL.
- disable compression in commit_write()? - disable compression in commit_write()?
- fine-tune the allocation / GC thresholds - fine-tune the allocation / GC thresholds
- chattr support - turning on/off and tuning compression per-inode - chattr support - turning on/off and tuning compression per-inode
...@@ -9,7 +8,6 @@ $Id: TODO,v 1.7 2002/03/11 12:36:59 dwmw2 Exp $ ...@@ -9,7 +8,6 @@ $Id: TODO,v 1.7 2002/03/11 12:36:59 dwmw2 Exp $
mount doesn't have to read the flash twice for large files. mount doesn't have to read the flash twice for large files.
Make this a per-inode option, changable with chattr, so you can Make this a per-inode option, changable with chattr, so you can
decide which inodes should be in-core immediately after mount. decide which inodes should be in-core immediately after mount.
- stop it depending on a block device.
- test, test, test - test, test, test
- NAND flash support: - NAND flash support:
...@@ -22,3 +20,25 @@ $Id: TODO,v 1.7 2002/03/11 12:36:59 dwmw2 Exp $ ...@@ -22,3 +20,25 @@ $Id: TODO,v 1.7 2002/03/11 12:36:59 dwmw2 Exp $
- timed flush of old wbuf - timed flush of old wbuf
- fix magical second arg of jffs2_flush_wbuf(). Split into two or more functions instead. - fix magical second arg of jffs2_flush_wbuf(). Split into two or more functions instead.
- Optimisations:
- Stop GC from decompressing and immediately recompressing nodes which could
just be copied intact.
- 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 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
_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
help.
- 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
got a match, and in readdir().
- 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
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
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.
...@@ -5,45 +5,21 @@ ...@@ -5,45 +5,21 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: background.c,v 1.29 2002/06/07 10:04:28 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: background.c,v 1.23 2002/03/06 12:37:08 dwmw2 Exp $
* *
*/ */
#define __KERNEL_SYSCALLS__ #define __KERNEL_SYSCALLS__
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/unistd.h>
#include <linux/jffs2.h> #include <linux/jffs2.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/mtd/compatmac.h> /* recalc_sigpending() */ #include <linux/mtd/compatmac.h> /* recalc_sigpending() */
#include <linux/unistd.h>
#include "nodelist.h" #include "nodelist.h"
...@@ -86,6 +62,13 @@ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c) ...@@ -86,6 +62,13 @@ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c) void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
{ {
if (c->mtd->type == MTD_NANDFLASH) {
/* stop a eventually scheduled wbuf flush timer */
del_timer_sync(&c->wbuf_timer);
/* make sure, that a scheduled wbuf flush task is completed */
flush_scheduled_tasks();
}
spin_lock_bh(&c->erase_completion_lock); spin_lock_bh(&c->erase_completion_lock);
if (c->gc_task) { if (c->gc_task) {
D1(printk(KERN_DEBUG "jffs2: Killing GC task %d\n", c->gc_task->pid)); D1(printk(KERN_DEBUG "jffs2: Killing GC task %d\n", c->gc_task->pid));
...@@ -171,11 +154,23 @@ static int jffs2_garbage_collect_thread(void *_c) ...@@ -171,11 +154,23 @@ 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)
{ {
D1(printk(KERN_DEBUG "thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x\n", uint32_t gcnodeofs = 0;
c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size)); int ret;
/* Don't count any progress we've already made through the gcblock
as dirty space, for the purposes of this calculation */
if (c->gcblock && c->gcblock->gc_node)
gcnodeofs = c->gcblock->gc_node->flash_offset & ~3 & (c->sector_size-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 > c->sector_size) (c->dirty_size - gcnodeofs) > c->sector_size)
return 1; ret = 1;
else else
return 0; 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",
c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size,
c->dirty_size - gcnodeofs, ret?"yes":"no"));
return ret;
} }
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: build.c,v 1.35 2002/05/20 14:56:37 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: build.c,v 1.32 2002/03/08 15:11:24 dwmw2 Exp $
* *
*/ */
...@@ -124,6 +100,9 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) ...@@ -124,6 +100,9 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c)
} }
D1(printk(KERN_DEBUG "Pass 3 complete\n")); D1(printk(KERN_DEBUG "Pass 3 complete\n"));
/* Rotate the lists by some number to ensure wear levelling */
jffs2_rotate_lists(c);
return ret; return ret;
} }
...@@ -304,6 +283,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) ...@@ -304,6 +283,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c)
spin_lock_init(&c->inocache_lock); spin_lock_init(&c->inocache_lock);
INIT_LIST_HEAD(&c->clean_list); INIT_LIST_HEAD(&c->clean_list);
INIT_LIST_HEAD(&c->very_dirty_list);
INIT_LIST_HEAD(&c->dirty_list); INIT_LIST_HEAD(&c->dirty_list);
INIT_LIST_HEAD(&c->erasable_list); INIT_LIST_HEAD(&c->erasable_list);
INIT_LIST_HEAD(&c->erasing_list); INIT_LIST_HEAD(&c->erasing_list);
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by Arjan van de Ven <arjanv@redhat.com> * Created by Arjan van de Ven <arjanv@redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: compr.c,v 1.24 2002/05/20 14:56:37 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr.c,v 1.23 2002/01/25 01:49:26 dwmw2 Exp $
* *
*/ */
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by Arjan van de Ven <arjanv@redhat.com> * Created by Arjan van de Ven <arjanv@redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: compr_rtime.c,v 1.9 2002/05/20 14:56:37 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr_rtime.c,v 1.8 2002/01/25 01:49:26 dwmw2 Exp $
* *
* *
* Very simple lz77-ish encoder. * Very simple lz77-ish encoder.
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by Arjan van de Ven <arjanv@redhat.com> * Created by Arjan van de Ven <arjanv@redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: compr_rubin.c,v 1.17 2002/05/20 14:56:37 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr_rubin.c,v 1.16 2002/01/25 01:49:26 dwmw2 Exp $
* *
*/ */
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: compr_zlib.c,v 1.18 2002/05/20 14:56:37 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: compr_zlib.c,v 1.15 2002/03/04 09:35:48 dwmw2 Exp $
* *
*/ */
...@@ -65,21 +41,21 @@ int __init jffs2_zlib_init(void) ...@@ -65,21 +41,21 @@ int __init jffs2_zlib_init(void)
{ {
deflate_workspace = vmalloc(zlib_deflate_workspacesize()); deflate_workspace = vmalloc(zlib_deflate_workspacesize());
if (!deflate_workspace) { if (!deflate_workspace) {
printk("Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize()); printk(KERN_WARNING "Failed to allocate %d bytes for deflate workspace\n", zlib_deflate_workspacesize());
return -ENOMEM; return -ENOMEM;
} }
D1(printk("Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize())); D1(printk(KERN_DEBUG "Allocated %d bytes for deflate workspace\n", zlib_deflate_workspacesize()));
inflate_workspace = vmalloc(zlib_inflate_workspacesize()); inflate_workspace = vmalloc(zlib_inflate_workspacesize());
if (!inflate_workspace) { if (!inflate_workspace) {
printk("Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize()); printk(KERN_WARNING "Failed to allocate %d bytes for inflate workspace\n", zlib_inflate_workspacesize());
vfree(deflate_workspace); vfree(deflate_workspace);
return -ENOMEM; return -ENOMEM;
} }
D1(printk("Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize())); D1(printk(KERN_DEBUG "Allocated %d bytes for inflate workspace\n", zlib_inflate_workspacesize()));
return 0; return 0;
} }
void __exit jffs2_zlib_exit(void) void jffs2_zlib_exit(void)
{ {
vfree(deflate_workspace); vfree(deflate_workspace);
vfree(inflate_workspace); vfree(inflate_workspace);
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: dir.c,v 1.71 2002/07/23 17:00:45 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: dir.c,v 1.68 2002/03/11 12:36:59 dwmw2 Exp $
* *
*/ */
...@@ -45,7 +21,6 @@ ...@@ -45,7 +21,6 @@
#include <linux/jffs2_fs_i.h> #include <linux/jffs2_fs_i.h>
#include <linux/jffs2_fs_sb.h> #include <linux/jffs2_fs_sb.h>
#include <linux/time.h> #include <linux/time.h>
#include <linux/smp_lock.h>
#include "nodelist.h" #include "nodelist.h"
static int jffs2_readdir (struct file *, void *, filldir_t); static int jffs2_readdir (struct file *, void *, filldir_t);
...@@ -63,25 +38,25 @@ static int jffs2_rename (struct inode *, struct dentry *, ...@@ -63,25 +38,25 @@ static int jffs2_rename (struct inode *, struct dentry *,
struct file_operations jffs2_dir_operations = struct file_operations jffs2_dir_operations =
{ {
read: generic_read_dir, .read = generic_read_dir,
readdir: jffs2_readdir, .readdir = jffs2_readdir,
ioctl: jffs2_ioctl, .ioctl = jffs2_ioctl,
fsync: jffs2_fsync .fsync = jffs2_fsync
}; };
struct inode_operations jffs2_dir_inode_operations = struct inode_operations jffs2_dir_inode_operations =
{ {
create: jffs2_create, .create = jffs2_create,
lookup: jffs2_lookup, .lookup = jffs2_lookup,
link: jffs2_link, .link = jffs2_link,
unlink: jffs2_unlink, .unlink = jffs2_unlink,
symlink: jffs2_symlink, .symlink = jffs2_symlink,
mkdir: jffs2_mkdir, .mkdir = jffs2_mkdir,
rmdir: jffs2_rmdir, .rmdir = jffs2_rmdir,
mknod: jffs2_mknod, .mknod = jffs2_mknod,
rename: jffs2_rename, .rename = jffs2_rename,
setattr: jffs2_setattr, .setattr = jffs2_setattr,
}; };
/***********************************************************************/ /***********************************************************************/
...@@ -144,8 +119,6 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -144,8 +119,6 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_dentry->d_inode->i_ino)); D1(printk(KERN_DEBUG "jffs2_readdir() for dir_i #%lu\n", filp->f_dentry->d_inode->i_ino));
lock_kernel();
f = JFFS2_INODE_INFO(inode); f = JFFS2_INODE_INFO(inode);
c = JFFS2_SB_INFO(inode->i_sb); c = JFFS2_SB_INFO(inode->i_sb);
...@@ -189,7 +162,6 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -189,7 +162,6 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
up(&f->sem); up(&f->sem);
out: out:
filp->f_pos = offset; filp->f_pos = offset;
unlock_kernel();
return 0; return 0;
} }
...@@ -744,8 +716,30 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, ...@@ -744,8 +716,30 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
{ {
int ret; int ret;
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb); struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
struct jffs2_inode_info *victim_f = NULL;
uint8_t type; uint8_t type;
/* The VFS will check for us and prevent trying to rename a
* file over a directory and vice versa, but if it's a directory,
* the VFS can't check whether the victim is empty. The filesystem
* needs to do that for itself.
*/
if (new_dentry->d_inode) {
victim_f = JFFS2_INODE_INFO(new_dentry->d_inode);
if (S_ISDIR(new_dentry->d_inode->i_mode)) {
struct jffs2_full_dirent *fd;
down(&victim_f->sem);
for (fd = victim_f->dents; fd; fd = fd->next) {
if (fd->ino) {
up(&victim_f->sem);
return -ENOTEMPTY;
}
}
up(&victim_f->sem);
}
}
/* XXX: We probably ought to alloc enough space for /* XXX: We probably ought to alloc enough space for
both nodes at the same time. Writing the new link, both nodes at the same time. Writing the new link,
then getting -ENOSPC, is quite bad :) then getting -ENOSPC, is quite bad :)
...@@ -764,7 +758,21 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, ...@@ -764,7 +758,21 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry,
if (ret) if (ret)
return ret; return ret;
if (S_ISDIR(old_dentry->d_inode->i_mode)) if (victim_f) {
/* There was a victim. Kill it off nicely */
new_dentry->d_inode->i_nlink--;
/* Don't oops if the victim was a dirent pointing to an
inode which didn't exist. */
if (victim_f->inocache) {
down(&victim_f->sem);
victim_f->inocache->nlink--;
up(&victim_f->sem);
}
}
/* If it was a directory we moved, and there was no victim,
increase i_nlink on its new parent */
if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f)
new_dir_i->i_nlink++; new_dir_i->i_nlink++;
/* Unlink the original */ /* Unlink the original */
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: erase.c,v 1.39 2002/07/23 17:00:45 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: erase.c,v 1.35 2002/03/08 15:11:24 dwmw2 Exp $
* *
*/ */
...@@ -286,20 +262,12 @@ void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) ...@@ -286,20 +262,12 @@ void jffs2_erase_pending_trigger(struct jffs2_sb_info *c)
void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) void jffs2_mark_erased_blocks(struct jffs2_sb_info *c)
{ {
static struct jffs2_unknown_node marker = {
magic: JFFS2_MAGIC_BITMASK,
nodetype: JFFS2_NODETYPE_CLEANMARKER,
totlen: sizeof(struct jffs2_unknown_node)
};
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;
if (unlikely(!marker.hdr_crc))
marker.hdr_crc = crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4);
spin_lock_bh(&c->erase_completion_lock); spin_lock_bh(&c->erase_completion_lock);
while (!list_empty(&c->erase_complete_list)) { while (!list_empty(&c->erase_complete_list)) {
jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list);
...@@ -359,6 +327,7 @@ void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) ...@@ -359,6 +327,7 @@ void jffs2_mark_erased_blocks(struct jffs2_sb_info *c)
} }
} }
ofs += readlen; ofs += readlen;
cond_resched();
} }
kfree(ebuf); kfree(ebuf);
} }
...@@ -376,22 +345,30 @@ void jffs2_mark_erased_blocks(struct jffs2_sb_info *c) ...@@ -376,22 +345,30 @@ void jffs2_mark_erased_blocks(struct jffs2_sb_info *c)
jeb->used_size = 0; jeb->used_size = 0;
jeb->dirty_size = 0; jeb->dirty_size = 0;
} else { } else {
ret = jffs2_flash_write(c, jeb->offset, sizeof(marker), &retlen, (char *)&marker); struct jffs2_unknown_node marker = {
.magic = JFFS2_MAGIC_BITMASK,
.nodetype = JFFS2_NODETYPE_CLEANMARKER,
.totlen = c->cleanmarker_size
};
marker.hdr_crc = crc32(0, &marker, marker.totlen - 4);
ret = jffs2_flash_write(c, jeb->offset, 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 != sizeof(marker)) { if (retlen != 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, sizeof(marker), retlen); jeb->offset, 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;
marker_ref->totlen = PAD(sizeof(marker)); marker_ref->totlen = PAD(marker.totlen);
jeb->first_node = jeb->last_node = marker_ref; jeb->first_node = jeb->last_node = marker_ref;
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: file.c,v 1.76 2002/07/29 08:25:35 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: file.c,v 1.70 2002/03/05 09:55:07 dwmw2 Exp $
* *
*/ */
...@@ -43,7 +19,6 @@ ...@@ -43,7 +19,6 @@
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/crc32.h> #include <linux/crc32.h>
#include <linux/jffs2.h> #include <linux/jffs2.h>
#include <linux/smp_lock.h>
#include "nodelist.h" #include "nodelist.h"
extern int generic_file_open(struct inode *, struct file *) __attribute__((weak)); extern int generic_file_open(struct inode *, struct file *) __attribute__((weak));
...@@ -66,37 +41,41 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) ...@@ -66,37 +41,41 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync)
* maybe we have to think about it to find a smarter * maybe we have to think about it to find a smarter
* solution. * solution.
*/ */
down(&c->alloc_sem);
down(&f->sem); down(&f->sem);
jffs2_flush_wbuf(c,2); jffs2_flush_wbuf(c,2);
up(&f->sem); up(&f->sem);
up(&c->alloc_sem);
return 0; return 0;
} }
struct file_operations jffs2_file_operations = struct file_operations jffs2_file_operations =
{ {
llseek: generic_file_llseek, .llseek = generic_file_llseek,
open: generic_file_open, .open = generic_file_open,
read: generic_file_read, .read = generic_file_read,
write: generic_file_write, .write = generic_file_write,
ioctl: jffs2_ioctl, .ioctl = jffs2_ioctl,
mmap: generic_file_mmap, .mmap = generic_file_mmap,
fsync: jffs2_fsync .fsync = jffs2_fsync,
sendfile: generic_file_sendfile, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,29)
.sendfile = generic_file_sendfile
#endif
}; };
/* jffs2_file_inode_operations */ /* jffs2_file_inode_operations */
struct inode_operations jffs2_file_inode_operations = struct inode_operations jffs2_file_inode_operations =
{ {
setattr: jffs2_setattr .setattr = jffs2_setattr
}; };
struct address_space_operations jffs2_file_address_operations = struct address_space_operations jffs2_file_address_operations =
{ {
readpage: jffs2_readpage, .readpage = jffs2_readpage,
prepare_write: jffs2_prepare_write, .prepare_write =jffs2_prepare_write,
commit_write: jffs2_commit_write .commit_write = jffs2_commit_write
}; };
int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
...@@ -111,12 +90,11 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ...@@ -111,12 +90,11 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
int mdatalen = 0; int mdatalen = 0;
unsigned int ivalid; unsigned int ivalid;
uint32_t phys_ofs, alloclen; uint32_t phys_ofs, alloclen;
int ret = 0; int ret;
lock_kernel();
D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino));
ret = inode_change_ok(inode, iattr); ret = inode_change_ok(inode, iattr);
if (ret) if (ret)
goto out; return ret;
/* Special cases - we don't want more than one data node /* Special cases - we don't want more than one data node
for these types on the medium at any time. So setattr for these types on the medium at any time. So setattr
...@@ -133,14 +111,12 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ...@@ -133,14 +111,12 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
} else if (S_ISLNK(inode->i_mode)) { } else if (S_ISLNK(inode->i_mode)) {
mdatalen = f->metadata->size; mdatalen = f->metadata->size;
mdata = kmalloc(f->metadata->size, GFP_USER); mdata = kmalloc(f->metadata->size, GFP_USER);
if (!mdata) { if (!mdata)
ret = -ENOMEM; return -ENOMEM;
goto out;
}
ret = jffs2_read_dnode(c, f->metadata, mdata, 0, mdatalen); ret = jffs2_read_dnode(c, f->metadata, mdata, 0, mdatalen);
if (ret) { if (ret) {
kfree(mdata); kfree(mdata);
goto out; return ret;
} }
D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen));
} }
...@@ -149,8 +125,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ...@@ -149,8 +125,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
if (!ri) { if (!ri) {
if (S_ISLNK(inode->i_mode)) if (S_ISLNK(inode->i_mode))
kfree(mdata); kfree(mdata);
ret = -ENOMEM; return -ENOMEM;
goto out;
} }
ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL);
...@@ -158,7 +133,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ...@@ -158,7 +133,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
jffs2_free_raw_inode(ri); jffs2_free_raw_inode(ri);
if (S_ISLNK(inode->i_mode & S_IFMT)) if (S_ISLNK(inode->i_mode & S_IFMT))
kfree(mdata); kfree(mdata);
goto out; return ret;
} }
down(&f->sem); down(&f->sem);
ivalid = iattr->ia_valid; ivalid = iattr->ia_valid;
...@@ -207,8 +182,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ...@@ -207,8 +182,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
jffs2_free_raw_inode(ri); jffs2_free_raw_inode(ri);
up(&f->sem); up(&f->sem);
ret = PTR_ERR(new_metadata); return PTR_ERR(new_metadata);
goto out;
} }
/* It worked. Update the inode */ /* It worked. Update the inode */
inode->i_atime = ri->atime; inode->i_atime = ri->atime;
...@@ -242,9 +216,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr) ...@@ -242,9 +216,7 @@ int jffs2_setattr (struct dentry *dentry, struct iattr *iattr)
up(&f->sem); up(&f->sem);
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
out: return 0;
unlock_kernel();
return ret;
} }
int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg) int jffs2_do_readpage_nolock (struct inode *inode, struct page *pg)
...@@ -289,18 +261,18 @@ int jffs2_do_readpage_unlock(struct inode *inode, struct page *pg) ...@@ -289,18 +261,18 @@ int jffs2_do_readpage_unlock(struct inode *inode, struct page *pg)
int jffs2_readpage (struct file *filp, struct page *pg) int jffs2_readpage (struct file *filp, struct page *pg)
{ {
struct jffs2_inode_info *f = JFFS2_INODE_INFO(filp->f_dentry->d_inode); struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host);
int ret; int ret;
down(&f->sem); down(&f->sem);
ret = jffs2_do_readpage_unlock(filp->f_dentry->d_inode, pg); ret = jffs2_do_readpage_unlock(pg->mapping->host, pg);
up(&f->sem); up(&f->sem);
return ret; return ret;
} }
int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, unsigned end) int jffs2_prepare_write (struct file *filp, struct page *pg, unsigned start, unsigned end)
{ {
struct inode *inode = filp->f_dentry->d_inode; struct inode *inode = pg->mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT; uint32_t pageofs = pg->index << PAGE_CACHE_SHIFT;
int ret = 0; int ret = 0;
...@@ -384,7 +356,7 @@ int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsi ...@@ -384,7 +356,7 @@ int jffs2_commit_write (struct file *filp, struct page *pg, unsigned start, unsi
/* Actually commit the write from the page cache page we're looking at. /* Actually commit the write from the page cache page we're looking at.
* For now, we write the full page out each time. It sucks, but it's simple * For now, we write the full page out each time. It sucks, but it's simple
*/ */
struct inode *inode = filp->f_dentry->d_inode; struct inode *inode = pg->mapping->host;
struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
struct jffs2_raw_inode *ri; struct jffs2_raw_inode *ri;
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: fs.c,v 1.13 2002/07/02 22:48:24 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: fs.c,v 1.4 2002/03/11 12:36:59 dwmw2 Exp $
* *
*/ */
...@@ -44,7 +20,6 @@ ...@@ -44,7 +20,6 @@
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/smp_lock.h>
#include "nodelist.h" #include "nodelist.h"
int jffs2_statfs(struct super_block *sb, struct statfs *buf) int jffs2_statfs(struct super_block *sb, struct statfs *buf)
...@@ -69,122 +44,10 @@ int jffs2_statfs(struct super_block *sb, struct statfs *buf) ...@@ -69,122 +44,10 @@ int jffs2_statfs(struct super_block *sb, struct statfs *buf)
buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT;
#if CONFIG_JFFS2_FS_DEBUG > 0 D1(jffs2_dump_block_lists(c));
printk(KERN_DEBUG "STATFS:\n");
printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size);
printk(KERN_DEBUG "used_size: %08x\n", c->used_size);
printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size);
printk(KERN_DEBUG "free_size: %08x\n", c->free_size);
printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size);
printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size);
printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size);
printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE);
if (c->nextblock) {
printk(KERN_DEBUG "nextblock: 0x%08x\n", c->nextblock->offset);
} else {
printk(KERN_DEBUG "nextblock: NULL\n");
}
if (c->gcblock) {
printk(KERN_DEBUG "gcblock: 0x%08x\n", c->gcblock->offset);
} else {
printk(KERN_DEBUG "gcblock: NULL\n");
}
if (list_empty(&c->clean_list)) {
printk(KERN_DEBUG "clean_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->clean_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "clean_list: %08x\n", jeb->offset);
}
}
if (list_empty(&c->dirty_list)) {
printk(KERN_DEBUG "dirty_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->dirty_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "dirty_list: %08x\n", jeb->offset);
}
}
if (list_empty(&c->erasable_list)) {
printk(KERN_DEBUG "erasable_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->erasable_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "erasable_list: %08x\n", jeb->offset);
}
}
if (list_empty(&c->erasing_list)) {
printk(KERN_DEBUG "erasing_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->erasing_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "erasing_list: %08x\n", jeb->offset);
}
}
if (list_empty(&c->erase_pending_list)) {
printk(KERN_DEBUG "erase_pending_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->erase_pending_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "erase_pending_list: %08x\n", jeb->offset);
}
}
if (list_empty(&c->erasable_pending_wbuf_list)) {
printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->erasable_pending_wbuf_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "erase_pending_wbuf_list: %08x\n", jeb->offset);
}
}
if (list_empty(&c->free_list)) {
printk(KERN_DEBUG "free_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->free_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "free_list: %08x\n", jeb->offset);
}
}
if (list_empty(&c->bad_list)) {
printk(KERN_DEBUG "bad_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->bad_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "bad_list: %08x\n", jeb->offset);
}
}
if (list_empty(&c->bad_used_list)) {
printk(KERN_DEBUG "bad_used_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->bad_used_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "bad_used_list: %08x\n", jeb->offset);
}
}
#endif /* CONFIG_JFFS2_FS_DEBUG */
spin_unlock_bh(&c->erase_completion_lock); spin_unlock_bh(&c->erase_completion_lock);
return 0; return 0;
} }
...@@ -275,9 +138,9 @@ void jffs2_read_inode (struct inode *inode) ...@@ -275,9 +138,9 @@ void jffs2_read_inode (struct inode *inode)
if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { if (jffs2_read_dnode(c, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) {
/* Eep */ /* Eep */
printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino);
up(&f->sem);
jffs2_do_clear_inode(c, f); jffs2_do_clear_inode(c, f);
make_bad_inode(inode); make_bad_inode(inode);
up(&f->sem);
return; return;
} }
...@@ -321,21 +184,24 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) ...@@ -321,21 +184,24 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data)
void jffs2_write_super (struct super_block *sb) void jffs2_write_super (struct super_block *sb)
{ {
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
lock_kernel();
sb->s_dirt = 0; sb->s_dirt = 0;
if (sb->s_flags & MS_RDONLY) { if (sb->s_flags & MS_RDONLY)
unlock_kernel();
return; return;
}
D1(printk("jffs2_write_super(): flush_wbuf before gc-trigger\n")); D1(printk(KERN_DEBUG "jffs2_write_super(): flush_wbuf before gc-trigger\n"));
jffs2_flush_wbuf(c, 2);
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); jffs2_mark_erased_blocks(c);
unlock_kernel(); /* 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.
} }
...@@ -400,33 +266,61 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) ...@@ -400,33 +266,61 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
{ {
struct jffs2_sb_info *c; struct jffs2_sb_info *c;
struct inode *root_i; struct inode *root_i;
int ret;
c = JFFS2_SB_INFO(sb); c = JFFS2_SB_INFO(sb);
c->sector_size = c->mtd->erasesize; c->sector_size = c->mtd->erasesize;
c->flash_size = c->mtd->size; c->flash_size = c->mtd->size;
#if 0
if (c->sector_size < 0x10000) { if (c->sector_size < 0x10000) {
printk(KERN_INFO "jffs2: Erase block size too small (%dKiB). Using 64KiB instead\n", printk(KERN_INFO "jffs2: Erase block size too small (%dKiB). Using 64KiB instead\n",
c->sector_size / 1024); c->sector_size / 1024);
c->sector_size = 0x10000; c->sector_size = 0x10000;
} }
#endif
if (c->flash_size < 5*c->sector_size) { if (c->flash_size < 5*c->sector_size) {
printk(KERN_ERR "jffs2: Too few erase blocks (%d)\n", printk(KERN_ERR "jffs2: Too few erase blocks (%d)\n",
c->flash_size / c->sector_size); c->flash_size / c->sector_size);
return -EINVAL; return -EINVAL;
} }
c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
/* Jrn -- stick alignment for weird 8-byte-page flash here */
if (jffs2_cleanmarker_oob(c)) {
/* Cleanmarker is out-of-band, so inline size zero */
c->cleanmarker_size = 0;
}
if (c->mtd->type == MTD_NANDFLASH) { if (c->mtd->type == MTD_NANDFLASH) {
/* Initialise write buffer */ /* Initialise write buffer */
c->wbuf_pagesize = c->mtd->oobblock; c->wbuf_pagesize = c->mtd->oobblock;
c->wbuf_ofs = 0xFFFFFFFF; c->wbuf_ofs = 0xFFFFFFFF;
c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
if (!c->wbuf) if (!c->wbuf)
goto out_mtd; return -ENOMEM;
/* Initialize process for timed wbuf flush */
INIT_TQUEUE(&c->wbuf_task,(void*) jffs2_wbuf_process, (void *)c);
/* Initialize timer for timed wbuf flush */
init_timer(&c->wbuf_timer);
c->wbuf_timer.function = jffs2_wbuf_timeout;
c->wbuf_timer.data = (unsigned long) c;
} }
if (jffs2_do_mount_fs(c)) c->inocache_list = kmalloc(INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
goto out_mtd; if (!c->inocache_list) {
ret = -ENOMEM;
goto out_wbuf;
}
memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *));
if ((ret = jffs2_do_mount_fs(c)))
goto out_inohash;
ret = -EINVAL;
D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n")); D1(printk(KERN_DEBUG "jffs2_do_fill_super(): Getting root inode\n"));
root_i = iget(sb, 1); root_i = iget(sb, 1);
...@@ -456,6 +350,10 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) ...@@ -456,6 +350,10 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent)
jffs2_free_ino_caches(c); jffs2_free_ino_caches(c);
jffs2_free_raw_node_refs(c); jffs2_free_raw_node_refs(c);
kfree(c->blocks); kfree(c->blocks);
out_mtd: out_inohash:
return -EINVAL; kfree(c->inocache_list);
out_wbuf:
if (c->wbuf)
kfree(c->wbuf);
return ret;
} }
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: gc.c,v 1.74 2002/05/20 14:56:38 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: gc.c,v 1.68 2002/03/08 15:11:24 dwmw2 Exp $
* *
*/ */
...@@ -65,14 +41,21 @@ static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c) ...@@ -65,14 +41,21 @@ static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c)
/* Pick an eraseblock to garbage collect next. This is where we'll /* Pick an eraseblock to garbage collect next. This is where we'll
put the clever wear-levelling algorithms. Eventually. */ put the clever wear-levelling algorithms. Eventually. */
/* We possibly want to favour the dirtier blocks more when the
number of free blocks is low. */
if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > JFFS2_RESERVED_BLOCKS_GCBAD) { if (!list_empty(&c->bad_used_list) && c->nr_free_blocks > JFFS2_RESERVED_BLOCKS_GCBAD) {
D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n")); D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n"));
nextlist = &c->bad_used_list; nextlist = &c->bad_used_list;
} else if (n < 100 && !list_empty(&c->erasable_list)) { } else if (n < 50 && !list_empty(&c->erasable_list)) {
/* Note that most of them will have gone directly to be erased.
So don't favour the erasable_list _too_ much. */
D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n")); D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n"));
nextlist = &c->erasable_list; nextlist = &c->erasable_list;
} else if (n < 110 && !list_empty(&c->very_dirty_list)) {
/* Most of the time, pick one off the very_dirty list */
D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next\n"));
nextlist = &c->very_dirty_list;
} else if (n < 126 && !list_empty(&c->dirty_list)) { } else if (n < 126 && !list_empty(&c->dirty_list)) {
/* Most of the time, pick one off the dirty list */
D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n")); D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next\n"));
nextlist = &c->dirty_list; nextlist = &c->dirty_list;
} else if (!list_empty(&c->clean_list)) { } else if (!list_empty(&c->clean_list)) {
...@@ -82,12 +65,15 @@ static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c) ...@@ -82,12 +65,15 @@ static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c)
D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n")); D1(printk(KERN_DEBUG "Picking block from dirty_list to GC next (clean_list was empty)\n"));
nextlist = &c->dirty_list; nextlist = &c->dirty_list;
} else if (!list_empty(&c->very_dirty_list)) {
D1(printk(KERN_DEBUG "Picking block from very_dirty_list to GC next (clean_list and dirty_list were empty)\n"));
nextlist = &c->very_dirty_list;
} else if (!list_empty(&c->erasable_list)) { } else if (!list_empty(&c->erasable_list)) {
D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and dirty_list were empty)\n")); D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next (clean_list and {very_,}dirty_list were empty)\n"));
nextlist = &c->erasable_list; nextlist = &c->erasable_list;
} else { } else {
/* Eep. Both were empty */ /* Eep. All were empty */
printk(KERN_NOTICE "jffs2: No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n"); printk(KERN_NOTICE "jffs2: No clean, dirty _or_ erasable blocks to GC from! Where are they all?\n");
return NULL; return NULL;
} }
...@@ -100,6 +86,8 @@ static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c) ...@@ -100,6 +86,8 @@ static struct jffs2_eraseblock *jffs2_find_gc_block(struct jffs2_sb_info *c)
printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset); printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset);
BUG(); BUG();
} }
D1(jffs2_dump_block_lists(c));
return ret; return ret;
} }
...@@ -138,7 +126,9 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) ...@@ -138,7 +126,9 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c)
return -EIO; return -EIO;
} }
D1(printk(KERN_DEBUG "garbage collect from block at phys 0x%08x\n", jeb->offset)); D1(printk(KERN_DEBUG "GC from block %08x, used_size %08x, dirty_size %08x, free_size %08x\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size));
D1(if (c->nextblock)
printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size));
if (!jeb->used_size) if (!jeb->used_size)
goto eraseit; goto eraseit;
...@@ -606,9 +596,21 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ...@@ -606,9 +596,21 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras
jffs2_mark_node_obsolete(c, f->metadata->raw); jffs2_mark_node_obsolete(c, f->metadata->raw);
jffs2_free_full_dnode(f->metadata); jffs2_free_full_dnode(f->metadata);
f->metadata = NULL; f->metadata = NULL;
return 0;
} }
return 0;
} }
/*
* We should only get here in the case where the node we are
* replacing had more than one frag, so we kept the same version
* number as before. (Except in case of error -- see 'goto fill;'
* above.)
*/
D1(if(unlikely(fn->frags <= 1)) {
printk(KERN_WARNING "jffs2_garbage_collect_hole: Replacing fn with %d frag(s) but new ver %d != highest_version %d of ino #%d\n",
fn->frags, ri.version, f->highest_version, ri.ino);
});
for (frag = f->fraglist; frag; frag = frag->next) { for (frag = f->fraglist; frag; frag = frag->next) {
if (frag->ofs > fn->size + fn->ofs) if (frag->ofs > fn->size + fn->ofs)
break; break;
...@@ -760,7 +762,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era ...@@ -760,7 +762,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era
kunmap(pg); kunmap(pg);
/* XXX: Does the page get freed automatically? */ /* XXX: Does the page get freed automatically? */
/* AAA: Judging by the unmount getting stuck in __wait_on_page_locked, nope. */ /* AAA: Judging by the unmount getting stuck in __wait_on_page, nope. */
page_cache_release(pg); page_cache_release(pg);
return ret; return ret;
} }
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: ioctl.c,v 1.6 2002/05/20 14:56:38 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: ioctl.c,v 1.5 2001/03/15 15:38:24 dwmw2 Exp $
* *
*/ */
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: malloc.c,v 1.22 2002/05/20 14:56:38 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: malloc.c,v 1.21 2002/03/12 17:36:55 dwmw2 Exp $
* *
*/ */
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: nodelist.c,v 1.47 2002/06/26 01:25:30 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: nodelist.c,v 1.42 2002/03/11 11:17:29 dwmw2 Exp $
* *
*/ */
...@@ -69,7 +45,7 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new ...@@ -69,7 +45,7 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new
*prev = new; *prev = new;
out: out:
D1(while(*list) { D2(while(*list) {
printk(KERN_DEBUG "Dirent \"%s\" (hash 0x%08x, ino #%u\n", (*list)->name, (*list)->nhash, (*list)->ino); printk(KERN_DEBUG "Dirent \"%s\" (hash 0x%08x, ino #%u\n", (*list)->name, (*list)->nhash, (*list)->ino);
list = &(*list)->next; list = &(*list)->next;
}); });
...@@ -311,9 +287,6 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, int ino) ...@@ -311,9 +287,6 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, int ino)
D2(printk(KERN_DEBUG "jffs2_get_ino_cache(): ino %u\n", ino)); D2(printk(KERN_DEBUG "jffs2_get_ino_cache(): ino %u\n", ino));
spin_lock (&c->inocache_lock); spin_lock (&c->inocache_lock);
if (c->inocache_last && c->inocache_last->ino == ino) {
ret = c->inocache_last;
} else {
ret = c->inocache_list[ino % INOCACHE_HASHSIZE]; ret = c->inocache_list[ino % INOCACHE_HASHSIZE];
while (ret && ret->ino < ino) { while (ret && ret->ino < ino) {
ret = ret->next; ret = ret->next;
...@@ -321,7 +294,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, int ino) ...@@ -321,7 +294,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, int ino)
if (ret && ret->ino != ino) if (ret && ret->ino != ino)
ret = NULL; ret = NULL;
}
spin_unlock(&c->inocache_lock); spin_unlock(&c->inocache_lock);
D2(printk(KERN_DEBUG "jffs2_get_ino_cache found %p for ino %u\n", ret, ino)); D2(printk(KERN_DEBUG "jffs2_get_ino_cache found %p for ino %u\n", ret, ino));
...@@ -342,8 +315,6 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new ...@@ -342,8 +315,6 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new
new->next = *prev; new->next = *prev;
*prev = new; *prev = new;
c->inocache_last = new;
spin_unlock(&c->inocache_lock); spin_unlock(&c->inocache_lock);
} }
...@@ -361,8 +332,6 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) ...@@ -361,8 +332,6 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old)
if ((*prev) == old) { if ((*prev) == old) {
*prev = old->next; *prev = old->next;
} }
if (c->inocache_last == old)
c->inocache_last = NULL;
spin_unlock(&c->inocache_lock); spin_unlock(&c->inocache_lock);
} }
...@@ -382,7 +351,6 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c) ...@@ -382,7 +351,6 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c)
} }
c->inocache_list[i] = NULL; c->inocache_list[i] = NULL;
} }
c->inocache_last = NULL;
} }
void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) void jffs2_free_raw_node_refs(struct jffs2_sb_info *c)
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: nodelist.h,v 1.74 2002/06/26 01:20:43 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: nodelist.h,v 1.68 2002/03/08 11:27:19 dwmw2 Exp $
* *
*/ */
...@@ -117,6 +93,8 @@ struct jffs2_inode_cache { ...@@ -117,6 +93,8 @@ struct jffs2_inode_cache {
int nlink; int nlink;
}; };
#define INOCACHE_HASHSIZE 128
struct jffs2_scan_info { struct jffs2_scan_info {
struct jffs2_full_dirent *dents; struct jffs2_full_dirent *dents;
struct jffs2_tmp_dnode_info *tmpnodes; struct jffs2_tmp_dnode_info *tmpnodes;
...@@ -172,7 +150,6 @@ struct jffs2_node_frag ...@@ -172,7 +150,6 @@ struct jffs2_node_frag
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 */
uint32_t node_ofs; /* offset within the physical node */
}; };
struct jffs2_eraseblock struct jffs2_eraseblock
...@@ -240,6 +217,9 @@ struct jffs2_eraseblock ...@@ -240,6 +217,9 @@ struct jffs2_eraseblock
#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 */
/* How much dirty space before it goes on the very_dirty_list */
#define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2))
#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)
...@@ -271,6 +251,7 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * ...@@ -271,6 +251,7 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *
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, uint32_t len, int dirty);
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);
/* write.c */ /* write.c */
int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri);
...@@ -331,6 +312,7 @@ int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, ...@@ -331,6 +312,7 @@ int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in,
/* scan.c */ /* scan.c */
int jffs2_scan_medium(struct jffs2_sb_info *c); int jffs2_scan_medium(struct jffs2_sb_info *c);
void jffs2_rotate_lists(struct jffs2_sb_info *c);
/* build.c */ /* build.c */
int jffs2_do_mount_fs(struct jffs2_sb_info *c); int jffs2_do_mount_fs(struct jffs2_sb_info *c);
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: nodemgmt.c,v 1.70 2002/07/02 22:48:24 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: nodemgmt.c,v 1.63 2002/03/08 14:54:09 dwmw2 Exp $
* *
*/ */
...@@ -158,9 +134,15 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ui ...@@ -158,9 +134,15 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ui
c->free_size -= jeb->free_size; c->free_size -= jeb->free_size;
jeb->dirty_size += jeb->free_size; jeb->dirty_size += jeb->free_size;
jeb->free_size = 0; jeb->free_size = 0;
if (VERYDIRTY(c, jeb->dirty_size)) {
D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size));
list_add_tail(&jeb->list, &c->very_dirty_list);
} else {
D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n",
jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size));
list_add_tail(&jeb->list, &c->dirty_list); list_add_tail(&jeb->list, &c->dirty_list);
}
c->nextblock = jeb = NULL; c->nextblock = jeb = NULL;
} }
...@@ -180,6 +162,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ui ...@@ -180,6 +162,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ui
list_del(&ejeb->list); list_del(&ejeb->list);
list_add_tail(&ejeb->list, &c->erase_pending_list); list_add_tail(&ejeb->list, &c->erase_pending_list);
c->nr_erasing_blocks++; c->nr_erasing_blocks++;
jffs2_erase_pending_trigger(c);
D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n", D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n",
ejeb->offset)); ejeb->offset));
} }
...@@ -232,10 +215,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ui ...@@ -232,10 +215,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ui
c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list); c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list);
c->nr_free_blocks--; c->nr_free_blocks--;
/* On NAND free_size == sector_size, cleanmarker is in spare area !*/ if (jeb->free_size != c->sector_size - c->cleanmarker_size) {
if (jeb->free_size != c->sector_size -
(jffs2_cleanmarker_oob(c)) ? 0 : sizeof(struct jffs2_unknown_node)) {
printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size);
goto restart; goto restart;
} }
...@@ -420,9 +400,20 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ...@@ -420,9 +400,20 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
BUG(); BUG();
} }
} else { } else {
if (jiffies & 127) {
/* Most of the time, we just erase it immediately. Otherwise we
spend ages scanning it on mount, etc. */
D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n"));
list_add_tail(&jeb->list, &c->erase_pending_list);
c->nr_erasing_blocks++;
jffs2_erase_pending_trigger(c);
} else {
/* Sometimes, however, we leave it elsewhere so it doesn't get
immediately reused, and we spread the load a bit. */
D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); D1(printk(KERN_DEBUG "...and adding to erasable_list\n"));
list_add_tail(&jeb->list, &c->erasable_list); list_add_tail(&jeb->list, &c->erasable_list);
} }
}
D1(printk(KERN_DEBUG "Done OK\n")); D1(printk(KERN_DEBUG "Done OK\n"));
} else if (jeb == c->gcblock) { } else if (jeb == c->gcblock) {
D2(printk(KERN_DEBUG "Not moving gcblock 0x%08x to dirty_list\n", jeb->offset)); D2(printk(KERN_DEBUG "Not moving gcblock 0x%08x to dirty_list\n", jeb->offset));
...@@ -431,6 +422,12 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ...@@ -431,6 +422,12 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
list_del(&jeb->list); list_del(&jeb->list);
D1(printk(KERN_DEBUG "...and adding to dirty_list\n")); D1(printk(KERN_DEBUG "...and adding to dirty_list\n"));
list_add_tail(&jeb->list, &c->dirty_list); list_add_tail(&jeb->list, &c->dirty_list);
} else if (VERYDIRTY(c, jeb->dirty_size) &&
!VERYDIRTY(c, jeb->dirty_size - ref->totlen)) {
D1(printk(KERN_DEBUG "Eraseblock at 0x%08x is now very dirty. Removing from dirty list...\n", jeb->offset));
list_del(&jeb->list);
D1(printk(KERN_DEBUG "...and adding to very_dirty_list\n"));
list_add_tail(&jeb->list, &c->very_dirty_list);
} }
spin_unlock_bh(&c->erase_completion_lock); spin_unlock_bh(&c->erase_completion_lock);
...@@ -469,3 +466,129 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ...@@ -469,3 +466,129 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
return; return;
} }
} }
#if CONFIG_JFFS2_FS_DEBUG > 0
void jffs2_dump_block_lists(struct jffs2_sb_info *c)
{
printk(KERN_DEBUG "jffs2_dump_block_lists:\n");
printk(KERN_DEBUG "flash_size: %08x\n", c->flash_size);
printk(KERN_DEBUG "used_size: %08x\n", c->used_size);
printk(KERN_DEBUG "dirty_size: %08x\n", c->dirty_size);
printk(KERN_DEBUG "free_size: %08x\n", c->free_size);
printk(KERN_DEBUG "erasing_size: %08x\n", c->erasing_size);
printk(KERN_DEBUG "bad_size: %08x\n", c->bad_size);
printk(KERN_DEBUG "sector_size: %08x\n", c->sector_size);
printk(KERN_DEBUG "jffs2_reserved_blocks size: %08x\n",c->sector_size * JFFS2_RESERVED_BLOCKS_WRITE);
if (c->nextblock) {
printk(KERN_DEBUG "nextblock: %08x (used %08x, dirty %08x, free %08x)\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->free_size);
} else {
printk(KERN_DEBUG "nextblock: NULL\n");
}
if (c->gcblock) {
printk(KERN_DEBUG "gcblock: %08x (used %08x, dirty %08x, free %08x)\n", c->gcblock->offset, c->gcblock->used_size, c->gcblock->dirty_size, c->gcblock->free_size);
} else {
printk(KERN_DEBUG "gcblock: NULL\n");
}
if (list_empty(&c->clean_list)) {
printk(KERN_DEBUG "clean_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->clean_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "clean_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->very_dirty_list)) {
printk(KERN_DEBUG "very_dirty_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->very_dirty_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "very_dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->dirty_list)) {
printk(KERN_DEBUG "dirty_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->dirty_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "dirty_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->erasable_list)) {
printk(KERN_DEBUG "erasable_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->erasable_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "erasable_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->erasing_list)) {
printk(KERN_DEBUG "erasing_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->erasing_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "erasing_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->erase_pending_list)) {
printk(KERN_DEBUG "erase_pending_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->erase_pending_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "erase_pending_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->erasable_pending_wbuf_list)) {
printk(KERN_DEBUG "erasable_pending_wbuf_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->erasable_pending_wbuf_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "erase_pending_wbuf_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->free_list)) {
printk(KERN_DEBUG "free_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->free_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "free_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->bad_list)) {
printk(KERN_DEBUG "bad_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->bad_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "bad_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
if (list_empty(&c->bad_used_list)) {
printk(KERN_DEBUG "bad_used_list: empty\n");
} else {
struct list_head *this;
list_for_each(this, &c->bad_used_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
printk(KERN_DEBUG "bad_used_list: %08x (used %08x, dirty %08x, free %08x)\n", jeb->offset, jeb->used_size, jeb->dirty_size, jeb->free_size);
}
}
}
#endif /* CONFIG_JFFS2_FS_DEBUG */
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: os-linux.h,v 1.19 2002/05/20 14:56:38 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: os-linux.h,v 1.16 2002/03/17 10:18:42 dwmw2 Exp $
* *
*/ */
...@@ -101,6 +77,8 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) ...@@ -101,6 +77,8 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
#define jffs2_nand_read_failcnt(c,jeb) do { ; } while(0) #define jffs2_nand_read_failcnt(c,jeb) do { ; } while(0)
#define jffs2_write_nand_badblock(c,jeb) do { ; } while(0) #define jffs2_write_nand_badblock(c,jeb) do { ; } while(0)
#define jffs2_flash_writev jffs2_flash_direct_writev #define jffs2_flash_writev jffs2_flash_direct_writev
#define jffs2_wbuf_timeout NULL
#define jffs2_wbuf_process NULL
#else /* NAND support present */ #else /* NAND support present */
...@@ -119,6 +97,8 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, ...@@ -119,6 +97,8 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb,
int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
void jffs2_wbuf_timeout(unsigned long data);
void jffs2_wbuf_process(void *data);
#endif /* NAND */ #endif /* NAND */
/* background.c */ /* background.c */
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: pushpull.h,v 1.8 2002/05/20 14:56:38 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: pushpull.h,v 1.7 2002/03/06 12:37:08 dwmw2 Exp $
* *
*/ */
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: read.c,v 1.23 2002/05/20 14:56:38 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: read.c,v 1.22 2002/03/02 22:08:27 dwmw2 Exp $
* *
*/ */
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: readinode.c,v 1.73 2002/05/20 14:56:38 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: readinode.c,v 1.71 2002/03/06 12:25:59 dwmw2 Exp $
* *
*/ */
...@@ -337,6 +313,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, ...@@ -337,6 +313,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %ld of %d bytes read\n", printk(KERN_NOTICE "MTD read in jffs2_do_read_inode() failed: Returned %d, %ld of %d bytes read\n",
ret, (long)retlen, sizeof(*latest_node)); ret, (long)retlen, sizeof(*latest_node));
/* FIXME: If this fails, there seems to be a memory leak. Find it. */ /* FIXME: If this fails, there seems to be a memory leak. Find it. */
up(&f->sem);
jffs2_do_clear_inode(c, f); jffs2_do_clear_inode(c, f);
return ret?ret:-EIO; return ret?ret:-EIO;
} }
...@@ -344,6 +321,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, ...@@ -344,6 +321,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
crc = crc32(0, latest_node, sizeof(*latest_node)-8); crc = crc32(0, latest_node, sizeof(*latest_node)-8);
if (crc != latest_node->node_crc) { if (crc != latest_node->node_crc) {
printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", ino, fn->raw->flash_offset & ~3); printk(KERN_NOTICE "CRC failed for read_inode of inode %u at physical location 0x%x\n", ino, fn->raw->flash_offset & ~3);
up(&f->sem);
jffs2_do_clear_inode(c, f); jffs2_do_clear_inode(c, f);
return -EIO; return -EIO;
} }
...@@ -378,11 +356,13 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, ...@@ -378,11 +356,13 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
kept as the metadata node */ kept as the metadata node */
if (f->metadata) { if (f->metadata) {
printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", ino, latest_node->mode); printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had metadata node\n", ino, latest_node->mode);
up(&f->sem);
jffs2_do_clear_inode(c, f); jffs2_do_clear_inode(c, f);
return -EIO; return -EIO;
} }
if (!f->fraglist) { if (!f->fraglist) {
printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", ino, latest_node->mode); printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o has no fragments\n", ino, latest_node->mode);
up(&f->sem);
jffs2_do_clear_inode(c, f); jffs2_do_clear_inode(c, f);
return -EIO; return -EIO;
} }
...@@ -390,6 +370,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, ...@@ -390,6 +370,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
if (f->fraglist->next) { if (f->fraglist->next) {
printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had more than one node\n", ino, latest_node->mode); printk(KERN_WARNING "Argh. Special inode #%u with mode 0%o had more than one node\n", ino, latest_node->mode);
/* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */
up(&f->sem);
jffs2_do_clear_inode(c, f); jffs2_do_clear_inode(c, f);
return -EIO; return -EIO;
} }
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: scan.c,v 1.79 2002/07/25 20:48:51 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: scan.c,v 1.69 2002/03/08 11:03:23 dwmw2 Exp $
* *
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -62,7 +38,6 @@ ...@@ -62,7 +38,6 @@
} while(0) } while(0)
static uint32_t pseudo_random; static uint32_t pseudo_random;
static void jffs2_rotate_lists(struct jffs2_sb_info *c);
static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
...@@ -141,14 +116,24 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) ...@@ -141,14 +116,24 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
not the one with most free space. not the one with most free space.
*/ */
if (jeb->free_size > 2*sizeof(struct jffs2_raw_inode) && if (jeb->free_size > 2*sizeof(struct jffs2_raw_inode) &&
(jffs2_can_mark_obsolete(c) || jeb->free_size > c->wbuf_pagesize) &&
(!c->nextblock || c->nextblock->free_size < jeb->free_size)) { (!c->nextblock || c->nextblock->free_size < jeb->free_size)) {
/* Better candidate for the next writes to go to */ /* Better candidate for the next writes to go to */
if (c->nextblock) if (c->nextblock) {
if (VERYDIRTY(c, c->nextblock->dirty_size)) {
list_add(&c->nextblock->list, &c->very_dirty_list);
} else {
list_add(&c->nextblock->list, &c->dirty_list); list_add(&c->nextblock->list, &c->dirty_list);
}
}
c->nextblock = jeb; c->nextblock = jeb;
} else {
if (VERYDIRTY(c, jeb->dirty_size)) {
list_add(&jeb->list, &c->very_dirty_list);
} else { } else {
list_add(&jeb->list, &c->dirty_list); list_add(&jeb->list, &c->dirty_list);
} }
}
break; break;
case BLK_STATE_ALLDIRTY: case BLK_STATE_ALLDIRTY:
...@@ -167,14 +152,26 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) ...@@ -167,14 +152,26 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
bad_blocks++; bad_blocks++;
break; break;
default: default:
printk("jffs2_scan_medium(): unknown block state\n"); printk(KERN_WARNING "jffs2_scan_medium(): unknown block state\n");
BUG(); BUG();
} }
} }
/* Rotate the lists by some number to ensure wear levelling */ if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) {
jffs2_rotate_lists(c); /* If we're going to start writing into a block which already
contains data, and the end of the data isn't page-aligned,
skip a little and align it. */
uint32_t skip = c->nextblock->free_size & (c->wbuf_pagesize-1);
D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n",
skip));
c->nextblock->dirty_size += skip;
c->dirty_size += skip;
c->nextblock->free_size -= skip;
c->free_size -= skip;
}
if (c->nr_erasing_blocks) { if (c->nr_erasing_blocks) {
if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { if ( !c->used_size && ((empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) {
printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n");
...@@ -246,6 +243,8 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo ...@@ -246,6 +243,8 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
size_t retlen; size_t retlen;
ACCT_PARANOIA_CHECK(jeb); ACCT_PARANOIA_CHECK(jeb);
cond_resched();
if (ofs & 3) { if (ofs & 3) {
printk(KERN_WARNING "Eep. ofs 0x%08x not word-aligned!\n", ofs); printk(KERN_WARNING "Eep. ofs 0x%08x not word-aligned!\n", ofs);
ofs = (ofs+3)&~3; ofs = (ofs+3)&~3;
...@@ -323,6 +322,16 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo ...@@ -323,6 +322,16 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
continue; continue;
} }
if (ofs + node.totlen > jeb->offset + c->sector_size) {
/* Eep. Node goes over the end of the erase block. */
printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n",
ofs, node.totlen);
printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n");
DIRTY_SPACE(4);
ofs += 4;
continue;
}
if (!(node.nodetype & JFFS2_NODE_ACCURATE)) { if (!(node.nodetype & JFFS2_NODE_ACCURATE)) {
/* Wheee. This is an obsoleted node */ /* Wheee. This is an obsoleted node */
D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs));
...@@ -343,9 +352,9 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo ...@@ -343,9 +352,9 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
break; break;
case JFFS2_NODETYPE_CLEANMARKER: case JFFS2_NODETYPE_CLEANMARKER:
if (node.totlen != sizeof(struct jffs2_unknown_node)) { if (node.totlen != c->cleanmarker_size) {
printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n",
ofs, node.totlen, sizeof(struct jffs2_unknown_node)); ofs, node.totlen, c->cleanmarker_size);
DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node)));
} else if (jeb->first_node) { } else if (jeb->first_node) {
printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset);
...@@ -369,6 +378,11 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo ...@@ -369,6 +378,11 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
ofs += PAD(sizeof(struct jffs2_unknown_node)); ofs += PAD(sizeof(struct jffs2_unknown_node));
break; break;
case JFFS2_NODETYPE_PADDING:
DIRTY_SPACE(PAD(node.totlen));
ofs += PAD(node.totlen);
break;
default: default:
switch (node.nodetype & JFFS2_COMPAT_MASK) { switch (node.nodetype & JFFS2_COMPAT_MASK) {
case JFFS2_FEATURE_ROCOMPAT: case JFFS2_FEATURE_ROCOMPAT:
...@@ -378,7 +392,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo ...@@ -378,7 +392,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo
return -EROFS; return -EROFS;
DIRTY_SPACE(PAD(node.totlen)); DIRTY_SPACE(PAD(node.totlen));
ofs += PAD(node.totlen); ofs += PAD(node.totlen);
continue; break;
case JFFS2_FEATURE_INCOMPAT: case JFFS2_FEATURE_INCOMPAT:
printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs); printk(KERN_NOTICE "Incompatible feature node (0x%04x) found at offset 0x%08x\n", node.nodetype, ofs);
...@@ -650,7 +664,11 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc ...@@ -650,7 +664,11 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc
tn->version = ri.version; tn->version = ri.version;
USED_SPACE(PAD(ri.totlen)); USED_SPACE(PAD(ri.totlen));
jffs2_add_tn_to_list(tn, &ic->scan->tmpnodes);
/* No need to scan from the beginning of the list again.
We can start from tn_list instead (Thanks Jocke) */
jffs2_add_tn_to_list(tn, tn_list);
/* Make sure the one we just added is the _last_ in the list /* Make sure the one we just added is the _last_ in the list
with this version number, so the older ones get obsoleted */ with this version number, so the older ones get obsoleted */
while (tn->next && tn->next->version == tn->version) { while (tn->next && tn->next->version == tn->version) {
...@@ -813,22 +831,84 @@ static void rotate_list(struct list_head *head, uint32_t count) ...@@ -813,22 +831,84 @@ static void rotate_list(struct list_head *head, uint32_t count)
list_add(head, n); list_add(head, n);
} }
static void jffs2_rotate_lists(struct jffs2_sb_info *c) void jffs2_rotate_lists(struct jffs2_sb_info *c)
{ {
uint32_t x; uint32_t x;
uint32_t rotateby;
x = count_list(&c->clean_list); x = count_list(&c->clean_list);
if (x) if (x) {
rotate_list((&c->clean_list), pseudo_random % x); rotateby = pseudo_random % x;
D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby));
rotate_list((&c->clean_list), rotateby);
D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n",
list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset));
} else {
D1(printk(KERN_DEBUG "Not rotating empty clean_list\n"));
}
x = count_list(&c->very_dirty_list);
if (x) {
rotateby = pseudo_random % x;
D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby));
rotate_list((&c->very_dirty_list), rotateby);
D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n",
list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset));
} else {
D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n"));
}
x = count_list(&c->dirty_list); x = count_list(&c->dirty_list);
if (x) if (x) {
rotate_list((&c->dirty_list), pseudo_random % x); rotateby = pseudo_random % x;
D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby));
rotate_list((&c->dirty_list), rotateby);
D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n",
list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset));
} else {
D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n"));
}
if (c->nr_erasing_blocks) x = count_list(&c->erasable_list);
rotate_list((&c->erase_pending_list), pseudo_random % c->nr_erasing_blocks); if (x) {
rotateby = pseudo_random % x;
D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby));
if (c->nr_free_blocks) /* Not that it should ever be zero */ rotate_list((&c->erasable_list), rotateby);
rotate_list((&c->free_list), pseudo_random % c->nr_free_blocks);
D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n",
list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset));
} else {
D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n"));
}
if (c->nr_erasing_blocks) {
rotateby = pseudo_random % c->nr_erasing_blocks;
D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby));
rotate_list((&c->erase_pending_list), rotateby);
D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n",
list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset));
} else {
D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n"));
}
if (c->nr_free_blocks) {
rotateby = pseudo_random % c->nr_free_blocks;
D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby));
rotate_list((&c->free_list), rotateby);
D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n",
list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset));
} else {
D1(printk(KERN_DEBUG "Not rotating empty free_list\n"));
}
} }
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: super.c,v 1.73 2002/07/23 17:00:45 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: super.c,v 1.64 2002/03/17 10:18:42 dwmw2 Exp $
* *
*/ */
...@@ -43,12 +19,12 @@ ...@@ -43,12 +19,12 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/namei.h>
#include <linux/jffs2.h> #include <linux/jffs2.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/mtd/mtd.h> #include <linux/mtd/mtd.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/namei.h>
#include "nodelist.h" #include "nodelist.h"
void jffs2_put_super (struct super_block *); void jffs2_put_super (struct super_block *);
...@@ -83,14 +59,14 @@ static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long f ...@@ -83,14 +59,14 @@ static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long f
static struct super_operations jffs2_super_operations = static struct super_operations jffs2_super_operations =
{ {
alloc_inode: jffs2_alloc_inode, .alloc_inode = jffs2_alloc_inode,
destroy_inode: jffs2_destroy_inode, .destroy_inode =jffs2_destroy_inode,
read_inode: jffs2_read_inode, .read_inode = jffs2_read_inode,
put_super: jffs2_put_super, .put_super = jffs2_put_super,
write_super: jffs2_write_super, .write_super = jffs2_write_super,
statfs: jffs2_statfs, .statfs = jffs2_statfs,
remount_fs: jffs2_remount_fs, .remount_fs = jffs2_remount_fs,
clear_inode: jffs2_clear_inode .clear_inode = jffs2_clear_inode
}; };
static int jffs2_sb_compare(struct super_block *sb, void *data) static int jffs2_sb_compare(struct super_block *sb, void *data)
...@@ -101,11 +77,11 @@ static int jffs2_sb_compare(struct super_block *sb, void *data) ...@@ -101,11 +77,11 @@ static int jffs2_sb_compare(struct super_block *sb, void *data)
/* The superblocks are considered to be equivalent if the underlying MTD /* The superblocks are considered to be equivalent if the underlying MTD
device is the same one */ device is the same one */
if (c->mtd == p->mtd) { if (c->mtd == p->mtd) {
D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", mtd->index, mtd->name)); D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name));
return 1; return 1;
} else { } else {
D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n", D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n",
c->mtd->index, c->mtd->name, mtd->index, mtd->name)); c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name));
return 0; return 0;
} }
} }
...@@ -282,10 +258,15 @@ void jffs2_put_super (struct super_block *sb) ...@@ -282,10 +258,15 @@ void jffs2_put_super (struct super_block *sb)
if (!(sb->s_flags & MS_RDONLY)) if (!(sb->s_flags & MS_RDONLY))
jffs2_stop_garbage_collect_thread(c); jffs2_stop_garbage_collect_thread(c);
down(&c->alloc_sem);
jffs2_flush_wbuf(c, 1); jffs2_flush_wbuf(c, 1);
up(&c->alloc_sem);
jffs2_free_ino_caches(c); jffs2_free_ino_caches(c);
jffs2_free_raw_node_refs(c); jffs2_free_raw_node_refs(c);
kfree(c->blocks); kfree(c->blocks);
if (c->wbuf)
kfree(c->wbuf);
kfree(c->inocache_list);
if (c->mtd->sync) if (c->mtd->sync)
c->mtd->sync(c->mtd); c->mtd->sync(c->mtd);
...@@ -301,10 +282,10 @@ static void jffs2_kill_sb(struct super_block *sb) ...@@ -301,10 +282,10 @@ static void jffs2_kill_sb(struct super_block *sb)
} }
static struct file_system_type jffs2_fs_type = { static struct file_system_type jffs2_fs_type = {
owner: THIS_MODULE, .owner = THIS_MODULE,
name: "jffs2", .name = "jffs2",
get_sb: jffs2_get_sb, .get_sb = jffs2_get_sb,
kill_sb: jffs2_kill_sb, .kill_sb = jffs2_kill_sb,
}; };
...@@ -326,18 +307,25 @@ static int __init init_jffs2_fs(void) ...@@ -326,18 +307,25 @@ static int __init init_jffs2_fs(void)
ret = jffs2_zlib_init(); ret = jffs2_zlib_init();
if (ret) { if (ret) {
printk(KERN_ERR "JFFS2 error: Failed to initialise zlib workspaces\n"); printk(KERN_ERR "JFFS2 error: Failed to initialise zlib workspaces\n");
return ret; goto out;
} }
ret = jffs2_create_slab_caches(); ret = jffs2_create_slab_caches();
if (ret) { if (ret) {
printk(KERN_ERR "JFFS2 error: Failed to initialise slab caches\n"); printk(KERN_ERR "JFFS2 error: Failed to initialise slab caches\n");
return ret; goto out_zlib;
} }
ret = register_filesystem(&jffs2_fs_type); ret = register_filesystem(&jffs2_fs_type);
if (ret) { if (ret) {
printk(KERN_ERR "JFFS2 error: Failed to register filesystem\n"); printk(KERN_ERR "JFFS2 error: Failed to register filesystem\n");
jffs2_destroy_slab_caches(); goto out_slab;
} }
return 0;
out_slab:
jffs2_destroy_slab_caches();
out_zlib:
jffs2_zlib_exit();
out:
return ret; return ret;
} }
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: symlink.c,v 1.11 2002/07/23 17:00:45 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: symlink.c,v 1.9 2002/01/10 09:29:53 dwmw2 Exp $
* *
*/ */
...@@ -46,9 +22,9 @@ int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); ...@@ -46,9 +22,9 @@ int jffs2_follow_link(struct dentry *dentry, struct nameidata *nd);
struct inode_operations jffs2_symlink_inode_operations = struct inode_operations jffs2_symlink_inode_operations =
{ {
readlink: jffs2_readlink, .readlink = jffs2_readlink,
follow_link: jffs2_follow_link, .follow_link = jffs2_follow_link,
setattr: jffs2_setattr .setattr = jffs2_setattr
}; };
int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen) int jffs2_readlink(struct dentry *dentry, char *buffer, int buflen)
......
...@@ -5,34 +5,10 @@ ...@@ -5,34 +5,10 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
*
* The contents of this file are subject to the Red Hat eCos Public
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: wbuf.c,v 1.7 2002/03/08 11:27:59 dwmw2 Exp $
* *
* $Id: wbuf.c,v 1.12 2002/05/20 14:56:39 dwmw2 Exp $
* -- with the NAND definitions added back pending MTD update for 2.5.
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -51,26 +27,101 @@ ...@@ -51,26 +27,101 @@
#define NAND_JFFS2_OOB8_FSDALEN 2 #define NAND_JFFS2_OOB8_FSDALEN 2
#define NAND_JFFS2_OOB16_FSDALEN 8 #define NAND_JFFS2_OOB16_FSDALEN 8
/* max. erase failures before we mark a block bad */
#define MAX_ERASE_FAILURES 5 #define MAX_ERASE_FAILURES 5
/* two seconds timeout for timed wbuf-flushing */
#define WBUF_FLUSH_TIMEOUT 2 * HZ
static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c) static inline void jffs2_refile_wbuf_blocks(struct jffs2_sb_info *c)
{ {
struct list_head *this, *next; struct list_head *this, *next;
static int n;
if (list_empty(&c->erasable_pending_wbuf_list)) if (list_empty(&c->erasable_pending_wbuf_list))
return; return;
list_for_each_safe(this, next, &c->erasable_pending_wbuf_list) { list_for_each_safe(this, next, &c->erasable_pending_wbuf_list) {
struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list);
D1(printk(KERN_DEBUG "Removing eraseblock at 0x%08x from erasable_pending_wbuf_list...\n", jeb->offset));
list_del(this); list_del(this);
list_add_tail(this, &c->erasable_list); if ((jiffies + (n++)) & 127) {
/* Most of the time, we just erase it immediately. Otherwise we
spend ages scanning it on mount, etc. */
D1(printk(KERN_DEBUG "...and adding to erase_pending_list\n"));
list_add_tail(&jeb->list, &c->erase_pending_list);
c->nr_erasing_blocks++;
jffs2_erase_pending_trigger(c);
} else {
/* Sometimes, however, we leave it elsewhere so it doesn't get
immediately reused, and we spread the load a bit. */
D1(printk(KERN_DEBUG "...and adding to erasable_list\n"));
list_add_tail(&jeb->list, &c->erasable_list);
}
}
}
/*
* Timed flushing of wbuf. If we have no consecutive write to wbuf, within
* the specified time, we flush the contents with padding !
*/
void jffs2_wbuf_timeout (unsigned long data)
{
struct jffs2_sb_info *c = (struct jffs2_sb_info *) data;
/*
* Wake up the flush process, we need process context to have the right
* to sleep on flash write
*/
D1(printk(KERN_DEBUG "jffs2_wbuf_timeout(): timer expired\n"));
schedule_task(&c->wbuf_task);
}
/*
* Process for timed wbuf flush
*
* FIXME What happens, if we have a write failure there ????
*/
void jffs2_wbuf_process (void *data)
{
struct jffs2_sb_info *c = (struct jffs2_sb_info *) data;
D1(printk(KERN_DEBUG "jffs2_wbuf_process() entered\n"));
if (!down_trylock(&c->alloc_sem)) {
D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem got\n"));
if(!c->nextblock || (c->nextblock->free_size < (c->wbuf_pagesize - c->wbuf_len)))
jffs2_flush_wbuf(c, 1); /* pad only */
else
jffs2_flush_wbuf(c, 2); /* pad and adjust nextblock */
up(&c->alloc_sem);
} else {
D1(printk (KERN_DEBUG "jffs2_wbuf_process() alloc_sem already occupied\n"));
} }
} }
/* Meaning of pad argument:
0: Do not pad. Probably pointless - we only ever use this when we can't pad anyway.
1: Pad, do not adjust nextblock free_size
2: Pad, adjust nextblock free_size
*/
int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) int jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
{ {
int ret; int ret;
size_t retlen; size_t retlen;
if (!down_trylock(&c->alloc_sem)) {
up(&c->alloc_sem);
printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
BUG();
}
/* delete a eventually started timed wbuf flush */
del_timer_sync(&c->wbuf_timer);
if(!c->wbuf || !c->wbuf_len) if(!c->wbuf || !c->wbuf_len)
return 0; return 0;
...@@ -339,6 +390,11 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *invecs, unsi ...@@ -339,6 +390,11 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct iovec *invecs, unsi
alldone: alldone:
*retlen = donelen; *retlen = donelen;
/* Setup timed wbuf flush, if buffer len != 0 */
if (c->wbuf_len) {
D1(printk (KERN_DEBUG "jffs2_flash_writev: mod wbuf_timer\n"));
mod_timer(&c->wbuf_timer, jiffies + WBUF_FLUSH_TIMEOUT);
}
return 0; return 0;
} }
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: write.c,v 1.56 2002/07/10 14:05:16 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: write.c,v 1.52 2002/03/08 11:01:43 dwmw2 Exp $
* *
*/ */
...@@ -89,7 +65,7 @@ static void writecheck(struct jffs2_sb_info *c, uint32_t ofs) ...@@ -89,7 +65,7 @@ static void writecheck(struct jffs2_sb_info *c, uint32_t ofs)
ret = 1; ret = 1;
} }
if (ret) { if (ret) {
printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there's data already there:\n", ofs); printk(KERN_WARNING "ARGH. About to write node to 0x%08x on flash, but there are data already there:\n", ofs);
printk(KERN_WARNING "0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", printk(KERN_WARNING "0x%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
ofs, ofs,
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
...@@ -386,8 +362,10 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str ...@@ -386,8 +362,10 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
*/ */
ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen));
if (ret) if (ret) {
up(&f->sem);
return ret; return ret;
}
ri->data_crc = 0; ri->data_crc = 0;
ri->node_crc = crc32(0, ri, sizeof(*ri)-8); ri->node_crc = crc32(0, ri, sizeof(*ri)-8);
...@@ -472,7 +450,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str ...@@ -472,7 +450,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str
} }
int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f) int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f,
const char *name, int namelen, struct jffs2_inode_info *dead_f)
{ {
struct jffs2_raw_dirent *rd; struct jffs2_raw_dirent *rd;
struct jffs2_full_dirent *fd; struct jffs2_full_dirent *fd;
...@@ -522,7 +501,10 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, con ...@@ -522,7 +501,10 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, con
jffs2_complete_reservation(c); jffs2_complete_reservation(c);
up(&dir_f->sem); up(&dir_f->sem);
if (dead_f) { /* Null if this was a rename not a real unlink */ /* dead_f is NULL if this was a rename not a real unlink */
/* Also catch the !f->inocache case, where there was a dirent
pointing to an inode which didn't exist. */
if (dead_f && dead_f->inocache) {
down(&dead_f->sem); down(&dead_f->sem);
......
...@@ -5,33 +5,9 @@ ...@@ -5,33 +5,9 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in this directory.
* was designed and implemented by Axis Communications AB.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: writev.c,v 1.2 2002/05/20 14:56:39 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: writev.c,v 1.1 2002/03/08 11:27:59 dwmw2 Exp $
* *
*/ */
......
...@@ -5,33 +5,10 @@ ...@@ -5,33 +5,10 @@
* *
* Created by David Woodhouse <dwmw2@cambridge.redhat.com> * Created by David Woodhouse <dwmw2@cambridge.redhat.com>
* *
* The original JFFS, from which the design for JFFS2 was derived, * For licensing information, see the file 'LICENCE' in the
* was designed and implemented by Axis Communications AB. * jffs2 directory.
* *
* The contents of this file are subject to the Red Hat eCos Public * $Id: jffs2.h,v 1.24 2002/05/20 14:56:37 dwmw2 Exp $
* License Version 1.1 (the "Licence"); you may not use this file
* except in compliance with the Licence. You may obtain a copy of
* the Licence at http://www.redhat.com/
*
* Software distributed under the Licence is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
* See the Licence for the specific language governing rights and
* limitations under the Licence.
*
* The Original Code is JFFS2 - Journalling Flash File System, version 2
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License version 2 (the "GPL"), in
* which case the provisions of the GPL are applicable instead of the
* above. If you wish to allow the use of your version of this file
* only under the terms of the GPL and not to allow others to use your
* version of this file under the RHEPL, indicate your decision by
* deleting the provisions above and replace them with the notice and
* other provisions required by the GPL. If you do not delete the
* provisions above, a recipient may use your version of this file
* under either the RHEPL or the GPL.
*
* $Id: jffs2.h,v 1.23 2002/02/21 17:03:45 dwmw2 Exp $
* *
*/ */
......
/* $Id: jffs2_fs_sb.h,v 1.26 2002/03/17 10:18:42 dwmw2 Exp $ */ /* $Id: jffs2_fs_sb.h,v 1.32 2002/07/23 14:35:34 dwmw2 Exp $ */
#ifndef _JFFS2_FS_SB #ifndef _JFFS2_FS_SB
#define _JFFS2_FS_SB #define _JFFS2_FS_SB
#include <linux/types.h> #include <linux/types.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/tqueue.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <linux/list.h> #include <linux/list.h>
#define INOCACHE_HASHSIZE 14
#define JFFS2_SB_FLAG_RO 1 #define JFFS2_SB_FLAG_RO 1
#define JFFS2_SB_FLAG_MOUNTING 2 #define JFFS2_SB_FLAG_MOUNTING 2
...@@ -33,6 +32,9 @@ struct jffs2_sb_info { ...@@ -33,6 +32,9 @@ struct jffs2_sb_info {
out-of-order writing of nodes. out-of-order writing of nodes.
And GC. And GC.
*/ */
uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER
(i.e. zero for OOB CLEANMARKER */
uint32_t flash_size; uint32_t flash_size;
uint32_t used_size; uint32_t used_size;
uint32_t dirty_size; uint32_t dirty_size;
...@@ -52,6 +54,7 @@ struct jffs2_sb_info { ...@@ -52,6 +54,7 @@ struct jffs2_sb_info {
struct jffs2_eraseblock *gcblock; /* The block we're currently garbage-collecting */ struct jffs2_eraseblock *gcblock; /* The block we're currently garbage-collecting */
struct list_head clean_list; /* Blocks 100% full of clean data */ struct list_head clean_list; /* Blocks 100% full of clean data */
struct list_head very_dirty_list; /* Blocks with lots of dirty space */
struct list_head dirty_list; /* Blocks with some dirty space */ struct list_head dirty_list; /* Blocks with some dirty space */
struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */ struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */
struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */ struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */
...@@ -66,10 +69,8 @@ struct jffs2_sb_info { ...@@ -66,10 +69,8 @@ struct jffs2_sb_info {
against erase completion handler */ against erase completion handler */
wait_queue_head_t erase_wait; /* For waiting for erases to complete */ wait_queue_head_t erase_wait; /* For waiting for erases to complete */
struct jffs2_inode_cache *inocache_list[INOCACHE_HASHSIZE]; struct jffs2_inode_cache **inocache_list;
spinlock_t inocache_lock; spinlock_t inocache_lock;
/* This _really_ speeds up mounts. */
struct jffs2_inode_cache *inocache_last;
/* Sem to allow jffs2_garbage_collect_deletion_dirent to /* Sem to allow jffs2_garbage_collect_deletion_dirent to
drop the erase_completion_lock while it's holding a pointer drop the erase_completion_lock while it's holding a pointer
...@@ -81,6 +82,8 @@ struct jffs2_sb_info { ...@@ -81,6 +82,8 @@ struct jffs2_sb_info {
uint32_t wbuf_ofs; uint32_t wbuf_ofs;
uint32_t wbuf_len; uint32_t wbuf_len;
uint32_t wbuf_pagesize; uint32_t wbuf_pagesize;
struct tq_struct wbuf_task; /* task for timed wbuf flush */
struct timer_list wbuf_timer; /* timer for flushing wbuf */
/* OS-private pointer for getting back to master superblock info */ /* OS-private pointer for getting back to master superblock info */
void *os_priv; void *os_priv;
......
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