diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-03-08 17:42:01 -0500 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2012-03-08 22:38:55 -0500 |
commit | 4fc8796d23819da814ec25b7793bde8f104f1a2a (patch) | |
tree | d86513109dd792087091b6054a983271b2536f60 /fs | |
parent | 0032a7a749a49b2c044092a1d0af5cfd0077f35d (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')
-rw-r--r-- | fs/nfs/nfs4_fs.h | 3 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 8 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 45 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 13 |
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 **); |
331 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | 331 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); |
332 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); | 332 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
333 | extern void nfs4_select_rw_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t); | 333 | extern void nfs4_select_rw_stateid(nfs4_stateid *, struct nfs4_state *, |
334 | fmode_t, fl_owner_t, pid_t); | ||
334 | 335 | ||
335 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask); | 336 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask); |
336 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); | 337 | extern 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 | /* | 889 | static 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 | */ | ||
893 | void 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); |
906 | out: | ||
907 | return ret; | ||
908 | } | ||
909 | |||
910 | static 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 | */ | ||
924 | void 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 | ||
913 | struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask) | 934 | struct 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 | ||
1494 | static void encode_open_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx, int zero_seqid) | 1494 | static 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); |