Every time cramfs_lookup() is called to lookup and inode for a dentry,
get_cramfs_inode() will allocate a new inode without checking to see
if that inode already exists in the inode cache.

This is fine the first time, but if the dentry cache entry(ies)
associated with that inode are aged out, but the inode entry is not
aged out (which can be quite common if the inode has buffer cache
linked to it), cramfs_lookup() will be called again and another inode
will be allocated and added to the inode cache creating a duplicate in
the inode cache.

The big issue here is that the buffers associated with each inode
cache entry are not shared between the duplicates!

The older inode entries are now orphaned as no dentry points to it and
won't be freed until the buffer cache assoicated with them are first
freed.  The newest entry will have to create all new buffer cache for
each part of its file as the old buffer cache is now orphaned as well.

Patch below fixes this by making get_cramfs_inode() use the inode
cache before blindly creating a new entry every time.  This eliminates
the duplicate inodes and duplicate buffer cache.

-- 
Dave Johnson
Starent Networks


===== fs/cramfs/inode.c 1.42 vs edited =====
--- 1.42/fs/cramfs/inode.c      2005-07-14 12:24:48 -04:00
+++ edited/fs/cramfs/inode.c    2005-08-19 15:39:05 -04:00
@@ -44,10 +44,10 @@
 
 static struct inode *get_cramfs_inode(struct super_block *sb, struct 
cramfs_inode * cramfs_inode)
 {
-       struct inode * inode = new_inode(sb);
+       struct inode * inode = iget_locked(sb, CRAMINO(cramfs_inode));
        static struct timespec zerotime;
 
-       if (inode) {
+       if (inode && (inode->i_state & I_NEW)) {
                inode->i_mode = cramfs_inode->mode;
                inode->i_uid = cramfs_inode->uid;
                inode->i_size = cramfs_inode->size;
@@ -57,11 +57,6 @@
                /* Struct copy intentional */
                inode->i_mtime = inode->i_atime = inode->i_ctime = zerotime;
                inode->i_ino = CRAMINO(cramfs_inode);
-               /* inode->i_nlink is left 1 - arguably wrong for directories,
-                  but it's the best we can do without reading the directory
-                  contents.  1 yields the right result in GNU find, even
-                  without -noleaf option. */
-               insert_inode_hash(inode);
                if (S_ISREG(inode->i_mode)) {
                        inode->i_fop = &generic_ro_fops;
                        inode->i_data.a_ops = &cramfs_aops;
@@ -76,6 +72,7 @@
                        init_special_inode(inode, inode->i_mode,
                                old_decode_dev(cramfs_inode->size));
                }
+               unlock_new_inode(inode);
        }
        return inode;
 }

-
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to