diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-02-18 10:28:37 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-02-18 10:28:37 -0500 |
commit | 65d2918e716afb89359cfa59734d76c1ff8700cb (patch) | |
tree | 4685404f96642243d62c3a1a823340913d087090 /fs/nfs | |
parent | bf40e5561fd288a505d5d8d8bf45eef96fe7253d (diff) | |
parent | 338d00cfef07d74a072f96821c64b20f98517d72 (diff) |
Merge branch 'cleanups'
Merge cleanups requested by Linus.
* cleanups: (3 commits)
pnfs: Refactor the *_layout_mark_request_commit to use pnfs_layout_mark_request_commit
nfs: Can call nfs_clear_page_commit() instead
nfs: Provide and use helper functions for marking a page as unstable
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/delegation.c | 23 | ||||
-rw-r--r-- | fs/nfs/file.c | 1 | ||||
-rw-r--r-- | fs/nfs/filelayout/filelayout.c | 53 | ||||
-rw-r--r-- | fs/nfs/flexfilelayout/flexfilelayout.c | 43 | ||||
-rw-r--r-- | fs/nfs/inode.c | 1 | ||||
-rw-r--r-- | fs/nfs/internal.h | 14 | ||||
-rw-r--r-- | fs/nfs/nfs4state.c | 70 | ||||
-rw-r--r-- | fs/nfs/nfs4super.c | 1 | ||||
-rw-r--r-- | fs/nfs/pagelist.c | 6 | ||||
-rw-r--r-- | fs/nfs/pnfs.h | 4 | ||||
-rw-r--r-- | fs/nfs/pnfs_nfs.c | 30 | ||||
-rw-r--r-- | fs/nfs/super.c | 24 | ||||
-rw-r--r-- | fs/nfs/write.c | 59 |
13 files changed, 161 insertions, 168 deletions
diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 4464eb06b0b6..a1f0685b42ff 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c | |||
@@ -85,25 +85,30 @@ static int nfs_delegation_claim_locks(struct nfs_open_context *ctx, struct nfs4_ | |||
85 | { | 85 | { |
86 | struct inode *inode = state->inode; | 86 | struct inode *inode = state->inode; |
87 | struct file_lock *fl; | 87 | struct file_lock *fl; |
88 | struct file_lock_context *flctx = inode->i_flctx; | ||
89 | struct list_head *list; | ||
88 | int status = 0; | 90 | int status = 0; |
89 | 91 | ||
90 | if (inode->i_flock == NULL) | 92 | if (flctx == NULL) |
91 | goto out; | 93 | goto out; |
92 | 94 | ||
93 | /* Protect inode->i_flock using the i_lock */ | 95 | list = &flctx->flc_posix; |
94 | spin_lock(&inode->i_lock); | 96 | spin_lock(&flctx->flc_lock); |
95 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 97 | restart: |
96 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) | 98 | list_for_each_entry(fl, list, fl_list) { |
97 | continue; | ||
98 | if (nfs_file_open_context(fl->fl_file) != ctx) | 99 | if (nfs_file_open_context(fl->fl_file) != ctx) |
99 | continue; | 100 | continue; |
100 | spin_unlock(&inode->i_lock); | 101 | spin_unlock(&flctx->flc_lock); |
101 | status = nfs4_lock_delegation_recall(fl, state, stateid); | 102 | status = nfs4_lock_delegation_recall(fl, state, stateid); |
102 | if (status < 0) | 103 | if (status < 0) |
103 | goto out; | 104 | goto out; |
104 | spin_lock(&inode->i_lock); | 105 | spin_lock(&flctx->flc_lock); |
105 | } | 106 | } |
106 | spin_unlock(&inode->i_lock); | 107 | if (list == &flctx->flc_posix) { |
108 | list = &flctx->flc_flock; | ||
109 | goto restart; | ||
110 | } | ||
111 | spin_unlock(&flctx->flc_lock); | ||
107 | out: | 112 | out: |
108 | return status; | 113 | return status; |
109 | } | 114 | } |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index 2ab6f00dba5b..94712fc781fa 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -646,7 +646,6 @@ static const struct vm_operations_struct nfs_file_vm_ops = { | |||
646 | .fault = filemap_fault, | 646 | .fault = filemap_fault, |
647 | .map_pages = filemap_map_pages, | 647 | .map_pages = filemap_map_pages, |
648 | .page_mkwrite = nfs_vm_page_mkwrite, | 648 | .page_mkwrite = nfs_vm_page_mkwrite, |
649 | .remap_pages = generic_file_remap_pages, | ||
650 | }; | 649 | }; |
651 | 650 | ||
652 | static int nfs_need_sync_write(struct file *filp, struct inode *inode) | 651 | static int nfs_need_sync_write(struct file *filp, struct inode *inode) |
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c index 3c9769441f36..91e88a7ecef0 100644 --- a/fs/nfs/filelayout/filelayout.c +++ b/fs/nfs/filelayout/filelayout.c | |||
@@ -960,52 +960,19 @@ filelayout_mark_request_commit(struct nfs_page *req, | |||
960 | { | 960 | { |
961 | struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); | 961 | struct nfs4_filelayout_segment *fl = FILELAYOUT_LSEG(lseg); |
962 | u32 i, j; | 962 | u32 i, j; |
963 | struct list_head *list; | ||
964 | struct pnfs_commit_bucket *buckets; | ||
965 | 963 | ||
966 | if (fl->commit_through_mds) { | 964 | if (fl->commit_through_mds) { |
967 | list = &cinfo->mds->list; | 965 | nfs_request_add_commit_list(req, &cinfo->mds->list, cinfo); |
968 | spin_lock(cinfo->lock); | 966 | } else { |
969 | goto mds_commit; | 967 | /* Note that we are calling nfs4_fl_calc_j_index on each page |
970 | } | 968 | * that ends up being committed to a data server. An attractive |
971 | 969 | * alternative is to add a field to nfs_write_data and nfs_page | |
972 | /* Note that we are calling nfs4_fl_calc_j_index on each page | 970 | * to store the value calculated in filelayout_write_pagelist |
973 | * that ends up being committed to a data server. An attractive | 971 | * and just use that here. |
974 | * alternative is to add a field to nfs_write_data and nfs_page | ||
975 | * to store the value calculated in filelayout_write_pagelist | ||
976 | * and just use that here. | ||
977 | */ | ||
978 | j = nfs4_fl_calc_j_index(lseg, req_offset(req)); | ||
979 | i = select_bucket_index(fl, j); | ||
980 | spin_lock(cinfo->lock); | ||
981 | buckets = cinfo->ds->buckets; | ||
982 | list = &buckets[i].written; | ||
983 | if (list_empty(list)) { | ||
984 | /* Non-empty buckets hold a reference on the lseg. That ref | ||
985 | * is normally transferred to the COMMIT call and released | ||
986 | * there. It could also be released if the last req is pulled | ||
987 | * off due to a rewrite, in which case it will be done in | ||
988 | * pnfs_generic_clear_request_commit | ||
989 | */ | 972 | */ |
990 | buckets[i].wlseg = pnfs_get_lseg(lseg); | 973 | j = nfs4_fl_calc_j_index(lseg, req_offset(req)); |
991 | } | 974 | i = select_bucket_index(fl, j); |
992 | set_bit(PG_COMMIT_TO_DS, &req->wb_flags); | 975 | pnfs_layout_mark_request_commit(req, lseg, cinfo, i); |
993 | cinfo->ds->nwritten++; | ||
994 | |||
995 | mds_commit: | ||
996 | /* nfs_request_add_commit_list(). We need to add req to list without | ||
997 | * dropping cinfo lock. | ||
998 | */ | ||
999 | set_bit(PG_CLEAN, &(req)->wb_flags); | ||
1000 | nfs_list_add_request(req, list); | ||
1001 | cinfo->mds->ncommit++; | ||
1002 | spin_unlock(cinfo->lock); | ||
1003 | if (!cinfo->dreq) { | ||
1004 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | ||
1005 | inc_bdi_stat(page_file_mapping(req->wb_page)->backing_dev_info, | ||
1006 | BDI_RECLAIMABLE); | ||
1007 | __mark_inode_dirty(req->wb_context->dentry->d_inode, | ||
1008 | I_DIRTY_DATASYNC); | ||
1009 | } | 976 | } |
1010 | } | 977 | } |
1011 | 978 | ||
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c index f29fb7d7e8f8..315cc68945b9 100644 --- a/fs/nfs/flexfilelayout/flexfilelayout.c +++ b/fs/nfs/flexfilelayout/flexfilelayout.c | |||
@@ -1332,47 +1332,6 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync) | |||
1332 | return PNFS_ATTEMPTED; | 1332 | return PNFS_ATTEMPTED; |
1333 | } | 1333 | } |
1334 | 1334 | ||
1335 | static void | ||
1336 | ff_layout_mark_request_commit(struct nfs_page *req, | ||
1337 | struct pnfs_layout_segment *lseg, | ||
1338 | struct nfs_commit_info *cinfo, | ||
1339 | u32 ds_commit_idx) | ||
1340 | { | ||
1341 | struct list_head *list; | ||
1342 | struct pnfs_commit_bucket *buckets; | ||
1343 | |||
1344 | spin_lock(cinfo->lock); | ||
1345 | buckets = cinfo->ds->buckets; | ||
1346 | list = &buckets[ds_commit_idx].written; | ||
1347 | if (list_empty(list)) { | ||
1348 | /* Non-empty buckets hold a reference on the lseg. That ref | ||
1349 | * is normally transferred to the COMMIT call and released | ||
1350 | * there. It could also be released if the last req is pulled | ||
1351 | * off due to a rewrite, in which case it will be done in | ||
1352 | * pnfs_common_clear_request_commit | ||
1353 | */ | ||
1354 | WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL); | ||
1355 | buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg); | ||
1356 | } | ||
1357 | set_bit(PG_COMMIT_TO_DS, &req->wb_flags); | ||
1358 | cinfo->ds->nwritten++; | ||
1359 | |||
1360 | /* nfs_request_add_commit_list(). We need to add req to list without | ||
1361 | * dropping cinfo lock. | ||
1362 | */ | ||
1363 | set_bit(PG_CLEAN, &(req)->wb_flags); | ||
1364 | nfs_list_add_request(req, list); | ||
1365 | cinfo->mds->ncommit++; | ||
1366 | spin_unlock(cinfo->lock); | ||
1367 | if (!cinfo->dreq) { | ||
1368 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | ||
1369 | inc_bdi_stat(page_file_mapping(req->wb_page)->backing_dev_info, | ||
1370 | BDI_RECLAIMABLE); | ||
1371 | __mark_inode_dirty(req->wb_context->dentry->d_inode, | ||
1372 | I_DIRTY_DATASYNC); | ||
1373 | } | ||
1374 | } | ||
1375 | |||
1376 | static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) | 1335 | static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i) |
1377 | { | 1336 | { |
1378 | return i; | 1337 | return i; |
@@ -1540,7 +1499,7 @@ static struct pnfs_layoutdriver_type flexfilelayout_type = { | |||
1540 | .pg_write_ops = &ff_layout_pg_write_ops, | 1499 | .pg_write_ops = &ff_layout_pg_write_ops, |
1541 | .get_ds_info = ff_layout_get_ds_info, | 1500 | .get_ds_info = ff_layout_get_ds_info, |
1542 | .free_deviceid_node = ff_layout_free_deveiceid_node, | 1501 | .free_deviceid_node = ff_layout_free_deveiceid_node, |
1543 | .mark_request_commit = ff_layout_mark_request_commit, | 1502 | .mark_request_commit = pnfs_layout_mark_request_commit, |
1544 | .clear_request_commit = pnfs_generic_clear_request_commit, | 1503 | .clear_request_commit = pnfs_generic_clear_request_commit, |
1545 | .scan_commit_lists = pnfs_generic_scan_commit_lists, | 1504 | .scan_commit_lists = pnfs_generic_scan_commit_lists, |
1546 | .recover_commit_reqs = pnfs_generic_recover_commit_reqs, | 1505 | .recover_commit_reqs = pnfs_generic_recover_commit_reqs, |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e211f975a69a..83107be3dd01 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -388,7 +388,6 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
388 | if (S_ISREG(inode->i_mode)) { | 388 | if (S_ISREG(inode->i_mode)) { |
389 | inode->i_fop = NFS_SB(sb)->nfs_client->rpc_ops->file_ops; | 389 | inode->i_fop = NFS_SB(sb)->nfs_client->rpc_ops->file_ops; |
390 | inode->i_data.a_ops = &nfs_file_aops; | 390 | inode->i_data.a_ops = &nfs_file_aops; |
391 | inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info; | ||
392 | } else if (S_ISDIR(inode->i_mode)) { | 391 | } else if (S_ISDIR(inode->i_mode)) { |
393 | inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops; | 392 | inode->i_op = NFS_SB(sb)->nfs_client->rpc_ops->dir_inode_ops; |
394 | inode->i_fop = &nfs_dir_operations; | 393 | inode->i_fop = &nfs_dir_operations; |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 21469e6e3834..b802fb3a2d99 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -430,7 +430,6 @@ int nfs_show_options(struct seq_file *, struct dentry *); | |||
430 | int nfs_show_devname(struct seq_file *, struct dentry *); | 430 | int nfs_show_devname(struct seq_file *, struct dentry *); |
431 | int nfs_show_path(struct seq_file *, struct dentry *); | 431 | int nfs_show_path(struct seq_file *, struct dentry *); |
432 | int nfs_show_stats(struct seq_file *, struct dentry *); | 432 | int nfs_show_stats(struct seq_file *, struct dentry *); |
433 | void nfs_put_super(struct super_block *); | ||
434 | int nfs_remount(struct super_block *sb, int *flags, char *raw_data); | 433 | int nfs_remount(struct super_block *sb, int *flags, char *raw_data); |
435 | 434 | ||
436 | /* write.c */ | 435 | /* write.c */ |
@@ -599,6 +598,19 @@ void nfs_super_set_maxbytes(struct super_block *sb, __u64 maxfilesize) | |||
599 | } | 598 | } |
600 | 599 | ||
601 | /* | 600 | /* |
601 | * Record the page as unstable and mark its inode as dirty. | ||
602 | */ | ||
603 | static inline | ||
604 | void nfs_mark_page_unstable(struct page *page) | ||
605 | { | ||
606 | struct inode *inode = page_file_mapping(page)->host; | ||
607 | |||
608 | inc_zone_page_state(page, NR_UNSTABLE_NFS); | ||
609 | inc_bdi_stat(inode_to_bdi(inode), BDI_RECLAIMABLE); | ||
610 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | ||
611 | } | ||
612 | |||
613 | /* | ||
602 | * Determine the number of bytes of data the page contains | 614 | * Determine the number of bytes of data the page contains |
603 | */ | 615 | */ |
604 | static inline | 616 | static inline |
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 590f096fd011..5ad908e9ce9c 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c | |||
@@ -1373,49 +1373,55 @@ static int nfs4_reclaim_locks(struct nfs4_state *state, const struct nfs4_state_ | |||
1373 | struct nfs_inode *nfsi = NFS_I(inode); | 1373 | struct nfs_inode *nfsi = NFS_I(inode); |
1374 | struct file_lock *fl; | 1374 | struct file_lock *fl; |
1375 | int status = 0; | 1375 | int status = 0; |
1376 | struct file_lock_context *flctx = inode->i_flctx; | ||
1377 | struct list_head *list; | ||
1376 | 1378 | ||
1377 | if (inode->i_flock == NULL) | 1379 | if (flctx == NULL) |
1378 | return 0; | 1380 | return 0; |
1379 | 1381 | ||
1382 | list = &flctx->flc_posix; | ||
1383 | |||
1380 | /* Guard against delegation returns and new lock/unlock calls */ | 1384 | /* Guard against delegation returns and new lock/unlock calls */ |
1381 | down_write(&nfsi->rwsem); | 1385 | down_write(&nfsi->rwsem); |
1382 | /* Protect inode->i_flock using the BKL */ | 1386 | spin_lock(&flctx->flc_lock); |
1383 | spin_lock(&inode->i_lock); | 1387 | restart: |
1384 | for (fl = inode->i_flock; fl != NULL; fl = fl->fl_next) { | 1388 | list_for_each_entry(fl, list, fl_list) { |
1385 | if (!(fl->fl_flags & (FL_POSIX|FL_FLOCK))) | ||
1386 | continue; | ||
1387 | if (nfs_file_open_context(fl->fl_file)->state != state) | 1389 | if (nfs_file_open_context(fl->fl_file)->state != state) |
1388 | continue; | 1390 | continue; |
1389 | spin_unlock(&inode->i_lock); | 1391 | spin_unlock(&flctx->flc_lock); |
1390 | status = ops->recover_lock(state, fl); | 1392 | status = ops->recover_lock(state, fl); |
1391 | switch (status) { | 1393 | switch (status) { |
1392 | case 0: | 1394 | case 0: |
1393 | break; | 1395 | break; |
1394 | case -ESTALE: | 1396 | case -ESTALE: |
1395 | case -NFS4ERR_ADMIN_REVOKED: | 1397 | case -NFS4ERR_ADMIN_REVOKED: |
1396 | case -NFS4ERR_STALE_STATEID: | 1398 | case -NFS4ERR_STALE_STATEID: |
1397 | case -NFS4ERR_BAD_STATEID: | 1399 | case -NFS4ERR_BAD_STATEID: |
1398 | case -NFS4ERR_EXPIRED: | 1400 | case -NFS4ERR_EXPIRED: |
1399 | case -NFS4ERR_NO_GRACE: | 1401 | case -NFS4ERR_NO_GRACE: |
1400 | case -NFS4ERR_STALE_CLIENTID: | 1402 | case -NFS4ERR_STALE_CLIENTID: |
1401 | case -NFS4ERR_BADSESSION: | 1403 | case -NFS4ERR_BADSESSION: |
1402 | case -NFS4ERR_BADSLOT: | 1404 | case -NFS4ERR_BADSLOT: |
1403 | case -NFS4ERR_BAD_HIGH_SLOT: | 1405 | case -NFS4ERR_BAD_HIGH_SLOT: |
1404 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: | 1406 | case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION: |
1405 | goto out; | 1407 | goto out; |
1406 | default: | 1408 | default: |
1407 | printk(KERN_ERR "NFS: %s: unhandled error %d\n", | 1409 | pr_err("NFS: %s: unhandled error %d\n", |
1408 | __func__, status); | 1410 | __func__, status); |
1409 | case -ENOMEM: | 1411 | case -ENOMEM: |
1410 | case -NFS4ERR_DENIED: | 1412 | case -NFS4ERR_DENIED: |
1411 | case -NFS4ERR_RECLAIM_BAD: | 1413 | case -NFS4ERR_RECLAIM_BAD: |
1412 | case -NFS4ERR_RECLAIM_CONFLICT: | 1414 | case -NFS4ERR_RECLAIM_CONFLICT: |
1413 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ | 1415 | /* kill_proc(fl->fl_pid, SIGLOST, 1); */ |
1414 | status = 0; | 1416 | status = 0; |
1415 | } | 1417 | } |
1416 | spin_lock(&inode->i_lock); | 1418 | spin_lock(&flctx->flc_lock); |
1417 | } | 1419 | } |
1418 | spin_unlock(&inode->i_lock); | 1420 | if (list == &flctx->flc_posix) { |
1421 | list = &flctx->flc_flock; | ||
1422 | goto restart; | ||
1423 | } | ||
1424 | spin_unlock(&flctx->flc_lock); | ||
1419 | out: | 1425 | out: |
1420 | up_write(&nfsi->rwsem); | 1426 | up_write(&nfsi->rwsem); |
1421 | return status; | 1427 | return status; |
diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 48cea3c30e5d..75090feeafad 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c | |||
@@ -53,7 +53,6 @@ static const struct super_operations nfs4_sops = { | |||
53 | .destroy_inode = nfs_destroy_inode, | 53 | .destroy_inode = nfs_destroy_inode, |
54 | .write_inode = nfs4_write_inode, | 54 | .write_inode = nfs4_write_inode, |
55 | .drop_inode = nfs_drop_inode, | 55 | .drop_inode = nfs_drop_inode, |
56 | .put_super = nfs_put_super, | ||
57 | .statfs = nfs_statfs, | 56 | .statfs = nfs_statfs, |
58 | .evict_inode = nfs4_evict_inode, | 57 | .evict_inode = nfs4_evict_inode, |
59 | .umount_begin = nfs_umount_begin, | 58 | .umount_begin = nfs_umount_begin, |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 960c99f75d3f..d57190a0d533 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -933,11 +933,15 @@ static bool nfs_can_coalesce_requests(struct nfs_page *prev, | |||
933 | struct nfs_pageio_descriptor *pgio) | 933 | struct nfs_pageio_descriptor *pgio) |
934 | { | 934 | { |
935 | size_t size; | 935 | size_t size; |
936 | struct file_lock_context *flctx; | ||
936 | 937 | ||
937 | if (prev) { | 938 | if (prev) { |
938 | if (!nfs_match_open_context(req->wb_context, prev->wb_context)) | 939 | if (!nfs_match_open_context(req->wb_context, prev->wb_context)) |
939 | return false; | 940 | return false; |
940 | if (req->wb_context->dentry->d_inode->i_flock != NULL && | 941 | flctx = req->wb_context->dentry->d_inode->i_flctx; |
942 | if (flctx != NULL && | ||
943 | !(list_empty_careful(&flctx->flc_posix) && | ||
944 | list_empty_careful(&flctx->flc_flock)) && | ||
941 | !nfs_match_lock_context(req->wb_lock_context, | 945 | !nfs_match_lock_context(req->wb_lock_context, |
942 | prev->wb_lock_context)) | 946 | prev->wb_lock_context)) |
943 | return false; | 947 | return false; |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 797cd6253adf..635f0865671c 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
@@ -344,6 +344,10 @@ void nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, | |||
344 | struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net, | 344 | struct nfs4_pnfs_ds_addr *nfs4_decode_mp_ds_addr(struct net *net, |
345 | struct xdr_stream *xdr, | 345 | struct xdr_stream *xdr, |
346 | gfp_t gfp_flags); | 346 | gfp_t gfp_flags); |
347 | void pnfs_layout_mark_request_commit(struct nfs_page *req, | ||
348 | struct pnfs_layout_segment *lseg, | ||
349 | struct nfs_commit_info *cinfo, | ||
350 | u32 ds_commit_idx); | ||
347 | 351 | ||
348 | static inline bool nfs_have_layout(struct inode *inode) | 352 | static inline bool nfs_have_layout(struct inode *inode) |
349 | { | 353 | { |
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index fdc4f6562bb7..54e36b38fb5f 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c | |||
@@ -838,3 +838,33 @@ out_err: | |||
838 | return NULL; | 838 | return NULL; |
839 | } | 839 | } |
840 | EXPORT_SYMBOL_GPL(nfs4_decode_mp_ds_addr); | 840 | EXPORT_SYMBOL_GPL(nfs4_decode_mp_ds_addr); |
841 | |||
842 | void | ||
843 | pnfs_layout_mark_request_commit(struct nfs_page *req, | ||
844 | struct pnfs_layout_segment *lseg, | ||
845 | struct nfs_commit_info *cinfo, | ||
846 | u32 ds_commit_idx) | ||
847 | { | ||
848 | struct list_head *list; | ||
849 | struct pnfs_commit_bucket *buckets; | ||
850 | |||
851 | spin_lock(cinfo->lock); | ||
852 | buckets = cinfo->ds->buckets; | ||
853 | list = &buckets[ds_commit_idx].written; | ||
854 | if (list_empty(list)) { | ||
855 | /* Non-empty buckets hold a reference on the lseg. That ref | ||
856 | * is normally transferred to the COMMIT call and released | ||
857 | * there. It could also be released if the last req is pulled | ||
858 | * off due to a rewrite, in which case it will be done in | ||
859 | * pnfs_common_clear_request_commit | ||
860 | */ | ||
861 | WARN_ON_ONCE(buckets[ds_commit_idx].wlseg != NULL); | ||
862 | buckets[ds_commit_idx].wlseg = pnfs_get_lseg(lseg); | ||
863 | } | ||
864 | set_bit(PG_COMMIT_TO_DS, &req->wb_flags); | ||
865 | cinfo->ds->nwritten++; | ||
866 | spin_unlock(cinfo->lock); | ||
867 | |||
868 | nfs_request_add_commit_list(req, list, cinfo); | ||
869 | } | ||
870 | EXPORT_SYMBOL_GPL(pnfs_layout_mark_request_commit); | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 368d9395d2e7..322b2de02988 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -311,7 +311,6 @@ const struct super_operations nfs_sops = { | |||
311 | .destroy_inode = nfs_destroy_inode, | 311 | .destroy_inode = nfs_destroy_inode, |
312 | .write_inode = nfs_write_inode, | 312 | .write_inode = nfs_write_inode, |
313 | .drop_inode = nfs_drop_inode, | 313 | .drop_inode = nfs_drop_inode, |
314 | .put_super = nfs_put_super, | ||
315 | .statfs = nfs_statfs, | 314 | .statfs = nfs_statfs, |
316 | .evict_inode = nfs_evict_inode, | 315 | .evict_inode = nfs_evict_inode, |
317 | .umount_begin = nfs_umount_begin, | 316 | .umount_begin = nfs_umount_begin, |
@@ -2572,7 +2571,7 @@ struct dentry *nfs_fs_mount_common(struct nfs_server *server, | |||
2572 | error = nfs_bdi_register(server); | 2571 | error = nfs_bdi_register(server); |
2573 | if (error) { | 2572 | if (error) { |
2574 | mntroot = ERR_PTR(error); | 2573 | mntroot = ERR_PTR(error); |
2575 | goto error_splat_bdi; | 2574 | goto error_splat_super; |
2576 | } | 2575 | } |
2577 | server->super = s; | 2576 | server->super = s; |
2578 | } | 2577 | } |
@@ -2604,9 +2603,6 @@ error_splat_root: | |||
2604 | dput(mntroot); | 2603 | dput(mntroot); |
2605 | mntroot = ERR_PTR(error); | 2604 | mntroot = ERR_PTR(error); |
2606 | error_splat_super: | 2605 | error_splat_super: |
2607 | if (server && !s->s_root) | ||
2608 | bdi_unregister(&server->backing_dev_info); | ||
2609 | error_splat_bdi: | ||
2610 | deactivate_locked_super(s); | 2606 | deactivate_locked_super(s); |
2611 | goto out; | 2607 | goto out; |
2612 | } | 2608 | } |
@@ -2654,27 +2650,19 @@ out: | |||
2654 | EXPORT_SYMBOL_GPL(nfs_fs_mount); | 2650 | EXPORT_SYMBOL_GPL(nfs_fs_mount); |
2655 | 2651 | ||
2656 | /* | 2652 | /* |
2657 | * Ensure that we unregister the bdi before kill_anon_super | ||
2658 | * releases the device name | ||
2659 | */ | ||
2660 | void nfs_put_super(struct super_block *s) | ||
2661 | { | ||
2662 | struct nfs_server *server = NFS_SB(s); | ||
2663 | |||
2664 | bdi_unregister(&server->backing_dev_info); | ||
2665 | } | ||
2666 | EXPORT_SYMBOL_GPL(nfs_put_super); | ||
2667 | |||
2668 | /* | ||
2669 | * Destroy an NFS2/3 superblock | 2653 | * Destroy an NFS2/3 superblock |
2670 | */ | 2654 | */ |
2671 | void nfs_kill_super(struct super_block *s) | 2655 | void nfs_kill_super(struct super_block *s) |
2672 | { | 2656 | { |
2673 | struct nfs_server *server = NFS_SB(s); | 2657 | struct nfs_server *server = NFS_SB(s); |
2658 | dev_t dev = s->s_dev; | ||
2659 | |||
2660 | generic_shutdown_super(s); | ||
2674 | 2661 | ||
2675 | kill_anon_super(s); | ||
2676 | nfs_fscache_release_super_cookie(s); | 2662 | nfs_fscache_release_super_cookie(s); |
2663 | |||
2677 | nfs_free_server(server); | 2664 | nfs_free_server(server); |
2665 | free_anon_bdev(dev); | ||
2678 | } | 2666 | } |
2679 | EXPORT_SYMBOL_GPL(nfs_kill_super); | 2667 | EXPORT_SYMBOL_GPL(nfs_kill_super); |
2680 | 2668 | ||
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index ceacfeeb28c2..595d81e354d1 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -789,13 +789,8 @@ nfs_request_add_commit_list(struct nfs_page *req, struct list_head *dst, | |||
789 | nfs_list_add_request(req, dst); | 789 | nfs_list_add_request(req, dst); |
790 | cinfo->mds->ncommit++; | 790 | cinfo->mds->ncommit++; |
791 | spin_unlock(cinfo->lock); | 791 | spin_unlock(cinfo->lock); |
792 | if (!cinfo->dreq) { | 792 | if (!cinfo->dreq) |
793 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 793 | nfs_mark_page_unstable(req->wb_page); |
794 | inc_bdi_stat(page_file_mapping(req->wb_page)->backing_dev_info, | ||
795 | BDI_RECLAIMABLE); | ||
796 | __mark_inode_dirty(req->wb_context->dentry->d_inode, | ||
797 | I_DIRTY_DATASYNC); | ||
798 | } | ||
799 | } | 794 | } |
800 | EXPORT_SYMBOL_GPL(nfs_request_add_commit_list); | 795 | EXPORT_SYMBOL_GPL(nfs_request_add_commit_list); |
801 | 796 | ||
@@ -858,7 +853,7 @@ static void | |||
858 | nfs_clear_page_commit(struct page *page) | 853 | nfs_clear_page_commit(struct page *page) |
859 | { | 854 | { |
860 | dec_zone_page_state(page, NR_UNSTABLE_NFS); | 855 | dec_zone_page_state(page, NR_UNSTABLE_NFS); |
861 | dec_bdi_stat(page_file_mapping(page)->backing_dev_info, BDI_RECLAIMABLE); | 856 | dec_bdi_stat(inode_to_bdi(page_file_mapping(page)->host), BDI_RECLAIMABLE); |
862 | } | 857 | } |
863 | 858 | ||
864 | /* Called holding inode (/cinfo) lock */ | 859 | /* Called holding inode (/cinfo) lock */ |
@@ -1097,6 +1092,7 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
1097 | { | 1092 | { |
1098 | struct nfs_open_context *ctx = nfs_file_open_context(file); | 1093 | struct nfs_open_context *ctx = nfs_file_open_context(file); |
1099 | struct nfs_lock_context *l_ctx; | 1094 | struct nfs_lock_context *l_ctx; |
1095 | struct file_lock_context *flctx = file_inode(file)->i_flctx; | ||
1100 | struct nfs_page *req; | 1096 | struct nfs_page *req; |
1101 | int do_flush, status; | 1097 | int do_flush, status; |
1102 | /* | 1098 | /* |
@@ -1115,7 +1111,9 @@ int nfs_flush_incompatible(struct file *file, struct page *page) | |||
1115 | do_flush = req->wb_page != page || req->wb_context != ctx; | 1111 | do_flush = req->wb_page != page || req->wb_context != ctx; |
1116 | /* for now, flush if more than 1 request in page_group */ | 1112 | /* for now, flush if more than 1 request in page_group */ |
1117 | do_flush |= req->wb_this_page != req; | 1113 | do_flush |= req->wb_this_page != req; |
1118 | if (l_ctx && ctx->dentry->d_inode->i_flock != NULL) { | 1114 | if (l_ctx && flctx && |
1115 | !(list_empty_careful(&flctx->flc_posix) && | ||
1116 | list_empty_careful(&flctx->flc_flock))) { | ||
1119 | do_flush |= l_ctx->lockowner.l_owner != current->files | 1117 | do_flush |= l_ctx->lockowner.l_owner != current->files |
1120 | || l_ctx->lockowner.l_pid != current->tgid; | 1118 | || l_ctx->lockowner.l_pid != current->tgid; |
1121 | } | 1119 | } |
@@ -1176,6 +1174,13 @@ out: | |||
1176 | return PageUptodate(page) != 0; | 1174 | return PageUptodate(page) != 0; |
1177 | } | 1175 | } |
1178 | 1176 | ||
1177 | static bool | ||
1178 | is_whole_file_wrlock(struct file_lock *fl) | ||
1179 | { | ||
1180 | return fl->fl_start == 0 && fl->fl_end == OFFSET_MAX && | ||
1181 | fl->fl_type == F_WRLCK; | ||
1182 | } | ||
1183 | |||
1179 | /* If we know the page is up to date, and we're not using byte range locks (or | 1184 | /* If we know the page is up to date, and we're not using byte range locks (or |
1180 | * if we have the whole file locked for writing), it may be more efficient to | 1185 | * if we have the whole file locked for writing), it may be more efficient to |
1181 | * extend the write to cover the entire page in order to avoid fragmentation | 1186 | * extend the write to cover the entire page in order to avoid fragmentation |
@@ -1186,17 +1191,36 @@ out: | |||
1186 | */ | 1191 | */ |
1187 | static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode) | 1192 | static int nfs_can_extend_write(struct file *file, struct page *page, struct inode *inode) |
1188 | { | 1193 | { |
1194 | int ret; | ||
1195 | struct file_lock_context *flctx = inode->i_flctx; | ||
1196 | struct file_lock *fl; | ||
1197 | |||
1189 | if (file->f_flags & O_DSYNC) | 1198 | if (file->f_flags & O_DSYNC) |
1190 | return 0; | 1199 | return 0; |
1191 | if (!nfs_write_pageuptodate(page, inode)) | 1200 | if (!nfs_write_pageuptodate(page, inode)) |
1192 | return 0; | 1201 | return 0; |
1193 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) | 1202 | if (NFS_PROTO(inode)->have_delegation(inode, FMODE_WRITE)) |
1194 | return 1; | 1203 | return 1; |
1195 | if (inode->i_flock == NULL || (inode->i_flock->fl_start == 0 && | 1204 | if (!flctx || (list_empty_careful(&flctx->flc_flock) && |
1196 | inode->i_flock->fl_end == OFFSET_MAX && | 1205 | list_empty_careful(&flctx->flc_posix))) |
1197 | inode->i_flock->fl_type != F_RDLCK)) | 1206 | return 0; |
1198 | return 1; | 1207 | |
1199 | return 0; | 1208 | /* Check to see if there are whole file write locks */ |
1209 | ret = 0; | ||
1210 | spin_lock(&flctx->flc_lock); | ||
1211 | if (!list_empty(&flctx->flc_posix)) { | ||
1212 | fl = list_first_entry(&flctx->flc_posix, struct file_lock, | ||
1213 | fl_list); | ||
1214 | if (is_whole_file_wrlock(fl)) | ||
1215 | ret = 1; | ||
1216 | } else if (!list_empty(&flctx->flc_flock)) { | ||
1217 | fl = list_first_entry(&flctx->flc_flock, struct file_lock, | ||
1218 | fl_list); | ||
1219 | if (fl->fl_type == F_WRLCK) | ||
1220 | ret = 1; | ||
1221 | } | ||
1222 | spin_unlock(&flctx->flc_lock); | ||
1223 | return ret; | ||
1200 | } | 1224 | } |
1201 | 1225 | ||
1202 | /* | 1226 | /* |
@@ -1576,11 +1600,8 @@ void nfs_retry_commit(struct list_head *page_list, | |||
1576 | req = nfs_list_entry(page_list->next); | 1600 | req = nfs_list_entry(page_list->next); |
1577 | nfs_list_remove_request(req); | 1601 | nfs_list_remove_request(req); |
1578 | nfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx); | 1602 | nfs_mark_request_commit(req, lseg, cinfo, ds_commit_idx); |
1579 | if (!cinfo->dreq) { | 1603 | if (!cinfo->dreq) |
1580 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 1604 | nfs_clear_page_commit(req->wb_page); |
1581 | dec_bdi_stat(page_file_mapping(req->wb_page)->backing_dev_info, | ||
1582 | BDI_RECLAIMABLE); | ||
1583 | } | ||
1584 | nfs_unlock_and_release_request(req); | 1605 | nfs_unlock_and_release_request(req); |
1585 | } | 1606 | } |
1586 | } | 1607 | } |