diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 231 |
1 files changed, 110 insertions, 121 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 89e36526d7f2..b83f8fb441e1 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
@@ -874,6 +874,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confi | |||
874 | * change request correctly. */ | 874 | * change request correctly. */ |
875 | atomic_set(&conf->cl_callback.cb_set, 0); | 875 | atomic_set(&conf->cl_callback.cb_set, 0); |
876 | gen_confirm(conf); | 876 | gen_confirm(conf); |
877 | nfsd4_remove_clid_dir(unconf); | ||
877 | expire_client(unconf); | 878 | expire_client(unconf); |
878 | status = nfs_ok; | 879 | status = nfs_ok; |
879 | 880 | ||
@@ -1159,6 +1160,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open * | |||
1159 | stp->st_deny_bmap = 0; | 1160 | stp->st_deny_bmap = 0; |
1160 | __set_bit(open->op_share_access, &stp->st_access_bmap); | 1161 | __set_bit(open->op_share_access, &stp->st_access_bmap); |
1161 | __set_bit(open->op_share_deny, &stp->st_deny_bmap); | 1162 | __set_bit(open->op_share_deny, &stp->st_deny_bmap); |
1163 | stp->st_openstp = NULL; | ||
1162 | } | 1164 | } |
1163 | 1165 | ||
1164 | static void | 1166 | static void |
@@ -1294,7 +1296,7 @@ nfs4_share_conflict(struct svc_fh *current_fh, unsigned int deny_type) | |||
1294 | fp = find_file(ino); | 1296 | fp = find_file(ino); |
1295 | if (!fp) | 1297 | if (!fp) |
1296 | return nfs_ok; | 1298 | return nfs_ok; |
1297 | ret = nfserr_share_denied; | 1299 | ret = nfserr_locked; |
1298 | /* Search for conflicting share reservations */ | 1300 | /* Search for conflicting share reservations */ |
1299 | list_for_each_entry(stp, &fp->fi_stateids, st_perfile) { | 1301 | list_for_each_entry(stp, &fp->fi_stateids, st_perfile) { |
1300 | if (test_bit(deny_type, &stp->st_deny_bmap) || | 1302 | if (test_bit(deny_type, &stp->st_deny_bmap) || |
@@ -1482,7 +1484,7 @@ nfsd4_process_open1(struct nfsd4_open *open) | |||
1482 | if (sop) { | 1484 | if (sop) { |
1483 | open->op_stateowner = sop; | 1485 | open->op_stateowner = sop; |
1484 | /* check for replay */ | 1486 | /* check for replay */ |
1485 | if (open->op_seqid == sop->so_seqid){ | 1487 | if (open->op_seqid == sop->so_seqid - 1){ |
1486 | if (sop->so_replay.rp_buflen) | 1488 | if (sop->so_replay.rp_buflen) |
1487 | return NFSERR_REPLAY_ME; | 1489 | return NFSERR_REPLAY_ME; |
1488 | else { | 1490 | else { |
@@ -1497,7 +1499,7 @@ nfsd4_process_open1(struct nfsd4_open *open) | |||
1497 | goto renew; | 1499 | goto renew; |
1498 | } | 1500 | } |
1499 | } else if (sop->so_confirmed) { | 1501 | } else if (sop->so_confirmed) { |
1500 | if (open->op_seqid == sop->so_seqid + 1) | 1502 | if (open->op_seqid == sop->so_seqid) |
1501 | goto renew; | 1503 | goto renew; |
1502 | status = nfserr_bad_seqid; | 1504 | status = nfserr_bad_seqid; |
1503 | goto out; | 1505 | goto out; |
@@ -1530,8 +1532,6 @@ renew: | |||
1530 | status = nfs_ok; | 1532 | status = nfs_ok; |
1531 | renew_client(sop->so_client); | 1533 | renew_client(sop->so_client); |
1532 | out: | 1534 | out: |
1533 | if (status && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) | ||
1534 | status = nfserr_reclaim_bad; | ||
1535 | return status; | 1535 | return status; |
1536 | } | 1536 | } |
1537 | 1537 | ||
@@ -1685,19 +1685,11 @@ nfs4_upgrade_open(struct svc_rqst *rqstp, struct svc_fh *cur_fh, struct nfs4_sta | |||
1685 | } | 1685 | } |
1686 | 1686 | ||
1687 | 1687 | ||
1688 | /* decrement seqid on successful reclaim, it will be bumped in encode_open */ | ||
1689 | static void | 1688 | static void |
1690 | nfs4_set_claim_prev(struct nfsd4_open *open, int *status) | 1689 | nfs4_set_claim_prev(struct nfsd4_open *open) |
1691 | { | 1690 | { |
1692 | if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) { | 1691 | open->op_stateowner->so_confirmed = 1; |
1693 | if (*status) | 1692 | open->op_stateowner->so_client->cl_firststate = 1; |
1694 | *status = nfserr_reclaim_bad; | ||
1695 | else { | ||
1696 | open->op_stateowner->so_confirmed = 1; | ||
1697 | open->op_stateowner->so_client->cl_firststate = 1; | ||
1698 | open->op_stateowner->so_seqid--; | ||
1699 | } | ||
1700 | } | ||
1701 | } | 1693 | } |
1702 | 1694 | ||
1703 | /* | 1695 | /* |
@@ -1789,6 +1781,12 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1789 | struct nfs4_delegation *dp = NULL; | 1781 | struct nfs4_delegation *dp = NULL; |
1790 | int status; | 1782 | int status; |
1791 | 1783 | ||
1784 | if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) | ||
1785 | return nfserr_grace; | ||
1786 | |||
1787 | if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) | ||
1788 | return nfserr_no_grace; | ||
1789 | |||
1792 | status = nfserr_inval; | 1790 | status = nfserr_inval; |
1793 | if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) | 1791 | if (!TEST_ACCESS(open->op_share_access) || !TEST_DENY(open->op_share_deny)) |
1794 | goto out; | 1792 | goto out; |
@@ -1823,6 +1821,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1823 | status = nfs4_upgrade_open(rqstp, current_fh, stp, open); | 1821 | status = nfs4_upgrade_open(rqstp, current_fh, stp, open); |
1824 | if (status) | 1822 | if (status) |
1825 | goto out; | 1823 | goto out; |
1824 | update_stateid(&stp->st_stateid); | ||
1826 | } else { | 1825 | } else { |
1827 | /* Stateid was not found, this is a new OPEN */ | 1826 | /* Stateid was not found, this is a new OPEN */ |
1828 | int flags = 0; | 1827 | int flags = 0; |
@@ -1856,8 +1855,8 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf | |||
1856 | out: | 1855 | out: |
1857 | if (fp) | 1856 | if (fp) |
1858 | put_nfs4_file(fp); | 1857 | put_nfs4_file(fp); |
1859 | /* CLAIM_PREVIOUS has different error returns */ | 1858 | if (status == 0 && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) |
1860 | nfs4_set_claim_prev(open, &status); | 1859 | nfs4_set_claim_prev(open); |
1861 | /* | 1860 | /* |
1862 | * To finish the open response, we just need to set the rflags. | 1861 | * To finish the open response, we just need to set the rflags. |
1863 | */ | 1862 | */ |
@@ -1990,14 +1989,11 @@ laundromat_main(void *not_used) | |||
1990 | queue_delayed_work(laundry_wq, &laundromat_work, t*HZ); | 1989 | queue_delayed_work(laundry_wq, &laundromat_work, t*HZ); |
1991 | } | 1990 | } |
1992 | 1991 | ||
1993 | /* search ownerid_hashtbl[] and close_lru for stateid owner | ||
1994 | * (stateid->si_stateownerid) | ||
1995 | */ | ||
1996 | static struct nfs4_stateowner * | 1992 | static struct nfs4_stateowner * |
1997 | find_openstateowner_id(u32 st_id, int flags) { | 1993 | search_close_lru(u32 st_id, int flags) |
1994 | { | ||
1998 | struct nfs4_stateowner *local = NULL; | 1995 | struct nfs4_stateowner *local = NULL; |
1999 | 1996 | ||
2000 | dprintk("NFSD: find_openstateowner_id %d\n", st_id); | ||
2001 | if (flags & CLOSE_STATE) { | 1997 | if (flags & CLOSE_STATE) { |
2002 | list_for_each_entry(local, &close_lru, so_close_lru) { | 1998 | list_for_each_entry(local, &close_lru, so_close_lru) { |
2003 | if (local->so_id == st_id) | 1999 | if (local->so_id == st_id) |
@@ -2163,14 +2159,19 @@ out: | |||
2163 | return status; | 2159 | return status; |
2164 | } | 2160 | } |
2165 | 2161 | ||
2162 | static inline int | ||
2163 | setlkflg (int type) | ||
2164 | { | ||
2165 | return (type == NFS4_READW_LT || type == NFS4_READ_LT) ? | ||
2166 | RD_STATE : WR_STATE; | ||
2167 | } | ||
2166 | 2168 | ||
2167 | /* | 2169 | /* |
2168 | * Checks for sequence id mutating operations. | 2170 | * Checks for sequence id mutating operations. |
2169 | */ | 2171 | */ |
2170 | static int | 2172 | static int |
2171 | nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid) | 2173 | nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, struct nfsd4_lock *lock) |
2172 | { | 2174 | { |
2173 | int status; | ||
2174 | struct nfs4_stateid *stp; | 2175 | struct nfs4_stateid *stp; |
2175 | struct nfs4_stateowner *sop; | 2176 | struct nfs4_stateowner *sop; |
2176 | 2177 | ||
@@ -2178,53 +2179,65 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
2178 | "stateid = (%08x/%08x/%08x/%08x)\n", seqid, | 2179 | "stateid = (%08x/%08x/%08x/%08x)\n", seqid, |
2179 | stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid, | 2180 | stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid, |
2180 | stateid->si_generation); | 2181 | stateid->si_generation); |
2181 | 2182 | ||
2182 | *stpp = NULL; | 2183 | *stpp = NULL; |
2183 | *sopp = NULL; | 2184 | *sopp = NULL; |
2184 | 2185 | ||
2185 | status = nfserr_bad_stateid; | ||
2186 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { | 2186 | if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { |
2187 | printk("NFSD: preprocess_seqid_op: magic stateid!\n"); | 2187 | printk("NFSD: preprocess_seqid_op: magic stateid!\n"); |
2188 | goto out; | 2188 | return nfserr_bad_stateid; |
2189 | } | 2189 | } |
2190 | 2190 | ||
2191 | status = nfserr_stale_stateid; | ||
2192 | if (STALE_STATEID(stateid)) | 2191 | if (STALE_STATEID(stateid)) |
2193 | goto out; | 2192 | return nfserr_stale_stateid; |
2194 | /* | 2193 | /* |
2195 | * We return BAD_STATEID if filehandle doesn't match stateid, | 2194 | * We return BAD_STATEID if filehandle doesn't match stateid, |
2196 | * the confirmed flag is incorrecly set, or the generation | 2195 | * the confirmed flag is incorrecly set, or the generation |
2197 | * number is incorrect. | 2196 | * number is incorrect. |
2198 | * If there is no entry in the openfile table for this id, | ||
2199 | * we can't always return BAD_STATEID; | ||
2200 | * this might be a retransmitted CLOSE which has arrived after | ||
2201 | * the openfile has been released. | ||
2202 | */ | 2197 | */ |
2203 | if (!(stp = find_stateid(stateid, flags))) | 2198 | stp = find_stateid(stateid, flags); |
2204 | goto no_nfs4_stateid; | 2199 | if (stp == NULL) { |
2205 | 2200 | /* | |
2206 | status = nfserr_bad_stateid; | 2201 | * Also, we should make sure this isn't just the result of |
2202 | * a replayed close: | ||
2203 | */ | ||
2204 | sop = search_close_lru(stateid->si_stateownerid, flags); | ||
2205 | if (sop == NULL) | ||
2206 | return nfserr_bad_stateid; | ||
2207 | *sopp = sop; | ||
2208 | goto check_replay; | ||
2209 | } | ||
2207 | 2210 | ||
2208 | /* for new lock stateowners: | 2211 | if (lock) { |
2209 | * check that the lock->v.new.open_stateid | ||
2210 | * refers to an open stateowner | ||
2211 | * | ||
2212 | * check that the lockclid (nfs4_lock->v.new.clientid) is the same | ||
2213 | * as the open_stateid->st_stateowner->so_client->clientid | ||
2214 | */ | ||
2215 | if (lockclid) { | ||
2216 | struct nfs4_stateowner *sop = stp->st_stateowner; | 2212 | struct nfs4_stateowner *sop = stp->st_stateowner; |
2213 | clientid_t *lockclid = &lock->v.new.clientid; | ||
2217 | struct nfs4_client *clp = sop->so_client; | 2214 | struct nfs4_client *clp = sop->so_client; |
2215 | int lkflg = 0; | ||
2216 | int status; | ||
2217 | |||
2218 | lkflg = setlkflg(lock->lk_type); | ||
2219 | |||
2220 | if (lock->lk_is_new) { | ||
2221 | if (!sop->so_is_open_owner) | ||
2222 | return nfserr_bad_stateid; | ||
2223 | if (!cmp_clid(&clp->cl_clientid, lockclid)) | ||
2224 | return nfserr_bad_stateid; | ||
2225 | /* stp is the open stateid */ | ||
2226 | status = nfs4_check_openmode(stp, lkflg); | ||
2227 | if (status) | ||
2228 | return status; | ||
2229 | } else { | ||
2230 | /* stp is the lock stateid */ | ||
2231 | status = nfs4_check_openmode(stp->st_openstp, lkflg); | ||
2232 | if (status) | ||
2233 | return status; | ||
2234 | } | ||
2218 | 2235 | ||
2219 | if (!sop->so_is_open_owner) | ||
2220 | goto out; | ||
2221 | if (!cmp_clid(&clp->cl_clientid, lockclid)) | ||
2222 | goto out; | ||
2223 | } | 2236 | } |
2224 | 2237 | ||
2225 | if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { | 2238 | if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { |
2226 | printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); | 2239 | printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); |
2227 | goto out; | 2240 | return nfserr_bad_stateid; |
2228 | } | 2241 | } |
2229 | 2242 | ||
2230 | *stpp = stp; | 2243 | *stpp = stp; |
@@ -2235,63 +2248,41 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei | |||
2235 | * For the moment, we ignore the possibility of | 2248 | * For the moment, we ignore the possibility of |
2236 | * generation number wraparound. | 2249 | * generation number wraparound. |
2237 | */ | 2250 | */ |
2238 | if (seqid != sop->so_seqid + 1) | 2251 | if (seqid != sop->so_seqid) |
2239 | goto check_replay; | 2252 | goto check_replay; |
2240 | 2253 | ||
2241 | if (sop->so_confirmed) { | 2254 | if (sop->so_confirmed && flags & CONFIRM) { |
2242 | if (flags & CONFIRM) { | 2255 | printk("NFSD: preprocess_seqid_op: expected" |
2243 | printk("NFSD: preprocess_seqid_op: expected unconfirmed stateowner!\n"); | 2256 | " unconfirmed stateowner!\n"); |
2244 | goto out; | 2257 | return nfserr_bad_stateid; |
2245 | } | ||
2246 | } | 2258 | } |
2247 | else { | 2259 | if (!sop->so_confirmed && !(flags & CONFIRM)) { |
2248 | if (!(flags & CONFIRM)) { | 2260 | printk("NFSD: preprocess_seqid_op: stateowner not" |
2249 | printk("NFSD: preprocess_seqid_op: stateowner not confirmed yet!\n"); | 2261 | " confirmed yet!\n"); |
2250 | goto out; | 2262 | return nfserr_bad_stateid; |
2251 | } | ||
2252 | } | 2263 | } |
2253 | if (stateid->si_generation > stp->st_stateid.si_generation) { | 2264 | if (stateid->si_generation > stp->st_stateid.si_generation) { |
2254 | printk("NFSD: preprocess_seqid_op: future stateid?!\n"); | 2265 | printk("NFSD: preprocess_seqid_op: future stateid?!\n"); |
2255 | goto out; | 2266 | return nfserr_bad_stateid; |
2256 | } | 2267 | } |
2257 | 2268 | ||
2258 | status = nfserr_old_stateid; | ||
2259 | if (stateid->si_generation < stp->st_stateid.si_generation) { | 2269 | if (stateid->si_generation < stp->st_stateid.si_generation) { |
2260 | printk("NFSD: preprocess_seqid_op: old stateid!\n"); | 2270 | printk("NFSD: preprocess_seqid_op: old stateid!\n"); |
2261 | goto out; | 2271 | return nfserr_old_stateid; |
2262 | } | 2272 | } |
2263 | /* XXX renew the client lease here */ | 2273 | renew_client(sop->so_client); |
2264 | status = nfs_ok; | 2274 | return nfs_ok; |
2265 | |||
2266 | out: | ||
2267 | return status; | ||
2268 | |||
2269 | no_nfs4_stateid: | ||
2270 | |||
2271 | /* | ||
2272 | * We determine whether this is a bad stateid or a replay, | ||
2273 | * starting by trying to look up the stateowner. | ||
2274 | * If stateowner is not found - stateid is bad. | ||
2275 | */ | ||
2276 | if (!(sop = find_openstateowner_id(stateid->si_stateownerid, flags))) { | ||
2277 | printk("NFSD: preprocess_seqid_op: no stateowner or nfs4_stateid!\n"); | ||
2278 | status = nfserr_bad_stateid; | ||
2279 | goto out; | ||
2280 | } | ||
2281 | *sopp = sop; | ||
2282 | 2275 | ||
2283 | check_replay: | 2276 | check_replay: |
2284 | if (seqid == sop->so_seqid) { | 2277 | if (seqid == sop->so_seqid - 1) { |
2285 | printk("NFSD: preprocess_seqid_op: retransmission?\n"); | 2278 | printk("NFSD: preprocess_seqid_op: retransmission?\n"); |
2286 | /* indicate replay to calling function */ | 2279 | /* indicate replay to calling function */ |
2287 | status = NFSERR_REPLAY_ME; | 2280 | return NFSERR_REPLAY_ME; |
2288 | } else { | ||
2289 | printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d\n", sop->so_seqid +1, seqid); | ||
2290 | |||
2291 | *sopp = NULL; | ||
2292 | status = nfserr_bad_seqid; | ||
2293 | } | 2281 | } |
2294 | goto out; | 2282 | printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n", |
2283 | sop->so_seqid, seqid); | ||
2284 | *sopp = NULL; | ||
2285 | return nfserr_bad_seqid; | ||
2295 | } | 2286 | } |
2296 | 2287 | ||
2297 | int | 2288 | int |
@@ -2609,7 +2600,6 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid, | |||
2609 | * occured. | 2600 | * occured. |
2610 | * | 2601 | * |
2611 | * strhashval = lock_ownerstr_hashval | 2602 | * strhashval = lock_ownerstr_hashval |
2612 | * so_seqid = lock->lk_new_lock_seqid - 1: it gets bumped in encode | ||
2613 | */ | 2603 | */ |
2614 | 2604 | ||
2615 | static struct nfs4_stateowner * | 2605 | static struct nfs4_stateowner * |
@@ -2634,7 +2624,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str | |||
2634 | sop->so_is_open_owner = 0; | 2624 | sop->so_is_open_owner = 0; |
2635 | sop->so_id = current_ownerid++; | 2625 | sop->so_id = current_ownerid++; |
2636 | sop->so_client = clp; | 2626 | sop->so_client = clp; |
2637 | sop->so_seqid = lock->lk_new_lock_seqid - 1; | 2627 | sop->so_seqid = lock->lk_new_lock_seqid; |
2638 | sop->so_confirmed = 1; | 2628 | sop->so_confirmed = 1; |
2639 | rp = &sop->so_replay; | 2629 | rp = &sop->so_replay; |
2640 | rp->rp_status = NFSERR_SERVERFAULT; | 2630 | rp->rp_status = NFSERR_SERVERFAULT; |
@@ -2669,6 +2659,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc | |||
2669 | stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */ | 2659 | stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */ |
2670 | stp->st_access_bmap = open_stp->st_access_bmap; | 2660 | stp->st_access_bmap = open_stp->st_access_bmap; |
2671 | stp->st_deny_bmap = open_stp->st_deny_bmap; | 2661 | stp->st_deny_bmap = open_stp->st_deny_bmap; |
2662 | stp->st_openstp = open_stp; | ||
2672 | 2663 | ||
2673 | out: | 2664 | out: |
2674 | return stp; | 2665 | return stp; |
@@ -2699,22 +2690,17 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2699 | (long long) lock->lk_offset, | 2690 | (long long) lock->lk_offset, |
2700 | (long long) lock->lk_length); | 2691 | (long long) lock->lk_length); |
2701 | 2692 | ||
2702 | if (nfs4_in_grace() && !lock->lk_reclaim) | ||
2703 | return nfserr_grace; | ||
2704 | if (!nfs4_in_grace() && lock->lk_reclaim) | ||
2705 | return nfserr_no_grace; | ||
2706 | |||
2707 | if (check_lock_length(lock->lk_offset, lock->lk_length)) | 2693 | if (check_lock_length(lock->lk_offset, lock->lk_length)) |
2708 | return nfserr_inval; | 2694 | return nfserr_inval; |
2709 | 2695 | ||
2710 | nfs4_lock_state(); | 2696 | nfs4_lock_state(); |
2711 | 2697 | ||
2712 | if (lock->lk_is_new) { | 2698 | if (lock->lk_is_new) { |
2713 | /* | 2699 | /* |
2714 | * Client indicates that this is a new lockowner. | 2700 | * Client indicates that this is a new lockowner. |
2715 | * Use open owner and open stateid to create lock owner and lock | 2701 | * Use open owner and open stateid to create lock owner and |
2716 | * stateid. | 2702 | * lock stateid. |
2717 | */ | 2703 | */ |
2718 | struct nfs4_stateid *open_stp = NULL; | 2704 | struct nfs4_stateid *open_stp = NULL; |
2719 | struct nfs4_file *fp; | 2705 | struct nfs4_file *fp; |
2720 | 2706 | ||
@@ -2724,23 +2710,14 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2724 | goto out; | 2710 | goto out; |
2725 | } | 2711 | } |
2726 | 2712 | ||
2727 | /* is the new lock seqid presented by the client zero? */ | ||
2728 | status = nfserr_bad_seqid; | ||
2729 | if (lock->v.new.lock_seqid != 0) | ||
2730 | goto out; | ||
2731 | |||
2732 | /* validate and update open stateid and open seqid */ | 2713 | /* validate and update open stateid and open seqid */ |
2733 | status = nfs4_preprocess_seqid_op(current_fh, | 2714 | status = nfs4_preprocess_seqid_op(current_fh, |
2734 | lock->lk_new_open_seqid, | 2715 | lock->lk_new_open_seqid, |
2735 | &lock->lk_new_open_stateid, | 2716 | &lock->lk_new_open_stateid, |
2736 | CHECK_FH | OPEN_STATE, | 2717 | CHECK_FH | OPEN_STATE, |
2737 | &open_sop, &open_stp, | 2718 | &open_sop, &open_stp, lock); |
2738 | &lock->v.new.clientid); | 2719 | if (status) |
2739 | if (status) { | ||
2740 | if (lock->lk_reclaim) | ||
2741 | status = nfserr_reclaim_bad; | ||
2742 | goto out; | 2720 | goto out; |
2743 | } | ||
2744 | /* create lockowner and lock stateid */ | 2721 | /* create lockowner and lock stateid */ |
2745 | fp = open_stp->st_file; | 2722 | fp = open_stp->st_file; |
2746 | strhashval = lock_ownerstr_hashval(fp->fi_inode, | 2723 | strhashval = lock_ownerstr_hashval(fp->fi_inode, |
@@ -2766,7 +2743,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2766 | lock->lk_old_lock_seqid, | 2743 | lock->lk_old_lock_seqid, |
2767 | &lock->lk_old_lock_stateid, | 2744 | &lock->lk_old_lock_stateid, |
2768 | CHECK_FH | LOCK_STATE, | 2745 | CHECK_FH | LOCK_STATE, |
2769 | &lock->lk_stateowner, &lock_stp, NULL); | 2746 | &lock->lk_stateowner, &lock_stp, lock); |
2770 | if (status) | 2747 | if (status) |
2771 | goto out; | 2748 | goto out; |
2772 | } | 2749 | } |
@@ -2778,6 +2755,13 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock | |||
2778 | goto out; | 2755 | goto out; |
2779 | } | 2756 | } |
2780 | 2757 | ||
2758 | status = nfserr_grace; | ||
2759 | if (nfs4_in_grace() && !lock->lk_reclaim) | ||
2760 | goto out; | ||
2761 | status = nfserr_no_grace; | ||
2762 | if (!nfs4_in_grace() && lock->lk_reclaim) | ||
2763 | goto out; | ||
2764 | |||
2781 | locks_init_lock(&file_lock); | 2765 | locks_init_lock(&file_lock); |
2782 | switch (lock->lk_type) { | 2766 | switch (lock->lk_type) { |
2783 | case NFS4_READ_LT: | 2767 | case NFS4_READ_LT: |
@@ -2844,10 +2828,10 @@ conflicting_lock: | |||
2844 | out_destroy_new_stateid: | 2828 | out_destroy_new_stateid: |
2845 | if (lock->lk_is_new) { | 2829 | if (lock->lk_is_new) { |
2846 | dprintk("NFSD: nfsd4_lock: destroy new stateid!\n"); | 2830 | dprintk("NFSD: nfsd4_lock: destroy new stateid!\n"); |
2847 | /* | 2831 | /* |
2848 | * An error encountered after instantiation of the new | 2832 | * An error encountered after instantiation of the new |
2849 | * stateid has forced us to destroy it. | 2833 | * stateid has forced us to destroy it. |
2850 | */ | 2834 | */ |
2851 | if (!seqid_mutating_err(status)) | 2835 | if (!seqid_mutating_err(status)) |
2852 | open_sop->so_seqid--; | 2836 | open_sop->so_seqid--; |
2853 | 2837 | ||
@@ -3083,7 +3067,12 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner * | |||
3083 | * of the lockowner state released; so don't release any until all | 3067 | * of the lockowner state released; so don't release any until all |
3084 | * have been checked. */ | 3068 | * have been checked. */ |
3085 | status = nfs_ok; | 3069 | status = nfs_ok; |
3086 | list_for_each_entry(sop, &matches, so_perclient) { | 3070 | while (!list_empty(&matches)) { |
3071 | sop = list_entry(matches.next, struct nfs4_stateowner, | ||
3072 | so_perclient); | ||
3073 | /* unhash_stateowner deletes so_perclient only | ||
3074 | * for openowners. */ | ||
3075 | list_del(&sop->so_perclient); | ||
3087 | release_stateowner(sop); | 3076 | release_stateowner(sop); |
3088 | } | 3077 | } |
3089 | out: | 3078 | out: |