aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/dir.c11
-rw-r--r--fs/nfs/direct.c10
-rw-r--r--fs/nfs/inode.c1
-rw-r--r--fs/nfs/nfs4proc.c18
-rw-r--r--fs/nfs/nfs4state.c2
-rw-r--r--fs/nfs/pnfs.c10
-rw-r--r--fs/nfs/pnfs_nfs.c12
-rw-r--r--fs/nfs/read.c4
8 files changed, 45 insertions, 23 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index aaf7bd0cbae2..d8015a03db4c 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -424,12 +424,17 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc,
424static 424static
425int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) 425int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
426{ 426{
427 struct inode *inode;
427 struct nfs_inode *nfsi; 428 struct nfs_inode *nfsi;
428 429
429 if (d_really_is_negative(dentry)) 430 if (d_really_is_negative(dentry))
430 return 0; 431 return 0;
431 432
432 nfsi = NFS_I(d_inode(dentry)); 433 inode = d_inode(dentry);
434 if (is_bad_inode(inode) || NFS_STALE(inode))
435 return 0;
436
437 nfsi = NFS_I(inode);
433 if (entry->fattr->fileid == nfsi->fileid) 438 if (entry->fattr->fileid == nfsi->fileid)
434 return 1; 439 return 1;
435 if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0) 440 if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0)
@@ -1363,7 +1368,6 @@ EXPORT_SYMBOL_GPL(nfs_dentry_operations);
1363struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags) 1368struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
1364{ 1369{
1365 struct dentry *res; 1370 struct dentry *res;
1366 struct dentry *parent;
1367 struct inode *inode = NULL; 1371 struct inode *inode = NULL;
1368 struct nfs_fh *fhandle = NULL; 1372 struct nfs_fh *fhandle = NULL;
1369 struct nfs_fattr *fattr = NULL; 1373 struct nfs_fattr *fattr = NULL;
@@ -1393,7 +1397,6 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in
1393 if (IS_ERR(label)) 1397 if (IS_ERR(label))
1394 goto out; 1398 goto out;
1395 1399
1396 parent = dentry->d_parent;
1397 /* Protect against concurrent sillydeletes */ 1400 /* Protect against concurrent sillydeletes */
1398 trace_nfs_lookup_enter(dir, dentry, flags); 1401 trace_nfs_lookup_enter(dir, dentry, flags);
1399 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label); 1402 error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr, label);
@@ -1536,9 +1539,9 @@ int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
1536 err = PTR_ERR(inode); 1539 err = PTR_ERR(inode);
1537 trace_nfs_atomic_open_exit(dir, ctx, open_flags, err); 1540 trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
1538 put_nfs_open_context(ctx); 1541 put_nfs_open_context(ctx);
1542 d_drop(dentry);
1539 switch (err) { 1543 switch (err) {
1540 case -ENOENT: 1544 case -ENOENT:
1541 d_drop(dentry);
1542 d_add(dentry, NULL); 1545 d_add(dentry, NULL);
1543 nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); 1546 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
1544 break; 1547 break;
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 979b3c4dee6a..c7326c2af2c3 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -353,10 +353,12 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq)
353 353
354 result = wait_for_completion_killable(&dreq->completion); 354 result = wait_for_completion_killable(&dreq->completion);
355 355
356 if (!result) {
357 result = dreq->count;
358 WARN_ON_ONCE(dreq->count < 0);
359 }
356 if (!result) 360 if (!result)
357 result = dreq->error; 361 result = dreq->error;
358 if (!result)
359 result = dreq->count;
360 362
361out: 363out:
362 return (ssize_t) result; 364 return (ssize_t) result;
@@ -386,8 +388,10 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write)
386 388
387 if (dreq->iocb) { 389 if (dreq->iocb) {
388 long res = (long) dreq->error; 390 long res = (long) dreq->error;
389 if (!res) 391 if (dreq->count != 0) {
390 res = (long) dreq->count; 392 res = (long) dreq->count;
393 WARN_ON_ONCE(dreq->count < 0);
394 }
391 dreq->iocb->ki_complete(dreq->iocb, res, 0); 395 dreq->iocb->ki_complete(dreq->iocb, res, 0);
392 } 396 }
393 397
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 52e7d6869e3b..dda689d7a8a7 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -282,6 +282,7 @@ nfs_init_locked(struct inode *inode, void *opaque)
282 struct nfs_fattr *fattr = desc->fattr; 282 struct nfs_fattr *fattr = desc->fattr;
283 283
284 set_nfs_fileid(inode, fattr->fileid); 284 set_nfs_fileid(inode, fattr->fileid);
285 inode->i_mode = fattr->mode;
285 nfs_copy_fh(NFS_FH(inode), desc->fh); 286 nfs_copy_fh(NFS_FH(inode), desc->fh);
286 return 0; 287 return 0;
287} 288}
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index de97567795a5..ff416d0e24bc 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2882,12 +2882,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)
2882 call_close |= is_wronly; 2882 call_close |= is_wronly;
2883 else if (is_wronly) 2883 else if (is_wronly)
2884 calldata->arg.fmode |= FMODE_WRITE; 2884 calldata->arg.fmode |= FMODE_WRITE;
2885 if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
2886 call_close |= is_rdwr;
2885 } else if (is_rdwr) 2887 } else if (is_rdwr)
2886 calldata->arg.fmode |= FMODE_READ|FMODE_WRITE; 2888 calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
2887 2889
2888 if (calldata->arg.fmode == 0)
2889 call_close |= is_rdwr;
2890
2891 if (!nfs4_valid_open_stateid(state)) 2890 if (!nfs4_valid_open_stateid(state))
2892 call_close = 0; 2891 call_close = 0;
2893 spin_unlock(&state->owner->so_lock); 2892 spin_unlock(&state->owner->so_lock);
@@ -7924,8 +7923,8 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
7924 break; 7923 break;
7925 } 7924 }
7926 lo = NFS_I(inode)->layout; 7925 lo = NFS_I(inode)->layout;
7927 if (lo && nfs4_stateid_match(&lgp->args.stateid, 7926 if (lo && !test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) &&
7928 &lo->plh_stateid)) { 7927 nfs4_stateid_match_other(&lgp->args.stateid, &lo->plh_stateid)) {
7929 LIST_HEAD(head); 7928 LIST_HEAD(head);
7930 7929
7931 /* 7930 /*
@@ -7936,10 +7935,10 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
7936 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0); 7935 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
7937 spin_unlock(&inode->i_lock); 7936 spin_unlock(&inode->i_lock);
7938 pnfs_free_lseg_list(&head); 7937 pnfs_free_lseg_list(&head);
7938 status = -EAGAIN;
7939 goto out;
7939 } else 7940 } else
7940 spin_unlock(&inode->i_lock); 7941 spin_unlock(&inode->i_lock);
7941 status = -EAGAIN;
7942 goto out;
7943 } 7942 }
7944 7943
7945 status = nfs4_handle_exception(server, status, exception); 7944 status = nfs4_handle_exception(server, status, exception);
@@ -8036,7 +8035,10 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags)
8036 .flags = RPC_TASK_ASYNC, 8035 .flags = RPC_TASK_ASYNC,
8037 }; 8036 };
8038 struct pnfs_layout_segment *lseg = NULL; 8037 struct pnfs_layout_segment *lseg = NULL;
8039 struct nfs4_exception exception = { .timeout = *timeout }; 8038 struct nfs4_exception exception = {
8039 .inode = inode,
8040 .timeout = *timeout,
8041 };
8040 int status = 0; 8042 int status = 0;
8041 8043
8042 dprintk("--> %s\n", __func__); 8044 dprintk("--> %s\n", __func__);
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 9679f4749364..834b875900d6 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1488,9 +1488,9 @@ restart:
1488 } 1488 }
1489 spin_unlock(&state->state_lock); 1489 spin_unlock(&state->state_lock);
1490 } 1490 }
1491 nfs4_put_open_state(state);
1492 clear_bit(NFS_STATE_RECLAIM_NOGRACE, 1491 clear_bit(NFS_STATE_RECLAIM_NOGRACE,
1493 &state->flags); 1492 &state->flags);
1493 nfs4_put_open_state(state);
1494 spin_lock(&sp->so_lock); 1494 spin_lock(&sp->so_lock);
1495 goto restart; 1495 goto restart;
1496 } 1496 }
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 0c7e0d45a4de..0fbe734cc38c 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -361,8 +361,10 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo,
361 list_del_init(&lseg->pls_list); 361 list_del_init(&lseg->pls_list);
362 /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */ 362 /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */
363 atomic_dec(&lo->plh_refcount); 363 atomic_dec(&lo->plh_refcount);
364 if (list_empty(&lo->plh_segs)) 364 if (list_empty(&lo->plh_segs)) {
365 set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
365 clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags); 366 clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
367 }
366 rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq); 368 rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq);
367} 369}
368 370
@@ -1290,6 +1292,7 @@ alloc_init_layout_hdr(struct inode *ino,
1290 INIT_LIST_HEAD(&lo->plh_bulk_destroy); 1292 INIT_LIST_HEAD(&lo->plh_bulk_destroy);
1291 lo->plh_inode = ino; 1293 lo->plh_inode = ino;
1292 lo->plh_lc_cred = get_rpccred(ctx->cred); 1294 lo->plh_lc_cred = get_rpccred(ctx->cred);
1295 lo->plh_flags |= 1 << NFS_LAYOUT_INVALID_STID;
1293 return lo; 1296 return lo;
1294} 1297}
1295 1298
@@ -1297,6 +1300,8 @@ static struct pnfs_layout_hdr *
1297pnfs_find_alloc_layout(struct inode *ino, 1300pnfs_find_alloc_layout(struct inode *ino,
1298 struct nfs_open_context *ctx, 1301 struct nfs_open_context *ctx,
1299 gfp_t gfp_flags) 1302 gfp_t gfp_flags)
1303 __releases(&ino->i_lock)
1304 __acquires(&ino->i_lock)
1300{ 1305{
1301 struct nfs_inode *nfsi = NFS_I(ino); 1306 struct nfs_inode *nfsi = NFS_I(ino);
1302 struct pnfs_layout_hdr *new = NULL; 1307 struct pnfs_layout_hdr *new = NULL;
@@ -1565,8 +1570,7 @@ lookup_again:
1565 * stateid, or it has been invalidated, then we must use the open 1570 * stateid, or it has been invalidated, then we must use the open
1566 * stateid. 1571 * stateid.
1567 */ 1572 */
1568 if (lo->plh_stateid.seqid == 0 || 1573 if (test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) {
1569 test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) {
1570 1574
1571 /* 1575 /*
1572 * The first layoutget for the file. Need to serialize per 1576 * The first layoutget for the file. Need to serialize per
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c
index 0dfc476da3e1..b38e3c0dc790 100644
--- a/fs/nfs/pnfs_nfs.c
+++ b/fs/nfs/pnfs_nfs.c
@@ -247,7 +247,11 @@ void pnfs_fetch_commit_bucket_list(struct list_head *pages,
247} 247}
248 248
249/* Helper function for pnfs_generic_commit_pagelist to catch an empty 249/* Helper function for pnfs_generic_commit_pagelist to catch an empty
250 * page list. This can happen when two commits race. */ 250 * page list. This can happen when two commits race.
251 *
252 * This must be called instead of nfs_init_commit - call one or the other, but
253 * not both!
254 */
251static bool 255static bool
252pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, 256pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages,
253 struct nfs_commit_data *data, 257 struct nfs_commit_data *data,
@@ -256,7 +260,11 @@ pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages,
256 if (list_empty(pages)) { 260 if (list_empty(pages)) {
257 if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) 261 if (atomic_dec_and_test(&cinfo->mds->rpcs_out))
258 wake_up_atomic_t(&cinfo->mds->rpcs_out); 262 wake_up_atomic_t(&cinfo->mds->rpcs_out);
259 nfs_commitdata_release(data); 263 /* don't call nfs_commitdata_release - it tries to put
264 * the open_context which is not acquired until nfs_init_commit
265 * which has not been called on @data */
266 WARN_ON_ONCE(data->context);
267 nfs_commit_free(data);
260 return true; 268 return true;
261 } 269 }
262 270
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 6776d7a7839e..572e5b3b06f1 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -367,13 +367,13 @@ readpage_async_filler(void *data, struct page *page)
367 nfs_list_remove_request(new); 367 nfs_list_remove_request(new);
368 nfs_readpage_release(new); 368 nfs_readpage_release(new);
369 error = desc->pgio->pg_error; 369 error = desc->pgio->pg_error;
370 goto out_unlock; 370 goto out;
371 } 371 }
372 return 0; 372 return 0;
373out_error: 373out_error:
374 error = PTR_ERR(new); 374 error = PTR_ERR(new);
375out_unlock:
376 unlock_page(page); 375 unlock_page(page);
376out:
377 return error; 377 return error;
378} 378}
379 379