diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 71 |
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 | ||
1766 | static struct workqueue_struct *laundry_wq; | ||
1767 | static void laundromat_main(struct work_struct *); | ||
1768 | static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main); | ||
1769 | |||
1770 | __be32 | 1766 | __be32 |
1771 | nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | 1767 | nfsd4_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 | ||
1877 | void | 1873 | static struct workqueue_struct *laundry_wq; |
1874 | static void laundromat_main(struct work_struct *); | ||
1875 | static DECLARE_DELAYED_WORK(laundromat_work, laundromat_main); | ||
1876 | |||
1877 | static void | ||
1878 | laundromat_main(struct work_struct *not_used) | 1878 | laundromat_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 | ||
1978 | static 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 | ||