nfsd4: remove HAS_SESSION
[firefly-linux-kernel-4.4.55.git] / fs / nfsd / nfs4state.c
index 3787ec11740014a64e13ca3eb336d6fdf80f7310..14c8dd64e136930eda8c439ac38ed536c769a063 100644 (file)
@@ -64,8 +64,6 @@ static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags);
 static struct nfs4_stateid * search_for_stateid(stateid_t *stid);
 static struct nfs4_delegation * search_for_delegation(stateid_t *stid);
 static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid);
-static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
-static void nfs4_set_recdir(char *recdir);
 static int check_for_locks(struct nfs4_file *filp, struct nfs4_stateowner *lowner);
 
 /* Locking: */
@@ -136,18 +134,27 @@ unsigned int max_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)
+/* hash tables for open owners */
+#define OPEN_OWNER_HASH_BITS              8
+#define OPEN_OWNER_HASH_SIZE             (1 << OPEN_OWNER_HASH_BITS)
+#define OPEN_OWNER_HASH_MASK             (OPEN_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 unsigned int open_ownerid_hashval(const u32 id)
+{
+       return id & OPEN_OWNER_HASH_MASK;
+}
 
-static struct list_head        ownerid_hashtbl[OWNER_HASH_SIZE];
-static struct list_head        ownerstr_hashtbl[OWNER_HASH_SIZE];
+static unsigned int open_ownerstr_hashval(u32 clientid, struct xdr_netobj *ownername)
+{
+       unsigned int ret;
+
+       ret = opaque_hashval(ownername->data, ownername->len);
+       ret += clientid;
+       return ret & OPEN_OWNER_HASH_MASK;
+}
+
+static struct list_head        open_ownerid_hashtbl[OPEN_OWNER_HASH_SIZE];
+static struct list_head        open_ownerstr_hashtbl[OPEN_OWNER_HASH_SIZE];
 
 /* hash table for nfs4_file */
 #define FILE_HASH_BITS                   8
@@ -158,10 +165,16 @@ static struct list_head   ownerstr_hashtbl[OWNER_HASH_SIZE];
 #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 unsigned int file_hashval(struct inode *ino)
