mtd/fs/jffs2/ecos/src dir-ecos.c,1.6,1.7 fs-ecos.c,1.16,1.17
jffs2port.h,1.7,1.8
David Woodhouse
dwmw2 at infradead.org
Tue Nov 25 06:25:51 EST 2003
Update of /home/cvs/mtd/fs/jffs2/ecos/src
In directory phoenix.infradead.org:/tmp/cvs-serv18523
Modified Files:
dir-ecos.c fs-ecos.c jffs2port.h
Log Message:
fix inode use counts
Index: dir-ecos.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/ecos/src/dir-ecos.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- dir-ecos.c 24 Nov 2003 14:54:39 -0000 1.6
+++ dir-ecos.c 25 Nov 2003 11:25:48 -0000 1.7
@@ -150,7 +150,7 @@
return ret;
}
-int jffs2_mkdir (struct _inode *dir_i, struct qstr *d_name, int mode, struct _inode **new_i)
+int jffs2_mkdir (struct _inode *dir_i, struct qstr *d_name, int mode)
{
struct jffs2_inode_info *f, *dir_f;
struct jffs2_sb_info *c;
@@ -267,7 +267,7 @@
jffs2_add_fd_to_list(c, fd, &dir_f->dents);
up(&dir_f->sem);
- *new_i = inode;
+ iput(inode);
return 0;
}
Index: fs-ecos.c
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/ecos/src/fs-ecos.c,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -r1.16 -r1.17
--- fs-ecos.c 24 Nov 2003 16:09:21 -0000 1.16
+++ fs-ecos.c 25 Nov 2003 11:25:48 -0000 1.17
@@ -171,6 +171,7 @@
{
struct _inode *this = root_i, *next;
+ restart:
D2(printf("icache_evict\n"));
// If this is an absolute search path from the root,
// remove all cached inodes with i_count of zero (these are only
@@ -178,13 +179,19 @@
while (this) {
next = this->i_cache_next;
if (this != i && this->i_count == 0) {
-
+ struct _inode *parent = this->i_parent;
if (this->i_cache_next)
this->i_cache_next->i_cache_prev = this->i_cache_prev;
if (this->i_cache_prev)
this->i_cache_prev->i_cache_next = this->i_cache_next;
jffs2_clear_inode(this);
+ memset(this, 0x5a, sizeof(*this));
free(this);
+ if (parent && parent != this) {
+ parent->i_count--;
+ this = root_i;
+ goto restart;
+ }
}
this = next;
}
@@ -203,7 +210,6 @@
D2(printf("init_dirsearch name = %s\n", name));
D2(printf("init_dirsearch dir = %x\n", dir));
- /* Increase inode refcount since find_entry will decrease it again */
dir->i_count++;
ds->dir = dir;
ds->path = name;
@@ -260,16 +266,15 @@
// Dot Dot
// Move back up the search path
D2(printf("find_entry found ..\n"));
+ ds->dir = ds->node;
ds->node = ds->dir->i_parent;
- if (ds->dir->i_count == 0) {
- iput(ds->dir); // This inode may be evicted
- ds->dir = NULL;
- }
+ ds->node->i_count++;
return ENOERR;
case 1:
// Dot is consumed
D2(printf("find_entry found .\n"));
ds->node = ds->dir;
+ ds->dir->i_count++;
return ENOERR;
}
// Here we have the name and its length set up.
@@ -295,11 +300,14 @@
if (d == NULL)
return ENOENT;
- // The back path for dotdot to follow
- d->i_parent = dir;
+ // If it's a new directory inode, increase refcount on its parent
+ if (S_ISDIR(d->i_mode) && !d->i_parent) {
+ d->i_parent = dir;
+ dir->i_count++;
+ }
+
// pass back the node we have found
ds->node = d;
-
return ENOERR;
}
@@ -310,15 +318,18 @@
// level operations to locate the object named by the pathname.
// Returns with use count incremented on both the sought object and
-// the directory it was found in.
+// the directory it was found in
static int jffs2_find(jffs2_dirsearch * d)
{
int err;
D2(printf("jffs2_find for path =%s\n", d->path));
+
// Short circuit empty paths
- if (*(d->path) == '\0')
+ if (*(d->path) == '\0') {
+ d->node->i_count++;
return ENOERR;
+ }
// iterate down directory tree until we find the object
// we want.
@@ -331,7 +342,8 @@
if (d->last)
return ENOERR;
- // Drop the directory we were using.
+ /* We're done with it, although it we found a subdir that
+ will have caused the refcount to have been increased */
iput(d->dir);
// Update dirsearch object to search next directory.
@@ -486,7 +498,7 @@
static int jffs2_mount(cyg_fstab_entry * fste, cyg_mtab_entry * mte)
{
- extern cyg_mtab_entry mtab[], mtab_end;
+ extern cyg_mtab_entry cyg_mtab[], cyg_mtab_end;
struct super_block *jffs2_sb = NULL;
struct jffs2_sb_info *c;
cyg_mtab_entry *m;
@@ -502,10 +514,10 @@
// Iterate through the mount table to see if we're mounted
// FIXME: this should be done better - perhaps if the superblock
// can be stored as an inode in the icache.
- for (m = &mtab[0]; m != &mtab_end; m++) {
+ for (m = &cyg_mtab[0]; m != &cyg_mtab_end; m++) {
// stop if there are more than the configured maximum
- if (m - &mtab[0] >= CYGNUM_FILEIO_MTAB_MAX) {
- m = &mtab_end;
+ if (m - &cyg_mtab[0] >= CYGNUM_FILEIO_MTAB_MAX) {
+ m = &cyg_mtab_end;
break;
}
if (m->valid && strcmp(m->fsname, "jffs2") == 0 &&
@@ -577,7 +589,7 @@
if (jffs2_sb->s_mount_count == 1) {
icache_evict(root, NULL);
if (root->i_cache_next != NULL) {
- struct _inode *inode = root->i_cache_next;
+ struct _inode *inode = root;
printf("Refuse to unmount.\n");
while (inode) {
printf("Ino #%u has use count %d\n",
@@ -587,6 +599,11 @@
// root icount was set to 1 on mount
return EBUSY;
}
+ if (root->i_count != 1) {
+ printf("Ino #1 has use count %d\n",
+ root->i_count);
+ return EBUSY;
+ }
iput(root); // Time to free the root inode
//Clear root inode
@@ -768,7 +785,6 @@
static int jffs2_ops_mkdir(cyg_mtab_entry * mte, cyg_dir dir, const char *name)
{
jffs2_dirsearch ds;
- struct _inode *node = NULL;
int err;
D2(printf("jffs2_ops_mkdir\n"));
@@ -799,7 +815,7 @@
this.len = hashname - (const char *) this.name;
this.hash = end_name_hash(hash);
- err = -jffs2_mkdir(ds.dir, &this, 0, &node);
+ err = -jffs2_mkdir(ds.dir, &this, S_IRUGO|S_IXUGO|S_IWUSR);
}
// If this was not the last element, then an intermediate
// directory does not exist.
@@ -1128,7 +1144,6 @@
err = jffs2_find(&ds);
iput(ds.dir);
- iput((struct _inode *)dir);
if (err != ENOERR)
return err;
@@ -1382,8 +1397,9 @@
ri.atime = ri.ctime = ri.mtime = cpu_to_je32(cyg_timestamp());
if (pos > inode->i_size) {
+ int err;
ri.version = cpu_to_je32(++f->highest_version);
- int err = jffs2_extend_file(inode, &ri, pos);
+ err = jffs2_extend_file(inode, &ri, pos);
if (err)
return -err;
}
@@ -1733,8 +1749,7 @@
memset(inode, 0, sizeof (struct _inode));
inode->i_sb = sb;
inode->i_ino = 1;
- inode->i_count = 0; //1; // Let ecos manage the open count
-
+ inode->i_count = 1;
inode->i_nlink = 1; // Let JFFS2 manage the link count
inode->i_size = 0;
@@ -1792,7 +1807,6 @@
return 0;
inode->i_ino = ino;
- inode->i_count = 1;
err = jffs2_read_inode(inode);
if (err) {
@@ -1810,31 +1824,43 @@
void iput(struct _inode *i)
{
-
// Called in jffs2_find
// (and jffs2_open and jffs2_ops_mkdir?)
// super.c jffs2_read_super,
// and gc.c jffs2_garbage_collect_pass
-
+ recurse:
if (!i) {
printf("iput() called with NULL inode\n");
// and let it fault...
}
-
+
i->i_count--;
+ if (i->i_count < 0)
+ BUG();
+
if (i->i_count)
return;
if (!i->i_nlink) {
+ struct _inode *parent;
+
// Remove from the icache linked list and free immediately
if (i->i_cache_prev)
i->i_cache_prev->i_cache_next = i->i_cache_next;
if (i->i_cache_next)
i->i_cache_next->i_cache_prev = i->i_cache_prev;
+ parent = i->i_parent;
jffs2_clear_inode(i);
+ memset(i, 0x5a, sizeof(*i));
free(i);
+
+ if (parent && parent != i) {
+ i = parent;
+ goto recurse;
+ }
+
} else {
// Evict some _other_ inode with i_count zero, leaving
// this latest one in the cache for a while
Index: jffs2port.h
===================================================================
RCS file: /home/cvs/mtd/fs/jffs2/ecos/src/jffs2port.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- jffs2port.h 24 Nov 2003 14:54:39 -0000 1.7
+++ jffs2port.h 25 Nov 2003 11:25:48 -0000 1.8
@@ -188,7 +188,7 @@
struct _inode *jffs2_lookup(struct _inode *dir_i, struct qstr *name);
int jffs2_readdir (struct _inode *d_inode, unsigned long f_pos, char *nbuf, int nlen);
int jffs2_create(struct _inode *dir_i, struct qstr *d_name, int mode, struct _inode **new_i);
-int jffs2_mkdir (struct _inode *dir_i, struct qstr *d_name, int mode, struct _inode **new_i);
+int jffs2_mkdir (struct _inode *dir_i, struct qstr *d_name, int mode);
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, struct qstr *d_name);
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, struct qstr *d_name);
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, struct qstr *d_name);
More information about the linux-mtd-cvs
mailing list