diff options
Diffstat (limited to 'fs/ubifs/commit.c')
| -rw-r--r-- | fs/ubifs/commit.c | 60 |
1 files changed, 58 insertions, 2 deletions
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c index 02429d81ca33..1bd01ded7123 100644 --- a/fs/ubifs/commit.c +++ b/fs/ubifs/commit.c | |||
| @@ -48,6 +48,56 @@ | |||
| 48 | #include <linux/slab.h> | 48 | #include <linux/slab.h> |
| 49 | #include "ubifs.h" | 49 | #include "ubifs.h" |
| 50 | 50 | ||
| 51 | /* | ||
| 52 | * nothing_to_commit - check if there is nothing to commit. | ||
| 53 | * @c: UBIFS file-system description object | ||
| 54 | * | ||
| 55 | * This is a helper function which checks if there is anything to commit. It is | ||
| 56 | * used as an optimization to avoid starting the commit if it is not really | ||
| 57 | * necessary. Indeed, the commit operation always assumes flash I/O (e.g., | ||
| 58 | * writing the commit start node to the log), and it is better to avoid doing | ||
| 59 | * this unnecessarily. E.g., 'ubifs_sync_fs()' runs the commit, but if there is | ||
| 60 | * nothing to commit, it is more optimal to avoid any flash I/O. | ||
| 61 | * | ||
| 62 | * This function has to be called with @c->commit_sem locked for writing - | ||
| 63 | * this function does not take LPT/TNC locks because the @c->commit_sem | ||
| 64 | * guarantees that we have exclusive access to the TNC and LPT data structures. | ||
| 65 | * | ||
| 66 | * This function returns %1 if there is nothing to commit and %0 otherwise. | ||
| 67 | */ | ||
| 68 | static int nothing_to_commit(struct ubifs_info *c) | ||
| 69 | { | ||
| 70 | /* | ||
| 71 | * During mounting or remounting from R/O mode to R/W mode we may | ||
| 72 | * commit for various recovery-related reasons. | ||
| 73 | */ | ||
| 74 | if (c->mounting || c->remounting_rw) | ||
| 75 | return 0; | ||
| 76 | |||
| 77 | /* | ||
| 78 | * If the root TNC node is dirty, we definitely have something to | ||
| 79 | * commit. | ||
| 80 | */ | ||
| 81 | if (c->zroot.znode && test_bit(DIRTY_ZNODE, &c->zroot.znode->flags)) | ||
| 82 | return 0; | ||
| 83 | |||
| 84 | /* | ||
| 85 | * Even though the TNC is clean, the LPT tree may have dirty nodes. For | ||
| 86 | * example, this may happen if the budgeting subsystem invoked GC to | ||
| 87 | * make some free space, and the GC found an LEB with only dirty and | ||
| 88 | * free space. In this case GC would just change the lprops of this | ||
| 89 | * LEB (by turning all space into free space) and unmap it. | ||
| 90 | */ | ||
| 91 | if (c->nroot && test_bit(DIRTY_CNODE, &c->nroot->flags)) | ||
| 92 | return 0; | ||
| 93 | |||
| 94 | ubifs_assert(atomic_long_read(&c->dirty_zn_cnt) == 0); | ||
| 95 | ubifs_assert(c->dirty_pn_cnt == 0); | ||
| 96 | ubifs_assert(c->dirty_nn_cnt == 0); | ||
| 97 | |||
| 98 | return 1; | ||
| 99 | } | ||
| 100 | |||
| 51 | /** | 101 | /** |
| 52 | * do_commit - commit the journal. | 102 | * do_commit - commit the journal. |
| 53 | * @c: UBIFS file-system description object | 103 | * @c: UBIFS file-system description object |
| @@ -70,6 +120,12 @@ static int do_commit(struct ubifs_info *c) | |||
| 70 | goto out_up; | 120 | goto out_up; |
| 71 | } | 121 | } |
| 72 | 122 | ||
| 123 | if (nothing_to_commit(c)) { | ||
| 124 | up_write(&c->commit_sem); | ||
| 125 | err = 0; | ||
| 126 | goto out_cancel; | ||
| 127 | } | ||
| 128 | |||
| 73 | /* Sync all write buffers (necessary for recovery) */ | 129 | /* Sync all write buffers (necessary for recovery) */ |
| 74 | for (i = 0; i < c->jhead_cnt; i++) { | 130 | for (i = 0; i < c->jhead_cnt; i++) { |
| 75 | err = ubifs_wbuf_sync(&c->jheads[i].wbuf); | 131 | err = ubifs_wbuf_sync(&c->jheads[i].wbuf); |
| @@ -162,12 +218,12 @@ static int do_commit(struct ubifs_info *c) | |||
| 162 | if (err) | 218 | if (err) |
| 163 | goto out; | 219 | goto out; |
| 164 | 220 | ||
| 221 | out_cancel: | ||
| 165 | spin_lock(&c->cs_lock); | 222 | spin_lock(&c->cs_lock); |
| 166 | c->cmt_state = COMMIT_RESTING; | 223 | c->cmt_state = COMMIT_RESTING; |
| 167 | wake_up(&c->cmt_wq); | 224 | wake_up(&c->cmt_wq); |
| 168 | dbg_cmt("commit end"); | 225 | dbg_cmt("commit end"); |
| 169 | spin_unlock(&c->cs_lock); | 226 | spin_unlock(&c->cs_lock); |
| 170 | |||
| 171 | return 0; | 227 | return 0; |
| 172 | 228 | ||
| 173 | out_up: | 229 | out_up: |
| @@ -521,7 +577,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot) | |||
| 521 | size_t sz; | 577 | size_t sz; |
| 522 | 578 | ||
| 523 | if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX)) | 579 | if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX)) |
| 524 | goto out; | 580 | return 0; |
| 525 | 581 | ||
| 526 | INIT_LIST_HEAD(&list); | 582 | INIT_LIST_HEAD(&list); |
| 527 | 583 | ||
