NFSv4: Ensure the lockowners are labelled using the fl_owner and/or fl_pid
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Thu, 1 Jul 2010 16:49:11 +0000 (12:49 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 30 Jul 2010 18:46:10 +0000 (14:46 -0400)
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>
fs/nfs/nfs4_fs.h
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c

index deaf37f5a7a962daa5235fbc4adaabcdafb90d26..311e15cc8af0c961074714a738bc87ff4b7021d5 100644 (file)
@@ -142,10 +142,20 @@ enum {
  * LOCK: one nfs4_state (LOCK) to hold the lock stateid nfs4_state(OPEN)
  */
 
+struct nfs4_lock_owner {
+       unsigned int lo_type;
+#define NFS4_ANY_LOCK_TYPE     (0U)
+#define NFS4_FLOCK_LOCK_TYPE   (1U << 0)
+#define NFS4_POSIX_LOCK_TYPE   (1U << 1)
+       union {
+               fl_owner_t posix_owner;
+               pid_t flock_owner;
+       } lo_u;
+};
+
 struct nfs4_lock_state {
        struct list_head        ls_locks;       /* Other lock stateids */
        struct nfs4_state *     ls_state;       /* Pointer to open state */
-       fl_owner_t              ls_owner;       /* POSIX lock owner */
 #define NFS_LOCK_INITIALIZED 1
        int                     ls_flags;
        struct nfs_seqid_counter        ls_seqid;
@@ -153,6 +163,7 @@ struct nfs4_lock_state {
        struct nfs_unique_id    ls_id;
        nfs4_stateid            ls_stateid;
        atomic_t                ls_count;
+       struct nfs4_lock_owner  ls_owner;
 };
 
 /* bits for nfs4_state->flags */
@@ -310,7 +321,7 @@ extern void nfs41_handle_sequence_flag_errors(struct nfs_client *clp, u32 flags)
 extern void nfs41_handle_recall_slot(struct nfs_client *clp);
 extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp);
 extern int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl);
-extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t);
+extern void nfs4_copy_stateid(nfs4_stateid *, struct nfs4_state *, fl_owner_t, pid_t);
 
 extern struct nfs_seqid *nfs_alloc_seqid(struct nfs_seqid_counter *counter, gfp_t gfp_mask);
 extern int nfs_wait_on_sequence(struct nfs_seqid *seqid, struct rpc_task *task);
index 5d3e8a2db99fe1cdec5101348bcc0bf133325593..d6413b48b0572df6a0569946d428adcc28368ab3 100644 (file)
@@ -1767,7 +1767,7 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred,
        if (nfs4_copy_delegation_stateid(&arg.stateid, inode)) {
                /* Use that stateid */
        } else if (state != NULL) {
-               nfs4_copy_stateid(&arg.stateid, state, current->files);
+               nfs4_copy_stateid(&arg.stateid, state, current->files, current->tgid);
        } else
                memcpy(&arg.stateid, &zero_stateid, sizeof(arg.stateid));
 
index 13a4f27e72719f7bdf438ce2b7fc6e95bb2c5860..3e2f19b04c06b4b3fb0f01cb409a544054940222 100644 (file)
@@ -602,12 +602,21 @@ void nfs4_close_sync(struct path *path, struct nfs4_state *state, fmode_t fmode)
  * that is compatible with current->files
  */
 static struct nfs4_lock_state *