+{
+       /* XXX: why are we hashing on inode pointer, anyway? */
+       return hash_ptr(ino, FILE_HASH_BITS);
+}
+
+static unsigned int stateid_hashval(u32 owner_id, u32 file_id)
+{
+       return (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];
@@ -292,10 +305,16 @@ static DEFINE_SPINLOCK(client_lock);
 #define CLIENT_HASH_SIZE                (1 << CLIENT_HASH_BITS)
 #define CLIENT_HASH_MASK                (CLIENT_HASH_SIZE - 1)
 
-#define clientid_hashval(id) \
-       ((id) & CLIENT_HASH_MASK)
-#define clientstr_hashval(name) \
-       (opaque_hashval((name), 8) & CLIENT_HASH_MASK)
+static unsigned int clientid_hashval(u32 id)
+{
+       return id & CLIENT_HASH_MASK;
+}
+
+static unsigned int clientstr_hashval(const char *name)
+{
+       return opaque_hashval(name, 8) & CLIENT_HASH_MASK;
+}
+
 /*
  * reclaim_str_hashtbl[] holds known client info from previous reset/reboot
  * used in reboot/reset lease grace period processing
@@ -1946,7 +1965,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
         * of 5 bullet points, labeled as CASE0 - CASE4 below.
         */
        unconf = find_unconfirmed_client_by_str(dname, strhashval);
-       status = nfserr_resource;
+       status = nfserr_jukebox;
        if (!conf) {
                /*
                 * RFC 3530 14.2.33 CASE 4:
@@ -2196,51 +2215,61 @@ nfs4_free_stateowner(struct kref *kref)
        kmem_cache_free(stateowner_slab, sop);
 }
 
-static inline struct nfs4_stateowner *
-alloc_stateowner(struct xdr_netobj *owner)
+static void init_nfs4_replay(struct nfs4_replay *rp)
+{
+       rp->rp_status = nfserr_serverfault;
+       rp->rp_buflen = 0;
+       rp->rp_buf = rp->rp_ibuf;
+}
+
+static inline struct nfs4_stateowner *alloc_stateowner(struct xdr_netobj *owner, struct nfs4_client *clp)
 {
        struct nfs4_stateowner *sop;
 
-       if ((sop = kmem_cache_alloc(stateowner_slab, GFP_KERNEL))) {
-               if ((sop->so_owner.data = kmalloc(owner->len, GFP_KERNEL))) {
-                       memcpy(sop->so_owner.data, owner->data, owner->len);
-                       sop->so_owner.len = owner->len;
-                       kref_init(&sop->so_ref);
-                       return sop;
-               } 
+       sop = kmem_cache_alloc(stateowner_slab, GFP_KERNEL);
+       if (!sop)
+               return NULL;
+
+       sop->so_owner.data = kmemdup(owner->data, owner->len, GFP_KERNEL);
+       if (!sop->so_owner.data) {
                kmem_cache_free(stateowner_slab, sop);
+               return NULL;
        }
-       return NULL;
+       sop->so_owner.len = owner->len;
+
+       kref_init(&sop->so_ref);
+       INIT_LIST_HEAD(&sop->so_perclient);
+       INIT_LIST_HEAD(&sop->so_stateids);
+       INIT_LIST_HEAD(&sop->so_perstateid);
+       INIT_LIST_HEAD(&sop->so_close_lru);
+       sop->so_id = current_ownerid++;
+       sop->so_time = 0;
+       sop->so_client = clp;
+       init_nfs4_replay(&sop->so_replay);
+       return sop;
+}
+
+static void hash_openowner(struct nfs4_stateowner *sop, struct nfs4_client *clp, unsigned int strhashval)
+{
+       unsigned int idhashval;
+
+       idhashval = open_ownerid_hashval(sop->so_id);
+       list_add(&sop->so_idhash, &open_ownerid_hashtbl[idhashval]);
+       list_add(&sop->so_strhash, &open_ownerstr_hashtbl[strhashval]);
+       list_add(&sop->so_perclient, &clp->cl_openowners);
 }
 
 static struct nfs4_stateowner *
 alloc_init_open_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfsd4_open *open) {
        struct nfs4_stateowner *sop;
-       struct nfs4_replay *rp;
-       unsigned int idhashval;
 
-       if (!(sop = alloc_stateowner(&open->op_owner)))
+       sop = alloc_stateowner(&open->op_owner, clp);
+       if (!sop)
                return NULL;
-       idhashval = ownerid_hashval(current_ownerid);
-       INIT_LIST_HEAD(&sop->so_idhash);
-       INIT_LIST_HEAD(&sop->so_strhash);
-       INIT_LIST_HEAD(&sop->so_perclient);
-       INIT_LIST_HEAD(&sop->so_stateids);
-       INIT_LIST_HEAD(&sop->so_perstateid);  /* not used */
-       INIT_LIST_HEAD(&sop->so_close_lru);
-       sop->so_time = 0;
-       list_add(&sop->so_idhash, &ownerid_hashtbl[idhashval]);
-       list_add(&sop->so_strhash, &ownerstr_hashtbl[strhashval]);
-       list_add(&sop->so_perclient, &clp->cl_openowners);
        sop->so_is_open_owner = 1;
-       sop->so_id = current_ownerid++;
-       sop->so_client = clp;
        sop->so_seqid = open->op_seqid;
        sop->so_confirmed = 0;
-       rp = &sop->so_replay;
-       rp->rp_status = nfserr_serverfault;
-       rp->rp_buflen = 0;
-       rp->rp_buf = rp->rp_ibuf;
+       hash_openowner(sop, clp, strhashval);
        return sop;
 }
 
@@ -2294,7 +2323,7 @@ find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open)
 {
        struct nfs4_stateowner *so = NULL;
 
-       list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) {
+       list_for_each_entry(so, &open_ownerstr_hashtbl[hashval], so_strhash) {
                if (same_owner_str(so, &open->op_owner, &open->op_clientid))
                        return so;
        }
@@ -2445,7 +2474,7 @@ nfsd4_process_open1(struct nfsd4_compound_state *cstate,
        if (STALE_CLIENTID(&open->op_clientid))
                return nfserr_stale_clientid;
 
-       strhashval = ownerstr_hashval(clientid->cl_id, open->op_owner);
+       strhashval = open_ownerstr_hashval(clientid->cl_id, &open->op_owner);
        sop = find_openstateowner_str(strhashval, open);
        open->op_stateowner = sop;
        if (!sop) {
@@ -2483,7 +2512,7 @@ renew:
        if (open->op_stateowner == NULL) {
                sop = alloc_init_open_stateowner(strhashval, clp, open);
                if (sop == NULL)
-                       return nfserr_resource;
+                       return nfserr_jukebox;
                open->op_stateowner = sop;
        }
        list_del_init(&sop->so_close_lru);
@@ -2619,7 +2648,7 @@ nfs4_new_open(struct svc_rqst *rqstp, struct nfs4_stateid **stpp,
 
        stp = nfs4_alloc_stateid();
        if (stp == NULL)
-               return nfserr_resource;
+               return nfserr_jukebox;
 
        status = nfs4_get_vfs_file(rqstp, fp, cur_fh, open);
        if (status) {
@@ -2850,7 +2879,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
                status = nfserr_bad_stateid;
                if (open->op_claim_type == NFS4_OPEN_CLAIM_DELEGATE_CUR)
                        goto out;
-               status = nfserr_resource;
+               status = nfserr_jukebox;
                fp = alloc_init_file(ino);
                if (fp == NULL)
                        goto out;
@@ -3139,13 +3168,13 @@ grace_disallows_io(struct inode *inode)
        return locks_in_grace() && mandatory_lock(inode);
 }
 
-static int check_stateid_generation(stateid_t *in, stateid_t *ref, int flags)
+static int check_stateid_generation(stateid_t *in, stateid_t *ref, bool has_session)
 {
        /*
         * When sessions are used the stateid generation number is ignored
         * when it is zero.
         */
-       if ((flags & HAS_SESSION) && in->si_generation == 0)
+       if (has_session && in->si_generation == 0)
                goto out;
 
        /* If the client sends us a stateid from the future, it's buggy: */
@@ -3177,7 +3206,7 @@ static int is_open_stateid(struct nfs4_stateid *stateid)
        return stateid->st_openstp == NULL;
 }
 
-__be32 nfs4_validate_stateid(stateid_t *stateid, int flags)
+__be32 nfs4_validate_stateid(stateid_t *stateid, bool has_session)
 {
        struct nfs4_stateid *stp = NULL;
        __be32 status = nfserr_stale_stateid;
@@ -3194,7 +3223,7 @@ __be32 nfs4_validate_stateid(stateid_t *stateid, int flags)
        if (!stp->st_stateowner->so_confirmed)
                goto out;
 
-       status = check_stateid_generation(stateid, &stp->st_stateid, flags);
+       status = check_stateid_generation(stateid, &stp->st_stateid, has_session);
        if (status)
                goto out;
 
@@ -3222,9 +3251,6 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
        if (grace_disallows_io(ino))
                return nfserr_grace;
 
-       if (nfsd4_has_session(cstate))
-               flags |= HAS_SESSION;
-
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
                return check_special_stateids(current_fh, stateid, flags);
 
@@ -3241,8 +3267,7 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
                dp = find_delegation_stateid(ino, stateid);
                if (!dp)
                        goto out;
-               status = check_stateid_generation(stateid, &dp->dl_stateid,
-                                                 flags);
+               status = check_stateid_generation(stateid, &dp->dl_stateid, nfsd4_has_session(cstate));
                if (status)
                        goto out;
                status = nfs4_check_delegmode(dp, flags);
@@ -3263,7 +3288,7 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
                if (!stp->st_stateowner->so_confirmed)
                        goto out;
                status = check_stateid_generation(stateid, &stp->st_stateid,
-                                                 flags);
+                                                 nfsd4_has_session(cstate));
                if (status)
                        goto out;
                status = nfs4_check_openmode(stp, flags);
@@ -3392,9 +3417,6 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
        if (STALE_STATEID(stateid))
                return nfserr_stale_stateid;
 
-       if (nfsd4_has_session(cstate))
-               flags |= HAS_SESSION;
-
        /*
        * We return BAD_STATEID if filehandle doesn't match stateid, 
        * the confirmed flag is incorrecly set, or the generation 
@@ -3428,7 +3450,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
                if (lock->lk_is_new) {
                        if (!sop->so_is_open_owner)
                                return nfserr_bad_stateid;
-                       if (!(flags & HAS_SESSION) &&
+                       if (!nfsd4_has_session(cstate) &&
                            !same_clid(&clp->cl_clientid, lockclid))
                                return nfserr_bad_stateid;
                        /* stp is the open stateid */
@@ -3453,7 +3475,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
        *  For the moment, we ignore the possibility of 
        *  generation number wraparound.
        */
-       if (!(flags & HAS_SESSION) && seqid != sop->so_seqid)
+       if (!nfsd4_has_session(cstate) && seqid != sop->so_seqid)
                goto check_replay;
 
        if (sop->so_confirmed && flags & CONFIRM) {
@@ -3466,7 +3488,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
                                " confirmed yet!\n");
                return nfserr_bad_stateid;
        }
-       status = check_stateid_generation(stateid, &stp->st_stateid, flags);
+       status = check_stateid_generation(stateid, &stp->st_stateid, nfsd4_has_session(cstate));
        if (status)
                return status;
        renew_client(sop->so_client);
@@ -3650,14 +3672,11 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        stateid_t *stateid = &dr->dr_stateid;
        struct inode *inode;
        __be32 status;
-       int flags = 0;
 
        if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
                return status;
        inode = cstate->current_fh.fh_dentry->d_inode;
 
-       if (nfsd4_has_session(cstate))
-               flags |= HAS_SESSION;
        nfs4_lock_state();
        status = nfserr_bad_stateid;
        if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
@@ -3672,7 +3691,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        dp = find_delegation_stateid(inode, stateid);
        if (!dp)
                goto out;
-       status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
+       status = check_stateid_generation(stateid, &dp->dl_stateid, nfsd4_has_session(cstate));
        if (status)
                goto out;
        renew_client(dp->dl_client);
@@ -3713,8 +3732,10 @@ last_byte_offset(u64 start, u64 len)
        return end > start ? end - 1: NFS4_MAX_UINT64;
 }
 
-#define lockownerid_hashval(id) \
-        ((id) & LOCK_HASH_MASK)
+static unsigned int lockownerid_hashval(u32 id)
+{
+       return id & LOCK_HASH_MASK;
+}
 
 static inline unsigned int
 lock_ownerstr_hashval(struct inode *inode, u32 cl_id,
@@ -3881,6 +3902,16 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid,
        return NULL;
 }
 
+static void hash_lockowner(struct nfs4_stateowner *sop, unsigned int strhashval, struct nfs4_client *clp, struct nfs4_stateid *open_stp)
+{
+       unsigned int idhashval;
+
+       idhashval = lockownerid_hashval(sop->so_id);
+       list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
+       list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
+       list_add(&sop->so_perstateid, &open_stp->st_lockowners);
+}
+
 /*
  * Alloc a lock owner structure.
  * Called in nfsd4_lock - therefore, OPEN and OPEN_CONFIRM (if needed) has 
@@ -3892,33 +3923,17 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid,
 static struct nfs4_stateowner *
 alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, struct nfs4_stateid *open_stp, struct nfsd4_lock *lock) {
        struct nfs4_stateowner *sop;
-       struct nfs4_replay *rp;
-       unsigned int idhashval;
 
-       if (!(sop = alloc_stateowner(&lock->lk_new_owner)))
+       sop = alloc_stateowner(&lock->lk_new_owner, clp);
+       if (!sop)
                return NULL;
-       idhashval = lockownerid_hashval(current_ownerid);
-       INIT_LIST_HEAD(&sop->so_idhash);
-       INIT_LIST_HEAD(&sop->so_strhash);
-       INIT_LIST_HEAD(&sop->so_perclient);
        INIT_LIST_HEAD(&sop->so_stateids);
-       INIT_LIST_HEAD(&sop->so_perstateid);
-       INIT_LIST_HEAD(&sop->so_close_lru); /* not used */
-       sop->so_time = 0;
-       list_add(&sop->so_idhash, &lock_ownerid_hashtbl[idhashval]);
-       list_add(&sop->so_strhash, &lock_ownerstr_hashtbl[strhashval]);
-       list_add(&sop->so_perstateid, &open_stp->st_lockowners);
        sop->so_is_open_owner = 0;
-       sop->so_id = current_ownerid++;
-       sop->so_client = clp;
        /* It is the openowner seqid that will be incremented in encode in the
         * case of new lockowners; so increment the lock seqid manually: */
        sop->so_seqid = lock->lk_new_lock_seqid + 1;
        sop->so_confirmed = 1;
-       rp = &sop->so_replay;
-       rp->rp_status = nfserr_serverfault;
-       rp->rp_buflen = 0;
-       rp->rp_buf = rp->rp_ibuf;
+       hash_lockowner(sop, strhashval, clp, open_stp);
        return sop;
 }
 
@@ -4035,7 +4050,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
                /* XXX: Do we need to check for duplicate stateowners on
                 * the same file, or should they just be allowed (and
                 * create new stateids)? */
-               status = nfserr_resource;
+               status = nfserr_jukebox;
                lock_sop = alloc_init_lock_stateowner(strhashval,
                                open_sop->so_client, open_stp, lock);
                if (lock_sop == NULL)
@@ -4119,9 +4134,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        case (EDEADLK):
                status = nfserr_deadlock;
                break;
-       default:        
+       default:
                dprintk("NFSD: nfsd4_lock: vfs_lock_file() failed! status %d\n",err);
-               status = nfserr_resource;
+               status = nfserrno(err);
                break;
        }
 out:
