From: Jan Harkes <jaharkes@cs.cmu.edu> To: torvalds@transmeta.com Subject: [PATCH] iget-locked [2/6] Date: Fri, 10 May 2002 12:07:30 -0400 Cc: linux-kernel@vger.kernel.org, Alexander Viro <viro@math.psu.edu>, trond.myklebust@fys.uio.no, reiserfs-dev@namesys.com Now we introduce iget_locked and iget5_locked. These are similar to iget, but return a locked inode and read_inode has not been called. So the FS has to call read_inode to initialize the inode and then unlock it with unlock_new_inode(). This patch is based on the icreate patch from the XFS group, i.e. it is still pretty much identical except for function naming. ====== diff -urN iget_locked-1/fs/Makefile iget_locked-2/fs/Makefile --- iget_locked-1/fs/Makefile Wed May 1 00:27:34 2002 +++ iget_locked-2/fs/Makefile Fri May 10 10:33:12 2002 @@ -7,7 +7,7 @@ O_TARGET := fs.o -export-objs := filesystems.o open.o dcache.o buffer.o bio.o +export-objs := filesystems.o open.o dcache.o buffer.o bio.o inode.o mod-subdirs := nls obj-y := open.o read_write.o devices.o file_table.o buffer.o \ diff -urN iget_locked-1/fs/inode.c iget_locked-2/fs/inode.c --- iget_locked-1/fs/inode.c Fri May 10 10:32:03 2002 +++ iget_locked-2/fs/inode.c Fri May 10 10:33:12 2002 @@ -12,6 +12,7 @@ #include <linux/quotaops.h> #include <linux/slab.h> #include <linux/writeback.h> +#include <linux/module.h> /* * New inode.c implementation. @@ -501,6 +502,21 @@ return inode; } +void unlock_new_inode(struct inode *inode) +{ + /* + * This is special! We do not need the spinlock + * when clearing I_LOCK, because we're guaranteed + * that nobody else tries to do anything about the + * state of the inode when it is locked, as we + * just created it (so there can be no old holders + * that haven't tested I_LOCK). + */ + inode->i_state &= ~(I_LOCK|I_NEW); + wake_up(&inode->i_wait); +} + + /* * This is called without the inode lock held.. Be careful. * @@ -527,7 +543,7 @@ inodes_stat.nr_inodes++; list_add(&inode->i_list, &inode_in_use); list_add(&inode->i_hash, head); - inode->i_state = I_LOCK; + inode->i_state = I_LOCK|I_NEW; } spin_unlock(&inode_lock); @@ -536,28 +552,9 @@ return NULL; } - /* reiserfs specific hack right here. We don't - ** want this to last, and are looking for VFS changes - ** that will allow us to get rid of it. - ** -- mason@suse.com - */ - if (sb->s_op->read_inode2) { - sb->s_op->read_inode2(inode, data) ; - } else { - sb->s_op->read_inode(inode); - } - - /* - * This is special! We do not need the spinlock - * when clearing I_LOCK, because we're guaranteed - * that nobody else tries to do anything about the - * state of the inode when it is locked, as we - * just created it (so there can be no old holders - * that haven't tested I_LOCK). + /* Return the locked inode with I_NEW set, the + * caller is responsible for filling in the contents */ - inode->i_state &= ~I_LOCK; - wake_up(&inode->i_wait); - return inode; } @@ -637,8 +634,12 @@ return inode; } - -struct inode *iget4(struct super_block *sb, unsigned long ino, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data) +/* + * This is iget without the read_inode portion of get_new_inode + * the filesystem gets back a new locked and hashed inode and gets + * to fill it in before unlocking it via unlock_new_inode(). + */ +struct inode *iget5_locked(struct super_block *sb, unsigned long ino, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data) { struct list_head * head = inode_hashtable + hash(sb,ino); struct inode * inode; @@ -658,6 +659,36 @@ * in case it had to block at any point. */ return get_new_inode(sb, ino, head, test, set, data); +} + +struct inode *iget_locked(struct super_block *sb, unsigned long ino) +{ + return iget5_locked(sb, ino, NULL, NULL, NULL); +} + +EXPORT_SYMBOL(iget5_locked); +EXPORT_SYMBOL(iget_locked); +EXPORT_SYMBOL(unlock_new_inode); + +struct inode *iget4(struct super_block *sb, unsigned long ino, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *data) +{ + struct inode *inode = iget5_locked(sb, ino, test, set, data); + + if (inode && (inode->i_state & I_NEW)) { + /* reiserfs specific hack right here. We don't + ** want this to last, and are looking for VFS changes + ** that will allow us to get rid of it. + ** -- mason@suse.com + */ + if (sb->s_op->read_inode2) { + sb->s_op->read_inode2(inode, data); + } else { + sb->s_op->read_inode(inode); + } + unlock_new_inode(inode); + } + + return inode; } /** diff -urN iget_locked-1/include/linux/fs.h iget_locked-2/include/linux/fs.h --- iget_locked-1/include/linux/fs.h Fri May 10 10:32:04 2002 +++ iget_locked-2/include/linux/fs.h Fri May 10 10:33:12 2002 @@ -832,6 +832,7 @@ #define I_LOCK 8 #define I_FREEING 16 #define I_CLEAR 32 +#define I_NEW 64 #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) @@ -1239,6 +1240,10 @@ extern void force_delete(struct inode *); extern struct inode * igrab(struct inode *); extern ino_t iunique(struct super_block *, ino_t); + +extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); +extern struct inode * iget_locked(struct super_block *, unsigned long); +extern void unlock_new_inode(struct inode *); extern struct inode * iget4(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); static inline struct inode *iget(struct super_block *sb, unsigned long ino) - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/