Message ID | 1380220831-13136-1-git-send-email-bhalevy@primarydata.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
See previous comments. What guarantees these superblock pointers stay good as long as they're in the cache? --b. On Thu, Sep 26, 2013 at 02:40:31PM -0400, Benny Halevy wrote: > From: Benny Halevy <bhalevy@panasas.com> > > Signed-off-by: Benny Halevy <bhalevy@panasas.com> > [pnfsd: alloc_sid should kmalloc a object not a pointer] > Signed-off-by: Bian Naimeng <biannm@cn.fujitsu.com> > Signed-off-by: Benny Halevy <bhalevy@panasas.com> > Signed-off-by: Benny Halevy <bhalevy@primarydata.com> > --- > fs/nfsd/nfs4pnfsd.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > fs/nfsd/pnfsd.h | 2 + > 2 files changed, 122 insertions(+) > > diff --git a/fs/nfsd/nfs4pnfsd.c b/fs/nfsd/nfs4pnfsd.c > index cb28207..9a7cbc9 100644 > --- a/fs/nfsd/nfs4pnfsd.c > +++ b/fs/nfsd/nfs4pnfsd.c > @@ -25,3 +25,123 @@ > > #define NFSDDBG_FACILITY NFSDDBG_PNFS > > +static DEFINE_SPINLOCK(layout_lock); > + > +/* hash table for nfsd4_pnfs_deviceid.sbid */ > +#define SBID_HASH_BITS 8 > +#define SBID_HASH_SIZE (1 << SBID_HASH_BITS) > +#define SBID_HASH_MASK (SBID_HASH_SIZE - 1) > + > +struct sbid_tracker { > + u64 id; > + struct super_block *sb; > + struct list_head hash; > +}; > + > +static u64 current_sbid; > +static struct list_head sbid_hashtbl[SBID_HASH_SIZE]; > + > +static unsigned long > +sbid_hashval(struct super_block *sb) > +{ > + return hash_ptr(sb, SBID_HASH_BITS); > +} > + > +static struct sbid_tracker * > +alloc_sbid(void) > +{ > + return kmalloc(sizeof(struct sbid_tracker), GFP_KERNEL); > +} > + > +static void > +destroy_sbid(struct sbid_tracker *sbid) > +{ > + spin_lock(&layout_lock); > + list_del(&sbid->hash); > + spin_unlock(&layout_lock); > + kfree(sbid); > +} > + > +void > +nfsd4_free_pnfs_slabs(void) > +{ > + int i; > + struct sbid_tracker *sbid; > + > + for (i = 0; i < SBID_HASH_SIZE; i++) { > + while (!list_empty(&sbid_hashtbl[i])) { > + sbid = list_first_entry(&sbid_hashtbl[i], > + struct sbid_tracker, > + hash); > + destroy_sbid(sbid); > + } > + } > +} > + > +int > +nfsd4_init_pnfs_slabs(void) > +{ > + int i; > + > + for (i = 0; i < SBID_HASH_SIZE; i++) > + INIT_LIST_HEAD(&sbid_hashtbl[i]); > + > + return 0; > +} > + > +static u64 > +alloc_init_sbid(struct super_block *sb) > +{ > + struct sbid_tracker *sbid; > + struct sbid_tracker *new = alloc_sbid(); > + unsigned long hash_idx = sbid_hashval(sb); > + u64 id = 0; > + > + if (likely(new)) { > + spin_lock(&layout_lock); > + id = ++current_sbid; > + new->id = (id << SBID_HASH_BITS) | (hash_idx & SBID_HASH_MASK); > + id = new->id; > + BUG_ON(id == 0); > + new->sb = sb; > + > + list_for_each_entry (sbid, &sbid_hashtbl[hash_idx], hash) > + if (sbid->sb == sb) { > + kfree(new); > + id = sbid->id; > + spin_unlock(&layout_lock); > + return id; > + } > + list_add(&new->hash, &sbid_hashtbl[hash_idx]); > + spin_unlock(&layout_lock); > + } > + return id; > +} > + > +static u64 > +find_create_sbid(struct super_block *sb) > +{ > + struct sbid_tracker *sbid; > + unsigned long hash_idx = sbid_hashval(sb); > + int pos = 0; > + u64 id = 0; > + > + spin_lock(&layout_lock); > + list_for_each_entry (sbid, &sbid_hashtbl[hash_idx], hash) { > + pos++; > + if (sbid->sb != sb) > + continue; > + if (pos > 1) { > + list_del(&sbid->hash); > + list_add(&sbid->hash, &sbid_hashtbl[hash_idx]); > + } > + id = sbid->id; > + break; > + } > + spin_unlock(&layout_lock); > + > + if (!id) > + id = alloc_init_sbid(sb); > + > + return id; > +} > diff --git a/fs/nfsd/pnfsd.h b/fs/nfsd/pnfsd.h > index 7c46791..29ea2e7 100644 > --- a/fs/nfsd/pnfsd.h > +++ b/fs/nfsd/pnfsd.h > @@ -36,4 +36,6 @@ > > #include <linux/nfsd/nfsd4_pnfs.h> > > +#include "xdr4.h" > + > #endif /* LINUX_NFSD_PNFSD_H */ > -- > 1.8.3.1 > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-10-02 01:14, J. Bruce Fields wrote: > See previous comments. What guarantees these superblock pointers stay > good as long as they're in the cache? Currently, the dependency on nfsd.ko should hold them but that should go away. Trying to think about referencing svc_export instead, we use find_sbid_id to get to the superblock in nfsd4_getdevinfo since we have no current fh. And we need the superblock to call into the fs sb->s_pnfs_op->get_device_info later in nfsd4_encode_getdevinfo. Just to make sure, we can safely get to the sb via exp->ex_path.dentry->d_inode->i_sb right? Benny > > --b. > > On Thu, Sep 26, 2013 at 02:40:31PM -0400, Benny Halevy wrote: >> From: Benny Halevy <bhalevy@panasas.com> >> >> Signed-off-by: Benny Halevy <bhalevy@panasas.com> >> [pnfsd: alloc_sid should kmalloc a object not a pointer] >> Signed-off-by: Bian Naimeng <biannm@cn.fujitsu.com> >> Signed-off-by: Benny Halevy <bhalevy@panasas.com> >> Signed-off-by: Benny Halevy <bhalevy@primarydata.com> >> --- >> fs/nfsd/nfs4pnfsd.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ >> fs/nfsd/pnfsd.h | 2 + >> 2 files changed, 122 insertions(+) >> >> diff --git a/fs/nfsd/nfs4pnfsd.c b/fs/nfsd/nfs4pnfsd.c >> index cb28207..9a7cbc9 100644 >> --- a/fs/nfsd/nfs4pnfsd.c >> +++ b/fs/nfsd/nfs4pnfsd.c >> @@ -25,3 +25,123 @@ >> >> #define NFSDDBG_FACILITY NFSDDBG_PNFS >> >> +static DEFINE_SPINLOCK(layout_lock); >> + >> +/* hash table for nfsd4_pnfs_deviceid.sbid */ >> +#define SBID_HASH_BITS 8 >> +#define SBID_HASH_SIZE (1 << SBID_HASH_BITS) >> +#define SBID_HASH_MASK (SBID_HASH_SIZE - 1) >> + >> +struct sbid_tracker { >> + u64 id; >> + struct super_block *sb; >> + struct list_head hash; >> +}; >> + >> +static u64 current_sbid; >> +static struct list_head sbid_hashtbl[SBID_HASH_SIZE]; >> + >> +static unsigned long >> +sbid_hashval(struct super_block *sb) >> +{ >> + return hash_ptr(sb, SBID_HASH_BITS); >> +} >> + >> +static struct sbid_tracker * >> +alloc_sbid(void) >> +{ >> + return kmalloc(sizeof(struct sbid_tracker), GFP_KERNEL); >> +} >> + >> +static void >> +destroy_sbid(struct sbid_tracker *sbid) >> +{ >> + spin_lock(&layout_lock); >> + list_del(&sbid->hash); >> + spin_unlock(&layout_lock); >> + kfree(sbid); >> +} >> + >> +void >> +nfsd4_free_pnfs_slabs(void) >> +{ >> + int i; >> + struct sbid_tracker *sbid; >> + >> + for (i = 0; i < SBID_HASH_SIZE; i++) { >> + while (!list_empty(&sbid_hashtbl[i])) { >> + sbid = list_first_entry(&sbid_hashtbl[i], >> + struct sbid_tracker, >> + hash); >> + destroy_sbid(sbid); >> + } >> + } >> +} >> + >> +int >> +nfsd4_init_pnfs_slabs(void) >> +{ >> + int i; >> + >> + for (i = 0; i < SBID_HASH_SIZE; i++) >> + INIT_LIST_HEAD(&sbid_hashtbl[i]); >> + >> + return 0; >> +} >> + >> +static u64 >> +alloc_init_sbid(struct super_block *sb) >> +{ >> + struct sbid_tracker *sbid; >> + struct sbid_tracker *new = alloc_sbid(); >> + unsigned long hash_idx = sbid_hashval(sb); >> + u64 id = 0; >> + >> + if (likely(new)) { >> + spin_lock(&layout_lock); >> + id = ++current_sbid; >> + new->id = (id << SBID_HASH_BITS) | (hash_idx & SBID_HASH_MASK); >> + id = new->id; >> + BUG_ON(id == 0); >> + new->sb = sb; >> + >> + list_for_each_entry (sbid, &sbid_hashtbl[hash_idx], hash) >> + if (sbid->sb == sb) { >> + kfree(new); >> + id = sbid->id; >> + spin_unlock(&layout_lock); >> + return id; >> + } >> + list_add(&new->hash, &sbid_hashtbl[hash_idx]); >> + spin_unlock(&layout_lock); >> + } >> + return id; >> +} >> + >> +static u64 >> +find_create_sbid(struct super_block *sb) >> +{ >> + struct sbid_tracker *sbid; >> + unsigned long hash_idx = sbid_hashval(sb); >> + int pos = 0; >> + u64 id = 0; >> + >> + spin_lock(&layout_lock); >> + list_for_each_entry (sbid, &sbid_hashtbl[hash_idx], hash) { >> + pos++; >> + if (sbid->sb != sb) >> + continue; >> + if (pos > 1) { >> + list_del(&sbid->hash); >> + list_add(&sbid->hash, &sbid_hashtbl[hash_idx]); >> + } >> + id = sbid->id; >> + break; >> + } >> + spin_unlock(&layout_lock); >> + >> + if (!id) >> + id = alloc_init_sbid(sb); >> + >> + return id; >> +} >> diff --git a/fs/nfsd/pnfsd.h b/fs/nfsd/pnfsd.h >> index 7c46791..29ea2e7 100644 >> --- a/fs/nfsd/pnfsd.h >> +++ b/fs/nfsd/pnfsd.h >> @@ -36,4 +36,6 @@ >> >> #include <linux/nfsd/nfsd4_pnfs.h> >> >> +#include "xdr4.h" >> + >> #endif /* LINUX_NFSD_PNFSD_H */ >> -- >> 1.8.3.1 >> > -- > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Wed, Oct 02, 2013 at 05:32:32PM +0300, Benny Halevy wrote: > On 2013-10-02 01:14, J. Bruce Fields wrote: > > See previous comments. What guarantees these superblock pointers stay > > good as long as they're in the cache? > > Currently, the dependency on nfsd.ko should hold them but that should go away. I don't see how that prevents anyone from unmounting a filesystem. > Trying to think about referencing svc_export instead, we use find_sbid_id > to get to the superblock in nfsd4_getdevinfo since we have no current fh. > And we need the superblock to call into the fs sb->s_pnfs_op->get_device_info > later in nfsd4_encode_getdevinfo. > > Just to make sure, we can safely get to the sb via exp->ex_path.dentry->d_inode->i_sb > right? Right. --b. > > Benny > > > > > --b. > > > > On Thu, Sep 26, 2013 at 02:40:31PM -0400, Benny Halevy wrote: > >> From: Benny Halevy <bhalevy@panasas.com> > >> > >> Signed-off-by: Benny Halevy <bhalevy@panasas.com> > >> [pnfsd: alloc_sid should kmalloc a object not a pointer] > >> Signed-off-by: Bian Naimeng <biannm@cn.fujitsu.com> > >> Signed-off-by: Benny Halevy <bhalevy@panasas.com> > >> Signed-off-by: Benny Halevy <bhalevy@primarydata.com> > >> --- > >> fs/nfsd/nfs4pnfsd.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > >> fs/nfsd/pnfsd.h | 2 + > >> 2 files changed, 122 insertions(+) > >> > >> diff --git a/fs/nfsd/nfs4pnfsd.c b/fs/nfsd/nfs4pnfsd.c > >> index cb28207..9a7cbc9 100644 > >> --- a/fs/nfsd/nfs4pnfsd.c > >> +++ b/fs/nfsd/nfs4pnfsd.c > >> @@ -25,3 +25,123 @@ > >> > >> #define NFSDDBG_FACILITY NFSDDBG_PNFS > >> > >> +static DEFINE_SPINLOCK(layout_lock); > >> + > >> +/* hash table for nfsd4_pnfs_deviceid.sbid */ > >> +#define SBID_HASH_BITS 8 > >> +#define SBID_HASH_SIZE (1 << SBID_HASH_BITS) > >> +#define SBID_HASH_MASK (SBID_HASH_SIZE - 1) > >> + > >> +struct sbid_tracker { > >> + u64 id; > >> + struct super_block *sb; > >> + struct list_head hash; > >> +}; > >> + > >> +static u64 current_sbid; > >> +static struct list_head sbid_hashtbl[SBID_HASH_SIZE]; > >> + > >> +static unsigned long > >> +sbid_hashval(struct super_block *sb) > >> +{ > >> + return hash_ptr(sb, SBID_HASH_BITS); > >> +} > >> + > >> +static struct sbid_tracker * > >> +alloc_sbid(void) > >> +{ > >> + return kmalloc(sizeof(struct sbid_tracker), GFP_KERNEL); > >> +} > >> + > >> +static void > >> +destroy_sbid(struct sbid_tracker *sbid) > >> +{ > >> + spin_lock(&layout_lock); > >> + list_del(&sbid->hash); > >> + spin_unlock(&layout_lock); > >> + kfree(sbid); > >> +} > >> + > >> +void > >> +nfsd4_free_pnfs_slabs(void) > >> +{ > >> + int i; > >> + struct sbid_tracker *sbid; > >> + > >> + for (i = 0; i < SBID_HASH_SIZE; i++) { > >> + while (!list_empty(&sbid_hashtbl[i])) { > >> + sbid = list_first_entry(&sbid_hashtbl[i], > >> + struct sbid_tracker, > >> + hash); > >> + destroy_sbid(sbid); > >> + } > >> + } > >> +} > >> + > >> +int > >> +nfsd4_init_pnfs_slabs(void) > >> +{ > >> + int i; > >> + > >> + for (i = 0; i < SBID_HASH_SIZE; i++) > >> + INIT_LIST_HEAD(&sbid_hashtbl[i]); > >> + > >> + return 0; > >> +} > >> + > >> +static u64 > >> +alloc_init_sbid(struct super_block *sb) > >> +{ > >> + struct sbid_tracker *sbid; > >> + struct sbid_tracker *new = alloc_sbid(); > >> + unsigned long hash_idx = sbid_hashval(sb); > >> + u64 id = 0; > >> + > >> + if (likely(new)) { > >> + spin_lock(&layout_lock); > >> + id = ++current_sbid; > >> + new->id = (id << SBID_HASH_BITS) | (hash_idx & SBID_HASH_MASK); > >> + id = new->id; > >> + BUG_ON(id == 0); > >> + new->sb = sb; > >> + > >> + list_for_each_entry (sbid, &sbid_hashtbl[hash_idx], hash) > >> + if (sbid->sb == sb) { > >> + kfree(new); > >> + id = sbid->id; > >> + spin_unlock(&layout_lock); > >> + return id; > >> + } > >> + list_add(&new->hash, &sbid_hashtbl[hash_idx]); > >> + spin_unlock(&layout_lock); > >> + } > >> + return id; > >> +} > >> + > >> +static u64 > >> +find_create_sbid(struct super_block *sb) > >> +{ > >> + struct sbid_tracker *sbid; > >> + unsigned long hash_idx = sbid_hashval(sb); > >> + int pos = 0; > >> + u64 id = 0; > >> + > >> + spin_lock(&layout_lock); > >> + list_for_each_entry (sbid, &sbid_hashtbl[hash_idx], hash) { > >> + pos++; > >> + if (sbid->sb != sb) > >> + continue; > >> + if (pos > 1) { > >> + list_del(&sbid->hash); > >> + list_add(&sbid->hash, &sbid_hashtbl[hash_idx]); > >> + } > >> + id = sbid->id; > >> + break; > >> + } > >> + spin_unlock(&layout_lock); > >> + > >> + if (!id) > >> + id = alloc_init_sbid(sb); > >> + > >> + return id; > >> +} > >> diff --git a/fs/nfsd/pnfsd.h b/fs/nfsd/pnfsd.h > >> index 7c46791..29ea2e7 100644 > >> --- a/fs/nfsd/pnfsd.h > >> +++ b/fs/nfsd/pnfsd.h > >> @@ -36,4 +36,6 @@ > >> > >> #include <linux/nfsd/nfsd4_pnfs.h> > >> > >> +#include "xdr4.h" > >> + > >> #endif /* LINUX_NFSD_PNFSD_H */ > >> -- > >> 1.8.3.1 > >> > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in > > the body of a message to majordomo@vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, Sep 26, 2013 at 02:40:31PM -0400, Benny Halevy wrote:
> From: Benny Halevy <bhalevy@panasas.com>
This is entirely unessecary. Just make sure all layouts set the sbid
field in getdevicelist to the s_dev value of the filesystem and you
can just use user_get_super.
--
To unsubscribe from this list: send the line "unsubscribe linux-nfs" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-10-11 22:56, Christoph Hellwig wrote: > On Thu, Sep 26, 2013 at 02:40:31PM -0400, Benny Halevy wrote: >> From: Benny Halevy <bhalevy@panasas.com> > > This is entirely unessecary. Just make sure all layouts set the sbid > field in getdevicelist to the s_dev value of the filesystem and you > can just use user_get_super. That's true for filesystmes that have a meaningful s_dev, unlike exofs, but this functionality can be added later respectively. Benny -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sun, Oct 13, 2013 at 09:11:40AM +0300, Benny Halevy wrote: > On 2013-10-11 22:56, Christoph Hellwig wrote: > > On Thu, Sep 26, 2013 at 02:40:31PM -0400, Benny Halevy wrote: > >> From: Benny Halevy <bhalevy@panasas.com> > > > > This is entirely unessecary. Just make sure all layouts set the sbid > > field in getdevicelist to the s_dev value of the filesystem and you > > can just use user_get_super. > > That's true for filesystmes that have a meaningful s_dev, unlike exofs, > but this functionality can be added later respectively. Even exofs has a s_dev from the anon dev_T allocator. Given that layouts aren't supposed to surived over reboots of the server I don't see a problem with it. -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 2013-10-13 14:08, Christoph Hellwig wrote: > On Sun, Oct 13, 2013 at 09:11:40AM +0300, Benny Halevy wrote: >> On 2013-10-11 22:56, Christoph Hellwig wrote: >>> On Thu, Sep 26, 2013 at 02:40:31PM -0400, Benny Halevy wrote: >>>> From: Benny Halevy <bhalevy@panasas.com> >>> >>> This is entirely unessecary. Just make sure all layouts set the sbid >>> field in getdevicelist to the s_dev value of the filesystem and you >>> can just use user_get_super. >> >> That's true for filesystmes that have a meaningful s_dev, unlike exofs, >> but this functionality can be added later respectively. > > Even exofs has a s_dev from the anon dev_T allocator. Given that > layouts aren't supposed to surived over reboots of the server I don't > see a problem with it. As far as I can see, exofs doesn't actually doing that. Currently exofs_fill_super sets s_dev = 0; Boaz, did I miss anything? Benny > > -- > To unsubscribe from this list: send the line "unsubscribe linux-nfs" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Sun, Oct 13, 2013 at 03:44:30PM +0300, Benny Halevy wrote: > As far as I can see, exofs doesn't actually doing that. > Currently exofs_fill_super sets s_dev = 0; > Boaz, did I miss anything? Just removing that line should fix it, mount_nodev already takes care of getting a proper s_dev through set_anon_super. It'll also need to switch .kill_sb to kill_anon_super just like the other filesystems using mount_nodev. -- To unsubscribe from this list: send the line "unsubscribe linux-nfs" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/fs/nfsd/nfs4pnfsd.c b/fs/nfsd/nfs4pnfsd.c index cb28207..9a7cbc9 100644 --- a/fs/nfsd/nfs4pnfsd.c +++ b/fs/nfsd/nfs4pnfsd.c @@ -25,3 +25,123 @@ #define NFSDDBG_FACILITY NFSDDBG_PNFS +static DEFINE_SPINLOCK(layout_lock); + +/* hash table for nfsd4_pnfs_deviceid.sbid */ +#define SBID_HASH_BITS 8 +#define SBID_HASH_SIZE (1 << SBID_HASH_BITS) +#define SBID_HASH_MASK (SBID_HASH_SIZE - 1) + +struct sbid_tracker { + u64 id; + struct super_block *sb; + struct list_head hash; +}; + +static u64 current_sbid; +static struct list_head sbid_hashtbl[SBID_HASH_SIZE]; + +static unsigned long +sbid_hashval(struct super_block *sb) +{ + return hash_ptr(sb, SBID_HASH_BITS); +} + +static struct sbid_tracker * +alloc_sbid(void) +{ + return kmalloc(sizeof(struct sbid_tracker), GFP_KERNEL); +} + +static void +destroy_sbid(struct sbid_tracker *sbid) +{ + spin_lock(&layout_lock); + list_del(&sbid->hash); + spin_unlock(&layout_lock); + kfree(sbid); +} + +void +nfsd4_free_pnfs_slabs(void) +{ + int i; + struct sbid_tracker *sbid; + + for (i = 0; i < SBID_HASH_SIZE; i++) { + while (!list_empty(&sbid_hashtbl[i])) { + sbid = list_first_entry(&sbid_hashtbl[i], + struct sbid_tracker, + hash); + destroy_sbid(sbid); + } + } +} + +int +nfsd4_init_pnfs_slabs(void) +{ + int i; + + for (i = 0; i < SBID_HASH_SIZE; i++) + INIT_LIST_HEAD(&sbid_hashtbl[i]); + + return 0; +} + +static u64 +alloc_init_sbid(struct super_block *sb) +{ + struct sbid_tracker *sbid; + struct sbid_tracker *new = alloc_sbid(); + unsigned long hash_idx = sbid_hashval(sb); + u64 id = 0; + + if (likely(new)) { + spin_lock(&layout_lock); + id = ++current_sbid; + new->id = (id << SBID_HASH_BITS) | (hash_idx & SBID_HASH_MASK); + id = new->id; + BUG_ON(id == 0); + new->sb = sb; + + list_for_each_entry (sbid, &sbid_hashtbl[hash_idx], hash) + if (sbid->sb == sb) { + kfree(new); + id = sbid->id; + spin_unlock(&layout_lock); + return id; + } + list_add(&new->hash, &sbid_hashtbl[hash_idx]); + spin_unlock(&layout_lock); + } + return id; +} + +static u64 +find_create_sbid(struct super_block *sb) +{ + struct sbid_tracker *sbid; + unsigned long hash_idx = sbid_hashval(sb); + int pos = 0; + u64 id = 0; + + spin_lock(&layout_lock); + list_for_each_entry (sbid, &sbid_hashtbl[hash_idx], hash) { + pos++; + if (sbid->sb != sb) + continue; + if (pos > 1) { + list_del(&sbid->hash); + list_add(&sbid->hash, &sbid_hashtbl[hash_idx]); + } + id = sbid->id; + break; + } + spin_unlock(&layout_lock); + + if (!id) + id = alloc_init_sbid(sb); + + return id; +} diff --git a/fs/nfsd/pnfsd.h b/fs/nfsd/pnfsd.h index 7c46791..29ea2e7 100644 --- a/fs/nfsd/pnfsd.h +++ b/fs/nfsd/pnfsd.h @@ -36,4 +36,6 @@ #include <linux/nfsd/nfsd4_pnfs.h> +#include "xdr4.h" + #endif /* LINUX_NFSD_PNFSD_H */