@@ -4179,12 +4194,8 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
        if (!nfsd4_has_session(cstate) && STALE_CLIENTID(&lockt->lt_clientid))
                goto out;
 
-       if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) {
-               dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
-               if (status == nfserr_symlink)
-                       status = nfserr_inval;
+       if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
                goto out;
-       }
 
        inode = cstate->current_fh.fh_dentry->d_inode;
        locks_init_lock(&file_lock);
@@ -4501,9 +4512,9 @@ nfs4_state_init(void)
        for (i = 0; i < FILE_HASH_SIZE; i++) {
                INIT_LIST_HEAD(&file_hashtbl[i]);
        }
-       for (i = 0; i < OWNER_HASH_SIZE; i++) {
-               INIT_LIST_HEAD(&ownerstr_hashtbl[i]);
-               INIT_LIST_HEAD(&ownerid_hashtbl[i]);
+       for (i = 0; i < OPEN_OWNER_HASH_SIZE; i++) {
+               INIT_LIST_HEAD(&open_ownerstr_hashtbl[i]);
+               INIT_LIST_HEAD(&open_ownerid_hashtbl[i]);
        }
        for (i = 0; i < STATEID_HASH_SIZE; i++) {
                INIT_LIST_HEAD(&stateid_hashtbl[i]);
@@ -4527,7 +4538,7 @@ nfsd4_load_reboot_recovery_data(void)
        int status;
 
        nfs4_lock_state();
-       nfsd4_init_recdir(user_recovery_dirname);
+       nfsd4_init_recdir();
        status = nfsd4_recdir_load();
        nfs4_unlock_state();
        if (status)
@@ -4636,40 +4647,3 @@ nfs4_state_shutdown(void)
        nfs4_unlock_state();
        nfsd4_destroy_callback_queue();
 }
-
-/*
- * user_recovery_dirname is protected by the nfsd_mutex since it's only
- * accessed when nfsd is starting.
- */
-static void
-nfs4_set_recdir(char *recdir)
-{
-       strcpy(user_recovery_dirname, recdir);
-}
-
-/*
- * Change the NFSv4 recovery directory to recdir.
- */
-int
-nfs4_reset_recoverydir(char *recdir)
-{
-       int status;
-       struct path path;
-
-       status = kern_path(recdir, LOOKUP_FOLLOW, &path);
-       if (status)
-               return status;
-       status = -ENOTDIR;
-       if (S_ISDIR(path.dentry->d_inode->i_mode)) {
-               nfs4_set_recdir(recdir);
-               status = 0;
-       }
-       path_put(&path);
-       return status;
-}
-
-char *
-nfs4_recoverydir(void)
-{
-       return user_recovery_dirname;
-}