dect
/
linux-2.6
Archived
13
0
Fork 0

fs: simplify iget & friends

Merge get_new_inode/get_new_inode_fast into iget5_locked/iget_locked
as those were the only callers.  Remove the internal ifind/ifind_fast
helpers - ifind_fast only had a single caller, and ifind had two
callers wanting it to do different things.  Also clean up the comments
in this area to focus on information important to a developer trying
to use it, instead of overloading them with implementation details.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Christoph Hellwig 2011-03-23 15:03:28 -04:00 committed by Al Viro
parent 0f1b1fd86f
commit 0b2d0724e2
1 changed files with 86 additions and 182 deletions

View File

@ -931,20 +931,42 @@ void unlock_new_inode(struct inode *inode)
}
EXPORT_SYMBOL(unlock_new_inode);
/*
* This is called without the inode hash lock held.. Be careful.
/**
* iget5_locked - obtain an inode from a mounted file system
* @sb: super block of file system
* @hashval: hash value (usually inode number) to get
* @test: callback used for comparisons between inodes
* @set: callback used to initialize a new struct inode
* @data: opaque data pointer to pass to @test and @set
*
* We no longer cache the sb_flags in i_flags - see fs.h
* -- rmk@arm.uk.linux.org
* Search for the inode specified by @hashval and @data in the inode cache,
* and if present it is return it with an increased reference count. This is
* a generalized version of iget_locked() for file systems where the inode
* number is not sufficient for unique identification of an inode.
*
* If the inode is not in cache, allocate a new inode and return it locked,
* hashed, and with the I_NEW flag set. The file system gets to fill it in
* before unlocking it via unlock_new_inode().
*
* Note both @test and @set are called with the inode_hash_lock held, so can't
* sleep.
*/
static struct inode *get_new_inode(struct super_block *sb,
struct hlist_head *head,
int (*test)(struct inode *, void *),
int (*set)(struct inode *, void *),
void *data)
struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *),
int (*set)(struct inode *, void *), void *data)
{
struct hlist_head *head = inode_hashtable + hash(sb, hashval);
struct inode *inode;
spin_lock(&inode_hash_lock);
inode = find_inode(sb, head, test, data);
spin_unlock(&inode_hash_lock);
if (inode) {
wait_on_inode(inode);
return inode;
}
inode = alloc_inode(sb);
if (inode) {
struct inode *old;
@ -986,16 +1008,34 @@ set_failed:
destroy_inode(inode);
return NULL;
}
EXPORT_SYMBOL(iget5_locked);
/*
* get_new_inode_fast is the fast path version of get_new_inode, see the
* comment at iget_locked for details.
/**
* iget_locked - obtain an inode from a mounted file system
* @sb: super block of file system
* @ino: inode number to get
*
* Search for the inode specified by @ino in the inode cache and if present
* return it with an increased reference count. This is for file systems
* where the inode number is sufficient for unique identification of an inode.
*
* If the inode is not in cache, allocate a new inode and return it locked,
* hashed, and with the I_NEW flag set. The file system gets to fill it in
* before unlocking it via unlock_new_inode().
*/
static struct inode *get_new_inode_fast(struct super_block *sb,
struct hlist_head *head, unsigned long ino)
struct inode *iget_locked(struct super_block *sb, unsigned long ino)
{
struct hlist_head *head = inode_hashtable + hash(sb, ino);
struct inode *inode;
spin_lock(&inode_hash_lock);
inode = find_inode_fast(sb, head, ino);
spin_unlock(&inode_hash_lock);
if (inode) {
wait_on_inode(inode);
return inode;
}
inode = alloc_inode(sb);
if (inode) {
struct inode *old;
@ -1030,6 +1070,7 @@ static struct inode *get_new_inode_fast(struct super_block *sb,
}
return inode;
}
EXPORT_SYMBOL(iget_locked);
/*
* search the inode cache for a matching inode number.
@ -1112,74 +1153,6 @@ struct inode *igrab(struct inode *inode)
}
EXPORT_SYMBOL(igrab);
/**
* ifind - internal function, you want ilookup5() or iget5().
* @sb: super block of file system to search
* @head: the head of the list to search
* @test: callback used for comparisons between inodes
* @data: opaque data pointer to pass to @test
* @wait: if true wait for the inode to be unlocked, if false do not
*
* ifind() searches for the inode specified by @data in the inode
* cache. This is a generalized version of ifind_fast() for file systems where
* the inode number is not sufficient for unique identification of an inode.
*
* If the inode is in the cache, the inode is returned with an incremented
* reference count.
*
* Otherwise NULL is returned.
*
* Note, @test is called with the inode_hash_lock held, so can't sleep.
*/
static struct inode *ifind(struct super_block *sb,
struct hlist_head *head, int (*test)(struct inode *, void *),
void *data, const int wait)
{
struct inode *inode;
spin_lock(&inode_hash_lock);
inode = find_inode(sb, head, test, data);
if (inode) {
spin_unlock(&inode_hash_lock);
if (likely(wait))
wait_on_inode(inode);
return inode;
}
spin_unlock(&inode_hash_lock);
return NULL;
}
/**
* ifind_fast - internal function, you want ilookup() or iget().
* @sb: super block of file system to search
* @head: head of the list to search
* @ino: inode number to search for
*
* ifind_fast() searches for the inode @ino in the inode cache. This is for
* file systems where the inode number is sufficient for unique identification
* of an inode.
*
* If the inode is in the cache, the inode is returned with an incremented
* reference count.
*
* Otherwise NULL is returned.
*/
static struct inode *ifind_fast(struct super_block *sb,
struct hlist_head *head, unsigned long ino)
{
struct inode *inode;
spin_lock(&inode_hash_lock);
inode = find_inode_fast(sb, head, ino);
if (inode) {
spin_unlock(&inode_hash_lock);
wait_on_inode(inode);
return inode;
}
spin_unlock(&inode_hash_lock);
return NULL;
}
/**
* ilookup5_nowait - search for an inode in the inode cache
* @sb: super block of file system to search
@ -1187,26 +1160,26 @@ static struct inode *ifind_fast(struct super_block *sb,
* @test: callback used for comparisons between inodes
* @data: opaque data pointer to pass to @test
*
* ilookup5() uses ifind() to search for the inode specified by @hashval and
* @data in the inode cache. This is a generalized version of ilookup() for
* file systems where the inode number is not sufficient for unique
* identification of an inode.
*
* Search for the inode specified by @hashval and @data in the inode cache.
* If the inode is in the cache, the inode is returned with an incremented
* reference count. Note, the inode lock is not waited upon so you have to be
* very careful what you do with the returned inode. You probably should be
* using ilookup5() instead.
* reference count.
*
* Otherwise NULL is returned.
* Note: I_NEW is not waited upon so you have to be very careful what you do
* with the returned inode. You probably should be using ilookup5() instead.
*
* Note, @test is called with the inode_hash_lock held, so can't sleep.
* Note: @test is called with the inode_hash_lock held, so can't sleep.
*/
struct inode *ilookup5_nowait(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *), void *data)
{
struct hlist_head *head = inode_hashtable + hash(sb, hashval);
struct inode *inode;
return ifind(sb, head, test, data, 0);
spin_lock(&inode_hash_lock);
inode = find_inode(sb, head, test, data);
spin_unlock(&inode_hash_lock);
return inode;
}
EXPORT_SYMBOL(ilookup5_nowait);
@ -1217,24 +1190,24 @@ EXPORT_SYMBOL(ilookup5_nowait);
* @test: callback used for comparisons between inodes
* @data: opaque data pointer to pass to @test
*
* ilookup5() uses ifind() to search for the inode specified by @hashval and
* @data in the inode cache. This is a generalized version of ilookup() for
* file systems where the inode number is not sufficient for unique
* identification of an inode.
*
* If the inode is in the cache, the inode lock is waited upon and the inode is
* Search for the inode specified by @hashval and @data in the inode cache,
* and if the inode is in the cache, return the inode with an incremented
* reference count. Waits on I_NEW before returning the inode.
* returned with an incremented reference count.
*
* Otherwise NULL is returned.
* This is a generalized version of ilookup() for file systems where the
* inode number is not sufficient for unique identification of an inode.
*
* Note, @test is called with the inode_hash_lock held, so can't sleep.
* Note: @test is called with the inode_hash_lock held, so can't sleep.
*/
struct inode *ilookup5(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *), void *data)
{
struct hlist_head *head = inode_hashtable + hash(sb, hashval);
struct inode *inode = ilookup5_nowait(sb, hashval, test, data);
return ifind(sb, head, test, data, 1);
if (inode)
wait_on_inode(inode);
return inode;
}
EXPORT_SYMBOL(ilookup5);
@ -1243,93 +1216,24 @@ EXPORT_SYMBOL(ilookup5);
* @sb: super block of file system to search
* @ino: inode number to search for
*
* ilookup() uses ifind_fast() to search for the inode @ino in the inode cache.
* This is for file systems where the inode number is sufficient for unique
* identification of an inode.
*
* If the inode is in the cache, the inode is returned with an incremented
* reference count.
*
* Otherwise NULL is returned.
* Search for the inode @ino in the inode cache, and if the inode is in the
* cache, the inode is returned with an incremented reference count.
*/
struct inode *ilookup(struct super_block *sb, unsigned long ino)
{
struct hlist_head *head = inode_hashtable + hash(sb, ino);
struct inode *inode;
return ifind_fast(sb, head, ino);
spin_lock(&inode_hash_lock);
inode = find_inode_fast(sb, head, ino);
spin_unlock(&inode_hash_lock);
if (inode)
wait_on_inode(inode);
return inode;
}
EXPORT_SYMBOL(ilookup);
/**
* iget5_locked - obtain an inode from a mounted file system
* @sb: super block of file system
* @hashval: hash value (usually inode number) to get
* @test: callback used for comparisons between inodes
* @set: callback used to initialize a new struct inode
* @data: opaque data pointer to pass to @test and @set
*
* iget5_locked() uses ifind() to search for the inode specified by @hashval
* and @data in the inode cache and if present it is returned with an increased
* reference count. This is a generalized version of iget_locked() for file
* systems where the inode number is not sufficient for unique identification
* of an inode.
*
* If the inode is not in cache, get_new_inode() is called to allocate a new
* inode and this is returned locked, hashed, and with the I_NEW flag set. The
* file system gets to fill it in before unlocking it via unlock_new_inode().
*
* Note both @test and @set are called with the inode_hash_lock held, so can't
* sleep.
*/
struct inode *iget5_locked(struct super_block *sb, unsigned long hashval,
int (*test)(struct inode *, void *),
int (*set)(struct inode *, void *), void *data)
{
struct hlist_head *head = inode_hashtable + hash(sb, hashval);
struct inode *inode;
inode = ifind(sb, head, test, data, 1);
if (inode)
return inode;
/*
* get_new_inode() will do the right thing, re-trying the search
* in case it had to block at any point.
*/
return get_new_inode(sb, head, test, set, data);
}
EXPORT_SYMBOL(iget5_locked);
/**
* iget_locked - obtain an inode from a mounted file system
* @sb: super block of file system
* @ino: inode number to get
*
* iget_locked() uses ifind_fast() to search for the inode specified by @ino in
* the inode cache and if present it is returned with an increased reference
* count. This is for file systems where the inode number is sufficient for
* unique identification of an inode.
*
* If the inode is not in cache, get_new_inode_fast() is called to allocate a
* new inode and this is returned locked, hashed, and with the I_NEW flag set.
* The file system gets to fill it in before unlocking it via
* unlock_new_inode().
*/
struct inode *iget_locked(struct super_block *sb, unsigned long ino)
{
struct hlist_head *head = inode_hashtable + hash(sb, ino);
struct inode *inode;
inode = ifind_fast(sb, head, ino);
if (inode)
return inode;
/*
* get_new_inode_fast() will do the right thing, re-trying the search
* in case it had to block at any point.
*/
return get_new_inode_fast(sb, head, ino);
}
EXPORT_SYMBOL(iget_locked);
int insert_inode_locked(struct inode *inode)
{
struct super_block *sb = inode->i_sb;