[PATCH] Really ignore kmem_cache_destroy return value
[pandora-kernel.git] / fs / nfsd / nfs4state.c
index ffedce0..ebcf226 100644 (file)
@@ -123,7 +123,7 @@ static void release_stateid(struct nfs4_stateid *stp, int flags);
  */
 
 /* recall_lock protects the del_recall_lru */
-static spinlock_t recall_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(recall_lock);
 static struct list_head del_recall_lru;
 
 static void
@@ -147,6 +147,42 @@ get_nfs4_file(struct nfs4_file *fi)
        kref_get(&fi->fi_ref);
 }
 
+static int num_delegations;
+
+/*
+ * Open owner state (share locks)
+ */
+
+/* hash tables for nfs4_stateowner */
+#define OWNER_HASH_BITS              8
+#define OWNER_HASH_SIZE             (1 << OWNER_HASH_BITS)
+#define OWNER_HASH_MASK             (OWNER_HASH_SIZE - 1)
+
+#define ownerid_hashval(id) \
+        ((id) & OWNER_HASH_MASK)
+#define ownerstr_hashval(clientid, ownername) \
+        (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
+
+static struct list_head        ownerid_hashtbl[OWNER_HASH_SIZE];
+static struct list_head        ownerstr_hashtbl[OWNER_HASH_SIZE];
+
+/* hash table for nfs4_file */
+#define FILE_HASH_BITS                   8
+#define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
+#define FILE_HASH_MASK                  (FILE_HASH_SIZE - 1)
+/* hash table for (open)nfs4_stateid */
+#define STATEID_HASH_BITS              10
+#define STATEID_HASH_SIZE              (1 << STATEID_HASH_BITS)
+#define STATEID_HASH_MASK              (STATEID_HASH_SIZE - 1)
+
+#define file_hashval(x) \
+        hash_ptr(x, FILE_HASH_BITS)
+#define stateid_hashval(owner_id, file_id)  \
+        (((owner_id) + (file_id)) & STATEID_HASH_MASK)
+
+static struct list_head file_hashtbl[FILE_HASH_SIZE];
+static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
+
 static struct nfs4_delegation *
 alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_fh *current_fh, u32 type)
 {
@@ -155,9 +191,12 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
        struct nfs4_callback *cb = &stp->st_stateowner->so_client->cl_callback;
 
        dprintk("NFSD alloc_init_deleg\n");
+       if (num_delegations > STATEID_HASH_SIZE * 4)
+               return NULL;
        dp = kmem_cache_alloc(deleg_slab, GFP_KERNEL);
        if (dp == NULL)
                return dp;
+       num_delegations++;
        INIT_LIST_HEAD(&dp->dl_perfile);
        INIT_LIST_HEAD(&dp->dl_perclnt);
        INIT_LIST_HEAD(&dp->dl_recall_lru);
@@ -192,6 +231,7 @@ nfs4_put_delegation(struct nfs4_delegation *dp)
                dprintk("NFSD: freeing dp %p\n",dp);
                put_nfs4_file(dp->dl_file);
                kmem_cache_free(deleg_slab, dp);
+               num_delegations--;
        }
 }
 
