Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 366d5052 authored by Andy Adamson's avatar Andy Adamson Committed by Trond Myklebust
Browse files

NFSv4.1 mark layout when already returned



When the file layout driver is fencing a DS, _pnfs_return_layout can be
called mulitple times per inode due to in-flight i/o referencing lsegs on it's
plh_segs list.

Remember that LAYOUTRETURN has been called, and do not call it again.
Allow LAYOUTRETURNs after a subsequent LAYOUTGET.

Signed-off-by: default avatarAndy Adamson <andros@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent baf6c2a4
Loading
Loading
Loading
Loading
+8 −2
Original line number Diff line number Diff line
@@ -662,11 +662,11 @@ _pnfs_return_layout(struct inode *ino)
	nfs4_stateid stateid;
	int status = 0;

	dprintk("--> %s\n", __func__);
	dprintk("NFS: %s for inode %lu\n", __func__, ino->i_ino);

	spin_lock(&ino->i_lock);
	lo = nfsi->layout;
	if (!lo) {
	if (!lo || pnfs_test_layout_returned(lo)) {
		spin_unlock(&ino->i_lock);
		dprintk("%s: no layout to return\n", __func__);
		return status;
@@ -676,6 +676,7 @@ _pnfs_return_layout(struct inode *ino)
	get_layout_hdr(lo);
	mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
	lo->plh_block_lgets++;
	pnfs_mark_layout_returned(lo);
	spin_unlock(&ino->i_lock);
	pnfs_free_lseg_list(&tmp_list);

@@ -686,6 +687,7 @@ _pnfs_return_layout(struct inode *ino)
		status = -ENOMEM;
		set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags);
		set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags);
		pnfs_clear_layout_returned(lo);
		put_layout_hdr(lo);
		goto out;
	}
@@ -1075,6 +1077,10 @@ pnfs_update_layout(struct inode *ino,
	get_layout_hdr(lo);
	if (list_empty(&lo->plh_segs))
		first = true;

	/* Enable LAYOUTRETURNs */
	pnfs_clear_layout_returned(lo);

	spin_unlock(&ino->i_lock);
	if (first) {
		/* The lo must be on the clp list if there is any
+19 −0
Original line number Diff line number Diff line
@@ -64,6 +64,7 @@ enum {
	NFS_LAYOUT_ROC,			/* some lseg had roc bit set */
	NFS_LAYOUT_DESTROYED,		/* no new use of layout allowed */
	NFS_LAYOUT_INVALID,		/* layout is being destroyed */
	NFS_LAYOUT_RETURNED,		/* layout has already been returned */
};

enum layoutdriver_policy_flags {
@@ -255,6 +256,24 @@ struct nfs4_deviceid_node *nfs4_insert_deviceid_node(struct nfs4_deviceid_node *
bool nfs4_put_deviceid_node(struct nfs4_deviceid_node *);
void nfs4_deviceid_purge_client(const struct nfs_client *);

static inline void
pnfs_mark_layout_returned(struct pnfs_layout_hdr *lo)
{
	set_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
}

static inline void
pnfs_clear_layout_returned(struct pnfs_layout_hdr *lo)
{
	clear_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
}

static inline bool
pnfs_test_layout_returned(struct pnfs_layout_hdr *lo)
{
	return test_bit(NFS_LAYOUT_RETURNED, &lo->plh_flags);
}

static inline int lo_fail_bit(u32 iomode)
{
	return iomode == IOMODE_RW ?