diff options
Diffstat (limited to 'fs/ubifs')
-rw-r--r-- | fs/ubifs/file.c | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c index 6d34dc7e33e1..2e6481a7701c 100644 --- a/fs/ubifs/file.c +++ b/fs/ubifs/file.c | |||
@@ -21,34 +21,32 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * This file implements VFS file and inode operations of regular files, device | 24 | * This file implements VFS file and inode operations for regular files, device |
25 | * nodes and symlinks as well as address space operations. | 25 | * nodes and symlinks as well as address space operations. |
26 | * | 26 | * |
27 | * UBIFS uses 2 page flags: PG_private and PG_checked. PG_private is set if the | 27 | * UBIFS uses 2 page flags: @PG_private and @PG_checked. @PG_private is set if |
28 | * page is dirty and is used for budgeting purposes - dirty pages should not be | 28 | * the page is dirty and is used for optimization purposes - dirty pages are |
29 | * budgeted. The PG_checked flag is set if full budgeting is required for the | 29 | * not budgeted so the flag shows that 'ubifs_write_end()' should not release |
30 | * page e.g., when it corresponds to a file hole or it is just beyond the file | 30 | * the budget for this page. The @PG_checked flag is set if full budgeting is |
31 | * size. The budgeting is done in 'ubifs_write_begin()', because it is OK to | 31 | * required for the page e.g., when it corresponds to a file hole or it is |
32 | * fail in this function, and the budget is released in 'ubifs_write_end()'. So | 32 | * beyond the file size. The budgeting is done in 'ubifs_write_begin()', because |
33 | * the PG_private and PG_checked flags carry the information about how the page | 33 | * it is OK to fail in this function, and the budget is released in |
34 | * was budgeted, to make it possible to release the budget properly. | 34 | * 'ubifs_write_end()'. So the @PG_private and @PG_checked flags carry |
35 | * information about how the page was budgeted, to make it possible to release | ||
36 | * the budget properly. | ||
35 | * | 37 | * |
36 | * A thing to keep in mind: inode's 'i_mutex' is locked in most VFS operations | 38 | * A thing to keep in mind: inode @i_mutex is locked in most VFS operations we |
37 | * we implement. However, this is not true for '->writepage()', which might be | 39 | * implement. However, this is not true for 'ubifs_writepage()', which may be |
38 | * called with 'i_mutex' unlocked. For example, when pdflush is performing | 40 | * called with @i_mutex unlocked. For example, when pdflush is doing background |
39 | * write-back, it calls 'writepage()' with unlocked 'i_mutex', although the | 41 | * write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. At "normal" |
40 | * inode has 'I_LOCK' flag in this case. At "normal" work-paths 'i_mutex' is | 42 | * work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. in the |
41 | * locked in '->writepage', e.g. in "sys_write -> alloc_pages -> direct reclaim | 43 | * "sys_write -> alloc_pages -> direct reclaim path". So, in 'ubifs_writepage()' |
42 | * path'. So, in '->writepage()' we are only guaranteed that the page is | 44 | * we are only guaranteed that the page is locked. |
43 | * locked. | ||
44 | * | 45 | * |
45 | * Similarly, 'i_mutex' does not have to be locked in readpage(), e.g., | 46 | * Similarly, @i_mutex is not always locked in 'ubifs_readpage()', e.g., the |
46 | * readahead path does not have it locked ("sys_read -> generic_file_aio_read | 47 | * read-ahead path does not lock it ("sys_read -> generic_file_aio_read -> |
47 | * -> ondemand_readahead -> readpage"). In case of readahead, 'I_LOCK' flag is | 48 | * ondemand_readahead -> readpage"). In case of readahead, @I_LOCK flag is not |
48 | * not set as well. However, UBIFS disables readahead. | 49 | * set as well. However, UBIFS disables readahead. |
49 | * | ||
50 | * This, for example means that there might be 2 concurrent '->writepage()' | ||
51 | * calls for the same inode, but different inode dirty pages. | ||
52 | */ | 50 | */ |
53 | 51 | ||
54 | #include "ubifs.h" | 52 | #include "ubifs.h" |
@@ -449,9 +447,9 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, | |||
449 | /* | 447 | /* |
450 | * We change whole page so no need to load it. But we | 448 | * We change whole page so no need to load it. But we |
451 | * have to set the @PG_checked flag to make the further | 449 | * have to set the @PG_checked flag to make the further |
452 | * code the page is new. This might be not true, but it | 450 | * code know that the page is new. This might be not |
453 | * is better to budget more that to read the page from | 451 | * true, but it is better to budget more than to read |
454 | * the media. | 452 | * the page from the media. |
455 | */ | 453 | */ |
456 | SetPageChecked(page); | 454 | SetPageChecked(page); |
457 | skipped_read = 1; | 455 | skipped_read = 1; |
@@ -497,8 +495,8 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, | |||
497 | } | 495 | } |
498 | 496 | ||
499 | /* | 497 | /* |
500 | * Whee, we aquired budgeting quickly - without involving | 498 | * Whee, we acquired budgeting quickly - without involving |
501 | * garbage-collection, committing or forceing write-back. We return | 499 | * garbage-collection, committing or forcing write-back. We return |
502 | * with @ui->ui_mutex locked if we are appending pages, and unlocked | 500 | * with @ui->ui_mutex locked if we are appending pages, and unlocked |
503 | * otherwise. This is an optimization (slightly hacky though). | 501 | * otherwise. This is an optimization (slightly hacky though). |
504 | */ | 502 | */ |
@@ -562,7 +560,7 @@ static int ubifs_write_end(struct file *file, struct address_space *mapping, | |||
562 | 560 | ||
563 | /* | 561 | /* |
564 | * Return 0 to force VFS to repeat the whole operation, or the | 562 | * Return 0 to force VFS to repeat the whole operation, or the |
565 | * error code if 'do_readpage()' failes. | 563 | * error code if 'do_readpage()' fails. |
566 | */ | 564 | */ |
567 | copied = do_readpage(page); | 565 | copied = do_readpage(page); |
568 | goto out; | 566 | goto out; |
@@ -1175,11 +1173,11 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode, | |||
1175 | ui->ui_size = inode->i_size; | 1173 | ui->ui_size = inode->i_size; |
1176 | /* Truncation changes inode [mc]time */ | 1174 | /* Truncation changes inode [mc]time */ |
1177 | inode->i_mtime = inode->i_ctime = ubifs_current_time(inode); | 1175 | inode->i_mtime = inode->i_ctime = ubifs_current_time(inode); |
1178 | /* The other attributes may be changed at the same time as well */ | 1176 | /* Other attributes may be changed at the same time as well */ |
1179 | do_attr_changes(inode, attr); | 1177 | do_attr_changes(inode, attr); |
1180 | |||
1181 | err = ubifs_jnl_truncate(c, inode, old_size, new_size); | 1178 | err = ubifs_jnl_truncate(c, inode, old_size, new_size); |
1182 | mutex_unlock(&ui->ui_mutex); | 1179 | mutex_unlock(&ui->ui_mutex); |
1180 | |||
1183 | out_budg: | 1181 | out_budg: |
1184 | if (budgeted) | 1182 | if (budgeted) |
1185 | ubifs_release_budget(c, &req); | 1183 | ubifs_release_budget(c, &req); |