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@xxxxxxxxxxx> > > Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx> > [pnfsd: alloc_sid should kmalloc a object not a pointer] > Signed-off-by: Bian Naimeng <biannm@xxxxxxxxxxxxxx> > Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxx> > Signed-off-by: Benny Halevy <bhalevy@xxxxxxxxxxxxxxx> > --- > 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@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html