History

Merge tag 'nfs-for-4.7-2' of git://git.linux-nfs.org/projects/anna/linux-nfs

Pull NFS client bugfixes from Anna Schumaker: "Stable bugfixes: - Fix _cancel_empty_pagelist - Fix a double page unlock - Make nfs_atomic_open() call d_drop() on all ->open_context() errors. - Fix another OPEN_DOWNGRADE bug Other bugfixes: - Ensure we handle delegation errors in nfs4_proc_layoutget() - Layout stateids start out as being invalid - Add sparse lock annotations for pnfs_find_alloc_layout - Handle bad delegation stateids in nfs4_layoutget_handle_exception - Fix up O_DIRECT results - Fix potential use after free of state in nfs4_do_reclaim. - Mark the layout stateid invalid when all segments are removed - Don't let readdirplus revalidate an inode that was marked as stale - Fix potential race in nfs_fhget() - Fix an unused variable warning" * tag 'nfs-for-4.7-2' of git://git.linux-nfs.org/projects/anna/linux-nfs: NFS: Fix another OPEN_DOWNGRADE bug make nfs_atomic_open() call d_drop() on all ->open_context() errors. NFS: Fix an unused variable warning NFS: Fix potential race in nfs_fhget() NFS: Don't let readdirplus revalidate an inode that was marked as stale NFSv4.1/pnfs: Mark the layout stateid invalid when all segments are removed NFS: Fix a double page unlock pnfs_nfs: fix _cancel_empty_pagelist nfs4: Fix potential use after free of state in nfs4_do_reclaim. NFS: Fix up O_DIRECT results NFS/pnfs: handle bad delegation stateids in nfs4_layoutget_handle_exception NFSv4.1/pnfs: Add sparse lock annotations for pnfs_find_alloc_layout NFSv4.1/pnfs: Layout stateids start out as being invalid NFSv4.1/pnfs: Ensure we handle delegation errors in nfs4_proc_layoutget()

Linus Torvalds committed 10 years ago

Commit e7bdea72 parents 89a82a9 e547f268 files · +45 −23Browse files

Unified · Split

8 files
  1. fs/nfs/dir.c +7 −4
  2. fs/nfs/direct.c +7 −3
  3. fs/nfs/inode.c +1 −0
  4. fs/nfs/nfs4proc.c +10 −8
  5. fs/nfs/nfs4state.c +1 −1
  6. fs/nfs/pnfs.c +7 −3
  7. fs/nfs/pnfs_nfs.c +10 −2
  8. fs/nfs/read.c +2 −2
