Skip to content

Commit b50b9f4

Browse files
Artem BityutskiyArtem Bityutskiy
Artem Bityutskiy
authored and
Artem Bityutskiy
committed
UBIFS: do not free write-buffers when in R/O mode
Currently UBIFS has a small optimization - it frees write-buffers when it is re-mounted from R/W mode to R/O mode. Of course, when it is mounted R/O, it does not allocate write-buffers as well. This optimization is nice but it leads to subtle problems and complications in recovery, which I can reproduce using the integck test. The symptoms are that after a power cut the file-system cannot be mounted if we first mount it R/O, and then re-mount R/W - 'ubifs_rcvry_gc_commit()' prints: UBIFS error (pid 34456): could not find an empty LEB Analysis of the problem. When mounting R/W, the reply process sets journal heads to buds [1], but when mounting R/O - it does not do this, because the write-buffers are not allocated. So 'ubifs_rcvry_gc_commit()' works completely differently for the same file-system but for the following 2 cases: 1. mounting R/W after a power cut and recover 2. mounting R/O after a power cut, re-mounting R/W and run deferred recovery In the former case, we have journal heads seeked to the a bud, in the latter case, they are non-seeked (wbuf->lnum == -1). So in the latter case we do not try to recover the GC LEB by garbage-collecting to the GC head, but we just try to find an empty LEB, and there may be no empty LEBs, so we just fail. On the other hand, in the former case (mount R/W), we are able to make a GC LEB (@c->gc_lnum) by garbage-collecting. Thus, let's remove this small nice optimization and always allocate write-buffers. This should not make too big difference - we have only 3 of them, each of max. write unit size, which is usually 2KiB. So this is about 6KiB of RAM for the typical case, and only when mounted R/O. [1]: Note, currently the replay process is setting (seeking) the journal heads to _some_ buds, not necessarily to the buds which had been the journal heads before the power cut happened. This will be fixed separately. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com> Cc: stable@kernel.org
1 parent 8e10cd7 commit b50b9f4

File tree

2 files changed

+4
-31
lines changed

2 files changed

+4
-31
lines changed

fs/ubifs/log.c

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -174,26 +174,6 @@ void ubifs_add_bud(struct ubifs_info *c, struct ubifs_bud *bud)
174174
spin_unlock(&c->buds_lock);
175175
}
176176

177-
/**
178-
* ubifs_create_buds_lists - create journal head buds lists for remount rw.
179-
* @c: UBIFS file-system description object
180-
*/
181-
void ubifs_create_buds_lists(struct ubifs_info *c)
182-
{
183-
struct rb_node *p;
184-
185-
spin_lock(&c->buds_lock);
186-
p = rb_first(&c->buds);
187-
while (p) {
188-
struct ubifs_bud *bud = rb_entry(p, struct ubifs_bud, rb);
189-
struct ubifs_jhead *jhead = &c->jheads[bud->jhead];
190-
191-
list_add_tail(&bud->list, &jhead->buds_list);
192-
p = rb_next(p);
193-
}
194-
spin_unlock(&c->buds_lock);
195-
}
196-
197177
/**
198178
* ubifs_add_bud_to_log - add a new bud to the log.
199179
* @c: UBIFS file-system description object

fs/ubifs/super.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,12 +1257,12 @@ static int mount_ubifs(struct ubifs_info *c)
12571257
goto out_free;
12581258
}
12591259

1260+
err = alloc_wbufs(c);
1261+
if (err)
1262+
goto out_cbuf;
1263+
12601264
sprintf(c->bgt_name, BGT_NAME_PATTERN, c->vi.ubi_num, c->vi.vol_id);
12611265
if (!c->ro_mount) {
1262-
err = alloc_wbufs(c);
1263-
if (err)
1264-
goto out_cbuf;
1265-
12661266
/* Create background thread */
12671267
c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
12681268
if (IS_ERR(c->bgt)) {
@@ -1631,12 +1631,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
16311631
if (err)
16321632
goto out;
16331633

1634-
err = alloc_wbufs(c);
1635-
if (err)
1636-
goto out;
1637-
1638-
ubifs_create_buds_lists(c);
1639-
16401634
/* Create background thread */
16411635
c->bgt = kthread_create(ubifs_bg_thread, c, "%s", c->bgt_name);
16421636
if (IS_ERR(c->bgt)) {
@@ -1744,7 +1738,6 @@ static void ubifs_remount_ro(struct ubifs_info *c)
17441738
if (err)
17451739
ubifs_ro_mode(c, err);
17461740

1747-
free_wbufs(c);
17481741
vfree(c->orph_buf);
17491742
c->orph_buf = NULL;
17501743
kfree(c->write_reserve_buf);

0 commit comments

Comments
 (0)