Commit 2a4c8994eeef50796015f8a2005e4a75c1929166

Authored by Trond Myklebust
1 parent 39a50b42f7

NFSv4.1: Fix umount when filelayout DS is also the MDS

Currently there is a 'chicken and egg' issue when the DS is also the mounted
MDS. The nfs_match_client() reference from nfs4_set_ds_client bumps the
cl_count, the nfs_client is not freed at umount, and nfs4_deviceid_purge_client
is not called to dereference the MDS usage of a deviceid which holds a
reference to the DS nfs_client.  The result is the umount program returns,
but the nfs_client is not freed, and the cl_session hearbeat continues.

The MDS (and all other nfs mounts) lose their last nfs_client reference in
nfs_free_server when the last nfs_server (fsid) is umounted.
The file layout DS lose their last nfs_client reference in destroy_ds
when the last deviceid referencing the data server is put and destroy_ds is
called. This is triggered by a call to nfs4_deviceid_purge_client which
removes references to a pNFS deviceid used by an MDS mount.

The fix is to track how many pnfs enabled filesystems are mounted from
this server, and then to purge the device id cache once that count reaches
zero.

Reported-by: Jorge Mora <Jorge.Mora@netapp.com>
Reported-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>

Showing 3 changed files with 6 additions and 1 deletions Side-by-side Diff

... ... @@ -207,7 +207,6 @@
207 207 static void nfs4_shutdown_session(struct nfs_client *clp)
208 208 {
209 209 if (nfs4_has_session(clp)) {
210   - nfs4_deviceid_purge_client(clp);
211 210 nfs4_destroy_session(clp->cl_session);
212 211 nfs4_destroy_clientid(clp);
213 212 }
... ... @@ -80,6 +80,9 @@
80 80 if (nfss->pnfs_curr_ld) {
81 81 if (nfss->pnfs_curr_ld->clear_layoutdriver)
82 82 nfss->pnfs_curr_ld->clear_layoutdriver(nfss);
  83 + /* Decrement the MDS count. Purge the deviceid cache if zero */
  84 + if (atomic_dec_and_test(&nfss->nfs_client->cl_mds_count))
  85 + nfs4_deviceid_purge_client(nfss->nfs_client);
83 86 module_put(nfss->pnfs_curr_ld->owner);
84 87 }
85 88 nfss->pnfs_curr_ld = NULL;
... ... @@ -127,6 +130,8 @@
127 130 module_put(ld_type->owner);
128 131 goto out_no_driver;
129 132 }
  133 + /* Bump the MDS count */
  134 + atomic_inc(&server->nfs_client->cl_mds_count);
130 135  
131 136 dprintk("%s: pNFS module for %u set\n", __func__, id);
132 137 return;
include/linux/nfs_fs_sb.h
... ... @@ -25,6 +25,7 @@
25 25 */
26 26 struct nfs_client {
27 27 atomic_t cl_count;
  28 + atomic_t cl_mds_count;
28 29 int cl_cons_state; /* current construction state (-ve: init error) */
29 30 #define NFS_CS_READY 0 /* ready to be used */
30 31 #define NFS_CS_INITING 1 /* busy initialising */