diff options
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r-- | fs/nfs/pnfs.c | 86 |
1 files changed, 54 insertions, 32 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 38e5508555c6..e550e8836c37 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
@@ -76,8 +76,11 @@ find_pnfs_driver(u32 id) | |||
76 | void | 76 | void |
77 | unset_pnfs_layoutdriver(struct nfs_server *nfss) | 77 | unset_pnfs_layoutdriver(struct nfs_server *nfss) |
78 | { | 78 | { |
79 | if (nfss->pnfs_curr_ld) | 79 | if (nfss->pnfs_curr_ld) { |
80 | if (nfss->pnfs_curr_ld->clear_layoutdriver) | ||
81 | nfss->pnfs_curr_ld->clear_layoutdriver(nfss); | ||
80 | module_put(nfss->pnfs_curr_ld->owner); | 82 | module_put(nfss->pnfs_curr_ld->owner); |
83 | } | ||
81 | nfss->pnfs_curr_ld = NULL; | 84 | nfss->pnfs_curr_ld = NULL; |
82 | } | 85 | } |
83 | 86 | ||
@@ -88,7 +91,8 @@ unset_pnfs_layoutdriver(struct nfs_server *nfss) | |||
88 | * @id layout type. Zero (illegal layout type) indicates pNFS not in use. | 91 | * @id layout type. Zero (illegal layout type) indicates pNFS not in use. |
89 | */ | 92 | */ |
90 | void | 93 | void |
91 | set_pnfs_layoutdriver(struct nfs_server *server, u32 id) | 94 | set_pnfs_layoutdriver(struct nfs_server *server, const struct nfs_fh *mntfh, |
95 | u32 id) | ||
92 | { | 96 | { |
93 | struct pnfs_layoutdriver_type *ld_type = NULL; | 97 | struct pnfs_layoutdriver_type *ld_type = NULL; |
94 | 98 | ||
@@ -115,6 +119,13 @@ set_pnfs_layoutdriver(struct nfs_server *server, u32 id) | |||
115 | goto out_no_driver; | 119 | goto out_no_driver; |
116 | } | 120 | } |
117 | server->pnfs_curr_ld = ld_type; | 121 | server->pnfs_curr_ld = ld_type; |
122 | if (ld_type->set_layoutdriver | ||
123 | && ld_type->set_layoutdriver(server, mntfh)) { | ||
124 | printk(KERN_ERR "%s: Error initializing pNFS layout driver %u.\n", | ||
125 | __func__, id); | ||
126 | module_put(ld_type->owner); | ||
127 | goto out_no_driver; | ||
128 | } | ||
118 | 129 | ||
119 | dprintk("%s: pNFS module for %u set\n", __func__, id); | 130 | dprintk("%s: pNFS module for %u set\n", __func__, id); |
120 | return; | 131 | return; |
@@ -190,6 +201,7 @@ static void | |||
190 | pnfs_free_layout_hdr(struct pnfs_layout_hdr *lo) | 201 | pnfs_free_layout_hdr(struct pnfs_layout_hdr *lo) |
191 | { | 202 | { |
192 | struct pnfs_layoutdriver_type *ld = NFS_SERVER(lo->plh_inode)->pnfs_curr_ld; | 203 | struct pnfs_layoutdriver_type *ld = NFS_SERVER(lo->plh_inode)->pnfs_curr_ld; |
204 | put_rpccred(lo->plh_lc_cred); | ||
193 | return ld->alloc_layout_hdr ? ld->free_layout_hdr(lo) : kfree(lo); | 205 | return ld->alloc_layout_hdr ? ld->free_layout_hdr(lo) : kfree(lo); |
194 | } | 206 | } |
195 | 207 | ||
@@ -224,6 +236,7 @@ static void | |||
224 | init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg) | 236 | init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg) |
225 | { | 237 | { |
226 | INIT_LIST_HEAD(&lseg->pls_list); | 238 | INIT_LIST_HEAD(&lseg->pls_list); |
239 | INIT_LIST_HEAD(&lseg->pls_lc_list); | ||
227 | atomic_set(&lseg->pls_refcount, 1); | 240 | atomic_set(&lseg->pls_refcount, 1); |
228 | smp_mb(); | 241 | smp_mb(); |
229 | set_bit(NFS_LSEG_VALID, &lseg->pls_flags); | 242 | set_bit(NFS_LSEG_VALID, &lseg->pls_flags); |
@@ -816,7 +829,9 @@ out: | |||
816 | } | 829 | } |
817 | 830 | ||
818 | static struct pnfs_layout_hdr * | 831 | static struct pnfs_layout_hdr * |
819 | alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags) | 832 | alloc_init_layout_hdr(struct inode *ino, |
833 | struct nfs_open_context *ctx, | ||
834 | gfp_t gfp_flags) | ||
820 | { | 835 | { |
821 | struct pnfs_layout_hdr *lo; | 836 | struct pnfs_layout_hdr *lo; |
822 | 837 | ||
@@ -828,11 +843,14 @@ alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags) | |||
828 | INIT_LIST_HEAD(&lo->plh_segs); | 843 | INIT_LIST_HEAD(&lo->plh_segs); |
829 | INIT_LIST_HEAD(&lo->plh_bulk_recall); | 844 | INIT_LIST_HEAD(&lo->plh_bulk_recall); |
830 | lo->plh_inode = ino; | 845 | lo->plh_inode = ino; |
846 | lo->plh_lc_cred = get_rpccred(ctx->state->owner->so_cred); | ||
831 | return lo; | 847 | return lo; |
832 | } | 848 | } |
833 | 849 | ||
834 | static struct pnfs_layout_hdr * | 850 | static struct pnfs_layout_hdr * |
835 | pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags) | 851 | pnfs_find_alloc_layout(struct inode *ino, |
852 | struct nfs_open_context *ctx, | ||
853 | gfp_t gfp_flags) | ||
836 | { | 854 | { |
837 | struct nfs_inode *nfsi = NFS_I(ino); | 855 | struct nfs_inode *nfsi = NFS_I(ino); |
838 | struct pnfs_layout_hdr *new = NULL; | 856 | struct pnfs_layout_hdr *new = NULL; |
@@ -847,7 +865,7 @@ pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags) | |||
847 | return nfsi->layout; | 865 | return nfsi->layout; |
848 | } | 866 | } |
849 | spin_unlock(&ino->i_lock); | 867 | spin_unlock(&ino->i_lock); |
850 | new = alloc_init_layout_hdr(ino, gfp_flags); | 868 | new = alloc_init_layout_hdr(ino, ctx, gfp_flags); |
851 | spin_lock(&ino->i_lock); | 869 | spin_lock(&ino->i_lock); |
852 | 870 | ||
853 | if (likely(nfsi->layout == NULL)) /* Won the race? */ | 871 | if (likely(nfsi->layout == NULL)) /* Won the race? */ |
@@ -940,7 +958,7 @@ pnfs_update_layout(struct inode *ino, | |||
940 | if (!pnfs_enabled_sb(NFS_SERVER(ino))) | 958 | if (!pnfs_enabled_sb(NFS_SERVER(ino))) |
941 | return NULL; | 959 | return NULL; |
942 | spin_lock(&ino->i_lock); | 960 | spin_lock(&ino->i_lock); |
943 | lo = pnfs_find_alloc_layout(ino, gfp_flags); | 961 | lo = pnfs_find_alloc_layout(ino, ctx, gfp_flags); |
944 | if (lo == NULL) { | 962 | if (lo == NULL) { |
945 | dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__); | 963 | dprintk("%s ERROR: can't get pnfs_layout_hdr\n", __func__); |
946 | goto out_unlock; | 964 | goto out_unlock; |
@@ -1350,16 +1368,17 @@ pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc) | |||
1350 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages); | 1368 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages); |
1351 | 1369 | ||
1352 | /* | 1370 | /* |
1353 | * Currently there is only one (whole file) write lseg. | 1371 | * There can be multiple RW segments. |
1354 | */ | 1372 | */ |
1355 | static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode) | 1373 | static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp) |
1356 | { | 1374 | { |
1357 | struct pnfs_layout_segment *lseg, *rv = NULL; | 1375 | struct pnfs_layout_segment *lseg; |
1358 | 1376 | ||
1359 | list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) | 1377 | list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) { |
1360 | if (lseg->pls_range.iomode == IOMODE_RW) | 1378 | if (lseg->pls_range.iomode == IOMODE_RW && |
1361 | rv = lseg; | 1379 | test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags)) |
1362 | return rv; | 1380 | list_add(&lseg->pls_lc_list, listp); |
1381 | } | ||
1363 | } | 1382 | } |
1364 | 1383 | ||
1365 | void | 1384 | void |
@@ -1371,17 +1390,19 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) | |||
1371 | 1390 | ||
1372 | spin_lock(&nfsi->vfs_inode.i_lock); | 1391 | spin_lock(&nfsi->vfs_inode.i_lock); |
1373 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | 1392 | if (!test_and_set_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { |
1374 | /* references matched in nfs4_layoutcommit_release */ | ||
1375 | get_lseg(wdata->lseg); | ||
1376 | wdata->lseg->pls_lc_cred = | ||
1377 | get_rpccred(wdata->args.context->state->owner->so_cred); | ||
1378 | mark_as_dirty = true; | 1393 | mark_as_dirty = true; |
1379 | dprintk("%s: Set layoutcommit for inode %lu ", | 1394 | dprintk("%s: Set layoutcommit for inode %lu ", |
1380 | __func__, wdata->inode->i_ino); | 1395 | __func__, wdata->inode->i_ino); |
1381 | } | 1396 | } |
1382 | if (end_pos > wdata->lseg->pls_end_pos) | 1397 | if (!test_and_set_bit(NFS_LSEG_LAYOUTCOMMIT, &wdata->lseg->pls_flags)) { |
1383 | wdata->lseg->pls_end_pos = end_pos; | 1398 | /* references matched in nfs4_layoutcommit_release */ |
1399 | get_lseg(wdata->lseg); | ||
1400 | } | ||
1401 | if (end_pos > nfsi->layout->plh_lwb) | ||
1402 | nfsi->layout->plh_lwb = end_pos; | ||
1384 | spin_unlock(&nfsi->vfs_inode.i_lock); | 1403 | spin_unlock(&nfsi->vfs_inode.i_lock); |
1404 | dprintk("%s: lseg %p end_pos %llu\n", | ||
1405 | __func__, wdata->lseg, nfsi->layout->plh_lwb); | ||
1385 | 1406 | ||
1386 | /* if pnfs_layoutcommit_inode() runs between inode locks, the next one | 1407 | /* if pnfs_layoutcommit_inode() runs between inode locks, the next one |
1387 | * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ | 1408 | * will be a noop because NFS_INO_LAYOUTCOMMIT will not be set */ |
@@ -1390,6 +1411,14 @@ pnfs_set_layoutcommit(struct nfs_write_data *wdata) | |||
1390 | } | 1411 | } |
1391 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); | 1412 | EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); |
1392 | 1413 | ||
1414 | void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data) | ||
1415 | { | ||
1416 | struct nfs_server *nfss = NFS_SERVER(data->args.inode); | ||
1417 | |||
1418 | if (nfss->pnfs_curr_ld->cleanup_layoutcommit) | ||
1419 | nfss->pnfs_curr_ld->cleanup_layoutcommit(data); | ||
1420 | } | ||
1421 | |||
1393 | /* | 1422 | /* |
1394 | * For the LAYOUT4_NFSV4_1_FILES layout type, NFS_DATA_SYNC WRITEs and | 1423 | * For the LAYOUT4_NFSV4_1_FILES layout type, NFS_DATA_SYNC WRITEs and |
1395 | * NFS_UNSTABLE WRITEs with a COMMIT to data servers must store enough | 1424 | * NFS_UNSTABLE WRITEs with a COMMIT to data servers must store enough |
@@ -1403,8 +1432,6 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) | |||
1403 | { | 1432 | { |
1404 | struct nfs4_layoutcommit_data *data; | 1433 | struct nfs4_layoutcommit_data *data; |
1405 | struct nfs_inode *nfsi = NFS_I(inode); | 1434 | struct nfs_inode *nfsi = NFS_I(inode); |
1406 | struct pnfs_layout_segment *lseg; | ||
1407 | struct rpc_cred *cred; | ||
1408 | loff_t end_pos; | 1435 | loff_t end_pos; |
1409 | int status = 0; | 1436 | int status = 0; |
1410 | 1437 | ||
@@ -1421,30 +1448,25 @@ pnfs_layoutcommit_inode(struct inode *inode, bool sync) | |||
1421 | goto out; | 1448 | goto out; |
1422 | } | 1449 | } |
1423 | 1450 | ||
1451 | INIT_LIST_HEAD(&data->lseg_list); | ||
1424 | spin_lock(&inode->i_lock); | 1452 | spin_lock(&inode->i_lock); |
1425 | if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { | 1453 | if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) { |
1426 | spin_unlock(&inode->i_lock); | 1454 | spin_unlock(&inode->i_lock); |
1427 | kfree(data); | 1455 | kfree(data); |
1428 | goto out; | 1456 | goto out; |
1429 | } | 1457 | } |
1430 | /* | ||
1431 | * Currently only one (whole file) write lseg which is referenced | ||
1432 | * in pnfs_set_layoutcommit and will be found. | ||
1433 | */ | ||
1434 | lseg = pnfs_list_write_lseg(inode); | ||
1435 | 1458 | ||
1436 | end_pos = lseg->pls_end_pos; | 1459 | pnfs_list_write_lseg(inode, &data->lseg_list); |
1437 | cred = lseg->pls_lc_cred; | 1460 | |
1438 | lseg->pls_end_pos = 0; | 1461 | end_pos = nfsi->layout->plh_lwb; |
1439 | lseg->pls_lc_cred = NULL; | 1462 | nfsi->layout->plh_lwb = 0; |
1440 | 1463 | ||
1441 | memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data, | 1464 | memcpy(&data->args.stateid.data, nfsi->layout->plh_stateid.data, |
1442 | sizeof(nfsi->layout->plh_stateid.data)); | 1465 | sizeof(nfsi->layout->plh_stateid.data)); |
1443 | spin_unlock(&inode->i_lock); | 1466 | spin_unlock(&inode->i_lock); |
1444 | 1467 | ||
1445 | data->args.inode = inode; | 1468 | data->args.inode = inode; |
1446 | data->lseg = lseg; | 1469 | data->cred = get_rpccred(nfsi->layout->plh_lc_cred); |
1447 | data->cred = cred; | ||
1448 | nfs_fattr_init(&data->fattr); | 1470 | nfs_fattr_init(&data->fattr); |
1449 | data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; | 1471 | data->args.bitmask = NFS_SERVER(inode)->cache_consistency_bitmask; |
1450 | data->res.fattr = &data->fattr; | 1472 | data->res.fattr = &data->fattr; |