diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-07-01 12:49:11 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-07-30 14:46:10 -0400 |
commit | 77041ed9b49a9e10f374bfa6e482d30ee7a3d46e (patch) | |
tree | 8e5f98880863aaaa761735cb483730f8520d6b26 /fs/nfs | |
parent | d3c7b7ccc199ee564177ee914c04771d6bc00295 (diff) |
NFSv4: Ensure the lockowners are labelled using the fl_owner and/or fl_pid
flock locks want to be labelled using the process pid, while posix locks
want to be labelled using the fl_owner.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4_fs.h | 15 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 45 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 2 |
4 files changed, 50 insertions, 14 deletions
diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index deaf37f5a7a9..311e15cc8af0 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h | |||
@@ -142,10 +142,20 @@ enum { | |||
142 | * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN) | 142 | * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN) |
143 | */ | 143 | */ |
144 | 144 | ||
145 | struct nfs4_lock_owner { | ||
146 | unsigned int lo_type; | ||
147 | #define NFS4_ANY_LOCK_TYPE (0U) | ||
148 | #define NFS4_FLOCK_LOCK_TYPE (1U << 0) | ||
149 | #define NFS4_POSIX_LOCK_TYPE (1U << 1) | ||
150 | union { | ||
151 | fl_owner_t posix_owner; | ||
152 | pid_t flock_owner; | ||
153 | } lo_u; | ||
154 | }; | ||
155 | |||
145 | struct nfs4_lock_state { | 156 | struct nfs4_lock_state { |
146 | struct list_head ls_locks; /* Other lock stateids */ | 157 | struct list_head ls_locks; /* Other lock stateids */ |
147 | struct nfs4_state * ls_state; /* Pointer to open state */ | 158 | struct nfs4_state * ls_state; /* Pointer to open state */ |
148 | fl_owner_t ls_owner; /* POSIX lock owner */ | ||
149 | #define NFS_LOCK_INITIALIZED 1 | 159 | #define NFS_LOCK_INITIALIZED 1 |
150 | int ls_flags; | 160 | int ls_flags; |
151 | struct nfs_seqid_counter ls_seqid; | 161 | struct nfs_seqid_counter ls_seqid; |
@@ -153,6 +163,7 @@ struct nfs4_lock_state { | |||
153 | struct nfs_unique_id ls_id; | 163 | struct nfs_unique_id ls_id; |
154 | nfs4_stateid ls_stateid; | 164 | nfs4_stateid ls_stateid; |
155 | atomic_t ls_count; | 165 | atomic_t ls_count; |
166 | struct nfs4_lock_owner ls_owner; | ||
156 | }; | 167 | }; |
157 | 168 | ||
158 | /* bits for nfs4_state->flags */ | 169 | /* bits for nfs4_state->flags */ |
@@ -310,7 +321,7 @@ extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags) | |||
310 | extern void nfs41_handle_recall_slot(struct nfs_client *clp); | 321 | extern void nfs41_handle_recall_slot(struct nfs_client *clp); |
311 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); | 322 | extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); |
312 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); | 323 | extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl); |
313 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t); | 324 | extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t); |
314 | 325 | ||
315 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask); | 326 | extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask); |
316 | extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task); | 327 | 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 5d3e8a2db99f..d6413b48b057 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1767,7 +1767,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
1767 | if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) { | 1767 | if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) { |
1768 | /* Use that stateid */ | 1768 | /* Use that stateid */ |
1769 | } else if (state != NULL) { | 1769 | } else if (state != NULL) { |
1770 | nfs4_copy_stateid(&arg.stateid, state, current->files); | 1770 | nfs4_copy_stateid(&arg.stateid, state, current->files, current->tgid); |
1771 | } else | 1771 | } else |
1772 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); | 1772 | memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid)); |
1773 | 1773 | ||
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 13a4f27e7271..3e2f19b04c06 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -602,12 +602,21 @@ void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode) | |||
602 | * that is compatible with current->files | 602 | * that is compatible with current->files |
603 | */ | 603 | */ |
604 | static struct nfs4_lock_state * | 604 | static struct nfs4_lock_state * |
605 | __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | 605 | __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type) |
606 | { | 606 | { |
607 | struct nfs4_lock_state *pos; | 607 | struct nfs4_lock_state *pos; |
608 | list_for_each_entry(pos, &state->lock_states, ls_locks) { | 608 | list_for_each_entry(pos, &state->lock_states, ls_locks) { |
609 | if (pos->ls_owner != fl_owner) | 609 | if (type != NFS4_ANY_LOCK_TYPE && pos->ls_owner.lo_type != type) |
610 | continue; | 610 | continue; |
611 | switch (pos->ls_owner.lo_type) { | ||
612 | case NFS4_POSIX_LOCK_TYPE: | ||
613 | if (pos->ls_owner.lo_u.posix_owner != fl_owner) | ||
614 | continue; | ||
615 | break; | ||
616 | case NFS4_FLOCK_LOCK_TYPE: | ||
617 | if (pos->ls_owner.lo_u.flock_owner != fl_pid) | ||
618 | continue; | ||
619 | } | ||
611 | atomic_inc(&pos->ls_count); | 620 | atomic_inc(&pos->ls_count); |
612 | return pos; | 621 | return pos; |
613 | } | 622 | } |
@@ -619,7 +628,7 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | |||
619 | * exists, return an uninitialized one. | 628 | * exists, return an uninitialized one. |
620 | * | 629 | * |
621 | */ | 630 | */ |
622 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner) | 631 | static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type) |
623 | { | 632 | { |
624 | struct nfs4_lock_state *lsp; | 633 | struct nfs4_lock_state *lsp; |
625 | struct nfs_client *clp = state->owner->so_server->nfs_client; | 634 | struct nfs_client *clp = state->owner->so_server->nfs_client; |
@@ -633,7 +642,18 @@ static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, f | |||
633 | lsp->ls_seqid.sequence = &lsp->ls_sequence; | 642 | lsp->ls_seqid.sequence = &lsp->ls_sequence; |
634 | atomic_set(&lsp->ls_count, 1); | 643 | atomic_set(&lsp->ls_count, 1); |
635 | lsp->ls_state = state; | 644 | lsp->ls_state = state; |
636 | lsp->ls_owner = fl_owner; | 645 | lsp->ls_owner.lo_type = type; |
646 | switch (lsp->ls_owner.lo_type) { | ||
647 | case NFS4_FLOCK_LOCK_TYPE: | ||
648 | lsp->ls_owner.lo_u.flock_owner = fl_pid; | ||
649 | break; | ||
650 | case NFS4_POSIX_LOCK_TYPE: | ||
651 | lsp->ls_owner.lo_u.posix_owner = fl_owner; | ||
652 | break; | ||
653 | default: | ||
654 | kfree(lsp); | ||
655 | return NULL; | ||
656 | } | ||
637 | spin_lock(&clp->cl_lock); | 657 | spin_lock(&clp->cl_lock); |
638 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); | 658 | nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64); |
639 | spin_unlock(&clp->cl_lock); | 659 | spin_unlock(&clp->cl_lock); |
@@ -657,13 +677,13 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp) | |||
657 | * exists, return an uninitialized one. | 677 | * exists, return an uninitialized one. |
658 | * | 678 | * |
659 | */ | 679 | */ |
660 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner) | 680 | static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner, pid_t pid, unsigned int type) |
661 | { | 681 | { |
662 | struct nfs4_lock_state *lsp, *new = NULL; | 682 | struct nfs4_lock_state *lsp, *new = NULL; |
663 | 683 | ||
664 | for(;;) { | 684 | for(;;) { |
665 | spin_lock(&state->state_lock); | 685 | spin_lock(&state->state_lock); |
666 | lsp = __nfs4_find_lock_state(state, owner); | 686 | lsp = __nfs4_find_lock_state(state, owner, pid, type); |
667 | if (lsp != NULL) | 687 | if (lsp != NULL) |
668 | break; | 688 | break; |
669 | if (new != NULL) { | 689 | if (new != NULL) { |
@@ -674,7 +694,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_ | |||
674 | break; | 694 | break; |
675 | } | 695 | } |
676 | spin_unlock(&state->state_lock); | 696 | spin_unlock(&state->state_lock); |
677 | new = nfs4_alloc_lock_state(state, owner); | 697 | new = nfs4_alloc_lock_state(state, owner, pid, type); |
678 | if (new == NULL) | 698 | if (new == NULL) |
679 | return NULL; | 699 | return NULL; |
680 | } | 700 | } |
@@ -730,7 +750,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) | |||
730 | 750 | ||
731 | if (fl->fl_ops != NULL) | 751 | if (fl->fl_ops != NULL) |
732 | return 0; | 752 | return 0; |
733 | lsp = nfs4_get_lock_state(state, fl->fl_owner); | 753 | if (fl->fl_flags & FL_POSIX) |
754 | lsp = nfs4_get_lock_state(state, fl->fl_owner, 0, NFS4_POSIX_LOCK_TYPE); | ||
755 | else if (fl->fl_flags & FL_FLOCK) | ||
756 | lsp = nfs4_get_lock_state(state, 0, fl->fl_pid, NFS4_FLOCK_LOCK_TYPE); | ||
757 | else | ||
758 | return -EINVAL; | ||
734 | if (lsp == NULL) | 759 | if (lsp == NULL) |
735 | return -ENOMEM; | 760 | return -ENOMEM; |
736 | fl->fl_u.nfs4_fl.owner = lsp; | 761 | fl->fl_u.nfs4_fl.owner = lsp; |
@@ -742,7 +767,7 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl) | |||
742 | * Byte-range lock aware utility to initialize the stateid of read/write | 767 | * Byte-range lock aware utility to initialize the stateid of read/write |
743 | * requests. | 768 | * requests. |
744 | */ | 769 | */ |
745 | void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner) | 770 | void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid) |
746 | { | 771 | { |
747 | struct nfs4_lock_state *lsp; | 772 | struct nfs4_lock_state *lsp; |
748 | int seq; | 773 | int seq; |
@@ -755,7 +780,7 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f | |||
755 | return; | 780 | return; |
756 | 781 | ||
757 | spin_lock(&state->state_lock); | 782 | spin_lock(&state->state_lock); |
758 | lsp = __nfs4_find_lock_state(state, fl_owner); | 783 | lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE); |
759 | if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) | 784 | if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0) |
760 | memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); | 785 | memcpy(dst, &lsp->ls_stateid, sizeof(*dst)); |
761 | spin_unlock(&state->state_lock); | 786 | spin_unlock(&state->state_lock); |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 15185c2abd11..257c1811feb4 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -1361,7 +1361,7 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context | |||
1361 | 1361 | ||
1362 | p = reserve_space(xdr, NFS4_STATEID_SIZE); | 1362 | p = reserve_space(xdr, NFS4_STATEID_SIZE); |
1363 | if (ctx->state != NULL) { | 1363 | if (ctx->state != NULL) { |
1364 | nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner); | 1364 | nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid); |
1365 | xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); | 1365 | xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE); |
1366 | } else | 1366 | } else |
1367 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); | 1367 | xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE); |