fs/nfs/dir.c+7−4
@@ -424,12 +424,17 @@ static int xdr_decode(nfs_readdir_descriptor_t *desc, · 423 unmodified lines
424424 static
425425 int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry)
426426 {
427+ struct inode *inode;
427428 struct nfs_inode *nfsi;
428429
429430 if (d_really_is_negative(dentry))
430431 return 0;
431432
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);
433438 if (entry->fattr->fileid == nfsi->fileid)
434439 return 1;
435440 if (nfs_compare_fh(entry->fh, &nfsi->fh) == 0)
@@ -1363,7 +1368,6 @@ EXPORT_SYMBOL_GPL(nfs_dentry_operations); · 927 unmodified lines
13631368 struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
13641369 {
13651370 struct dentry *res;
1366− struct dentry *parent;
13671371 struct inode *inode = NULL;
13681372 struct nfs_fh *fhandle = NULL;
13691373 struct nfs_fattr *fattr = NULL;
@@ -1393,7 +1397,6 @@ struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned in · 23 unmodified lines
13931397 if (IS_ERR(label))
13941398 goto out;
13951399
1396− parent = dentry->d_parent;
13971400 /* Protect against concurrent sillydeletes */
13981401 trace_nfs_lookup_enter(dir, dentry, flags);
13991402 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, · 136 unmodified lines
15361539 err = PTR_ERR(inode);
15371540 trace_nfs_atomic_open_exit(dir, ctx, open_flags, err);
15381541 put_nfs_open_context(ctx);
1542+ d_drop(dentry);
15391543 switch (err) {
15401544 case -ENOENT:
1541− d_drop(dentry);
15421545 d_add(dentry, NULL);
15431546 nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
15441547 break;
fs/nfs/direct.c+7−3
@@ -353,10 +353,12 @@ static ssize_t nfs_direct_wait(struct nfs_direct_req *dreq) · 352 unmodified lines
353353
354354 result = wait_for_completion_killable(&dreq->completion);
355355
356+ if (!result) {
357+ result = dreq->count;
358+ WARN_ON_ONCE(dreq->count < 0);
359+ }
356360 if (!result)
357361 result = dreq->error;
358− if (!result)
359− result = dreq->count;
360362
361363 out:
362364 return (ssize_t) result;
@@ -386,8 +388,10 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq, bool write) · 23 unmodified lines
386388
387389 if (dreq->iocb) {
388390 long res = (long) dreq->error;
389− if (!res)
391+ if (dreq->count != 0) {
390392 res = (long) dreq->count;
393+ WARN_ON_ONCE(dreq->count < 0);
394+ }
391395 dreq->iocb->ki_complete(dreq->iocb, res, 0);
392396 }
393397
fs/nfs/inode.c+1−0
@@ -282,6 +282,7 @@ nfs_init_locked(struct inode *inode, void *opaque) · 281 unmodified lines
282282 struct nfs_fattr *fattr = desc->fattr;
283283
284284 set_nfs_fileid(inode, fattr->fileid);
285+ inode->i_mode = fattr->mode;
285286 nfs_copy_fh(NFS_FH(inode), desc->fh);
286287 return 0;
287288 }
fs/nfs/nfs4proc.c+10−8
@@ -2882,12 +2882,11 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data) · 2881 unmodified lines
28822882 call_close |= is_wronly;
28832883 else if (is_wronly)
28842884 calldata->arg.fmode |= FMODE_WRITE;
2885+ if (calldata->arg.fmode != (FMODE_READ|FMODE_WRITE))
2886+ call_close |= is_rdwr;
28852887 } else if (is_rdwr)
28862888 calldata->arg.fmode |= FMODE_READ|FMODE_WRITE;
28872889
2888− if (calldata->arg.fmode == 0)
2889− call_close |= is_rdwr;
2890−
28912890 if (!nfs4_valid_open_stateid(state))
28922891 call_close = 0;
28932892 spin_unlock(&state->owner->so_lock);
@@ -7924,8 +7923,8 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, · 5030 unmodified lines
79247923 break;
79257924 }
79267925 lo = NFS_I(inode)->layout;
7927− if (lo && nfs4_stateid_match(&lgp->args.stateid,
7928− &lo->plh_stateid)) {
7926+ if (lo && !test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags) &&
7927+ nfs4_stateid_match_other(&lgp->args.stateid, &lo->plh_stateid)) {
79297928 LIST_HEAD(head);
79307929
79317930 /*
@@ -7936,10 +7935,10 @@ nfs4_layoutget_handle_exception(struct rpc_task *task, · 4 unmodified lines
79367935 pnfs_mark_matching_lsegs_invalid(lo, &head, NULL, 0);
79377936 spin_unlock(&inode->i_lock);
79387937 pnfs_free_lseg_list(&head);
7938+ status = -EAGAIN;
7939+ goto out;
79397940 } else
79407941 spin_unlock(&inode->i_lock);
7941− status = -EAGAIN;
7942− goto out;
79437942 }
79447943
79457944 status = nfs4_handle_exception(server, status, exception);
@@ -8036,7 +8035,10 @@ nfs4_proc_layoutget(struct nfs4_layoutget *lgp, long *timeout, gfp_t gfp_flags) · 90 unmodified lines
80368035 .flags = RPC_TASK_ASYNC,
80378036 };
80388037 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+ };
80408042 int status = 0;
80418043
80428044 dprintk("--> %s\n", __func__);
fs/nfs/nfs4state.c+1−1
@@ -1488,9 +1488,9 @@ restart: · 1487 unmodified lines
14881488 }
14891489 spin_unlock(&state->state_lock);
14901490 }
1491− nfs4_put_open_state(state);
14921491 clear_bit(NFS_STATE_RECLAIM_NOGRACE,
14931492 &state->flags);
1493+ nfs4_put_open_state(state);
14941494 spin_lock(&sp->so_lock);
14951495 goto restart;
14961496 }
fs/nfs/pnfs.c+7−3
@@ -361,8 +361,10 @@ pnfs_layout_remove_lseg(struct pnfs_layout_hdr *lo, · 360 unmodified lines
361361 list_del_init(&lseg->pls_list);
362362 /* Matched by pnfs_get_layout_hdr in pnfs_layout_insert_lseg */
363363 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);
365366 clear_bit(NFS_LAYOUT_BULK_RECALL, &lo->plh_flags);
367+ }
366368 rpc_wake_up(&NFS_SERVER(inode)->roc_rpcwaitq);
367369 }
368370
@@ -1290,6 +1292,7 @@ alloc_init_layout_hdr(struct inode *ino, · 921 unmodified lines
12901292 INIT_LIST_HEAD(&lo->plh_bulk_destroy);
12911293 lo->plh_inode = ino;
12921294 lo->plh_lc_cred = get_rpccred(ctx->cred);
1295+ lo->plh_flags |= 1 << NFS_LAYOUT_INVALID_STID;
12931296 return lo;
12941297 }
12951298
@@ -1297,6 +1300,8 @@ static struct pnfs_layout_hdr * · 1 unmodified line
12971300 pnfs_find_alloc_layout(struct inode *ino,
12981301 struct nfs_open_context *ctx,
12991302 gfp_t gfp_flags)
1303+ __releases(&ino->i_lock)
1304+ __acquires(&ino->i_lock)
13001305 {
13011306 struct nfs_inode *nfsi = NFS_I(ino);
13021307 struct pnfs_layout_hdr *new = NULL;
@@ -1565,8 +1570,7 @@ lookup_again: · 262 unmodified lines
15651570 * stateid, or it has been invalidated, then we must use the open
15661571 * stateid.
15671572 */
1568− if (lo->plh_stateid.seqid == 0 ||
1569− test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) {
1573+ if (test_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags)) {
15701574
15711575 /*
15721576 * The first layoutget for the file. Need to serialize per
fs/nfs/pnfs_nfs.c+10−2
@@ -247,7 +247,11 @@ void pnfs_fetch_commit_bucket_list(struct list_head *pages, · 246 unmodified lines
247247 }
248248
249249 /* 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+ */
251255 static bool
252256 pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages,
253257 struct nfs_commit_data *data,
@@ -256,7 +260,11 @@ pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, · 2 unmodified lines
256260 if (list_empty(pages)) {
257261 if (atomic_dec_and_test(&cinfo->mds->rpcs_out))
258262 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);
260268 return true;
261269 }
262270
fs/nfs/read.c+2−2
@@ -367,13 +367,13 @@ readpage_async_filler(void *data, struct page *page) · 366 unmodified lines
367367 nfs_list_remove_request(new);
368368 nfs_readpage_release(new);
369369 error = desc->pgio->pg_error;
370− goto out_unlock;
370+ goto out;
371371 }
372372 return 0;
373373 out_error:
374374 error = PTR_ERR(new);
375−out_unlock:
376375 unlock_page(page);
376+out:
377377 return error;
378378 }
379379

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t