diff options
Diffstat (limited to 'fs/nfs/pnfs_dev.c')
| -rw-r--r-- | fs/nfs/pnfs_dev.c | 64 | 
1 files changed, 31 insertions, 33 deletions
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index f0f8e1e22f6..6fda5228ef5 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c @@ -100,8 +100,8 @@ _find_get_deviceid(const struct pnfs_layoutdriver_type *ld,  	rcu_read_lock();  	d = _lookup_deviceid(ld, clp, id, hash); -	if (d && !atomic_inc_not_zero(&d->ref)) -		d = NULL; +	if (d != NULL) +		atomic_inc(&d->ref);  	rcu_read_unlock();  	return d;  } @@ -115,15 +115,15 @@ nfs4_find_get_deviceid(const struct pnfs_layoutdriver_type *ld,  EXPORT_SYMBOL_GPL(nfs4_find_get_deviceid);  /* - * Unhash and put deviceid + * Remove a deviceid from cache   *   * @clp nfs_client associated with deviceid   * @id the deviceid to unhash   *   * @ret the unhashed node, if found and dereferenced to zero, NULL otherwise.   */ -struct nfs4_deviceid_node * -nfs4_unhash_put_deviceid(const struct pnfs_layoutdriver_type *ld, +void +nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld,  			 const struct nfs_client *clp, const struct nfs4_deviceid *id)  {  	struct nfs4_deviceid_node *d; @@ -134,7 +134,7 @@ nfs4_unhash_put_deviceid(const struct pnfs_layoutdriver_type *ld,  	rcu_read_unlock();  	if (!d) {  		spin_unlock(&nfs4_deviceid_lock); -		return NULL; +		return;  	}  	hlist_del_init_rcu(&d->node);  	spin_unlock(&nfs4_deviceid_lock); @@ -142,28 +142,7 @@ nfs4_unhash_put_deviceid(const struct pnfs_layoutdriver_type *ld,  	/* balance the initial ref set in pnfs_insert_deviceid */  	if (atomic_dec_and_test(&d->ref)) -		return d; - -	return NULL; -} -EXPORT_SYMBOL_GPL(nfs4_unhash_put_deviceid); - -/* - * Delete a deviceid from cache - * - * @clp struct nfs_client qualifying the deviceid - * @id deviceid to delete - */ -void -nfs4_delete_deviceid(const struct pnfs_layoutdriver_type *ld, -		     const struct nfs_client *clp, const struct nfs4_deviceid *id) -{ -	struct nfs4_deviceid_node *d; - -	d = nfs4_unhash_put_deviceid(ld, clp, id); -	if (!d) -		return; -	d->ld->free_deviceid_node(d); +		d->ld->free_deviceid_node(d);  }  EXPORT_SYMBOL_GPL(nfs4_delete_deviceid); @@ -177,6 +156,7 @@ nfs4_init_deviceid_node(struct nfs4_deviceid_node *d,  	INIT_HLIST_NODE(&d->tmpnode);  	d->ld = ld;  	d->nfs_client = nfs_client; +	d->flags = 0;  	d->deviceid = *id;  	atomic_set(&d->ref, 1);  } @@ -221,16 +201,15 @@ EXPORT_SYMBOL_GPL(nfs4_insert_deviceid_node);   *   * @d deviceid node to put   * - * @ret true iff the node was deleted + * return true iff the node was deleted + * Note that since the test for d->ref == 0 is sufficient to establish + * that the node is no longer hashed in the global device id cache.   */  bool  nfs4_put_deviceid_node(struct nfs4_deviceid_node *d)  { -	if (!atomic_dec_and_lock(&d->ref, &nfs4_deviceid_lock)) +	if (!atomic_dec_and_test(&d->ref))  		return false; -	hlist_del_init_rcu(&d->node); -	spin_unlock(&nfs4_deviceid_lock); -	synchronize_rcu();  	d->ld->free_deviceid_node(d);  	return true;  } @@ -275,3 +254,22 @@ nfs4_deviceid_purge_client(const struct nfs_client *clp)  	for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++)  		_deviceid_purge_client(clp, h);  } + +/* + * Stop use of all deviceids associated with an nfs_client + */ +void +nfs4_deviceid_mark_client_invalid(struct nfs_client *clp) +{ +	struct nfs4_deviceid_node *d; +	struct hlist_node *n; +	int i; + +	rcu_read_lock(); +	for (i = 0; i < NFS4_DEVICE_ID_HASH_SIZE; i ++){ +		hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[i], node) +			if (d->nfs_client == clp) +				set_bit(NFS_DEVICEID_INVALID, &d->flags); +	} +	rcu_read_unlock(); +}  |