]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/nfs/nfs4state.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / fs / nfs / nfs4state.c
index 0959c96616623f876a5905deb6e03c1a438fe338..daeb94e3acd49bd6553601bd15adb8f72236825b 100644 (file)
@@ -494,21 +494,18 @@ nfs4_alloc_state_owner(struct nfs_server *server,
 }
 
 static void
-nfs4_drop_state_owner(struct nfs4_state_owner *sp)
-{
-       struct rb_node *rb_node = &sp->so_server_node;
-
-       if (!RB_EMPTY_NODE(rb_node)) {
-               struct nfs_server *server = sp->so_server;
-               struct nfs_client *clp = server->nfs_client;
-
-               spin_lock(&clp->cl_lock);
-               if (!RB_EMPTY_NODE(rb_node)) {
-                       rb_erase(rb_node, &server->state_owners);
-                       RB_CLEAR_NODE(rb_node);
-               }
-               spin_unlock(&clp->cl_lock);
-       }
+nfs4_reset_state_owner(struct nfs4_state_owner *sp)
+{
+       /* This state_owner is no longer usable, but must
+        * remain in place so that state recovery can find it
+        * and the opens associated with it.
+        * It may also be used for new 'open' request to
+        * return a delegation to the server.
+        * So update the 'create_time' so that it looks like
+        * a new state_owner.  This will cause the server to
+        * request an OPEN_CONFIRM to start a new sequence.
+        */
+       sp->so_seqid.create_time = ktime_get();
 }
 
 static void nfs4_free_state_owner(struct nfs4_state_owner *sp)
@@ -797,19 +794,33 @@ void nfs4_close_sync(struct nfs4_state *state, fmode_t fmode)
 
 /*
  * Search the state->lock_states for an existing lock_owner
- * that is compatible with current->files
+ * that is compatible with either of the given owners.
+ * If the second is non-zero, then the first refers to a Posix-lock
+ * owner (current->files) and the second refers to a flock/OFD
+ * owner (struct file*).  In that case, prefer a match for the first
+ * owner.
+ * If both sorts of locks are held on the one file we cannot know
+ * which stateid was intended to be used, so a "correct" choice cannot
+ * be made.  Failing that, a "consistent" choice is preferable.  The
+ * consistent choice we make is to prefer the first owner, that of a
+ * Posix lock.
  */
 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, fl_owner_t fl_owner2)
 {
-       struct nfs4_lock_state *pos;
+       struct nfs4_lock_state *pos, *ret = NULL;
        list_for_each_entry(pos, &state->lock_states, ls_locks) {
-               if (pos->ls_owner != fl_owner)
-                       continue;
-               atomic_inc(&pos->ls_count);
-               return pos;
+               if (pos->ls_owner == fl_owner) {
+                       ret = pos;
+                       break;
+               }
+               if (pos->ls_owner == fl_owner2)
+                       ret = pos;
        }
-       return NULL;
+       if (ret)
+               atomic_inc(&ret->ls_count);
+       return ret;
 }
 
 /*
@@ -857,7 +868,7 @@ static struct nfs4_lock_state *nfs4_get_lock_state(struct nfs4_state *state, fl_
        
        for(;;) {
                spin_lock(&state->state_lock);
-               lsp = __nfs4_find_lock_state(state, owner);
+               lsp = __nfs4_find_lock_state(state, owner, 0);
                if (lsp != NULL)
                        break;
                if (new != NULL) {
@@ -939,22 +950,23 @@ int nfs4_set_lock_state(struct nfs4_state *state, struct file_lock *fl)
 
 static int nfs4_copy_lock_stateid(nfs4_stateid *dst,
                struct nfs4_state *state,
-               const struct nfs_lockowner *lockowner)
+               const struct nfs_lock_context *l_ctx)
 {
        struct nfs4_lock_state *lsp;
-       fl_owner_t fl_owner;
+       fl_owner_t fl_owner, fl_flock_owner;
        int ret = -ENOENT;
 
-
-       if (lockowner == NULL)
+       if (l_ctx == NULL)
                goto out;
 
        if (test_bit(LK_STATE_IN_USE, &state->flags) == 0)
                goto out;
 
-       fl_owner = lockowner->l_owner;
+       fl_owner = l_ctx->lockowner;
+       fl_flock_owner = l_ctx->open_context->flock_owner;
+
        spin_lock(&state->state_lock);
-       lsp = __nfs4_find_lock_state(state, fl_owner);
+       lsp = __nfs4_find_lock_state(state, fl_owner, fl_flock_owner);
        if (lsp && test_bit(NFS_LOCK_LOST, &lsp->ls_flags))
                ret = -EIO;
        else if (lsp != NULL && test_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags) != 0) {
@@ -986,7 +998,7 @@ static void nfs4_copy_open_stateid(nfs4_stateid *dst, struct nfs4_state *state)
  * requests.
  */
 int nfs4_select_rw_stateid(struct nfs4_state *state,
-               fmode_t fmode, const struct nfs_lockowner *lockowner,
+               fmode_t fmode, const struct nfs_lock_context *l_ctx,
                nfs4_stateid *dst, struct rpc_cred **cred)
 {
        int ret;
@@ -995,7 +1007,7 @@ int nfs4_select_rw_stateid(struct nfs4_state *state,
                return -EIO;
        if (cred != NULL)
                *cred = NULL;
-       ret = nfs4_copy_lock_stateid(dst, state, lockowner);
+       ret = nfs4_copy_lock_stateid(dst, state, l_ctx);
        if (ret == -EIO)
                /* A lost lock - don't even consider delegations */
                goto out;
@@ -1079,6 +1091,7 @@ static void nfs_increment_seqid(int status, struct nfs_seqid *seqid)
                case -NFS4ERR_BADXDR:
                case -NFS4ERR_RESOURCE:
                case -NFS4ERR_NOFILEHANDLE:
+               case -NFS4ERR_MOVED:
                        /* Non-seqid mutating errors */
                        return;
        };
@@ -1098,7 +1111,7 @@ void nfs_increment_open_seqid(int status, struct nfs_seqid *seqid)
 
        sp = container_of(seqid->sequence, struct nfs4_state_owner, so_seqid);
        if (status == -NFS4ERR_BAD_SEQID)
-               nfs4_drop_state_owner(sp);
+               nfs4_reset_state_owner(sp);
        if (!nfs4_has_session(sp->so_server->nfs_client))
                nfs_increment_seqid(status, seqid);
 }
@@ -1717,7 +1730,6 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error)
                        break;
                case -NFS4ERR_STALE_CLIENTID:
                        set_bit(NFS4CLNT_LEASE_EXPIRED, &clp->cl_state);
-                       nfs4_state_clear_reclaim_reboot(clp);
                        nfs4_state_start_reclaim_reboot(clp);
                        break;
                case -NFS4ERR_EXPIRED:
@@ -2190,7 +2202,7 @@ void nfs4_schedule_session_recovery(struct nfs4_session *session, int err)
        case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
                set_bit(NFS4CLNT_BIND_CONN_TO_SESSION, &clp->cl_state);
        }
-       nfs4_schedule_lease_recovery(clp);
+       nfs4_schedule_state_manager(clp);
 }
 EXPORT_SYMBOL_GPL(nfs4_schedule_session_recovery);