]> Pileus Git - ~andy/linux/blobdiff - fs/nfs/delegation.c
Merge branch 'queue' of git://git.kernel.org/pub/scm/linux/kernel/git/nab/target...
[~andy/linux] / fs / nfs / delegation.c
index a377ea36381e8dbbfe2f57b792bb9b4fad397aed..57db3244f4d967dd5479dbf3ab883c6d28cc2cbd 100644 (file)
@@ -70,11 +70,9 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
        struct file_lock *fl;
        int status = 0;
 
-       if (inode->i_flock == NULL)
-               return 0;
-
        if (inode->i_flock == NULL)
                goto out;
+
        /* Protect inode->i_flock using the file locks lock */
        lock_flocks();
        for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
@@ -502,6 +500,45 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
        set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state);
 }
 
+static bool nfs_server_mark_return_all_delegations(struct nfs_server *server)
+{
+       struct nfs_delegation *delegation;
+       bool ret = false;
+
+       list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
+               nfs_mark_return_delegation(server, delegation);
+               ret = true;
+       }
+       return ret;
+}
+
+static void nfs_client_mark_return_all_delegations(struct nfs_client *clp)
+{
+       struct nfs_server *server;
+
+       rcu_read_lock();
+       list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
+               nfs_server_mark_return_all_delegations(server);
+       rcu_read_unlock();
+}
+
+static void nfs_delegation_run_state_manager(struct nfs_client *clp)
+{
+       if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
+               nfs4_schedule_state_manager(clp);
+}
+
+/**
+ * nfs_expire_all_delegations
+ * @clp: client to process
+ *
+ */
+void nfs_expire_all_delegations(struct nfs_client *clp)
+{
+       nfs_client_mark_return_all_delegations(clp);
+       nfs_delegation_run_state_manager(clp);
+}
+
 /**
  * nfs_super_return_all_delegations - return delegations for one superblock
  * @sb: sb to process
@@ -510,24 +547,22 @@ static void nfs_mark_return_delegation(struct nfs_server *server,
 void nfs_server_return_all_delegations(struct nfs_server *server)
 {
        struct nfs_client *clp = server->nfs_client;
-       struct nfs_delegation *delegation;
+       bool need_wait;
 
        if (clp == NULL)
                return;
 
        rcu_read_lock();
-       list_for_each_entry_rcu(delegation, &server->delegations, super_list) {
-               spin_lock(&delegation->lock);
-               set_bit(NFS_DELEGATION_RETURN, &delegation->flags);
-               spin_unlock(&delegation->lock);
-       }
+       need_wait = nfs_server_mark_return_all_delegations(server);
        rcu_read_unlock();
 
-       if (nfs_client_return_marked_delegations(clp) != 0)
+       if (need_wait) {
                nfs4_schedule_state_manager(clp);
+               nfs4_wait_clnt_recover(clp);
+       }
 }
 
-static void nfs_mark_return_all_delegation_types(struct nfs_server *server,
+static void nfs_mark_return_unused_delegation_types(struct nfs_server *server,
                                                 fmode_t flags)
 {
        struct nfs_delegation *delegation;
@@ -536,27 +571,21 @@ static void nfs_mark_return_all_delegation_types(struct nfs_server *server,
                if ((delegation->type == (FMODE_READ|FMODE_WRITE)) && !(flags & FMODE_WRITE))
                        continue;
                if (delegation->type & flags)
-                       nfs_mark_return_delegation(server, delegation);
+                       nfs_mark_return_if_closed_delegation(server, delegation);
        }
 }
 
-static void nfs_client_mark_return_all_delegation_types(struct nfs_client *clp,
+static void nfs_client_mark_return_unused_delegation_types(struct nfs_client *clp,
                                                        fmode_t flags)
 {
        struct nfs_server *server;
 
        rcu_read_lock();
        list_for_each_entry_rcu(server, &clp->cl_superblocks, client_link)
-               nfs_mark_return_all_delegation_types(server, flags);
+               nfs_mark_return_unused_delegation_types(server, flags);
        rcu_read_unlock();
 }
 
-static void nfs_delegation_run_state_manager(struct nfs_client *clp)
-{
-       if (test_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state))
-               nfs4_schedule_state_manager(clp);
-}
-
 void nfs_remove_bad_delegation(struct inode *inode)
 {
        struct nfs_delegation *delegation;
@@ -570,27 +599,17 @@ void nfs_remove_bad_delegation(struct inode *inode)
 EXPORT_SYMBOL_GPL(nfs_remove_bad_delegation);
 
 /**
- * nfs_expire_all_delegation_types
+ * nfs_expire_unused_delegation_types
  * @clp: client to process
  * @flags: delegation types to expire
  *
  */
-void nfs_expire_all_delegation_types(struct nfs_client *clp, fmode_t flags)
+void nfs_expire_unused_delegation_types(struct nfs_client *clp, fmode_t flags)
 {
-       nfs_client_mark_return_all_delegation_types(clp, flags);
+       nfs_client_mark_return_unused_delegation_types(clp, flags);
        nfs_delegation_run_state_manager(clp);
 }
 
-/**
- * nfs_expire_all_delegations
- * @clp: client to process
- *
- */
-void nfs_expire_all_delegations(struct nfs_client *clp)
-{
-       nfs_expire_all_delegation_types(clp, FMODE_READ|FMODE_WRITE);
-}
-
 static void nfs_mark_return_unreferenced_delegations(struct nfs_server *server)
 {
        struct nfs_delegation *delegation;