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.c231
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
1164static void 1166static 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);
1532out: 1534out:
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 */
1689static void 1688static void
1690nfs4_set_claim_prev(struct nfsd4_open *open, int *status) 1689nfs4_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
1856out: 1855out:
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 */
1996static struct nfs4_stateowner * 1992static struct nfs4_stateowner *
1997find_openstateowner_id(u32 st_id, int flags) { 1993search_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
2162static inline int
2163setlkflg (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 */
2170static int 2172static int
2171nfs4_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) 2173nfs4_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
2266out:
2267 return status;
2268
2269no_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
2283check_replay: 2276check_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
2297int 2288int
@@ -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
2615static struct nfs4_stateowner * 2605static 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
2673out: 2664out:
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:
2844out_destroy_new_stateid: 2828out_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 }
3089out: 3078out: