Commit 85b640c5 authored by Jan Harkes's avatar Jan Harkes Committed by Linus Torvalds

[PATCH] iget_locked [2/6]

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 pretty much identical except for function naming.
parent 7a24f1a6
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
O_TARGET := fs.o 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 mod-subdirs := nls
obj-y := open.o read_write.o devices.o file_table.o buffer.o \ obj-y := open.o read_write.o devices.o file_table.o buffer.o \
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/writeback.h> #include <linux/writeback.h>
#include <linux/module.h>
/* /*
* New inode.c implementation. * New inode.c implementation.
...@@ -501,6 +502,21 @@ struct inode *new_inode(struct super_block *sb) ...@@ -501,6 +502,21 @@ struct inode *new_inode(struct super_block *sb)
return inode; 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. * This is called without the inode lock held.. Be careful.
* *
...@@ -527,31 +543,12 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s ...@@ -527,31 +543,12 @@ static struct inode * get_new_inode(struct super_block *sb, unsigned long ino, s
inodes_stat.nr_inodes++; inodes_stat.nr_inodes++;
list_add(&inode->i_list, &inode_in_use); list_add(&inode->i_list, &inode_in_use);
list_add(&inode->i_hash, head); list_add(&inode->i_hash, head);
inode->i_state = I_LOCK; inode->i_state = I_LOCK|I_NEW;
spin_unlock(&inode_lock); spin_unlock(&inode_lock);
/* reiserfs specific hack right here. We don't /* Return the locked inode with I_NEW set, the
** want this to last, and are looking for VFS changes * caller is responsible for filling in the contents
** 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).
*/
inode->i_state &= ~I_LOCK;
wake_up(&inode->i_wait);
return inode; return inode;
} }
...@@ -636,8 +633,12 @@ struct inode *igrab(struct inode *inode) ...@@ -636,8 +633,12 @@ struct inode *igrab(struct inode *inode)
return inode; 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 list_head * head = inode_hashtable + hash(sb,ino);
struct inode * inode; struct inode * inode;
...@@ -659,6 +660,36 @@ struct inode *iget4(struct super_block *sb, unsigned long ino, int (*test)(struc ...@@ -659,6 +660,36 @@ struct inode *iget4(struct super_block *sb, unsigned long ino, int (*test)(struc
return get_new_inode(sb, ino, head, test, set, data); 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;
}
/** /**
* insert_inode_hash - hash an inode * insert_inode_hash - hash an inode
* @inode: unhashed inode * @inode: unhashed inode
......
...@@ -799,6 +799,7 @@ struct super_operations { ...@@ -799,6 +799,7 @@ struct super_operations {
#define I_LOCK 8 #define I_LOCK 8
#define I_FREEING 16 #define I_FREEING 16
#define I_CLEAR 32 #define I_CLEAR 32
#define I_NEW 64
#define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES)
...@@ -1207,6 +1208,10 @@ extern void force_delete(struct inode *); ...@@ -1207,6 +1208,10 @@ extern void force_delete(struct inode *);
extern struct inode * igrab(struct inode *); extern struct inode * igrab(struct inode *);
extern ino_t iunique(struct super_block *, ino_t); 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 *); 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) static inline struct inode *iget(struct super_block *sb, unsigned long ino)
{ {
......
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