@@ -299,8 +339,7 @@ alloc_client(struct xdr_netobj name)
 {
        struct nfs4_client *clp;
 
-       if ((clp = kmalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
-               memset(clp, 0, sizeof(*clp));
+       if ((clp = kzalloc(sizeof(struct nfs4_client), GFP_KERNEL))!= NULL) {
                if ((clp->cl_name.data = kmalloc(name.len, GFP_KERNEL)) != NULL) {
                        memcpy(clp->cl_name.data, name.data, name.len);
                        clp->cl_name.len = name.len;
@@ -329,23 +368,30 @@ put_nfs4_client(struct nfs4_client *clp)
                free_client(clp);
 }
 
+static void
+shutdown_callback_client(struct nfs4_client *clp)
+{
+       struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+
+       /* shutdown rpc client, ending any outstanding recall rpcs */
+       if (clnt) {
+               clp->cl_callback.cb_client = NULL;
+               rpc_shutdown_client(clnt);
+               rpciod_down();
+       }
+}
+
 static void
 expire_client(struct nfs4_client *clp)
 {
        struct nfs4_stateowner *sop;
        struct nfs4_delegation *dp;
-       struct nfs4_callback *cb = &clp->cl_callback;
-       struct rpc_clnt *clnt = clp->cl_callback.cb_client;
        struct list_head reaplist;
 
        dprintk("NFSD: expire_client cl_count %d\n",
                            atomic_read(&clp->cl_count));
 
-       /* shutdown rpc client, ending any outstanding recall rpcs */
-       if (atomic_read(&cb->cb_set) == 1 && clnt) {
-               rpc_shutdown_client(clnt);
-               clnt = clp->cl_callback.cb_client = NULL;
-       }
+       shutdown_callback_client(clp);
 
        INIT_LIST_HEAD(&reaplist);
        spin_lock(&recall_lock);
@@ -482,8 +528,7 @@ move_to_confirmed(struct nfs4_client *clp)
 
        dprintk("NFSD: move_to_confirm nfs4_client %p\n", clp);
        list_del_init(&clp->cl_strhash);
-       list_del_init(&clp->cl_idhash);
-       list_add(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
+       list_move(&clp->cl_idhash, &conf_id_hashtbl[idhashval]);
        strhashval = clientstr_hashval(clp->cl_recdir);
        list_add(&clp->cl_strhash, &conf_str_hashtbl[strhashval]);
        renew_client(clp);
@@ -936,40 +981,6 @@ out:
        return status;
 }
 
-/* 
- * Open owner state (share locks)
- */
-
-/* hash tables for nfs4_stateowner */
-#define OWNER_HASH_BITS              8
-#define OWNER_HASH_SIZE             (1 << OWNER_HASH_BITS)
-#define OWNER_HASH_MASK             (OWNER_HASH_SIZE - 1)
-
-#define ownerid_hashval(id) \
-        ((id) & OWNER_HASH_MASK)
-#define ownerstr_hashval(clientid, ownername) \
-        (((clientid) + opaque_hashval((ownername.data), (ownername.len))) & OWNER_HASH_MASK)
-
-static struct list_head        ownerid_hashtbl[OWNER_HASH_SIZE];
-static struct list_head        ownerstr_hashtbl[OWNER_HASH_SIZE];
-
-/* hash table for nfs4_file */
-#define FILE_HASH_BITS                   8
-#define FILE_HASH_SIZE                  (1 << FILE_HASH_BITS)
-#define FILE_HASH_MASK                  (FILE_HASH_SIZE - 1)
-/* hash table for (open)nfs4_stateid */
-#define STATEID_HASH_BITS              10
-#define STATEID_HASH_SIZE              (1 << STATEID_HASH_BITS)
-#define STATEID_HASH_MASK              (STATEID_HASH_SIZE - 1)
-
-#define file_hashval(x) \
-        hash_ptr(x, FILE_HASH_BITS)
-#define stateid_hashval(owner_id, file_id)  \
-        (((owner_id) + (file_id)) & STATEID_HASH_MASK)
-
-static struct list_head file_hashtbl[FILE_HASH_SIZE];
-static struct list_head stateid_hashtbl[STATEID_HASH_SIZE];
-
 /* OPEN Share state helper functions */
 static inline struct nfs4_file *
 alloc_init_file(struct inode *ino)
@@ -994,13 +1005,10 @@ alloc_init_file(struct inode *ino)
 static void
 nfsd4_free_slab(kmem_cache_t **slab)
 {
-       int status;
-
        if (*slab == NULL)
                return;
-       status = kmem_cache_destroy(*slab);
+       kmem_cache_destroy(*slab);
        *slab = NULL;
-       WARN_ON(status);
 }
 
 static void
@@ -1186,8 +1194,7 @@ move_to_close_lru(struct nfs4_stateowner *sop)
 {
        dprintk("NFSD: move_to_close_lru nfs4_stateowner %p\n", sop);
 
-       unhash_stateowner(sop);
-       list_add_tail(&sop->so_close_lru, &close_lru);
+       list_move_tail(&sop->so_close_lru, &close_lru);
        sop->so_time = get_seconds();
 }
 
@@ -1226,8 +1233,15 @@ find_file(struct inode *ino)
        return NULL;
 }
 
-#define TEST_ACCESS(x) ((x > 0 || x < 4)?1:0)
-#define TEST_DENY(x) ((x >= 0 || x < 5)?1:0)
+static int access_valid(u32 x)
+{
+       return (x > 0 && x < 4);
+}
+
+static int deny_valid(u32 x)
+{
+       return (x >= 0 && x < 5);
+}
 
 static void
 set_access(unsigned int *access, unsigned long bmap) {
@@ -1734,7 +1748,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
        int status;
 
        status = nfserr_inval;
-       if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny))
+       if (!access_valid(open->op_share_access)
+                       || !deny_valid(open->op_share_deny))
                goto out;
        /*
         * Lookup file; if found, lookup stateid and check open request,
@@ -1771,10 +1786,10 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
        } else {
                /* Stateid was not found, this is a new OPEN */
                int flags = 0;
+               if (open->op_share_access & NFS4_SHARE_ACCESS_READ)
+                       flags |= MAY_READ;
                if (open->op_share_access & NFS4_SHARE_ACCESS_WRITE)
-                       flags = MAY_WRITE;
-               else
-                       flags = MAY_READ;
+                       flags |= MAY_WRITE;
                status = nfs4_new_open(rqstp, &stp, dp, current_fh, flags);
                if (status)
                        goto out;
@@ -1916,8 +1931,7 @@ nfs4_laundromat(void)
                }
                dprintk("NFSD: purging unused open stateowner (so_id %d)\n",
                        sop->so_id);
-               list_del(&sop->so_close_lru);
-               nfs4_put_stateowner(sop);
+               release_stateowner(sop);
        }
        if (clientid_val < NFSD_LAUNDROMAT_MINTIMEOUT)
                clientid_val = NFSD_LAUNDROMAT_MINTIMEOUT;
@@ -2060,16 +2074,12 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
        if (!stateid->si_fileid) { /* delegation stateid */
                if(!(dp = find_delegation_stateid(ino, stateid))) {
                        dprintk("NFSD: delegation stateid not found\n");
-                       if (nfs4_in_grace())
-                               status = nfserr_grace;
                        goto out;
                }
                stidp = &dp->dl_stateid;
        } else { /* open or lock stateid */
                if (!(stp = find_stateid(stateid, flags))) {
                        dprintk("NFSD: open or lock stateid not found\n");
-                       if (nfs4_in_grace())
-                               status = nfserr_grace;
                        goto out;
                }
                if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
@@ -2242,8 +2252,9 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
                        (int)current_fh->fh_dentry->d_name.len,
                        current_fh->fh_dentry->d_name.name);
 
-       if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
-               goto out;
+       status = fh_verify(rqstp, current_fh, S_IFREG, 0);
+       if (status)
+               return status;
 
        nfs4_lock_state();
 
@@ -2310,7 +2321,8 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct n
                        (int)current_fh->fh_dentry->d_name.len,
                        current_fh->fh_dentry->d_name.name);
 
