diff options
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 214 |
1 files changed, 144 insertions, 70 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 47a3ad63e0d5..85d75254328e 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -59,6 +59,7 @@ struct nfs_write_data *nfs_commitdata_alloc(void) | |||
59 | } | 59 | } |
60 | return p; | 60 | return p; |
61 | } | 61 | } |
62 | EXPORT_SYMBOL_GPL(nfs_commitdata_alloc); | ||
62 | 63 | ||
63 | void nfs_commit_free(struct nfs_write_data *p) | 64 | void nfs_commit_free(struct nfs_write_data *p) |
64 | { | 65 | { |
@@ -66,6 +67,7 @@ void nfs_commit_free(struct nfs_write_data *p) | |||
66 | kfree(p->pagevec); | 67 | kfree(p->pagevec); |
67 | mempool_free(p, nfs_commit_mempool); | 68 | mempool_free(p, nfs_commit_mempool); |
68 | } | 69 | } |
70 | EXPORT_SYMBOL_GPL(nfs_commit_free); | ||
69 | 71 | ||
70 | struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) | 72 | struct nfs_write_data *nfs_writedata_alloc(unsigned int pagecount) |
71 | { | 73 | { |
@@ -179,8 +181,8 @@ static int wb_priority(struct writeback_control *wbc) | |||
179 | if (wbc->for_reclaim) | 181 | if (wbc->for_reclaim) |
180 | return FLUSH_HIGHPRI | FLUSH_STABLE; | 182 | return FLUSH_HIGHPRI | FLUSH_STABLE; |
181 | if (wbc->for_kupdate || wbc->for_background) | 183 | if (wbc->for_kupdate || wbc->for_background) |
182 | return FLUSH_LOWPRI; | 184 | return FLUSH_LOWPRI | FLUSH_COND_STABLE; |
183 | return 0; | 185 | return FLUSH_COND_STABLE; |
184 | } | 186 | } |
185 | 187 | ||
186 | /* | 188 | /* |
@@ -441,7 +443,7 @@ nfs_mark_request_dirty(struct nfs_page *req) | |||
441 | * Add a request to the inode's commit list. | 443 | * Add a request to the inode's commit list. |
442 | */ | 444 | */ |
443 | static void | 445 | static void |
444 | nfs_mark_request_commit(struct nfs_page *req) | 446 | nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
445 | { | 447 | { |
446 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 448 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
447 | struct nfs_inode *nfsi = NFS_I(inode); | 449 | struct nfs_inode *nfsi = NFS_I(inode); |
@@ -453,6 +455,7 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
453 | NFS_PAGE_TAG_COMMIT); | 455 | NFS_PAGE_TAG_COMMIT); |
454 | nfsi->ncommit++; | 456 | nfsi->ncommit++; |
455 | spin_unlock(&inode->i_lock); | 457 | spin_unlock(&inode->i_lock); |
458 | pnfs_mark_request_commit(req, lseg); | ||
456 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 459 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
457 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); | 460 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); |
458 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 461 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
@@ -474,14 +477,18 @@ nfs_clear_request_commit(struct nfs_page *req) | |||
474 | static inline | 477 | static inline |
475 | int nfs_write_need_commit(struct nfs_write_data *data) | 478 | int nfs_write_need_commit(struct nfs_write_data *data) |
476 | { | 479 | { |
477 | return data->verf.committed != NFS_FILE_SYNC; | 480 | if (data->verf.committed == NFS_DATA_SYNC) |
481 | return data->lseg == NULL; | ||
482 | else | ||
483 | return data->verf.committed != NFS_FILE_SYNC; | ||
478 | } | 484 | } |
479 | 485 | ||
480 | static inline | 486 | static inline |
481 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 487 | int nfs_reschedule_unstable_write(struct nfs_page *req, |
488 | struct nfs_write_data *data) | ||
482 | { | 489 | { |
483 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 490 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
484 | nfs_mark_request_commit(req); | 491 | nfs_mark_request_commit(req, data->lseg); |
485 | return 1; | 492 | return 1; |
486 | } | 493 | } |
487 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { | 494 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { |
@@ -492,7 +499,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req) | |||
492 | } | 499 | } |
493 | #else | 500 | #else |
494 | static inline void | 501 | static inline void |
495 | nfs_mark_request_commit(struct nfs_page *req) | 502 | nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
496 | { | 503 | { |
497 | } | 504 | } |
498 | 505 | ||
@@ -509,7 +516,8 @@ int nfs_write_need_commit(struct nfs_write_data *data) | |||
509 | } | 516 | } |
510 | 517 | ||
511 | static inline | 518 | static inline |
512 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 519 | int nfs_reschedule_unstable_write(struct nfs_page *req, |
520 | struct nfs_write_data *data) | ||
513 | { | 521 | { |
514 | return 0; | 522 | return 0; |
515 | } | 523 | } |
@@ -612,9 +620,11 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, | |||
612 | } | 620 | } |
613 | 621 | ||
614 | if (nfs_clear_request_commit(req) && | 622 | if (nfs_clear_request_commit(req) && |
615 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, | 623 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, |
616 | req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) | 624 | req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) { |
617 | NFS_I(inode)->ncommit--; | 625 | NFS_I(inode)->ncommit--; |
626 | pnfs_clear_request_commit(req); | ||
627 | } | ||
618 | 628 | ||
619 | /* Okay, the request matches. Update the region */ | 629 | /* Okay, the request matches. Update the region */ |
620 | if (offset < req->wb_offset) { | 630 | if (offset < req->wb_offset) { |
@@ -762,11 +772,12 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
762 | return status; | 772 | return status; |
763 | } | 773 | } |
764 | 774 | ||
765 | static void nfs_writepage_release(struct nfs_page *req) | 775 | static void nfs_writepage_release(struct nfs_page *req, |
776 | struct nfs_write_data *data) | ||
766 | { | 777 | { |
767 | struct page *page = req->wb_page; | 778 | struct page *page = req->wb_page; |
768 | 779 | ||
769 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) | 780 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req, data)) |
770 | nfs_inode_remove_request(req); | 781 | nfs_inode_remove_request(req); |
771 | nfs_clear_page_tag_locked(req); | 782 | nfs_clear_page_tag_locked(req); |
772 | nfs_end_page_writeback(page); | 783 | nfs_end_page_writeback(page); |
@@ -863,7 +874,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
863 | data->args.context = get_nfs_open_context(req->wb_context); | 874 | data->args.context = get_nfs_open_context(req->wb_context); |
864 | data->args.lock_context = req->wb_lock_context; | 875 | data->args.lock_context = req->wb_lock_context; |
865 | data->args.stable = NFS_UNSTABLE; | 876 | data->args.stable = NFS_UNSTABLE; |
866 | if (how & FLUSH_STABLE) { | 877 | if (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) { |
867 | data->args.stable = NFS_DATA_SYNC; | 878 | data->args.stable = NFS_DATA_SYNC; |
868 | if (!nfs_need_commit(NFS_I(inode))) | 879 | if (!nfs_need_commit(NFS_I(inode))) |
869 | data->args.stable = NFS_FILE_SYNC; | 880 | data->args.stable = NFS_FILE_SYNC; |
@@ -912,6 +923,12 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) | |||
912 | 923 | ||
913 | nfs_list_remove_request(req); | 924 | nfs_list_remove_request(req); |
914 | 925 | ||
926 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
927 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit || | ||
928 | desc->pg_count > wsize)) | ||
929 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
930 | |||
931 | |||
915 | nbytes = desc->pg_count; | 932 | nbytes = desc->pg_count; |
916 | do { | 933 | do { |
917 | size_t len = min(nbytes, wsize); | 934 | size_t len = min(nbytes, wsize); |
@@ -1002,6 +1019,10 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) | |||
1002 | if ((!lseg) && list_is_singular(&data->pages)) | 1019 | if ((!lseg) && list_is_singular(&data->pages)) |
1003 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); | 1020 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); |
1004 | 1021 | ||
1022 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
1023 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) | ||
1024 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
1025 | |||
1005 | /* Set up the argument struct */ | 1026 | /* Set up the argument struct */ |
1006 | ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags); | 1027 | ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags); |
1007 | out: | 1028 | out: |
@@ -1074,7 +1095,7 @@ static void nfs_writeback_release_partial(void *calldata) | |||
1074 | 1095 | ||
1075 | out: | 1096 | out: |
1076 | if (atomic_dec_and_test(&req->wb_complete)) | 1097 | if (atomic_dec_and_test(&req->wb_complete)) |
1077 | nfs_writepage_release(req); | 1098 | nfs_writepage_release(req, data); |
1078 | nfs_writedata_release(calldata); | 1099 | nfs_writedata_release(calldata); |
1079 | } | 1100 | } |
1080 | 1101 | ||
@@ -1141,7 +1162,7 @@ static void nfs_writeback_release_full(void *calldata) | |||
1141 | 1162 | ||
1142 | if (nfs_write_need_commit(data)) { | 1163 | if (nfs_write_need_commit(data)) { |
1143 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | 1164 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); |
1144 | nfs_mark_request_commit(req); | 1165 | nfs_mark_request_commit(req, data->lseg); |
1145 | dprintk(" marked for commit\n"); | 1166 | dprintk(" marked for commit\n"); |
1146 | goto next; | 1167 | goto next; |
1147 | } | 1168 | } |
@@ -1251,57 +1272,82 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1251 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1272 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
1252 | static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) | 1273 | static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) |
1253 | { | 1274 | { |
1275 | int ret; | ||
1276 | |||
1254 | if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) | 1277 | if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) |
1255 | return 1; | 1278 | return 1; |
1256 | if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags, | 1279 | if (!may_wait) |
1257 | NFS_INO_COMMIT, nfs_wait_bit_killable, | 1280 | return 0; |
1258 | TASK_KILLABLE)) | 1281 | ret = out_of_line_wait_on_bit_lock(&nfsi->flags, |
1259 | return 1; | 1282 | NFS_INO_COMMIT, |
1260 | return 0; | 1283 | nfs_wait_bit_killable, |
1284 | TASK_KILLABLE); | ||
1285 | return (ret < 0) ? ret : 1; | ||
1261 | } | 1286 | } |
1262 | 1287 | ||
1263 | static void nfs_commit_clear_lock(struct nfs_inode *nfsi) | 1288 | void nfs_commit_clear_lock(struct nfs_inode *nfsi) |
1264 | { | 1289 | { |
1265 | clear_bit(NFS_INO_COMMIT, &nfsi->flags); | 1290 | clear_bit(NFS_INO_COMMIT, &nfsi->flags); |
1266 | smp_mb__after_clear_bit(); | 1291 | smp_mb__after_clear_bit(); |
1267 | wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); | 1292 | wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); |
1268 | } | 1293 | } |
1294 | EXPORT_SYMBOL_GPL(nfs_commit_clear_lock); | ||
1269 | 1295 | ||
1270 | 1296 | void nfs_commitdata_release(void *data) | |
1271 | static void nfs_commitdata_release(void *data) | ||
1272 | { | 1297 | { |
1273 | struct nfs_write_data *wdata = data; | 1298 | struct nfs_write_data *wdata = data; |
1274 | 1299 | ||
1300 | put_lseg(wdata->lseg); | ||
1275 | put_nfs_open_context(wdata->args.context); | 1301 | put_nfs_open_context(wdata->args.context); |
1276 | nfs_commit_free(wdata); | 1302 | nfs_commit_free(wdata); |
1277 | } | 1303 | } |
1304 | EXPORT_SYMBOL_GPL(nfs_commitdata_release); | ||
1278 | 1305 | ||
1279 | /* | 1306 | int nfs_initiate_commit(struct nfs_write_data *data, struct rpc_clnt *clnt, |
1280 | * Set up the argument/result storage required for the RPC call. | 1307 | const struct rpc_call_ops *call_ops, |
1281 | */ | 1308 | int how) |
1282 | static int nfs_commit_rpcsetup(struct list_head *head, | ||
1283 | struct nfs_write_data *data, | ||
1284 | int how) | ||
1285 | { | 1309 | { |
1286 | struct nfs_page *first = nfs_list_entry(head->next); | ||
1287 | struct inode *inode = first->wb_context->path.dentry->d_inode; | ||
1288 | int priority = flush_task_priority(how); | ||
1289 | struct rpc_task *task; | 1310 | struct rpc_task *task; |
1311 | int priority = flush_task_priority(how); | ||
1290 | struct rpc_message msg = { | 1312 | struct rpc_message msg = { |
1291 | .rpc_argp = &data->args, | 1313 | .rpc_argp = &data->args, |
1292 | .rpc_resp = &data->res, | 1314 | .rpc_resp = &data->res, |
1293 | .rpc_cred = first->wb_context->cred, | 1315 | .rpc_cred = data->cred, |
1294 | }; | 1316 | }; |
1295 | struct rpc_task_setup task_setup_data = { | 1317 | struct rpc_task_setup task_setup_data = { |
1296 | .task = &data->task, | 1318 | .task = &data->task, |
1297 | .rpc_client = NFS_CLIENT(inode), | 1319 | .rpc_client = clnt, |
1298 | .rpc_message = &msg, | 1320 | .rpc_message = &msg, |
1299 | .callback_ops = &nfs_commit_ops, | 1321 | .callback_ops = call_ops, |
1300 | .callback_data = data, | 1322 | .callback_data = data, |
1301 | .workqueue = nfsiod_workqueue, | 1323 | .workqueue = nfsiod_workqueue, |
1302 | .flags = RPC_TASK_ASYNC, | 1324 | .flags = RPC_TASK_ASYNC, |
1303 | .priority = priority, | 1325 | .priority = priority, |
1304 | }; | 1326 | }; |
1327 | /* Set up the initial task struct. */ | ||
1328 | NFS_PROTO(data->inode)->commit_setup(data, &msg); | ||
1329 | |||
1330 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | ||
1331 | |||
1332 | task = rpc_run_task(&task_setup_data); | ||
1333 | if (IS_ERR(task)) | ||
1334 | return PTR_ERR(task); | ||
1335 | if (how & FLUSH_SYNC) | ||
1336 | rpc_wait_for_completion_task(task); | ||
1337 | rpc_put_task(task); | ||
1338 | return 0; | ||
1339 | } | ||
1340 | EXPORT_SYMBOL_GPL(nfs_initiate_commit); | ||
1341 | |||
1342 | /* | ||
1343 | * Set up the argument/result storage required for the RPC call. | ||
1344 | */ | ||
1345 | void nfs_init_commit(struct nfs_write_data *data, | ||
1346 | struct list_head *head, | ||
1347 | struct pnfs_layout_segment *lseg) | ||
1348 | { | ||
1349 | struct nfs_page *first = nfs_list_entry(head->next); | ||
1350 | struct inode *inode = first->wb_context->path.dentry->d_inode; | ||
1305 | 1351 | ||
1306 | /* Set up the RPC argument and reply structs | 1352 | /* Set up the RPC argument and reply structs |
1307 | * NB: take care not to mess about with data->commit et al. */ | 1353 | * NB: take care not to mess about with data->commit et al. */ |
@@ -1309,7 +1355,9 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1309 | list_splice_init(head, &data->pages); | 1355 | list_splice_init(head, &data->pages); |
1310 | 1356 | ||
1311 | data->inode = inode; | 1357 | data->inode = inode; |
1312 | data->cred = msg.rpc_cred; | 1358 | data->cred = first->wb_context->cred; |
1359 | data->lseg = lseg; /* reference transferred */ | ||
1360 | data->mds_ops = &nfs_commit_ops; | ||
1313 | 1361 | ||
1314 | data->args.fh = NFS_FH(data->inode); | 1362 | data->args.fh = NFS_FH(data->inode); |
1315 | /* Note: we always request a commit of the entire inode */ | 1363 | /* Note: we always request a commit of the entire inode */ |
@@ -1320,20 +1368,25 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1320 | data->res.fattr = &data->fattr; | 1368 | data->res.fattr = &data->fattr; |
1321 | data->res.verf = &data->verf; | 1369 | data->res.verf = &data->verf; |
1322 | nfs_fattr_init(&data->fattr); | 1370 | nfs_fattr_init(&data->fattr); |
1371 | } | ||
1372 | EXPORT_SYMBOL_GPL(nfs_init_commit); | ||
1323 | 1373 | ||
1324 | /* Set up the initial task struct. */ | 1374 | void nfs_retry_commit(struct list_head *page_list, |
1325 | NFS_PROTO(inode)->commit_setup(data, &msg); | 1375 | struct pnfs_layout_segment *lseg) |
1326 | 1376 | { | |
1327 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | 1377 | struct nfs_page *req; |
1328 | 1378 | ||
1329 | task = rpc_run_task(&task_setup_data); | 1379 | while (!list_empty(page_list)) { |
1330 | if (IS_ERR(task)) | 1380 | req = nfs_list_entry(page_list->next); |
1331 | return PTR_ERR(task); | 1381 | nfs_list_remove_request(req); |
1332 | if (how & FLUSH_SYNC) | 1382 | nfs_mark_request_commit(req, lseg); |
1333 | rpc_wait_for_completion_task(task); | 1383 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
1334 | rpc_put_task(task); | 1384 | dec_bdi_stat(req->wb_page->mapping->backing_dev_info, |
1335 | return 0; | 1385 | BDI_RECLAIMABLE); |
1386 | nfs_clear_page_tag_locked(req); | ||
1387 | } | ||
1336 | } | 1388 | } |
1389 | EXPORT_SYMBOL_GPL(nfs_retry_commit); | ||
1337 | 1390 | ||
1338 | /* | 1391 | /* |
1339 | * Commit dirty pages | 1392 | * Commit dirty pages |
@@ -1342,7 +1395,6 @@ static int | |||
1342 | nfs_commit_list(struct inode *inode, struct list_head *head, int how) | 1395 | nfs_commit_list(struct inode *inode, struct list_head *head, int how) |
1343 | { | 1396 | { |
1344 | struct nfs_write_data *data; | 1397 | struct nfs_write_data *data; |
1345 | struct nfs_page *req; | ||
1346 | 1398 | ||
1347 | data = nfs_commitdata_alloc(); | 1399 | data = nfs_commitdata_alloc(); |
1348 | 1400 | ||
@@ -1350,17 +1402,10 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
1350 | goto out_bad; | 1402 | goto out_bad; |
1351 | 1403 | ||
1352 | /* Set up the argument struct */ | 1404 | /* Set up the argument struct */ |
1353 | return nfs_commit_rpcsetup(head, data, how); | 1405 | nfs_init_commit(data, head, NULL); |
1406 | return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); | ||
1354 | out_bad: | 1407 | out_bad: |
1355 | while (!list_empty(head)) { | 1408 | nfs_retry_commit(head, NULL); |
1356 | req = nfs_list_entry(head->next); | ||
1357 | nfs_list_remove_request(req); | ||
1358 | nfs_mark_request_commit(req); | ||
1359 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | ||
1360 | dec_bdi_stat(req->wb_page->mapping->backing_dev_info, | ||
1361 | BDI_RECLAIMABLE); | ||
1362 | nfs_clear_page_tag_locked(req); | ||
1363 | } | ||
1364 | nfs_commit_clear_lock(NFS_I(inode)); | 1409 | nfs_commit_clear_lock(NFS_I(inode)); |
1365 | return -ENOMEM; | 1410 | return -ENOMEM; |
1366 | } | 1411 | } |
@@ -1380,10 +1425,9 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
1380 | return; | 1425 | return; |
1381 | } | 1426 | } |
1382 | 1427 | ||
1383 | static void nfs_commit_release(void *calldata) | 1428 | void nfs_commit_release_pages(struct nfs_write_data *data) |
1384 | { | 1429 | { |
1385 | struct nfs_write_data *data = calldata; | 1430 | struct nfs_page *req; |
1386 | struct nfs_page *req; | ||
1387 | int status = data->task.tk_status; | 1431 | int status = data->task.tk_status; |
1388 | 1432 | ||
1389 | while (!list_empty(&data->pages)) { | 1433 | while (!list_empty(&data->pages)) { |
@@ -1417,6 +1461,14 @@ static void nfs_commit_release(void *calldata) | |||
1417 | next: | 1461 | next: |
1418 | nfs_clear_page_tag_locked(req); | 1462 | nfs_clear_page_tag_locked(req); |
1419 | } | 1463 | } |
1464 | } | ||
1465 | EXPORT_SYMBOL_GPL(nfs_commit_release_pages); | ||
1466 | |||
1467 | static void nfs_commit_release(void *calldata) | ||
1468 | { | ||
1469 | struct nfs_write_data *data = calldata; | ||
1470 | |||
1471 | nfs_commit_release_pages(data); | ||
1420 | nfs_commit_clear_lock(NFS_I(data->inode)); | 1472 | nfs_commit_clear_lock(NFS_I(data->inode)); |
1421 | nfs_commitdata_release(calldata); | 1473 | nfs_commitdata_release(calldata); |
1422 | } | 1474 | } |
@@ -1433,23 +1485,30 @@ int nfs_commit_inode(struct inode *inode, int how) | |||
1433 | { | 1485 | { |
1434 | LIST_HEAD(head); | 1486 | LIST_HEAD(head); |
1435 | int may_wait = how & FLUSH_SYNC; | 1487 | int may_wait = how & FLUSH_SYNC; |
1436 | int res = 0; | 1488 | int res; |
1437 | 1489 | ||
1438 | if (!nfs_commit_set_lock(NFS_I(inode), may_wait)) | 1490 | res = nfs_commit_set_lock(NFS_I(inode), may_wait); |
1491 | if (res <= 0) | ||
1439 | goto out_mark_dirty; | 1492 | goto out_mark_dirty; |
1440 | spin_lock(&inode->i_lock); | 1493 | spin_lock(&inode->i_lock); |
1441 | res = nfs_scan_commit(inode, &head, 0, 0); | 1494 | res = nfs_scan_commit(inode, &head, 0, 0); |
1442 | spin_unlock(&inode->i_lock); | 1495 | spin_unlock(&inode->i_lock); |
1443 | if (res) { | 1496 | if (res) { |
1444 | int error = nfs_commit_list(inode, &head, how); | 1497 | int error; |
1498 | |||
1499 | error = pnfs_commit_list(inode, &head, how); | ||
1500 | if (error == PNFS_NOT_ATTEMPTED) | ||
1501 | error = nfs_commit_list(inode, &head, how); | ||
1445 | if (error < 0) | 1502 | if (error < 0) |
1446 | return error; | 1503 | return error; |
1447 | if (may_wait) | 1504 | if (!may_wait) |
1448 | wait_on_bit(&NFS_I(inode)->flags, NFS_INO_COMMIT, | ||
1449 | nfs_wait_bit_killable, | ||
1450 | TASK_KILLABLE); | ||
1451 | else | ||
1452 | goto out_mark_dirty; | 1505 | goto out_mark_dirty; |
1506 | error = wait_on_bit(&NFS_I(inode)->flags, | ||
1507 | NFS_INO_COMMIT, | ||
1508 | nfs_wait_bit_killable, | ||
1509 | TASK_KILLABLE); | ||
1510 | if (error < 0) | ||
1511 | return error; | ||
1453 | } else | 1512 | } else |
1454 | nfs_commit_clear_lock(NFS_I(inode)); | 1513 | nfs_commit_clear_lock(NFS_I(inode)); |
1455 | return res; | 1514 | return res; |
@@ -1503,7 +1562,22 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr | |||
1503 | 1562 | ||
1504 | int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) | 1563 | int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) |
1505 | { | 1564 | { |
1506 | return nfs_commit_unstable_pages(inode, wbc); | 1565 | int ret; |
1566 | |||
1567 | ret = nfs_commit_unstable_pages(inode, wbc); | ||
1568 | if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { | ||
1569 | int status; | ||
1570 | bool sync = true; | ||
1571 | |||
1572 | if (wbc->sync_mode == WB_SYNC_NONE || wbc->nonblocking || | ||
1573 | wbc->for_background) | ||
1574 | sync = false; | ||
1575 | |||
1576 | status = pnfs_layoutcommit_inode(inode, sync); | ||
1577 | if (status < 0) | ||
1578 | return status; | ||
1579 | } | ||
1580 | return ret; | ||
1507 | } | 1581 | } |
1508 | 1582 | ||
1509 | /* | 1583 | /* |