summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2011-06-15 17:52:40 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2011-07-12 13:40:29 -0400
commitc47abcf8ff4d0c56d20ce541e80d3e1c975f54b5 (patch)
tree9fc0bfddd899e415f9943a403b647ed7b05da71b
parenta56aaa02b1f723e28b41d339ddff02e958d32d43 (diff)
downloadlinux-3.10-c47abcf8ff4d0c56d20ce541e80d3e1c975f54b5.tar.gz
linux-3.10-c47abcf8ff4d0c56d20ce541e80d3e1c975f54b5.tar.bz2
linux-3.10-c47abcf8ff4d0c56d20ce541e80d3e1c975f54b5.zip
NFSv4.1: do not use deviceids after MDS clientid invalidation
Mark all deviceids established under an expired MDS clientid as invalid. Stop all new i/o through DS and send through the MDS. Don't use any new LAYOUTGETs that use the invalid deviceid. Purge all layouts established under the expired MDS clientid. Remove the MDS clientid deviceid and data servers reference Signed-off-by: Andy Adamson <andros@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs4filelayout.c10
-rw-r--r--fs/nfs/nfs4filelayout.h6
-rw-r--r--fs/nfs/pnfs.c3
-rw-r--r--fs/nfs/pnfs.h8
-rw-r--r--fs/nfs/pnfs_dev.c20
5 files changed, 47 insertions, 0 deletions
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c
index 51c19093022..af9bf9eed4c 100644
--- a/fs/nfs/nfs4filelayout.c
+++ b/fs/nfs/nfs4filelayout.c
@@ -334,6 +334,9 @@ filelayout_read_pagelist(struct nfs_read_data *data)
__func__, data->inode->i_ino,
data->args.pgbase, (size_t)data->args.count, offset);
+ if (test_bit(NFS_DEVICEID_INVALID, &FILELAYOUT_DEVID_NODE(lseg)->flags))
+ return PNFS_NOT_ATTEMPTED;
+
/* Retrieve the correct rpc_client for the byte range */
j = nfs4_fl_calc_j_index(lseg, offset);
idx = nfs4_fl_calc_ds_index(lseg, j);
@@ -373,6 +376,9 @@ filelayout_write_pagelist(struct nfs_write_data *data, int sync)
struct nfs_fh *fh;
int status;
+ if (test_bit(NFS_DEVICEID_INVALID, &FILELAYOUT_DEVID_NODE(lseg)->flags))
+ return PNFS_NOT_ATTEMPTED;
+
/* Retrieve the correct rpc_client for the byte range */
j = nfs4_fl_calc_j_index(lseg, offset);
idx = nfs4_fl_calc_ds_index(lseg, j);
@@ -456,6 +462,10 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
goto out;
} else
dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
+ /* Found deviceid is being reaped */
+ if (test_bit(NFS_DEVICEID_INVALID, &dsaddr->id_node.flags))
+ goto out_put;
+
fl->dsaddr = dsaddr;
if (fl->first_stripe_index < 0 ||
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h
index 68cce730b80..2e42284253f 100644
--- a/fs/nfs/nfs4filelayout.h
+++ b/fs/nfs/nfs4filelayout.h
@@ -96,6 +96,12 @@ FILELAYOUT_LSEG(struct pnfs_layout_segment *lseg)
generic_hdr);
}
+static inline struct nfs4_deviceid_node *
+FILELAYOUT_DEVID_NODE(struct pnfs_layout_segment *lseg)
+{
+ return &FILELAYOUT_LSEG(lseg)->dsaddr->id_node;
+}
+
extern struct nfs_fh *
nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 5fc2e5d755a..5b3cc3f4bb3 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -452,6 +452,9 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
struct pnfs_layout_hdr *lo;
LIST_HEAD(tmp_list);
+ nfs4_deviceid_mark_client_invalid(clp);
+ nfs4_deviceid_purge_client(clp);
+
spin_lock(&clp->cl_lock);
rcu_read_lock();
list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 678c4c7b14d..a59736eae6e 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -192,12 +192,20 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
enum pnfs_iomode iomode,
gfp_t gfp_flags);
+void nfs4_deviceid_mark_client_invalid(struct nfs_client *clp);
+
+/* nfs4_deviceid_flags */
+enum {
+ NFS_DEVICEID_INVALID = 0, /* set when MDS clientid recalled */
+};
+
/* pnfs_dev.c */
struct nfs4_deviceid_node {
struct hlist_node node;
struct hlist_node tmpnode;
const struct pnfs_layoutdriver_type *ld;
const struct nfs_client *nfs_client;
+ unsigned long flags;
struct nfs4_deviceid deviceid;
atomic_t ref;
};
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c
index fb9498d91f6..6fda5228ef5 100644
--- a/fs/nfs/pnfs_dev.c
+++ b/fs/nfs/pnfs_dev.c
@@ -156,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);
}
@@ -253,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();
+}