diff options
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r-- | fs/nfs/write.c | 233 |
1 files changed, 151 insertions, 82 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 47a3ad63e0d5..e4cbc11a74ab 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 | /* |
@@ -387,11 +389,8 @@ static int nfs_inode_add_request(struct inode *inode, struct nfs_page *req) | |||
387 | spin_lock(&inode->i_lock); | 389 | spin_lock(&inode->i_lock); |
388 | error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); | 390 | error = radix_tree_insert(&nfsi->nfs_page_tree, req->wb_index, req); |
389 | BUG_ON(error); | 391 | BUG_ON(error); |
390 | if (!nfsi->npages) { | 392 | if (!nfsi->npages && nfs_have_delegation(inode, FMODE_WRITE)) |
391 | igrab(inode); | 393 | nfsi->change_attr++; |
392 | if (nfs_have_delegation(inode, FMODE_WRITE)) | ||
393 | nfsi->change_attr++; | ||
394 | } | ||
395 | set_bit(PG_MAPPED, &req->wb_flags); | 394 | set_bit(PG_MAPPED, &req->wb_flags); |
396 | SetPagePrivate(req->wb_page); | 395 | SetPagePrivate(req->wb_page); |
397 | set_page_private(req->wb_page, (unsigned long)req); | 396 | set_page_private(req->wb_page, (unsigned long)req); |
@@ -421,11 +420,7 @@ static void nfs_inode_remove_request(struct nfs_page *req) | |||
421 | clear_bit(PG_MAPPED, &req->wb_flags); | 420 | clear_bit(PG_MAPPED, &req->wb_flags); |
422 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); | 421 | radix_tree_delete(&nfsi->nfs_page_tree, req->wb_index); |
423 | nfsi->npages--; | 422 | nfsi->npages--; |
424 | if (!nfsi->npages) { | 423 | spin_unlock(&inode->i_lock); |
425 | spin_unlock(&inode->i_lock); | ||
426 | iput(inode); | ||
427 | } else | ||
428 | spin_unlock(&inode->i_lock); | ||
429 | nfs_release_request(req); | 424 | nfs_release_request(req); |
430 | } | 425 | } |
431 | 426 | ||
@@ -441,7 +436,7 @@ nfs_mark_request_dirty(struct nfs_page *req) | |||
441 | * Add a request to the inode's commit list. | 436 | * Add a request to the inode's commit list. |
442 | */ | 437 | */ |
443 | static void | 438 | static void |
444 | nfs_mark_request_commit(struct nfs_page *req) | 439 | nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
445 | { | 440 | { |
446 | struct inode *inode = req->wb_context->path.dentry->d_inode; | 441 | struct inode *inode = req->wb_context->path.dentry->d_inode; |
447 | struct nfs_inode *nfsi = NFS_I(inode); | 442 | struct nfs_inode *nfsi = NFS_I(inode); |
@@ -453,6 +448,7 @@ nfs_mark_request_commit(struct nfs_page *req) | |||
453 | NFS_PAGE_TAG_COMMIT); | 448 | NFS_PAGE_TAG_COMMIT); |
454 | nfsi->ncommit++; | 449 | nfsi->ncommit++; |
455 | spin_unlock(&inode->i_lock); | 450 | spin_unlock(&inode->i_lock); |
451 | pnfs_mark_request_commit(req, lseg); | ||
456 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); | 452 | inc_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
457 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); | 453 | inc_bdi_stat(req->wb_page->mapping->backing_dev_info, BDI_RECLAIMABLE); |
458 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 454 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
@@ -474,14 +470,18 @@ nfs_clear_request_commit(struct nfs_page *req) | |||
474 | static inline | 470 | static inline |
475 | int nfs_write_need_commit(struct nfs_write_data *data) | 471 | int nfs_write_need_commit(struct nfs_write_data *data) |
476 | { | 472 | { |
477 | return data->verf.committed != NFS_FILE_SYNC; | 473 | if (data->verf.committed == NFS_DATA_SYNC) |
474 | return data->lseg == NULL; | ||
475 | else | ||
476 | return data->verf.committed != NFS_FILE_SYNC; | ||
478 | } | 477 | } |
479 | 478 | ||
480 | static inline | 479 | static inline |
481 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 480 | int nfs_reschedule_unstable_write(struct nfs_page *req, |
481 | struct nfs_write_data *data) | ||
482 | { | 482 | { |
483 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { | 483 | if (test_and_clear_bit(PG_NEED_COMMIT, &req->wb_flags)) { |
484 | nfs_mark_request_commit(req); | 484 | nfs_mark_request_commit(req, data->lseg); |
485 | return 1; | 485 | return 1; |
486 | } | 486 | } |
487 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { | 487 | if (test_and_clear_bit(PG_NEED_RESCHED, &req->wb_flags)) { |
@@ -492,7 +492,7 @@ int nfs_reschedule_unstable_write(struct nfs_page *req) | |||
492 | } | 492 | } |
493 | #else | 493 | #else |
494 | static inline void | 494 | static inline void |
495 | nfs_mark_request_commit(struct nfs_page *req) | 495 | nfs_mark_request_commit(struct nfs_page *req, struct pnfs_layout_segment *lseg) |
496 | { | 496 | { |
497 | } | 497 | } |
498 | 498 | ||
@@ -509,7 +509,8 @@ int nfs_write_need_commit(struct nfs_write_data *data) | |||
509 | } | 509 | } |
510 | 510 | ||
511 | static inline | 511 | static inline |
512 | int nfs_reschedule_unstable_write(struct nfs_page *req) | 512 | int nfs_reschedule_unstable_write(struct nfs_page *req, |
513 | struct nfs_write_data *data) | ||
513 | { | 514 | { |
514 | return 0; | 515 | return 0; |
515 | } | 516 | } |
@@ -541,11 +542,15 @@ nfs_scan_commit(struct inode *inode, struct list_head *dst, pgoff_t idx_start, u | |||
541 | if (!nfs_need_commit(nfsi)) | 542 | if (!nfs_need_commit(nfsi)) |
542 | return 0; | 543 | return 0; |
543 | 544 | ||
545 | spin_lock(&inode->i_lock); | ||
544 | ret = nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT); | 546 | ret = nfs_scan_list(nfsi, dst, idx_start, npages, NFS_PAGE_TAG_COMMIT); |
545 | if (ret > 0) | 547 | if (ret > 0) |
546 | nfsi->ncommit -= ret; | 548 | nfsi->ncommit -= ret; |
549 | spin_unlock(&inode->i_lock); | ||
550 | |||
547 | if (nfs_need_commit(NFS_I(inode))) | 551 | if (nfs_need_commit(NFS_I(inode))) |
548 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); | 552 | __mark_inode_dirty(inode, I_DIRTY_DATASYNC); |
553 | |||
549 | return ret; | 554 | return ret; |
550 | } | 555 | } |
551 | #else | 556 | #else |
@@ -612,9 +617,11 @@ static struct nfs_page *nfs_try_to_update_request(struct inode *inode, | |||
612 | } | 617 | } |
613 | 618 | ||
614 | if (nfs_clear_request_commit(req) && | 619 | if (nfs_clear_request_commit(req) && |
615 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, | 620 | radix_tree_tag_clear(&NFS_I(inode)->nfs_page_tree, |
616 | req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) | 621 | req->wb_index, NFS_PAGE_TAG_COMMIT) != NULL) { |
617 | NFS_I(inode)->ncommit--; | 622 | NFS_I(inode)->ncommit--; |
623 | pnfs_clear_request_commit(req); | ||
624 | } | ||
618 | 625 | ||
619 | /* Okay, the request matches. Update the region */ | 626 | /* Okay, the request matches. Update the region */ |
620 | if (offset < req->wb_offset) { | 627 | if (offset < req->wb_offset) { |
@@ -762,11 +769,12 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
762 | return status; | 769 | return status; |
763 | } | 770 | } |
764 | 771 | ||
765 | static void nfs_writepage_release(struct nfs_page *req) | 772 | static void nfs_writepage_release(struct nfs_page *req, |
773 | struct nfs_write_data *data) | ||
766 | { | 774 | { |
767 | struct page *page = req->wb_page; | 775 | struct page *page = req->wb_page; |
768 | 776 | ||
769 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req)) | 777 | if (PageError(req->wb_page) || !nfs_reschedule_unstable_write(req, data)) |
770 | nfs_inode_remove_request(req); | 778 | nfs_inode_remove_request(req); |
771 | nfs_clear_page_tag_locked(req); | 779 | nfs_clear_page_tag_locked(req); |
772 | nfs_end_page_writeback(page); | 780 | nfs_end_page_writeback(page); |
@@ -863,7 +871,7 @@ static int nfs_write_rpcsetup(struct nfs_page *req, | |||
863 | data->args.context = get_nfs_open_context(req->wb_context); | 871 | data->args.context = get_nfs_open_context(req->wb_context); |
864 | data->args.lock_context = req->wb_lock_context; | 872 | data->args.lock_context = req->wb_lock_context; |
865 | data->args.stable = NFS_UNSTABLE; | 873 | data->args.stable = NFS_UNSTABLE; |
866 | if (how & FLUSH_STABLE) { | 874 | if (how & (FLUSH_STABLE | FLUSH_COND_STABLE)) { |
867 | data->args.stable = NFS_DATA_SYNC; | 875 | data->args.stable = NFS_DATA_SYNC; |
868 | if (!nfs_need_commit(NFS_I(inode))) | 876 | if (!nfs_need_commit(NFS_I(inode))) |
869 | data->args.stable = NFS_FILE_SYNC; | 877 | data->args.stable = NFS_FILE_SYNC; |
@@ -912,6 +920,12 @@ static int nfs_flush_multi(struct nfs_pageio_descriptor *desc) | |||
912 | 920 | ||
913 | nfs_list_remove_request(req); | 921 | nfs_list_remove_request(req); |
914 | 922 | ||
923 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
924 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit || | ||
925 | desc->pg_count > wsize)) | ||
926 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
927 | |||
928 | |||
915 | nbytes = desc->pg_count; | 929 | nbytes = desc->pg_count; |
916 | do { | 930 | do { |
917 | size_t len = min(nbytes, wsize); | 931 | size_t len = min(nbytes, wsize); |
@@ -1002,6 +1016,10 @@ static int nfs_flush_one(struct nfs_pageio_descriptor *desc) | |||
1002 | if ((!lseg) && list_is_singular(&data->pages)) | 1016 | if ((!lseg) && list_is_singular(&data->pages)) |
1003 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); | 1017 | lseg = pnfs_update_layout(desc->pg_inode, req->wb_context, IOMODE_RW); |
1004 | 1018 | ||
1019 | if ((desc->pg_ioflags & FLUSH_COND_STABLE) && | ||
1020 | (desc->pg_moreio || NFS_I(desc->pg_inode)->ncommit)) | ||
1021 | desc->pg_ioflags &= ~FLUSH_COND_STABLE; | ||
1022 | |||
1005 | /* Set up the argument struct */ | 1023 | /* Set up the argument struct */ |
1006 | ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags); | 1024 | ret = nfs_write_rpcsetup(req, data, &nfs_write_full_ops, desc->pg_count, 0, lseg, desc->pg_ioflags); |
1007 | out: | 1025 | out: |
@@ -1074,7 +1092,7 @@ static void nfs_writeback_release_partial(void *calldata) | |||
1074 | 1092 | ||
1075 | out: | 1093 | out: |
1076 | if (atomic_dec_and_test(&req->wb_complete)) | 1094 | if (atomic_dec_and_test(&req->wb_complete)) |
1077 | nfs_writepage_release(req); | 1095 | nfs_writepage_release(req, data); |
1078 | nfs_writedata_release(calldata); | 1096 | nfs_writedata_release(calldata); |
1079 | } | 1097 | } |
1080 | 1098 | ||
@@ -1141,7 +1159,7 @@ static void nfs_writeback_release_full(void *calldata) | |||
1141 | 1159 | ||
1142 | if (nfs_write_need_commit(data)) { | 1160 | if (nfs_write_need_commit(data)) { |
1143 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); | 1161 | memcpy(&req->wb_verf, &data->verf, sizeof(req->wb_verf)); |
1144 | nfs_mark_request_commit(req); | 1162 | nfs_mark_request_commit(req, data->lseg); |
1145 | dprintk(" marked for commit\n"); | 1163 | dprintk(" marked for commit\n"); |
1146 | goto next; | 1164 | goto next; |
1147 | } | 1165 | } |
@@ -1251,57 +1269,82 @@ void nfs_writeback_done(struct rpc_task *task, struct nfs_write_data *data) | |||
1251 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) | 1269 | #if defined(CONFIG_NFS_V3) || defined(CONFIG_NFS_V4) |
1252 | static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) | 1270 | static int nfs_commit_set_lock(struct nfs_inode *nfsi, int may_wait) |
1253 | { | 1271 | { |
1272 | int ret; | ||
1273 | |||
1254 | if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) | 1274 | if (!test_and_set_bit(NFS_INO_COMMIT, &nfsi->flags)) |
1255 | return 1; | 1275 | return 1; |
1256 | if (may_wait && !out_of_line_wait_on_bit_lock(&nfsi->flags, | 1276 | if (!may_wait) |
1257 | NFS_INO_COMMIT, nfs_wait_bit_killable, | 1277 | return 0; |
1258 | TASK_KILLABLE)) | 1278 | ret = out_of_line_wait_on_bit_lock(&nfsi->flags, |
1259 | return 1; | 1279 | NFS_INO_COMMIT, |
1260 | return 0; | 1280 | nfs_wait_bit_killable, |
1281 | TASK_KILLABLE); | ||
1282 | return (ret < 0) ? ret : 1; | ||
1261 | } | 1283 | } |
1262 | 1284 | ||
1263 | static void nfs_commit_clear_lock(struct nfs_inode *nfsi) | 1285 | void nfs_commit_clear_lock(struct nfs_inode *nfsi) |
1264 | { | 1286 | { |
1265 | clear_bit(NFS_INO_COMMIT, &nfsi->flags); | 1287 | clear_bit(NFS_INO_COMMIT, &nfsi->flags); |
1266 | smp_mb__after_clear_bit(); | 1288 | smp_mb__after_clear_bit(); |
1267 | wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); | 1289 | wake_up_bit(&nfsi->flags, NFS_INO_COMMIT); |
1268 | } | 1290 | } |
1291 | EXPORT_SYMBOL_GPL(nfs_commit_clear_lock); | ||
1269 | 1292 | ||
1270 | 1293 | void nfs_commitdata_release(void *data) | |
1271 | static void nfs_commitdata_release(void *data) | ||
1272 | { | 1294 | { |
1273 | struct nfs_write_data *wdata = data; | 1295 | struct nfs_write_data *wdata = data; |
1274 | 1296 | ||
1297 | put_lseg(wdata->lseg); | ||
1275 | put_nfs_open_context(wdata->args.context); | 1298 | put_nfs_open_context(wdata->args.context); |
1276 | nfs_commit_free(wdata); | 1299 | nfs_commit_free(wdata); |
1277 | } | 1300 | } |
1301 | EXPORT_SYMBOL_GPL(nfs_commitdata_release); | ||
1278 | 1302 | ||
1279 | /* | 1303 | 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. | 1304 | const struct rpc_call_ops *call_ops, |
1281 | */ | 1305 | int how) |
1282 | static int nfs_commit_rpcsetup(struct list_head *head, | ||
1283 | struct nfs_write_data *data, | ||
1284 | int how) | ||
1285 | { | 1306 | { |
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; | 1307 | struct rpc_task *task; |
1308 | int priority = flush_task_priority(how); | ||
1290 | struct rpc_message msg = { | 1309 | struct rpc_message msg = { |
1291 | .rpc_argp = &data->args, | 1310 | .rpc_argp = &data->args, |
1292 | .rpc_resp = &data->res, | 1311 | .rpc_resp = &data->res, |
1293 | .rpc_cred = first->wb_context->cred, | 1312 | .rpc_cred = data->cred, |
1294 | }; | 1313 | }; |
1295 | struct rpc_task_setup task_setup_data = { | 1314 | struct rpc_task_setup task_setup_data = { |
1296 | .task = &data->task, | 1315 | .task = &data->task, |
1297 | .rpc_client = NFS_CLIENT(inode), | 1316 | .rpc_client = clnt, |
1298 | .rpc_message = &msg, | 1317 | .rpc_message = &msg, |
1299 | .callback_ops = &nfs_commit_ops, | 1318 | .callback_ops = call_ops, |
1300 | .callback_data = data, | 1319 | .callback_data = data, |
1301 | .workqueue = nfsiod_workqueue, | 1320 | .workqueue = nfsiod_workqueue, |
1302 | .flags = RPC_TASK_ASYNC, | 1321 | .flags = RPC_TASK_ASYNC, |
1303 | .priority = priority, | 1322 | .priority = priority, |
1304 | }; | 1323 | }; |
1324 | /* Set up the initial task struct. */ | ||
1325 | NFS_PROTO(data->inode)->commit_setup(data, &msg); | ||
1326 | |||
1327 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | ||
1328 | |||
1329 | task = rpc_run_task(&task_setup_data); | ||
1330 | if (IS_ERR(task)) | ||
1331 | return PTR_ERR(task); | ||
1332 | if (how & FLUSH_SYNC) | ||
1333 | rpc_wait_for_completion_task(task); | ||
1334 | rpc_put_task(task); | ||
1335 | return 0; | ||
1336 | } | ||
1337 | EXPORT_SYMBOL_GPL(nfs_initiate_commit); | ||
1338 | |||
1339 | /* | ||
1340 | * Set up the argument/result storage required for the RPC call. | ||
1341 | */ | ||
1342 | void nfs_init_commit(struct nfs_write_data *data, | ||
1343 | struct list_head *head, | ||
1344 | struct pnfs_layout_segment *lseg) | ||
1345 | { | ||
1346 | struct nfs_page *first = nfs_list_entry(head->next); | ||
1347 | struct inode *inode = first->wb_context->path.dentry->d_inode; | ||
1305 | 1348 | ||
1306 | /* Set up the RPC argument and reply structs | 1349 | /* Set up the RPC argument and reply structs |
1307 | * NB: take care not to mess about with data->commit et al. */ | 1350 | * NB: take care not to mess about with data->commit et al. */ |
@@ -1309,7 +1352,9 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1309 | list_splice_init(head, &data->pages); | 1352 | list_splice_init(head, &data->pages); |
1310 | 1353 | ||
1311 | data->inode = inode; | 1354 | data->inode = inode; |
1312 | data->cred = msg.rpc_cred; | 1355 | data->cred = first->wb_context->cred; |
1356 | data->lseg = lseg; /* reference transferred */ | ||
1357 | data->mds_ops = &nfs_commit_ops; | ||
1313 | 1358 | ||
1314 | data->args.fh = NFS_FH(data->inode); | 1359 | data->args.fh = NFS_FH(data->inode); |
1315 | /* Note: we always request a commit of the entire inode */ | 1360 | /* Note: we always request a commit of the entire inode */ |
@@ -1320,20 +1365,25 @@ static int nfs_commit_rpcsetup(struct list_head *head, | |||
1320 | data->res.fattr = &data->fattr; | 1365 | data->res.fattr = &data->fattr; |
1321 | data->res.verf = &data->verf; | 1366 | data->res.verf = &data->verf; |
1322 | nfs_fattr_init(&data->fattr); | 1367 | nfs_fattr_init(&data->fattr); |
1368 | } | ||
1369 | EXPORT_SYMBOL_GPL(nfs_init_commit); | ||
1323 | 1370 | ||
1324 | /* Set up the initial task struct. */ | 1371 | void nfs_retry_commit(struct list_head *page_list, |
1325 | NFS_PROTO(inode)->commit_setup(data, &msg); | 1372 | struct pnfs_layout_segment *lseg) |
1326 | 1373 | { | |
1327 | dprintk("NFS: %5u initiated commit call\n", data->task.tk_pid); | 1374 | struct nfs_page *req; |
1328 | 1375 | ||
1329 | task = rpc_run_task(&task_setup_data); | 1376 | while (!list_empty(page_list)) { |
1330 | if (IS_ERR(task)) | 1377 | req = nfs_list_entry(page_list->next); |
1331 | return PTR_ERR(task); | 1378 | nfs_list_remove_request(req); |
1332 | if (how & FLUSH_SYNC) | 1379 | nfs_mark_request_commit(req, lseg); |
1333 | rpc_wait_for_completion_task(task); | 1380 | dec_zone_page_state(req->wb_page, NR_UNSTABLE_NFS); |
1334 | rpc_put_task(task); | 1381 | dec_bdi_stat(req->wb_page->mapping->backing_dev_info, |
1335 | return 0; | 1382 | BDI_RECLAIMABLE); |
1383 | nfs_clear_page_tag_locked(req); | ||
1384 | } | ||
1336 | } | 1385 | } |
1386 | EXPORT_SYMBOL_GPL(nfs_retry_commit); | ||
1337 | 1387 | ||
1338 | /* | 1388 | /* |
1339 | * Commit dirty pages | 1389 | * Commit dirty pages |
@@ -1342,7 +1392,6 @@ static int | |||
1342 | nfs_commit_list(struct inode *inode, struct list_head *head, int how) | 1392 | nfs_commit_list(struct inode *inode, struct list_head *head, int how) |
1343 | { | 1393 | { |
1344 | struct nfs_write_data *data; | 1394 | struct nfs_write_data *data; |
1345 | struct nfs_page *req; | ||
1346 | 1395 | ||
1347 | data = nfs_commitdata_alloc(); | 1396 | data = nfs_commitdata_alloc(); |
1348 | 1397 | ||
@@ -1350,17 +1399,10 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how) | |||
1350 | goto out_bad; | 1399 | goto out_bad; |
1351 | 1400 | ||
1352 | /* Set up the argument struct */ | 1401 | /* Set up the argument struct */ |
1353 | return nfs_commit_rpcsetup(head, data, how); | 1402 | nfs_init_commit(data, head, NULL); |
1403 | return nfs_initiate_commit(data, NFS_CLIENT(inode), data->mds_ops, how); | ||
1354 | out_bad: | 1404 | out_bad: |
1355 | while (!list_empty(head)) { | 1405 | 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)); | 1406 | nfs_commit_clear_lock(NFS_I(inode)); |
1365 | return -ENOMEM; | 1407 | return -ENOMEM; |
1366 | } | 1408 | } |
@@ -1380,10 +1422,9 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata) | |||
1380 | return; | 1422 | return; |
1381 | } | 1423 | } |
1382 | 1424 | ||
1383 | static void nfs_commit_release(void *calldata) | 1425 | void nfs_commit_release_pages(struct nfs_write_data *data) |
1384 | { | 1426 | { |
1385 | struct nfs_write_data *data = calldata; | 1427 | struct nfs_page *req; |
1386 | struct nfs_page *req; | ||
1387 | int status = data->task.tk_status; | 1428 | int status = data->task.tk_status; |
1388 | 1429 | ||
1389 | while (!list_empty(&data->pages)) { | 1430 | while (!list_empty(&data->pages)) { |
@@ -1417,6 +1458,14 @@ static void nfs_commit_release(void *calldata) | |||
1417 | next: | 1458 | next: |
1418 | nfs_clear_page_tag_locked(req); | 1459 | nfs_clear_page_tag_locked(req); |
1419 | } | 1460 | } |
1461 | } | ||
1462 | EXPORT_SYMBOL_GPL(nfs_commit_release_pages); | ||
1463 | |||
1464 | static void nfs_commit_release(void *calldata) | ||
1465 | { | ||
1466 | struct nfs_write_data *data = calldata; | ||
1467 | |||
1468 | nfs_commit_release_pages(data); | ||
1420 | nfs_commit_clear_lock(NFS_I(data->inode)); | 1469 | nfs_commit_clear_lock(NFS_I(data->inode)); |
1421 | nfs_commitdata_release(calldata); | 1470 | nfs_commitdata_release(calldata); |
1422 | } | 1471 | } |
@@ -1433,23 +1482,28 @@ int nfs_commit_inode(struct inode *inode, int how) | |||
1433 | { | 1482 | { |
1434 | LIST_HEAD(head); | 1483 | LIST_HEAD(head); |
1435 | int may_wait = how & FLUSH_SYNC; | 1484 | int may_wait = how & FLUSH_SYNC; |
1436 | int res = 0; | 1485 | int res; |
1437 | 1486 | ||
1438 | if (!nfs_commit_set_lock(NFS_I(inode), may_wait)) | 1487 | res = nfs_commit_set_lock(NFS_I(inode), may_wait); |
1488 | if (res <= 0) | ||
1439 | goto out_mark_dirty; | 1489 | goto out_mark_dirty; |
1440 | spin_lock(&inode->i_lock); | ||
1441 | res = nfs_scan_commit(inode, &head, 0, 0); | 1490 | res = nfs_scan_commit(inode, &head, 0, 0); |
1442 | spin_unlock(&inode->i_lock); | ||
1443 | if (res) { | 1491 | if (res) { |
1444 | int error = nfs_commit_list(inode, &head, how); | 1492 | int error; |
1493 | |||
1494 | error = pnfs_commit_list(inode, &head, how); | ||
1495 | if (error == PNFS_NOT_ATTEMPTED) | ||
1496 | error = nfs_commit_list(inode, &head, how); | ||
1445 | if (error < 0) | 1497 | if (error < 0) |
1446 | return error; | 1498 | return error; |
1447 | if (may_wait) | 1499 | 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; | 1500 | goto out_mark_dirty; |
1501 | error = wait_on_bit(&NFS_I(inode)->flags, | ||
1502 | NFS_INO_COMMIT, | ||
1503 | nfs_wait_bit_killable, | ||
1504 | TASK_KILLABLE); | ||
1505 | if (error < 0) | ||
1506 | return error; | ||
1453 | } else | 1507 | } else |
1454 | nfs_commit_clear_lock(NFS_I(inode)); | 1508 | nfs_commit_clear_lock(NFS_I(inode)); |
1455 | return res; | 1509 | return res; |
@@ -1503,7 +1557,22 @@ static int nfs_commit_unstable_pages(struct inode *inode, struct writeback_contr | |||
1503 | 1557 | ||
1504 | int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) | 1558 | int nfs_write_inode(struct inode *inode, struct writeback_control *wbc) |
1505 | { | 1559 | { |
1506 | return nfs_commit_unstable_pages(inode, wbc); | 1560 | int ret; |
1561 | |||
1562 | ret = nfs_commit_unstable_pages(inode, wbc); | ||
1563 | if (ret >= 0 && test_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags)) { | ||
1564 | int status; | ||
1565 | bool sync = true; | ||
1566 | |||
1567 | if (wbc->sync_mode == WB_SYNC_NONE || wbc->nonblocking || | ||
1568 | wbc->for_background) | ||
1569 | sync = false; | ||
1570 | |||
1571 | status = pnfs_layoutcommit_inode(inode, sync); | ||
1572 | if (status < 0) | ||
1573 | return status; | ||
1574 | } | ||
1575 | return ret; | ||
1507 | } | 1576 | } |
1508 | 1577 | ||
1509 | /* | 1578 | /* |