diff options
Diffstat (limited to 'fs/nfs/nfs4filelayoutdev.c')
| -rw-r--r-- | fs/nfs/nfs4filelayoutdev.c | 104 | 
1 files changed, 13 insertions, 91 deletions
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 42e32663727..eda4527a57e 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c @@ -37,30 +37,6 @@  #define NFSDBG_FACILITY		NFSDBG_PNFS_LD  /* - * Device ID RCU cache. A device ID is unique per client ID and layout type. - */ -#define NFS4_FL_DEVICE_ID_HASH_BITS	5 -#define NFS4_FL_DEVICE_ID_HASH_SIZE	(1 << NFS4_FL_DEVICE_ID_HASH_BITS) -#define NFS4_FL_DEVICE_ID_HASH_MASK	(NFS4_FL_DEVICE_ID_HASH_SIZE - 1) - -static inline u32 -nfs4_fl_deviceid_hash(struct nfs4_deviceid *id) -{ -	unsigned char *cptr = (unsigned char *)id->data; -	unsigned int nbytes = NFS4_DEVICEID4_SIZE; -	u32 x = 0; - -	while (nbytes--) { -		x *= 37; -		x += *cptr++; -	} -	return x & NFS4_FL_DEVICE_ID_HASH_MASK; -} - -static struct hlist_head filelayout_deviceid_cache[NFS4_FL_DEVICE_ID_HASH_SIZE]; -static DEFINE_SPINLOCK(filelayout_deviceid_lock); - -/*   * Data server cache   *   * Data servers can be mapped to different device ids. @@ -89,27 +65,6 @@ print_ds(struct nfs4_pnfs_ds *ds)  		ds->ds_clp ? ds->ds_clp->cl_exchange_flags : 0);  } -void -print_ds_list(struct nfs4_file_layout_dsaddr *dsaddr) -{ -	int i; - -	ifdebug(FACILITY) { -		printk("%s dsaddr->ds_num %d\n", __func__, -		       dsaddr->ds_num); -		for (i = 0; i < dsaddr->ds_num; i++) -			print_ds(dsaddr->ds_list[i]); -	} -} - -void print_deviceid(struct nfs4_deviceid *id) -{ -	u32 *p = (u32 *)id; - -	dprintk("%s: device id= [%x%x%x%x]\n", __func__, -		p[0], p[1], p[2], p[3]); -} -  /* nfs4_ds_cache_lock is held */  static struct nfs4_pnfs_ds *  _data_server_lookup_locked(u32 ip_addr, u32 port) @@ -207,7 +162,7 @@ nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)  	struct nfs4_pnfs_ds *ds;  	int i; -	print_deviceid(&dsaddr->deviceid); +	nfs4_print_deviceid(&dsaddr->id_node.deviceid);  	for (i = 0; i < dsaddr->ds_num; i++) {  		ds = dsaddr->ds_list[i]; @@ -431,8 +386,8 @@ decode_device(struct inode *ino, struct pnfs_device *pdev, gfp_t gfp_flags)  	dsaddr->stripe_indices = stripe_indices;  	stripe_indices = NULL;  	dsaddr->ds_num = num; -	dsaddr->nfs_client = NFS_SERVER(ino)->nfs_client; -	memcpy(&dsaddr->deviceid, &pdev->dev_id, sizeof(pdev->dev_id)); +	nfs4_init_deviceid_node(&dsaddr->id_node, NFS_SERVER(ino)->nfs_client, +				&pdev->dev_id);  	for (i = 0; i < dsaddr->ds_num; i++) {  		int j; @@ -505,8 +460,8 @@ out_err:  static struct nfs4_file_layout_dsaddr *  decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_flags)  { -	struct nfs4_file_layout_dsaddr *d, *new; -	long hash; +	struct nfs4_deviceid_node *d; +	struct nfs4_file_layout_dsaddr *n, *new;  	new = decode_device(inode, dev, gfp_flags);  	if (!new) { @@ -515,20 +470,13 @@ decode_and_add_device(struct inode *inode, struct pnfs_device *dev, gfp_t gfp_fl  		return NULL;  	} -	spin_lock(&filelayout_deviceid_lock); -	d = nfs4_fl_find_get_deviceid(new->nfs_client, &new->deviceid); -	if (d) { -		spin_unlock(&filelayout_deviceid_lock); +	d = nfs4_insert_deviceid_node(&new->id_node); +	n = container_of(d, struct nfs4_file_layout_dsaddr, id_node); +	if (n != new) {  		nfs4_fl_free_deviceid(new); -		return d; +		return n;  	} -	INIT_HLIST_NODE(&new->node); -	atomic_set(&new->ref, 1); -	hash = nfs4_fl_deviceid_hash(&new->deviceid); -	hlist_add_head_rcu(&new->node, &filelayout_deviceid_cache[hash]); -	spin_unlock(&filelayout_deviceid_lock); -  	return new;  } @@ -600,34 +548,8 @@ out_free:  void  nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr)  { -	if (atomic_dec_and_lock(&dsaddr->ref, &filelayout_deviceid_lock)) { -		hlist_del_rcu(&dsaddr->node); -		spin_unlock(&filelayout_deviceid_lock); - -		synchronize_rcu(); +	if (nfs4_put_deviceid_node(&dsaddr->id_node))  		nfs4_fl_free_deviceid(dsaddr); -	} -} - -struct nfs4_file_layout_dsaddr * -nfs4_fl_find_get_deviceid(struct nfs_client *clp, struct nfs4_deviceid *id) -{ -	struct nfs4_file_layout_dsaddr *d; -	struct hlist_node *n; -	long hash = nfs4_fl_deviceid_hash(id); - -	rcu_read_lock(); -	hlist_for_each_entry_rcu(d, n, &filelayout_deviceid_cache[hash], node) { -		if (d->nfs_client == clp && !memcmp(&d->deviceid, id, sizeof(*id))) { -			if (!atomic_inc_not_zero(&d->ref)) -				goto fail; -			rcu_read_unlock(); -			return d; -		} -	} -fail: -	rcu_read_unlock(); -	return NULL;  }  /* @@ -675,15 +597,15 @@ static void  filelayout_mark_devid_negative(struct nfs4_file_layout_dsaddr *dsaddr,  			       int err, u32 ds_addr)  { -	u32 *p = (u32 *)&dsaddr->deviceid; +	u32 *p = (u32 *)&dsaddr->id_node.deviceid;  	printk(KERN_ERR "NFS: data server %x connection error %d."  		" Deviceid [%x%x%x%x] marked out of use.\n",  		ds_addr, err, p[0], p[1], p[2], p[3]); -	spin_lock(&filelayout_deviceid_lock); +	spin_lock(&nfs4_ds_cache_lock);  	dsaddr->flags |= NFS4_DEVICE_ID_NEG_ENTRY; -	spin_unlock(&filelayout_deviceid_lock); +	spin_unlock(&nfs4_ds_cache_lock);  }  struct nfs4_pnfs_ds *  |