NFSd: Move default initialisers from create_client() to alloc_client()
[pandora-kernel.git] / fs / nfsd / nfs4state.c
index 47e94e3..10eeccc 100644 (file)
@@ -188,13 +188,7 @@ static void __nfs4_file_put_access(struct nfs4_file *fp, int oflag)
 {
        if (atomic_dec_and_test(&fp->fi_access[oflag])) {
                nfs4_file_put_fd(fp, oflag);
-               /*
-                * It's also safe to get rid of the RDWR open *if*
-                * we no longer have need of the other kind of access
-                * or if we already have the other kind of open:
-                */
-               if (fp->fi_fds[1-oflag]
-                       || atomic_read(&fp->fi_access[1 - oflag]) == 0)
+               if (atomic_read(&fp->fi_access[1 - oflag]) == 0)
                        nfs4_file_put_fd(fp, O_RDWR);
        }
 }
@@ -992,6 +986,18 @@ static struct nfs4_client *alloc_client(struct xdr_netobj name)
        }
        memcpy(clp->cl_name.data, name.data, name.len);
        clp->cl_name.len = name.len;
+       INIT_LIST_HEAD(&clp->cl_sessions);
+       idr_init(&clp->cl_stateids);
+       atomic_set(&clp->cl_refcount, 0);
+       clp->cl_cb_state = NFSD4_CB_UNKNOWN;
+       INIT_LIST_HEAD(&clp->cl_idhash);
+       INIT_LIST_HEAD(&clp->cl_strhash);
+       INIT_LIST_HEAD(&clp->cl_openowners);
+       INIT_LIST_HEAD(&clp->cl_delegations);
+       INIT_LIST_HEAD(&clp->cl_lru);
+       INIT_LIST_HEAD(&clp->cl_callbacks);
+       spin_lock_init(&clp->cl_lock);
+       rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
        return clp;
 }
 
@@ -1009,6 +1015,8 @@ free_client(struct nfs4_client *clp)
                put_group_info(clp->cl_cred.cr_group_info);
        kfree(clp->cl_principal);
        kfree(clp->cl_name.data);
+       idr_remove_all(&clp->cl_stateids);
+       idr_destroy(&clp->cl_stateids);
        kfree(clp);
 }
 
@@ -1167,7 +1175,6 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
        if (clp == NULL)
                return NULL;
 
-       INIT_LIST_HEAD(&clp->cl_sessions);
 
        princ = svc_gss_principal(rqstp);
        if (princ) {
@@ -1178,21 +1185,10 @@ static struct nfs4_client *create_client(struct xdr_netobj name, char *recdir,
                }
        }
 
-       idr_init(&clp->cl_stateids);
        memcpy(clp->cl_recdir, recdir, HEXDIR_LEN);
-       atomic_set(&clp->cl_refcount, 0);
-       clp->cl_cb_state = NFSD4_CB_UNKNOWN;
-       INIT_LIST_HEAD(&clp->cl_idhash);
-       INIT_LIST_HEAD(&clp->cl_strhash);
-       INIT_LIST_HEAD(&clp->cl_openowners);
-       INIT_LIST_HEAD(&clp->cl_delegations);
-       INIT_LIST_HEAD(&clp->cl_lru);
-       INIT_LIST_HEAD(&clp->cl_callbacks);
-       spin_lock_init(&clp->cl_lock);
        INIT_WORK(&clp->cl_cb_null.cb_work, nfsd4_do_callback_rpc);
        clp->cl_time = get_seconds();
        clear_bit(0, &clp->cl_cb_slot_busy);
-       rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
        copy_verf(clp, verf);
        rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
        clp->cl_flavor = rqstp->rq_flavor;
@@ -2309,7 +2305,7 @@ nfsd4_init_slabs(void)
        if (openowner_slab == NULL)
                goto out_nomem;
        lockowner_slab = kmem_cache_create("nfsd4_lockowners",
-                       sizeof(struct nfs4_openowner), 0, 0, NULL);
+                       sizeof(struct nfs4_lockowner), 0, 0, NULL);
        if (lockowner_slab == NULL)
                goto out_nomem;
        file_slab = kmem_cache_create("nfsd4_files",
@@ -3673,6 +3669,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        memcpy(&close->cl_stateid, &stp->st_stid.sc_stateid, sizeof(stateid_t));
 
        nfsd4_close_open_stateid(stp);
+       release_last_closed_stateid(oo);
        oo->oo_last_closed_stid = stp;
 
        /* place unused nfs4_stateowners on so_close_lru list to be
@@ -3809,16 +3806,29 @@ nevermind:
                deny->ld_type = NFS4_WRITE_LT;
 }
 
+static bool same_lockowner_ino(struct nfs4_lockowner *lo, struct inode *inode, clientid_t *clid, struct xdr_netobj *owner)
+{
+       struct nfs4_ol_stateid *lst;
+
+       if (!same_owner_str(&lo->lo_owner, owner, clid))
+               return false;
+       lst = list_first_entry(&lo->lo_owner.so_stateids,
+                              struct nfs4_ol_stateid, st_perstateowner);
+       return lst->st_file->fi_inode == inode;
+}
+
 static struct nfs4_lockowner *
 find_lockowner_str(struct inode *inode, clientid_t *clid,
                struct xdr_netobj *owner)
 {
        unsigned int hashval = lock_ownerstr_hashval(inode, clid->cl_id, owner);
+       struct nfs4_lockowner *lo;
        struct nfs4_stateowner *op;
 
        list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) {
-               if (same_owner_str(op, owner, clid))
-                       return lockowner(op);
+               lo = lockowner(op);
+               if (same_lockowner_ino(lo, inode, clid, owner))
+                       return lo;
        }
        return NULL;
 }
@@ -4067,16 +4077,14 @@ out:
  * vfs_test_lock.  (Arguably perhaps test_lock should be done with an
  * inode operation.)
  */
-static int nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
+static __be32 nfsd_test_lock(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file_lock *lock)
 {
        struct file *file;
-       int err;
-
-       err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
-       if (err)
-               return err;
-       err = vfs_test_lock(file, lock);
-       nfsd_close(file);
+       __be32 err = nfsd_open(rqstp, fhp, S_IFREG, NFSD_MAY_READ, &file);
+       if (!err) {
+               err = nfserrno(vfs_test_lock(file, lock));
+               nfsd_close(file);
+       }
        return err;
 }
 
@@ -4090,7 +4098,6 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        struct inode *inode;
        struct file_lock file_lock;
        struct nfs4_lockowner *lo;
-       int error;
        __be32 status;
 
        if (locks_in_grace())
@@ -4136,12 +4143,10 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 
        nfs4_transform_lock_offset(&file_lock);
 
-       status = nfs_ok;
-       error = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
-       if (error) {
-               status = nfserrno(error);
+       status = nfsd_test_lock(rqstp, &cstate->current_fh, &file_lock);
+       if (status)
                goto out;
-       }
+
        if (file_lock.fl_type != F_UNLCK) {
                status = nfserr_denied;
                nfs4_set_lock_denied(&file_lock, &lockt->lt_denied);