nfsd4: don't check ip address in setclientid
[safe/jmp/linux-2.6] / fs / nfsd / nfs4state.c
index 3570a0d..070e9e5 100644 (file)
@@ -78,14 +78,18 @@ static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, state
 static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
 static void nfs4_set_recdir(char *recdir);
 
-/* Locking:
- *
- * client_mutex:
- *     protects clientid_hashtbl[], clientstr_hashtbl[],
- *     unconfstr_hashtbl[], uncofid_hashtbl[].
- */
+/* Locking: */
+
+/* Currently used for almost all code touching nfsv4 state: */
 static DEFINE_MUTEX(client_mutex);
 
+/*
+ * Currently used for the del_recall_lru and file hash table.  In an
+ * effort to decrease the scope of the client_mutex, this spinlock may
+ * eventually cover more:
+ */
+static DEFINE_SPINLOCK(recall_lock);
+
 static struct kmem_cache *stateowner_slab = NULL;
 static struct kmem_cache *file_slab = NULL;
 static struct kmem_cache *stateid_slab = NULL;
@@ -116,33 +120,23 @@ opaque_hashval(const void *ptr, int nbytes)
        return x;
 }
 
-/*
- * Delegation state
- */
-
-/* recall_lock protects the del_recall_lru */
-static DEFINE_SPINLOCK(recall_lock);
 static struct list_head del_recall_lru;
 
-static void
-free_nfs4_file(struct kref *kref)
-{
-       struct nfs4_file *fp = container_of(kref, struct nfs4_file, fi_ref);
-       list_del(&fp->fi_hash);
-       iput(fp->fi_inode);
-       kmem_cache_free(file_slab, fp);
-}
-
 static inline void
 put_nfs4_file(struct nfs4_file *fi)
 {
-       kref_put(&fi->fi_ref, free_nfs4_file);
+       if (atomic_dec_and_lock(&fi->fi_ref, &recall_lock)) {
+               list_del(&fi->fi_hash);
+               spin_unlock(&recall_lock);
+               iput(fi->fi_inode);
+               kmem_cache_free(file_slab, fi);
+       }
 }
 
 static inline void
 get_nfs4_file(struct nfs4_file *fi)
 {
-       kref_get(&fi->fi_ref);
+       atomic_inc(&fi->fi_ref);
 }
 
 static int num_delegations;
@@ -797,10 +791,9 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (conf) {
                /* RFC 3530 14.2.33 CASE 0: */
                status = nfserr_clid_inuse;
-               if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)
-                               || conf->cl_addr != sin->sin_addr.s_addr) {
-                       dprintk("NFSD: setclientid: string in use by clientat %pI4\n",
-                               &conf->cl_addr);
+               if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) {
+                       dprintk("NFSD: setclientid: string in use by client"
+                               " at %pI4\n", &conf->cl_addr);
                        goto out;
                }
        }
@@ -1000,11 +993,13 @@ alloc_init_file(struct inode *ino)
 
        fp = kmem_cache_alloc(file_slab, GFP_KERNEL);
        if (fp) {
-               kref_init(&fp->fi_ref);
+               atomic_set(&fp->fi_ref, 1);
                INIT_LIST_HEAD(&fp->fi_hash);
                INIT_LIST_HEAD(&fp->fi_stateids);
                INIT_LIST_HEAD(&fp->fi_delegations);
+               spin_lock(&recall_lock);
                list_add(&fp->fi_hash, &file_hashtbl[hashval]);
+               spin_unlock(&recall_lock);
                fp->fi_inode = igrab(ino);
                fp->fi_id = current_fileid++;
                fp->fi_had_conflict = false;
@@ -1177,12 +1172,15 @@ find_file(struct inode *ino)
        unsigned int hashval = file_hashval(ino);
        struct nfs4_file *fp;
 
+       spin_lock(&recall_lock);
        list_for_each_entry(fp, &file_hashtbl[hashval], fi_hash) {
                if (fp->fi_inode == ino) {
                        get_nfs4_file(fp);
+                       spin_unlock(&recall_lock);
                        return fp;
                }
        }
+       spin_unlock(&recall_lock);
        return NULL;
 }
 
@@ -2019,7 +2017,7 @@ check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
  * that are not able to provide mandatory locking.
  */
 static inline int
-io_during_grace_disallowed(struct inode *inode, int flags)
+grace_disallows_io(struct inode *inode)
 {
        return locks_in_grace() && mandatory_lock(inode);
 }
@@ -2063,7 +2061,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
        if (filpp)
                *filpp = NULL;
 
-       if (io_during_grace_disallowed(ino, flags))
+       if (grace_disallows_io(ino))
                return nfserr_grace;
 
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
@@ -2091,7 +2089,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
                stp = find_stateid(stateid, flags);
                if (!stp)
                        goto out;
-               if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp))
+               if (nfs4_check_fh(current_fh, stp))
                        goto out;
                if (!stp->st_stateowner->so_confirmed)
                        goto out;
@@ -2418,10 +2416,9 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        status = nfserr_stale_stateid;
        if (STALE_STATEID(stateid))
                goto out;
-       status = nfs_ok;
+       status = nfserr_bad_stateid;
        if (!is_delegation_stateid(stateid))
                goto out;
-       status = nfserr_bad_stateid;
        dp = find_delegation_stateid(inode, stateid);
        if (!dp)
                goto out;