Эх сурвалжийг харах

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>
Andy Adamson 14 жил өмнө
parent
commit
c47abcf8ff

+ 10 - 0
fs/nfs/nfs4filelayout.c

@@ -334,6 +334,9 @@ filelayout_read_pagelist(struct nfs_read_data *data)
 		__func__, data->inode->i_ino,
 		__func__, data->inode->i_ino,
 		data->args.pgbase, (size_t)data->args.count, offset);
 		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 */
 	/* Retrieve the correct rpc_client for the byte range */
 	j = nfs4_fl_calc_j_index(lseg, offset);
 	j = nfs4_fl_calc_j_index(lseg, offset);
 	idx = nfs4_fl_calc_ds_index(lseg, j);
 	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;
 	struct nfs_fh *fh;
 	int status;
 	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 */
 	/* Retrieve the correct rpc_client for the byte range */
 	j = nfs4_fl_calc_j_index(lseg, offset);
 	j = nfs4_fl_calc_j_index(lseg, offset);
 	idx = nfs4_fl_calc_ds_index(lseg, j);
 	idx = nfs4_fl_calc_ds_index(lseg, j);
@@ -456,6 +462,10 @@ filelayout_check_layout(struct pnfs_layout_hdr *lo,
 			goto out;
 			goto out;
 	} else
 	} else
 		dsaddr = container_of(d, struct nfs4_file_layout_dsaddr, id_node);
 		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;
 	fl->dsaddr = dsaddr;
 
 
 	if (fl->first_stripe_index < 0 ||
 	if (fl->first_stripe_index < 0 ||

+ 6 - 0
fs/nfs/nfs4filelayout.h

@@ -96,6 +96,12 @@ FILELAYOUT_LSEG(struct pnfs_layout_segment *lseg)
 			    generic_hdr);
 			    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 *
 extern struct nfs_fh *
 nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
 nfs4_fl_select_ds_fh(struct pnfs_layout_segment *lseg, u32 j);
 
 

+ 3 - 0
fs/nfs/pnfs.c

@@ -452,6 +452,9 @@ pnfs_destroy_all_layouts(struct nfs_client *clp)
 	struct pnfs_layout_hdr *lo;
 	struct pnfs_layout_hdr *lo;
 	LIST_HEAD(tmp_list);
 	LIST_HEAD(tmp_list);
 
 
+	nfs4_deviceid_mark_client_invalid(clp);
+	nfs4_deviceid_purge_client(clp);
+
 	spin_lock(&clp->cl_lock);
 	spin_lock(&clp->cl_lock);
 	rcu_read_lock();
 	rcu_read_lock();
 	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {
 	list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link) {

+ 8 - 0
fs/nfs/pnfs.h

@@ -192,12 +192,20 @@ struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
 					       enum pnfs_iomode iomode,
 					       enum pnfs_iomode iomode,
 					       gfp_t gfp_flags);
 					       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 */
 /* pnfs_dev.c */
 struct nfs4_deviceid_node {
 struct nfs4_deviceid_node {
 	struct hlist_node		node;
 	struct hlist_node		node;
 	struct hlist_node		tmpnode;
 	struct hlist_node		tmpnode;
 	const struct pnfs_layoutdriver_type *ld;
 	const struct pnfs_layoutdriver_type *ld;
 	const struct nfs_client		*nfs_client;
 	const struct nfs_client		*nfs_client;
+	unsigned long 			flags;
 	struct nfs4_deviceid		deviceid;
 	struct nfs4_deviceid		deviceid;
 	atomic_t			ref;
 	atomic_t			ref;
 };
 };

+ 20 - 0
fs/nfs/pnfs_dev.c

@@ -156,6 +156,7 @@ nfs4_init_deviceid_node(struct nfs4_deviceid_node *d,
 	INIT_HLIST_NODE(&d->tmpnode);
 	INIT_HLIST_NODE(&d->tmpnode);
 	d->ld = ld;
 	d->ld = ld;
 	d->nfs_client = nfs_client;
 	d->nfs_client = nfs_client;
+	d->flags = 0;
 	d->deviceid = *id;
 	d->deviceid = *id;
 	atomic_set(&d->ref, 1);
 	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++)
 	for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++)
 		_deviceid_purge_client(clp, 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();
+}