-__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
+__nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid, unsigned int type)
 {
        struct nfs4_lock_state *pos;
        list_for_each_entry(pos, &state->lock_states, ls_locks) {
-               if (pos->ls_owner != fl_owner)
+               if (type != NFS4_ANY_LOCK_TYPE && pos->ls_owner.lo_type != type)
                        continue;
+               switch (pos->ls_owner.lo_type) {
+               case NFS4_POSIX_LOCK_TYPE:
+                       if (pos->ls_owner.lo_u.posix_owner != fl_owner)
+                               continue;
+                       break;
+               case NFS4_FLOCK_LOCK_TYPE:
+                       if (pos->ls_owner.lo_u.flock_owner != fl_pid)
+                               continue;
+               }
                atomic_inc(&pos->ls_count);
                return pos;
        }
@@ -619,7 +628,7 @@ __nfs4_find_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
  * exists, return an uninitialized one.
  *
  */
-static struct nfs4_lock_state *nfs4_alloc_lock_state(struct nfs4_state *state, fl_owner_t fl_owner)
+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)
 {
        struct nfs4_lock_state *lsp;
        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
        lsp->ls_seqid.sequence = &lsp->ls_sequence;
        atomic_set(&lsp->ls_count, 1);
        lsp->ls_state = state;
-       lsp->ls_owner = fl_owner;
+       lsp->ls_owner.lo_type = type;
+       switch (lsp->ls_owner.lo_type) {
+       case NFS4_FLOCK_LOCK_TYPE:
+               lsp->ls_owner.lo_u.flock_owner = fl_pid;
+               break;
+       case NFS4_POSIX_LOCK_TYPE:
+               lsp->ls_owner.lo_u.posix_owner = fl_owner;
+               break;
+       default:
+               kfree(lsp);
+               return NULL;
+       }
        spin_lock(&clp->cl_lock);
        nfs_alloc_unique_id(&clp->cl_lockowner_id, &lsp->ls_id, 1, 64);
        spin_unlock(&clp->cl_lock);
@@ -657,13 +677,13 @@ static void nfs4_free_lock_state(struct nfs4_lock_state *lsp)
  * exists, return an uninitialized one.
  *
  */
-static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner)
+static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_owner_t owner, pid_t pid, unsigned int type)
 {
        struct nfs4_lock_state *lsp, *new = NULL;
        
        for(;;) {
                spin_lock(&state->state_lock);
-               lsp = __nfs4_find_lock_state(state, owner);
+               lsp = __nfs4_find_lock_state(state, owner, pid, type);
                if (lsp != NULL)
                        break;
                if (new != NULL) {
@@ -674,7 +694,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
                        break;
                }
                spin_unlock(&state->state_lock);
-               new = nfs4_alloc_lock_state(state, owner);
+               new = nfs4_alloc_lock_state(state, owner, pid, type);
                if (new == NULL)
                        return NULL;
        }
@@ -730,7 +750,12 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
 
        if (fl->fl_ops != NULL)
                return 0;
-       lsp = nfs4_get_lock_state(state, fl->fl_owner);
+       if (fl->fl_flags & FL_POSIX)
+               lsp = nfs4_get_lock_state(state, fl->fl_owner, 0, NFS4_POSIX_LOCK_TYPE);
+       else if (fl->fl_flags & FL_FLOCK)
+               lsp = nfs4_get_lock_state(state, 0, fl->fl_pid, NFS4_FLOCK_LOCK_TYPE);
+       else
+               return -EINVAL;
        if (lsp == NULL)
                return -ENOMEM;
        fl->fl_u.nfs4_fl.owner = lsp;
@@ -742,7 +767,7 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
  * Byte-range lock aware utility to initialize the stateid of read/write
  * requests.
  */
-void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner)
+void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t fl_owner, pid_t fl_pid)
 {
        struct nfs4_lock_state *lsp;
        int seq;
@@ -755,7 +780,7 @@ void nfs4_copy_stateid(nfs4_stateid *dst, struct nfs4_state *state, fl_owner_t f
                return;
 
        spin_lock(&state->state_lock);
-       lsp = __nfs4_find_lock_state(state, fl_owner);
+       lsp = __nfs4_find_lock_state(state, fl_owner, fl_pid, NFS4_ANY_LOCK_TYPE);
        if (lsp != NULL && (lsp->ls_flags & NFS_LOCK_INITIALIZED) != 0)
                memcpy(dst, &lsp->ls_stateid, sizeof(*dst));
        spin_unlock(&state->state_lock);
index 15185c2abd1102de7f010b0208c86adede45fac3..257c1811feb445bffe0c47909a8ebcb3c2b1d37a 100644 (file)
@@ -1361,7 +1361,7 @@ static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context
 
        p = reserve_space(xdr, NFS4_STATEID_SIZE);
        if (ctx->state != NULL) {
-               nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner);
+               nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid);
                xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
        } else
                xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);