-       if (!TEST_ACCESS(od->od_share_access) || !TEST_DENY(od->od_share_deny))
+       if (!access_valid(od->od_share_access)
+                       || !deny_valid(od->od_share_deny))
                return nfserr_inval;
 
        nfs4_lock_state();
@@ -2497,7 +2509,7 @@ nfs4_transform_lock_offset(struct file_lock *lock)
 
 /* Hack!: For now, we're defining this just so we can use a pointer to it
  * as a unique cookie to identify our (NFSv4's) posix locks. */
-struct lock_manager_operations nfsd_posix_mng_ops  = {
+static struct lock_manager_operations nfsd_posix_mng_ops  = {
 };
 
 static inline void
@@ -3205,15 +3217,8 @@ __nfs4_state_shutdown(void)
        int i;
        struct nfs4_client *clp = NULL;
        struct nfs4_delegation *dp = NULL;
-       struct nfs4_stateowner *sop = NULL;
        struct list_head *pos, *next, reaplist;
 
-       list_for_each_safe(pos, next, &close_lru) {
-               sop = list_entry(pos, struct nfs4_stateowner, so_close_lru);
-               list_del(&sop->so_close_lru);
-               nfs4_put_stateowner(sop);
-       }
-
        for (i = 0; i < CLIENT_HASH_SIZE; i++) {
                while (!list_empty(&conf_id_hashtbl[i])) {
                        clp = list_entry(conf_id_hashtbl[i].next, struct nfs4_client, cl_idhash);
@@ -3238,8 +3243,6 @@ __nfs4_state_shutdown(void)
        }
 
        cancel_delayed_work(&laundromat_work);
-       flush_workqueue(laundry_wq);
-       destroy_workqueue(laundry_wq);
        nfsd4_shutdown_recdir();
        nfs4_init = 0;
 }
@@ -3247,6 +3250,8 @@ __nfs4_state_shutdown(void)
 void
 nfs4_state_shutdown(void)
 {
+       cancel_rearming_delayed_workqueue(laundry_wq, &laundromat_work);
+       destroy_workqueue(laundry_wq);
        nfs4_lock_state();
        nfs4_release_reclaim();
        __nfs4_state_shutdown();