提交 cf7d63f1 编写于 作者: F Fred Isaman 提交者: Trond Myklebust

pnfs: serialize LAYOUTGET(openstateid)

We shouldn't send a LAYOUTGET(openstateid) unless all outstanding RPCs
using the previous stateid are completed.  This requires choosing the
stateid to encode earlier, so we can abort if one is not available (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: NFred Isaman <iisaman@netapp.com>
Signed-off-by: NTrond Myklebust <Trond.Myklebust@netapp.com>
上级 c31663d4
...@@ -5304,6 +5304,12 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata) ...@@ -5304,6 +5304,12 @@ nfs4_layoutget_prepare(struct rpc_task *task, void *calldata)
if (nfs4_setup_sequence(server, &lgp->args.seq_args, if (nfs4_setup_sequence(server, &lgp->args.seq_args,
&lgp->res.seq_res, 0, task)) &lgp->res.seq_res, 0, task))
return; return;
if (pnfs_choose_layoutget_stateid(&lgp->args.stateid,
NFS_I(lgp->args.inode)->layout,
lgp->args.ctx->state)) {
rpc_exit(task, NFS4_OK);
return;
}
rpc_call_start(task); rpc_call_start(task);
} }
...@@ -5338,7 +5344,6 @@ static void nfs4_layoutget_release(void *calldata) ...@@ -5338,7 +5344,6 @@ static void nfs4_layoutget_release(void *calldata)
struct nfs4_layoutget *lgp = calldata; struct nfs4_layoutget *lgp = calldata;
dprintk("--> %s\n", __func__); dprintk("--> %s\n", __func__);
put_layout_hdr(lgp->args.inode);
if (lgp->res.layout.buf != NULL) if (lgp->res.layout.buf != NULL)
free_page((unsigned long) lgp->res.layout.buf); free_page((unsigned long) lgp->res.layout.buf);
put_nfs_open_context(lgp->args.ctx); put_nfs_open_context(lgp->args.ctx);
......
...@@ -1787,7 +1787,6 @@ encode_layoutget(struct xdr_stream *xdr, ...@@ -1787,7 +1787,6 @@ encode_layoutget(struct xdr_stream *xdr,
const struct nfs4_layoutget_args *args, const struct nfs4_layoutget_args *args,
struct compound_hdr *hdr) struct compound_hdr *hdr)
{ {
nfs4_stateid stateid;
__be32 *p; __be32 *p;
p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE); p = reserve_space(xdr, 44 + NFS4_STATEID_SIZE);
...@@ -1798,9 +1797,7 @@ encode_layoutget(struct xdr_stream *xdr, ...@@ -1798,9 +1797,7 @@ encode_layoutget(struct xdr_stream *xdr,
p = xdr_encode_hyper(p, args->range.offset); p = xdr_encode_hyper(p, args->range.offset);
p = xdr_encode_hyper(p, args->range.length); p = xdr_encode_hyper(p, args->range.length);
p = xdr_encode_hyper(p, args->minlength); p = xdr_encode_hyper(p, args->minlength);
pnfs_choose_layoutget_stateid(&stateid, NFS_I(args->inode)->layout, p = xdr_encode_opaque_fixed(p, &args->stateid.data, NFS4_STATEID_SIZE);
args->ctx->state);
p = xdr_encode_opaque_fixed(p, &stateid.data, NFS4_STATEID_SIZE);
*p = cpu_to_be32(args->maxcount); *p = cpu_to_be32(args->maxcount);
dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n", dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n",
......
...@@ -371,6 +371,14 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, ...@@ -371,6 +371,14 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo,
memcpy(&lo->plh_stateid, &new->stateid, sizeof(new->stateid)); memcpy(&lo->plh_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->plh_segs) &&
(atomic_read(&lo->plh_outstanding) > lget));
}
int int
pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
struct nfs4_state *open_state) struct nfs4_state *open_state)
...@@ -379,7 +387,9 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo, ...@@ -379,7 +387,9 @@ pnfs_choose_layoutget_stateid(nfs4_stateid *dst, struct pnfs_layout_hdr *lo,
dprintk("--> %s\n", __func__); dprintk("--> %s\n", __func__);
spin_lock(&lo->plh_inode->i_lock); spin_lock(&lo->plh_inode->i_lock);
if (list_empty(&lo->plh_segs)) { if (pnfs_layoutgets_blocked(lo, 1)) {
status = -EAGAIN;
} else if (list_empty(&lo->plh_segs)) {
int seq; int seq;
do { do {
...@@ -414,10 +424,8 @@ send_layoutget(struct pnfs_layout_hdr *lo, ...@@ -414,10 +424,8 @@ send_layoutget(struct pnfs_layout_hdr *lo,
BUG_ON(ctx == NULL); BUG_ON(ctx == NULL);
lgp = kzalloc(sizeof(*lgp), GFP_KERNEL); lgp = kzalloc(sizeof(*lgp), GFP_KERNEL);
if (lgp == NULL) { if (lgp == NULL)
put_layout_hdr(lo->plh_inode);
return NULL; return NULL;
}
lgp->args.minlength = NFS4_MAX_UINT64; lgp->args.minlength = NFS4_MAX_UINT64;
lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE; lgp->args.maxcount = PNFS_LAYOUT_MAXSIZE;
lgp->args.range.iomode = iomode; lgp->args.range.iomode = iomode;
...@@ -613,10 +621,16 @@ pnfs_update_layout(struct inode *ino, ...@@ -613,10 +621,16 @@ pnfs_update_layout(struct inode *ino,
if (test_bit(lo_fail_bit(iomode), &nfsi->layout->plh_flags)) if (test_bit(lo_fail_bit(iomode), &nfsi->layout->plh_flags))
goto out_unlock; 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); spin_unlock(&ino->i_lock);
lseg = send_layoutget(lo, ctx, iomode); lseg = send_layoutget(lo, ctx, iomode);
atomic_dec(&lo->plh_outstanding);
put_layout_hdr(ino);
out: out:
dprintk("%s end, state 0x%lx lseg %p\n", __func__, dprintk("%s end, state 0x%lx lseg %p\n", __func__,
nfsi->layout->plh_flags, lseg); nfsi->layout->plh_flags, lseg);
......
...@@ -69,6 +69,7 @@ struct pnfs_layout_hdr { ...@@ -69,6 +69,7 @@ struct pnfs_layout_hdr {
struct list_head plh_layouts; /* other client layouts */ struct list_head plh_layouts; /* other client layouts */
struct list_head plh_segs; /* layout segments list */ struct list_head plh_segs; /* layout segments list */
nfs4_stateid plh_stateid; nfs4_stateid plh_stateid;
atomic_t plh_outstanding; /* number of RPCs out */
unsigned long plh_flags; unsigned long plh_flags;
struct inode *plh_inode; struct inode *plh_inode;
}; };
......
...@@ -208,6 +208,7 @@ struct nfs4_layoutget_args { ...@@ -208,6 +208,7 @@ struct nfs4_layoutget_args {
struct inode *inode; struct inode *inode;
struct nfs_open_context *ctx; struct nfs_open_context *ctx;
struct nfs4_sequence_args seq_args; struct nfs4_sequence_args seq_args;
nfs4_stateid stateid;
}; };
struct nfs4_layoutget_res { struct nfs4_layoutget_res {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册