aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/pnfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfs/pnfs.c')
-rw-r--r--fs/nfs/pnfs.c86
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)
76void 76void
77unset_pnfs_layoutdriver(struct nfs_server *nfss) 77unset_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 */
90void 93void
91set_pnfs_layoutdriver(struct nfs_server *server, u32 id) 94set_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
190pnfs_free_layout_hdr(struct pnfs_layout_hdr *lo) 201pnfs_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
224init_lseg(struct pnfs_layout_hdr *lo, struct pnfs_layout_segment *lseg) 236init_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
818static struct pnfs_layout_hdr * 831static struct pnfs_layout_hdr *
819alloc_init_layout_hdr(struct inode *ino, gfp_t gfp_flags) 832alloc_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
834static struct pnfs_layout_hdr * 850static struct pnfs_layout_hdr *
835pnfs_find_alloc_layout(struct inode *ino, gfp_t gfp_flags) 851pnfs_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)
1350EXPORT_SYMBOL_GPL(pnfs_generic_pg_readpages); 1368EXPORT_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 */
1355static struct pnfs_layout_segment *pnfs_list_write_lseg(struct inode *inode) 1373static 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
1365void 1384void
@@ -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}
1391EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit); 1412EXPORT_SYMBOL_GPL(pnfs_set_layoutcommit);
1392 1413
1414void 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;