aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-08 17:42:01 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-03-08 22:38:55 -0500
commit4fc8796d23819da814ec25b7793bde8f104f1a2a (patch)
treed86513109dd792087091b6054a983271b2536f60 /fs/nfs
parent0032a7a749a49b2c044092a1d0af5cfd0077f35d (diff)
NFSv4: Clean up nfs4_select_rw_stateid()
Ensure that we select delegation stateids first, then lock stateids and then open stateids. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4_fs.h3
-rw-r--r--fs/nfs/nfs4proc.c8
-rw-r--r--fs/nfs/nfs4state.c45
-rw-r--r--fs/nfs/nfs4xdr.c13
4 files changed, 49 insertions, 20 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h
index d1989e3f23c3..b47bdb9c1612 100644
--- a/fs/nfs/nfs4_fs.h
+++ b/fs/nfs/nfs4_fs.h
@@ -330,7 +330,8 @@ extern void nfs41_handle_server_scope(struct nfs_client *,
330 struct server_scope **); 330 struct server_scope **);
331extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); 331extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
332extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); 332extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
333extern void nfs4_select_rw_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t); 333extern void nfs4_select_rw_stateid(nfs4_stateid *, struct nfs4_state *,
334 fmode_t, fl_owner_t, pid_t);
334 335
335extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask); 336extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask);
336extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); 337extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 3578ad36a5b8..3bf5593741ee 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -1929,10 +1929,12 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
1929 1929
1930 nfs_fattr_init(fattr); 1930 nfs_fattr_init(fattr);
1931 1931
1932 if (nfs4_copy_delegation_stateid(&arg.stateid, inode, FMODE_WRITE)) { 1932 if (state != NULL) {
1933 nfs4_select_rw_stateid(&arg.stateid, state, FMODE_WRITE,
1934 current->files, current->tgid);
1935 } else if (nfs4_copy_delegation_stateid(&arg.stateid, inode,
1936 FMODE_WRITE)) {
1933 /* Use that stateid */ 1937 /* Use that stateid */
1934 } else if (state != NULL) {
1935 nfs4_select_rw_stateid(&arg.stateid, state, current->files, current->tgid);
1936 } else 1938 } else
1937 nfs4_stateid_copy(&arg.stateid, &zero_stateid); 1939 nfs4_stateid_copy(&arg.stateid, &zero_stateid);
1938 1940
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 7adc46b4c7f8..de44804d9864 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -886,28 +886,49 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
886 return 0; 886 return 0;
887} 887}
888 888
889/* 889static bool nfs4_copy_lock_stateid(nfs4_stateid *dst, struct nfs4_state *state,
890 * Byte-range lock aware utility to initialize the stateid of read/write 890 fl_owner_t fl_owner, pid_t fl_pid)
891 * requests.
892 */
893void nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid)
894{ 891{
895 struct nfs4_lock_state *lsp; 892 struct nfs4_lock_state *lsp;
896 int seq; 893 bool ret = false;
897 894
898 do {
899 seq = read_seqbegin(&state->seqlock);
900 nfs4_stateid_copy(dst, &state->stateid);
901 } while (read_seqretry(&state->seqlock, seq));
902 if (test_bit(LK_STATE_IN_USE, &state->flags) == 0) 895 if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
903 return; 896 goto out;
904 897
905 spin_lock(&state->state_lock); 898 spin_lock(&state->state_lock);
906 lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); 899 lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE);
907 if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) 900 if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) {
908 nfs4_stateid_copy(dst, &lsp->ls_stateid); 901 nfs4_stateid_copy(dst, &lsp->ls_stateid);
902 ret = true;
903 }
909 spin_unlock(&state->state_lock); 904 spin_unlock(&state->state_lock);
910 nfs4_put_lock_state(lsp); 905 nfs4_put_lock_state(lsp);
906out:
907 return ret;
908}
909
910static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
911{
912 int seq;
913
914 do {
915 seq = read_seqbegin(&state->seqlock);
916 nfs4_stateid_copy(dst, &state->stateid);
917 } while (read_seqretry(&state->seqlock, seq));
918}
919
920/*
921 * Byte-range lock aware utility to initialize the stateid of read/write
922 * requests.
923 */
924void nfs4_select_rw_stateid(nfs4_stateid *dst, struct nfs4_state *state,
925 fmode_t fmode, fl_owner_t fl_owner, pid_t fl_pid)
926{
927 if (nfs4_copy_delegation_stateid(dst, state->inode, fmode))
928 return;
929 if (nfs4_copy_lock_stateid(dst, state, fl_owner, fl_pid))
930 return;
931 nfs4_copy_open_stateid(dst, state);
911} 932}
912 933
913struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask) 934struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask)
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index e4bb8e6409a7..f7e064d997f6 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1491,12 +1491,17 @@ static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
1491 encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr); 1491 encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr);
1492} 1492}
1493 1493
1494static void encode_open_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx, int zero_seqid) 1494static void encode_open_stateid(struct xdr_stream *xdr,
1495 const struct nfs_open_context *ctx,
1496 const struct nfs_lock_context *l_ctx,
1497 fmode_t fmode,
1498 int zero_seqid)
1495{ 1499{
1496 nfs4_stateid stateid; 1500 nfs4_stateid stateid;
1497 1501
1498 if (ctx->state != NULL) { 1502 if (ctx->state != NULL) {
1499 nfs4_select_rw_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid); 1503 nfs4_select_rw_stateid(&stateid, ctx->state,
1504 fmode, l_ctx->lockowner, l_ctx->pid);
1500 if (zero_seqid) 1505 if (zero_seqid)
1501 stateid.seqid = 0; 1506 stateid.seqid = 0;
1502 encode_nfs4_stateid(xdr, &stateid); 1507 encode_nfs4_stateid(xdr, &stateid);
@@ -1510,7 +1515,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
1510 1515
1511 encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr); 1516 encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr);
1512 encode_open_stateid(xdr, args->context, args->lock_context, 1517 encode_open_stateid(xdr, args->context, args->lock_context,
1513 hdr->minorversion); 1518 FMODE_READ, hdr->minorversion);
1514 1519
1515 p = reserve_space(xdr, 12); 1520 p = reserve_space(xdr, 12);
1516 p = xdr_encode_hyper(p, args->offset); 1521 p = xdr_encode_hyper(p, args->offset);
@@ -1648,7 +1653,7 @@ static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *arg
1648 1653
1649 encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr); 1654 encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr);
1650 encode_open_stateid(xdr, args->context, args->lock_context, 1655 encode_open_stateid(xdr, args->context, args->lock_context,
1651 hdr->minorversion); 1656 FMODE_WRITE, hdr->minorversion);
1652 1657
1653 p = reserve_space(xdr, 16); 1658 p = reserve_space(xdr, 16);
1654 p = xdr_encode_hyper(p, args->offset); 1659 p = xdr_encode_hyper(p, args->offset);