NFSv4: Remove nfs_client->cl_sem
[safe/jmp/linux-2.6] / fs / nfs / delegation.c
index b9eadd1..ebc06f2 100644 (file)
@@ -49,7 +49,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
        struct file_lock *fl;
        int status;
 
-       for (fl = inode->i_flock; fl != 0; fl = fl->fl_next) {
+       for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) {
                if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK)))
                        continue;
                if (nfs_file_open_context(fl->fl_file) != ctx)
@@ -60,7 +60,7 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_
                switch (status) {
                        default:
                                printk(KERN_ERR "%s: unhandled error %d.\n",
-                                               __FUNCTION__, status);
+                                               __func__, status);
                        case -NFS4ERR_EXPIRED:
                                /* kill_proc(fl->fl_pid, SIGLOST, 1); */
                        case -NFS4ERR_STALE_CLIENTID:
@@ -119,7 +119,7 @@ void nfs_inode_reclaim_delegation(struct inode *inode, struct rpc_cred *cred, st
        delegation->maxsize = res->maxsize;
        oldcred = delegation->cred;
        delegation->cred = get_rpccred(cred);
-       delegation->flags &= ~NFS_DELEGATION_NEED_RECLAIM;
+       clear_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
        NFS_I(inode)->delegation_state = delegation->type;
        smp_wmb();
        put_rpccred(oldcred);
@@ -134,19 +134,35 @@ static int nfs_do_return_delegation(struct inode *inode, struct nfs_delegation *
        return res;
 }
 
+static struct inode *nfs_delegation_grab_inode(struct nfs_delegation *delegation)
+{
+       struct inode *inode = NULL;
+
+       spin_lock(&delegation->lock);
+       if (delegation->inode != NULL)
+               inode = igrab(delegation->inode);
+       spin_unlock(&delegation->lock);
+       return inode;
+}
+
 static struct nfs_delegation *nfs_detach_delegation_locked(struct nfs_inode *nfsi, const nfs4_stateid *stateid)
 {
        struct nfs_delegation *delegation = rcu_dereference(nfsi->delegation);
 
        if (delegation == NULL)
                goto nomatch;
+       spin_lock(&delegation->lock);
        if (stateid != NULL && memcmp(delegation->stateid.data, stateid->data,
                                sizeof(delegation->stateid.data)) != 0)
-               goto nomatch;
+               goto nomatch_unlock;
        list_del_rcu(&delegation->super_list);
+       delegation->inode = NULL;
        nfsi->delegation_state = 0;
        rcu_assign_pointer(nfsi->delegation, NULL);
+       spin_unlock(&delegation->lock);
        return delegation;
+nomatch_unlock:
+       spin_unlock(&delegation->lock);
 nomatch:
        return NULL;
 }
@@ -172,6 +188,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
        delegation->change_attr = nfsi->change_attr;
        delegation->cred = get_rpccred(cred);
        delegation->inode = inode;
+       spin_lock_init(&delegation->lock);
 
        spin_lock(&clp->cl_lock);
        if (rcu_dereference(nfsi->delegation) != NULL) {
@@ -186,7 +203,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
                 */
                dfprintk(FILE, "%s: server %s handed out "
                                "a duplicate delegation!\n",
-                               __FUNCTION__, clp->cl_hostname);
+                               __func__, clp->cl_hostname);
                if (delegation->type <= nfsi->delegation->type) {
                        freeme = delegation;
                        delegation = NULL;
@@ -226,16 +243,13 @@ static void nfs_msync_inode(struct inode *inode)
  */
 static int __nfs_inode_return_delegation(struct inode *inode, struct nfs_delegation *delegation)
 {
-       struct nfs_client *clp = NFS_SERVER(inode)->nfs_client;
        struct nfs_inode *nfsi = NFS_I(inode);
 
        nfs_msync_inode(inode);
-       down_read(&clp->cl_sem);
        /* Guard against new delegated open calls */
        down_write(&nfsi->rwsem);
        nfs_delegation_claim_opens(inode, &delegation->stateid);
        up_write(&nfsi->rwsem);
-       up_read(&clp->cl_sem);
        nfs_msync_inode(inode);
 
        return nfs_do_return_delegation(inode, delegation, 1);
@@ -293,9 +307,11 @@ void nfs_return_all_delegations(struct super_block *sb)
 restart:
        rcu_read_lock();
        list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
-               if (delegation->inode->i_sb != sb)
-                       continue;
-               inode = igrab(delegation->inode);
+               inode = NULL;
+               spin_lock(&delegation->lock);
+               if (delegation->inode != NULL && delegation->inode->i_sb == sb)
+                       inode = igrab(delegation->inode);
+               spin_unlock(&delegation->lock);
                if (inode == NULL)
                        continue;
                spin_lock(&clp->cl_lock);
@@ -324,7 +340,7 @@ restart:
                goto out;
        rcu_read_lock();
        list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
-               inode = igrab(delegation->inode);
+               inode = nfs_delegation_grab_inode(delegation);
                if (inode == NULL)
                        continue;
                spin_lock(&clp->cl_lock);
@@ -371,7 +387,7 @@ void nfs_handle_cb_pathdown(struct nfs_client *clp)
 restart:
        rcu_read_lock();
        list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
-               inode = igrab(delegation->inode);
+               inode = nfs_delegation_grab_inode(delegation);
                if (inode == NULL)
                        continue;
                spin_lock(&clp->cl_lock);
@@ -406,7 +422,6 @@ static int recall_thread(void *data)
        daemonize("nfsv4-delegreturn");
 
        nfs_msync_inode(inode);
-       down_read(&clp->cl_sem);
        down_write(&nfsi->rwsem);
        spin_lock(&clp->cl_lock);
        delegation = nfs_detach_delegation_locked(nfsi, args->stateid);
@@ -418,7 +433,6 @@ static int recall_thread(void *data)
        complete(&args->started);
        nfs_delegation_claim_opens(inode, args->stateid);
        up_write(&nfsi->rwsem);
-       up_read(&clp->cl_sem);
        nfs_msync_inode(inode);
 
        if (delegation != NULL)
@@ -459,10 +473,14 @@ struct inode *nfs_delegation_find_inode(struct nfs_client *clp, const struct nfs
        struct inode *res = NULL;
        rcu_read_lock();
        list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
-               if (nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
+               spin_lock(&delegation->lock);
+               if (delegation->inode != NULL &&
+                   nfs_compare_fh(fhandle, &NFS_I(delegation->inode)->fh) == 0) {
                        res = igrab(delegation->inode);
-                       break;
                }
+               spin_unlock(&delegation->lock);
+               if (res != NULL)
+                       break;
        }
        rcu_read_unlock();
        return res;
@@ -476,7 +494,7 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp)
        struct nfs_delegation *delegation;
        rcu_read_lock();
        list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list)
-               delegation->flags |= NFS_DELEGATION_NEED_RECLAIM;
+               set_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags);
        rcu_read_unlock();
 }
 
@@ -486,17 +504,22 @@ void nfs_delegation_mark_reclaim(struct nfs_client *clp)
 void nfs_delegation_reap_unclaimed(struct nfs_client *clp)
 {
        struct nfs_delegation *delegation;
+       struct inode *inode;
 restart:
        rcu_read_lock();
        list_for_each_entry_rcu(delegation, &clp->cl_delegations, super_list) {
-               if ((delegation->flags & NFS_DELEGATION_NEED_RECLAIM) == 0)
+               if (test_bit(NFS_DELEGATION_NEED_RECLAIM, &delegation->flags) == 0)
+                       continue;
+               inode = nfs_delegation_grab_inode(delegation);
+               if (inode == NULL)
                        continue;
                spin_lock(&clp->cl_lock);
-               delegation = nfs_detach_delegation_locked(NFS_I(delegation->inode), NULL);
+               delegation = nfs_detach_delegation_locked(NFS_I(inode), NULL);
                spin_unlock(&clp->cl_lock);
                rcu_read_unlock();
                if (delegation != NULL)
                        nfs_free_delegation(delegation);
+               iput(inode);
                goto restart;
        }
        rcu_read_unlock();