From: Fred Isaman <iisaman@netapp.com>
To: linux-nfs@vger.kernel.org
Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
Subject: [PATCH 07/14] pnfs: wave 2: serialize LAYOUTGET(openstateid)
Date: Mon, 20 Dec 2010 21:20:39 -0500 [thread overview]
Message-ID: <1292898046-7336-8-git-send-email-iisaman@netapp.com> (raw)
In-Reply-To: <1292898046-7336-1-git-send-email-iisaman@netapp.com>
We shouldn't send a LAYOUTGET(openstateid) unless all outstanding RPCs
using the previous stateid are completed. This requires adding a
status to encode_layoutget() to handle the case where we can't choose
an appropriate stateid (we want to use the open stateid, but a
LAYOUTGET is already out using it), and adding a count of the number
of outstanding rpc calls using layout state (which for now consist
solely of LAYOUTGETs).
Signed-off-by: Fred Isaman <iisaman@netapp.com>
---
fs/nfs/nfs4proc.c | 1 -
fs/nfs/nfs4xdr.c | 16 ++++++++++++----
fs/nfs/pnfs.c | 27 ++++++++++++++++++++++-----
fs/nfs/pnfs.h | 1 +
4 files changed, 35 insertions(+), 10 deletions(-)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 408021a..58cebac 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5342,7 +5342,6 @@ static void nfs4_layoutget_release(void *calldata)
struct nfs4_layoutget *lgp = calldata;
dprintk("--> %s\n", __func__);
- put_layout_hdr(lgp->args.inode);
if (lgp->res.layout.buf != NULL)
free_page((unsigned long) lgp->res.layout.buf);
put_nfs_open_context(lgp->args.ctx);
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index 99effb2..57e5b94 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1784,13 +1784,14 @@ encode_getdeviceinfo(struct xdr_stream *xdr,
hdr->replen += decode_getdeviceinfo_maxsz;
}
-static void
+static int
encode_layoutget(struct xdr_stream *xdr,
const struct nfs4_layoutget_args *args,
struct compound_hdr *hdr)
{
nfs4_stateid stateid;
__be32 *p;
+ int status;
p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE);
*p++ = cpu_to_be32(OP_LAYOUTGET);
@@ -1800,8 +1801,11 @@ encode_layoutget(struct xdr_stream *xdr,
p = xdr_encode_hyper(p, args->range.offset);
p = xdr_encode_hyper(p, args->range.length);
p = xdr_encode_hyper(p, args->minlength);
- pnfs_choose_layoutget_stateid(&stateid, NFS_I(args->inode)->layout,
- args->ctx->state);
+ status = pnfs_choose_layoutget_stateid(&stateid,
+ NFS_I(args->inode)->layout,
+ args->ctx->state);
+ if (status)
+ return status;
p = xdr_encode_opaque_fixed(p, &stateid.data, NFS4_STATEID_SIZE);
*p = cpu_to_be32(args->maxcount);
@@ -1814,6 +1818,7 @@ encode_layoutget(struct xdr_stream *xdr,
args->maxcount);
hdr->nops++;
hdr->replen += decode_layoutget_maxsz;
+ return 0;
}
#endif /* CONFIG_NFS_V4_1 */
@@ -2670,12 +2675,15 @@ static int nfs4_xdr_enc_layoutget(struct rpc_rqst *req, uint32_t *p,
struct compound_hdr hdr = {
.minorversion = nfs4_xdr_minorversion(&args->seq_args),
};
+ int status;
xdr_init_encode(&xdr, &req->rq_snd_buf, p);
encode_compound_hdr(&xdr, req, &hdr);
encode_sequence(&xdr, &args->seq_args, &hdr);
encode_putfh(&xdr, NFS_FH(args->inode), &hdr);
- encode_layoutget(&xdr, args, &hdr);
+ status = encode_layoutget(&xdr, args, &hdr);
+ if (status)
+ return status;
encode_nops(&hdr);
return 0;
}
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 49591e4..25b67bd 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -362,6 +362,14 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
memcpy(&lo->stateid, &new->stateid, sizeof(new->stateid));
}
+/* lget is set to 1 if called from inside send_layoutget call chain */
+static bool
+pnfs_layoutgets_blocked(struct pnfs_layout_hdr *lo, int lget)
+{
+ return (list_empty(&lo->segs) &&
+ (atomic_read(&lo->plh_outstanding) > lget));
+}
+
int
pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
struct nfs4_state *open_state)
@@ -370,7 +378,12 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
dprintk("--> %s\n", __func__);
spin_lock(&lo->inode->i_lock);
- if (list_empty(&lo->segs)) {
+ if (pnfs_layoutgets_blocked(lo, 1)) {
+ /* We avoid -EAGAIN, as that has special meaning to
+ * some callers.
+ */
+ status = -NFS4ERR_LAYOUTTRYLATER;
+ } else if (list_empty(&lo->segs)) {
int seq;
do {
@@ -405,10 +418,8 @@ send_layoutget(struct pnfs_layout_hdr *lo,
BUG_ON(ctx == NULL);
lgp = kzalloc(sizeof(*lgp), GFP_KERNEL);
- if (lgp == NULL) {
- put_layout_hdr(lo->inode);
+ if (lgp == NULL)
return NULL;
- }
lgp->args.minlength = NFS4_MAX_UINT64;
lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
lgp->args.range.iomode = iomode;
@@ -604,10 +615,16 @@ pnfs_update_layout(struct inode *ino,
if (test_bit(lo_fail_bit(iomode), &nfsi->layout->plh_flags))
goto out_unlock;
- get_layout_hdr_locked(lo); /* Matched in nfs4_layoutget_release */
+ if (pnfs_layoutgets_blocked(lo, 0))
+ goto out_unlock;
+ atomic_inc(&lo->plh_outstanding);
+
+ get_layout_hdr_locked(lo);
spin_unlock(&ino->i_lock);
lseg = send_layoutget(lo, ctx, iomode);
+ atomic_dec(&lo->plh_outstanding);
+ put_layout_hdr(ino);
out:
dprintk("%s end, state 0x%lx lseg %p\n", __func__,
nfsi->layout->plh_flags, lseg);
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 96b23bc..0b8070f 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -69,6 +69,7 @@ struct pnfs_layout_hdr {
struct list_head layouts; /* other client layouts */
struct list_head segs; /* layout segments list */
nfs4_stateid stateid;
+ atomic_t plh_outstanding; /* number of RPCs out */
unsigned long plh_flags;
struct inode *inode;
};
--
1.7.2.1
next prev parent reply other threads:[~2010-12-21 2:20 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-21 2:20 [PATCH 00/14] pnfs wave 2 submission Fred Isaman
2010-12-21 2:20 ` [PATCH 01/14] pnfs: wave 2: fix incorrect comment in destroy_lseg Fred Isaman
2010-12-21 2:20 ` [PATCH 02/14] pnfs: wave 2: remove unnecessary field lgp->status Fred Isaman
2010-12-21 2:20 ` [PATCH 03/14] pnfs: wave 2: rename lo->state to lo->plh_flags Fred Isaman
2010-12-21 15:21 ` Christoph Hellwig
2010-12-21 15:42 ` Fred Isaman
2010-12-21 2:20 ` [PATCH 04/14] pnfs: wave 2: change layout state seqlock to a spinlock Fred Isaman
2010-12-21 15:26 ` Christoph Hellwig
2010-12-21 15:47 ` Fred Isaman
2010-12-21 2:20 ` [PATCH 05/14] pnfs: wave 2: change how lsegs are removed from layout list Fred Isaman
2010-12-21 2:20 ` [PATCH 06/14] pnfs: wave 2: layoutget rpc code cleanup Fred Isaman
2010-12-21 2:20 ` Fred Isaman [this message]
2010-12-21 2:20 ` [PATCH 08/14] pnfs: wave 2: Add layout to client list before sending rpc Fred Isaman
2010-12-21 2:20 ` [PATCH 09/14] pnfs: wave 2: check that partial LAYOUTGET return is ignored Fred Isaman
2010-12-21 2:20 ` [PATCH 10/14] pnfs: wave 2: change lo refcounting to atomic_t Fred Isaman
2010-12-21 2:20 ` [PATCH 11/14] pnfs: wave 2: CB_LAYOUTRECALL xdr code Fred Isaman
2010-12-21 2:20 ` [PATCH 12/14] pnfs: wave 2: add CB_LAYOUTRECALL handling Fred Isaman
2010-12-21 2:20 ` [PATCH 13/14] pnfs: wave 2: update nfs4_callback_recallany to handle layouts Fred Isaman
2010-12-21 2:20 ` [PATCH 14/14] pnfs: wave 2: layout roc code Fred Isaman
2010-12-21 15:20 ` [PATCH 00/14] pnfs wave 2 submission Christoph Hellwig
2010-12-21 15:38 ` Benny Halevy
2010-12-21 15:40 ` Fred Isaman
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1292898046-7336-8-git-send-email-iisaman@netapp.com \
--to=iisaman@netapp.com \
--cc=Trond.Myklebust@netapp.com \
--cc=linux-nfs@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).