Skip to content

Commit

Permalink
NFSv4.1: do not use deviceids after MDS clientid invalidation
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Andy Adamson authored and Trond Myklebust committed Jul 12, 2011
1 parent a56aaa0 commit c47abcf
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 0 deletions.
10 changes: 10 additions & 0 deletions fs/nfs/nfs4filelayout.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 ||
Expand Down
6 changes: 6 additions & 0 deletions fs/nfs/nfs4filelayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 3 additions & 0 deletions fs/nfs/pnfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions fs/nfs/pnfs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
20 changes: 20 additions & 0 deletions fs/nfs/pnfs_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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();
}

0 comments on commit c47abcf

Please sign in to comment.