aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c71
1 files changed, 41 insertions, 30 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 81a75f3081f4..55dfdd71f1b0 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1639,6 +1639,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
1639 locks_init_lock(&fl); 1639 locks_init_lock(&fl);
1640 fl.fl_lmops = &nfsd_lease_mng_ops; 1640 fl.fl_lmops = &nfsd_lease_mng_ops;
1641 fl.fl_flags = FL_LEASE; 1641 fl.fl_flags = FL_LEASE;
1642 fl.fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK;
1642 fl.fl_end = OFFSET_MAX; 1643 fl.fl_end = OFFSET_MAX;
1643 fl.fl_owner = (fl_owner_t)dp; 1644 fl.fl_owner = (fl_owner_t)dp;
1644 fl.fl_file = stp->st_vfs_file; 1645 fl.fl_file = stp->st_vfs_file;
@@ -1647,8 +1648,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta
1647 /* vfs_setlease checks to see if delegation should be handed out. 1648 /* vfs_setlease checks to see if delegation should be handed out.
1648 * the lock_manager callbacks fl_mylease and fl_change are used 1649 * the lock_manager callbacks fl_mylease and fl_change are used
1649 */ 1650 */
1650 if ((status = vfs_setlease(stp->st_vfs_file, 1651 if ((status = vfs_setlease(stp->st_vfs_file, fl.fl_type, &flp))) {
1651 flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK, &flp))) {
1652 dprintk("NFSD: setlease failed [%d], no delegation\n", status); 1652 dprintk("NFSD: setlease failed [%d], no delegation\n", status);
1653 unhash_delegation(dp); 1653 unhash_delegation(dp);
1654 flag = NFS4_OPEN_DELEGATE_NONE; 1654 flag = NFS4_OPEN_DELEGATE_NONE;
@@ -1763,10 +1763,6 @@ out:
1763 return status; 1763 return status;
1764} 1764}
1765 1765
1766static struct workqueue_struct *laundry_wq;
1767static void laundromat_main(struct work_struct *);
1768static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
1769
1770__be32 1766__be32
1771nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, 1767nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
1772 clientid_t *clid) 1768 clientid_t *clid)
@@ -1874,7 +1870,11 @@ nfs4_laundromat(void)
1874 return clientid_val; 1870 return clientid_val;
1875} 1871}
1876 1872
1877void 1873static struct workqueue_struct *laundry_wq;
1874static void laundromat_main(struct work_struct *);
1875static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main);
1876
1877static void
1878laundromat_main(struct work_struct *not_used) 1878laundromat_main(struct work_struct *not_used)
1879{ 1879{
1880 time_t t; 1880 time_t t;
@@ -1975,6 +1975,26 @@ io_during_grace_disallowed(struct inode *inode, int flags)
1975 && mandatory_lock(inode); 1975 && mandatory_lock(inode);
1976} 1976}
1977 1977
1978static int check_stateid_generation(stateid_t *in, stateid_t *ref)
1979{
1980 /* If the client sends us a stateid from the future, it's buggy: */
1981 if (in->si_generation > ref->si_generation)
1982 return nfserr_bad_stateid;
1983 /*
1984 * The following, however, can happen. For example, if the
1985 * client sends an open and some IO at the same time, the open
1986 * may bump si_generation while the IO is still in flight.
1987 * Thanks to hard links and renames, the client never knows what
1988 * file an open will affect. So it could avoid that situation
1989 * only by serializing all opens and IO from the same open
1990 * owner. To recover from the old_stateid error, the client
1991 * will just have to retry the IO:
1992 */
1993 if (in->si_generation < ref->si_generation)
1994 return nfserr_old_stateid;
1995 return nfs_ok;
1996}
1997
1978/* 1998/*
1979* Checks for stateid operations 1999* Checks for stateid operations
1980*/ 2000*/
@@ -2023,12 +2043,8 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
2023 goto out; 2043 goto out;
2024 stidp = &stp->st_stateid; 2044 stidp = &stp->st_stateid;
2025 } 2045 }
2026 if (stateid->si_generation > stidp->si_generation) 2046 status = check_stateid_generation(stateid, stidp);
2027 goto out; 2047 if (status)
2028
2029 /* OLD STATEID */
2030 status = nfserr_old_stateid;
2031 if (stateid->si_generation < stidp->si_generation)
2032 goto out; 2048 goto out;
2033 if (stp) { 2049 if (stp) {
2034 if ((status = nfs4_check_openmode(stp,flags))) 2050 if ((status = nfs4_check_openmode(stp,flags)))
@@ -2036,7 +2052,7 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
2036 renew_client(stp->st_stateowner->so_client); 2052 renew_client(stp->st_stateowner->so_client);
2037 if (filpp) 2053 if (filpp)
2038 *filpp = stp->st_vfs_file; 2054 *filpp = stp->st_vfs_file;
2039 } else if (dp) { 2055 } else {
2040 if ((status = nfs4_check_delegmode(dp, flags))) 2056 if ((status = nfs4_check_delegmode(dp, flags)))
2041 goto out; 2057 goto out;
2042 renew_client(dp->dl_client); 2058 renew_client(dp->dl_client);
@@ -2065,6 +2081,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
2065{ 2081{
2066 struct nfs4_stateid *stp; 2082 struct nfs4_stateid *stp;
2067 struct nfs4_stateowner *sop; 2083 struct nfs4_stateowner *sop;
2084 __be32 status;
2068 2085
2069 dprintk("NFSD: preprocess_seqid_op: seqid=%d " 2086 dprintk("NFSD: preprocess_seqid_op: seqid=%d "
2070 "stateid = (%08x/%08x/%08x/%08x)\n", seqid, 2087 "stateid = (%08x/%08x/%08x/%08x)\n", seqid,
@@ -2127,7 +2144,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
2127 } 2144 }
2128 } 2145 }
2129 2146
2130 if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { 2147 if (nfs4_check_fh(current_fh, stp)) {
2131 dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); 2148 dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
2132 return nfserr_bad_stateid; 2149 return nfserr_bad_stateid;
2133 } 2150 }
@@ -2150,15 +2167,9 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
2150 " confirmed yet!\n"); 2167 " confirmed yet!\n");
2151 return nfserr_bad_stateid; 2168 return nfserr_bad_stateid;
2152 } 2169 }
2153 if (stateid->si_generation > stp->st_stateid.si_generation) { 2170 status = check_stateid_generation(stateid, &stp->st_stateid);
2154 dprintk("NFSD: preprocess_seqid_op: future stateid?!\n"); 2171 if (status)
2155 return nfserr_bad_stateid; 2172 return status;
2156 }
2157
2158 if (stateid->si_generation < stp->st_stateid.si_generation) {
2159 dprintk("NFSD: preprocess_seqid_op: old stateid!\n");
2160 return nfserr_old_stateid;
2161 }
2162 renew_client(sop->so_client); 2173 renew_client(sop->so_client);
2163 return nfs_ok; 2174 return nfs_ok;
2164 2175
@@ -2194,7 +2205,7 @@ nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2194 2205
2195 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh, 2206 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2196 oc->oc_seqid, &oc->oc_req_stateid, 2207 oc->oc_seqid, &oc->oc_req_stateid,
2197 CHECK_FH | CONFIRM | OPEN_STATE, 2208 CONFIRM | OPEN_STATE,
2198 &oc->oc_stateowner, &stp, NULL))) 2209 &oc->oc_stateowner, &stp, NULL)))
2199 goto out; 2210 goto out;
2200 2211
@@ -2265,7 +2276,7 @@ nfsd4_open_downgrade(struct svc_rqst *rqstp,
2265 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh, 2276 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2266 od->od_seqid, 2277 od->od_seqid,
2267 &od->od_stateid, 2278 &od->od_stateid,
2268 CHECK_FH | OPEN_STATE, 2279 OPEN_STATE,
2269 &od->od_stateowner, &stp, NULL))) 2280 &od->od_stateowner, &stp, NULL)))
2270 goto out; 2281 goto out;
2271 2282
@@ -2318,7 +2329,7 @@ nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2318 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh, 2329 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2319 close->cl_seqid, 2330 close->cl_seqid,
2320 &close->cl_stateid, 2331 &close->cl_stateid,
2321 CHECK_FH | OPEN_STATE | CLOSE_STATE, 2332 OPEN_STATE | CLOSE_STATE,
2322 &close->cl_stateowner, &stp, NULL))) 2333 &close->cl_stateowner, &stp, NULL)))
2323 goto out; 2334 goto out;
2324 status = nfs_ok; 2335 status = nfs_ok;
@@ -2623,7 +2634,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2623 status = nfs4_preprocess_seqid_op(&cstate->current_fh, 2634 status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2624 lock->lk_new_open_seqid, 2635 lock->lk_new_open_seqid,
2625 &lock->lk_new_open_stateid, 2636 &lock->lk_new_open_stateid,
2626 CHECK_FH | OPEN_STATE, 2637 OPEN_STATE,
2627 &lock->lk_replay_owner, &open_stp, 2638 &lock->lk_replay_owner, &open_stp,
2628 lock); 2639 lock);
2629 if (status) 2640 if (status)
@@ -2650,7 +2661,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2650 status = nfs4_preprocess_seqid_op(&cstate->current_fh, 2661 status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2651 lock->lk_old_lock_seqid, 2662 lock->lk_old_lock_seqid,
2652 &lock->lk_old_lock_stateid, 2663 &lock->lk_old_lock_stateid,
2653 CHECK_FH | LOCK_STATE, 2664 LOCK_STATE,
2654 &lock->lk_replay_owner, &lock_stp, lock); 2665 &lock->lk_replay_owner, &lock_stp, lock);
2655 if (status) 2666 if (status)
2656 goto out; 2667 goto out;
@@ -2847,7 +2858,7 @@ nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
2847 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh, 2858 if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
2848 locku->lu_seqid, 2859 locku->lu_seqid,
2849 &locku->lu_stateid, 2860 &locku->lu_stateid,
2850 CHECK_FH | LOCK_STATE, 2861 LOCK_STATE,
2851 &locku->lu_stateowner, &stp, NULL))) 2862 &locku->lu_stateowner, &stp, NULL)))
2852 goto out; 2863 goto out;
2853 2864