Merge branch 'linux-next' of git://git.infradead.org/ubifs-2.6
* 'linux-next' of git://git.infradead.org/ubifs-2.6: UBIFS: fix corruption dump UBIFS: clean up free space checking UBIFS: small amendments in the LEB scanning code UBIFS: dump a little more in case of corruptions MAINTAINERS: update ahunter's e-mail address UBIFS: allow more than one volume to be mounted UBIFS: fix assertion warning UBIFS: minor spelling and grammar fixes UBIFS: fix 64-bit divisions in debug print UBIFS: few spelling fixes UBIFS: set write-buffer timout to 3-5 seconds UBIFS: slightly optimize write-buffer timer usage UBIFS: improve debugging messaged UBIFS: fix integer overflow warning
This commit is contained in:
@@ -5854,7 +5854,7 @@ UBI FILE SYSTEM (UBIFS)
|
|||||||
P: Artem Bityutskiy
|
P: Artem Bityutskiy
|
||||||
M: dedekind@infradead.org
|
M: dedekind@infradead.org
|
||||||
P: Adrian Hunter
|
P: Adrian Hunter
|
||||||
M: ext-adrian.hunter@nokia.com
|
M: adrian.hunter@nokia.com
|
||||||
L: linux-mtd@lists.infradead.org
|
L: linux-mtd@lists.infradead.org
|
||||||
T: git git://git.infradead.org/ubifs-2.6.git
|
T: git git://git.infradead.org/ubifs-2.6.git
|
||||||
W: http://www.linux-mtd.infradead.org/doc/ubifs.html
|
W: http://www.linux-mtd.infradead.org/doc/ubifs.html
|
||||||
|
@@ -297,6 +297,7 @@ static enum hrtimer_restart wbuf_timer_callback_nolock(struct hrtimer *timer)
|
|||||||
{
|
{
|
||||||
struct ubifs_wbuf *wbuf = container_of(timer, struct ubifs_wbuf, timer);
|
struct ubifs_wbuf *wbuf = container_of(timer, struct ubifs_wbuf, timer);
|
||||||
|
|
||||||
|
dbg_io("jhead %d", wbuf->jhead);
|
||||||
wbuf->need_sync = 1;
|
wbuf->need_sync = 1;
|
||||||
wbuf->c->need_wbuf_sync = 1;
|
wbuf->c->need_wbuf_sync = 1;
|
||||||
ubifs_wake_up_bgt(wbuf->c);
|
ubifs_wake_up_bgt(wbuf->c);
|
||||||
@@ -311,8 +312,12 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
|
|||||||
{
|
{
|
||||||
ubifs_assert(!hrtimer_active(&wbuf->timer));
|
ubifs_assert(!hrtimer_active(&wbuf->timer));
|
||||||
|
|
||||||
if (!ktime_to_ns(wbuf->softlimit))
|
if (wbuf->no_timer)
|
||||||
return;
|
return;
|
||||||
|
dbg_io("set timer for jhead %d, %llu-%llu millisecs", wbuf->jhead,
|
||||||
|
div_u64(ktime_to_ns(wbuf->softlimit), USEC_PER_SEC),
|
||||||
|
div_u64(ktime_to_ns(wbuf->softlimit) + wbuf->delta,
|
||||||
|
USEC_PER_SEC));
|
||||||
hrtimer_start_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta,
|
hrtimer_start_range_ns(&wbuf->timer, wbuf->softlimit, wbuf->delta,
|
||||||
HRTIMER_MODE_REL);
|
HRTIMER_MODE_REL);
|
||||||
}
|
}
|
||||||
@@ -323,11 +328,8 @@ static void new_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
|
|||||||
*/
|
*/
|
||||||
static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
|
static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)
|
||||||
{
|
{
|
||||||
/*
|
if (wbuf->no_timer)
|
||||||
* If the syncer is waiting for the lock (from the background thread's
|
return;
|
||||||
* context) and another task is changing write-buffer then the syncing
|
|
||||||
* should be canceled.
|
|
||||||
*/
|
|
||||||
wbuf->need_sync = 0;
|
wbuf->need_sync = 0;
|
||||||
hrtimer_cancel(&wbuf->timer);
|
hrtimer_cancel(&wbuf->timer);
|
||||||
}
|
}
|
||||||
@@ -349,8 +351,8 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
|
|||||||
/* Write-buffer is empty or not seeked */
|
/* Write-buffer is empty or not seeked */
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dbg_io("LEB %d:%d, %d bytes",
|
dbg_io("LEB %d:%d, %d bytes, jhead %d",
|
||||||
wbuf->lnum, wbuf->offs, wbuf->used);
|
wbuf->lnum, wbuf->offs, wbuf->used, wbuf->jhead);
|
||||||
ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
|
ubifs_assert(!(c->vfs_sb->s_flags & MS_RDONLY));
|
||||||
ubifs_assert(!(wbuf->avail & 7));
|
ubifs_assert(!(wbuf->avail & 7));
|
||||||
ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
|
ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size);
|
||||||
@@ -390,7 +392,7 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
|
|||||||
* @offs: logical eraseblock offset to seek to
|
* @offs: logical eraseblock offset to seek to
|
||||||
* @dtype: data type
|
* @dtype: data type
|
||||||
*
|
*
|
||||||
* This function targets the write buffer to logical eraseblock @lnum:@offs.
|
* This function targets the write-buffer to logical eraseblock @lnum:@offs.
|
||||||
* The write-buffer is synchronized if it is not empty. Returns zero in case of
|
* The write-buffer is synchronized if it is not empty. Returns zero in case of
|
||||||
* success and a negative error code in case of failure.
|
* success and a negative error code in case of failure.
|
||||||
*/
|
*/
|
||||||
@@ -399,7 +401,7 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
|
|||||||
{
|
{
|
||||||
const struct ubifs_info *c = wbuf->c;
|
const struct ubifs_info *c = wbuf->c;
|
||||||
|
|
||||||
dbg_io("LEB %d:%d", lnum, offs);
|
dbg_io("LEB %d:%d, jhead %d", lnum, offs, wbuf->jhead);
|
||||||
ubifs_assert(lnum >= 0 && lnum < c->leb_cnt);
|
ubifs_assert(lnum >= 0 && lnum < c->leb_cnt);
|
||||||
ubifs_assert(offs >= 0 && offs <= c->leb_size);
|
ubifs_assert(offs >= 0 && offs <= c->leb_size);
|
||||||
ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7));
|
ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7));
|
||||||
@@ -506,9 +508,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
|
|||||||
struct ubifs_info *c = wbuf->c;
|
struct ubifs_info *c = wbuf->c;
|
||||||
int err, written, n, aligned_len = ALIGN(len, 8), offs;
|
int err, written, n, aligned_len = ALIGN(len, 8), offs;
|
||||||
|
|
||||||
dbg_io("%d bytes (%s) to wbuf at LEB %d:%d", len,
|
dbg_io("%d bytes (%s) to jhead %d wbuf at LEB %d:%d", len,
|
||||||
dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->lnum,
|
dbg_ntype(((struct ubifs_ch *)buf)->node_type), wbuf->jhead,
|
||||||
wbuf->offs + wbuf->used);
|
wbuf->lnum, wbuf->offs + wbuf->used);
|
||||||
ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
|
ubifs_assert(len > 0 && wbuf->lnum >= 0 && wbuf->lnum < c->leb_cnt);
|
||||||
ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
|
ubifs_assert(wbuf->offs >= 0 && wbuf->offs % c->min_io_size == 0);
|
||||||
ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
|
ubifs_assert(!(wbuf->offs & 7) && wbuf->offs <= c->leb_size);
|
||||||
@@ -533,8 +535,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
|
|||||||
memcpy(wbuf->buf + wbuf->used, buf, len);
|
memcpy(wbuf->buf + wbuf->used, buf, len);
|
||||||
|
|
||||||
if (aligned_len == wbuf->avail) {
|
if (aligned_len == wbuf->avail) {
|
||||||
dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum,
|
dbg_io("flush jhead %d wbuf to LEB %d:%d",
|
||||||
wbuf->offs);
|
wbuf->jhead, wbuf->lnum, wbuf->offs);
|
||||||
err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
|
err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
|
||||||
wbuf->offs, c->min_io_size,
|
wbuf->offs, c->min_io_size,
|
||||||
wbuf->dtype);
|
wbuf->dtype);
|
||||||
@@ -562,7 +564,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
|
|||||||
* minimal I/O unit. We have to fill and flush write-buffer and switch
|
* minimal I/O unit. We have to fill and flush write-buffer and switch
|
||||||
* to the next min. I/O unit.
|
* to the next min. I/O unit.
|
||||||
*/
|
*/
|
||||||
dbg_io("flush wbuf to LEB %d:%d", wbuf->lnum, wbuf->offs);
|
dbg_io("flush jhead %d wbuf to LEB %d:%d",
|
||||||
|
wbuf->jhead, wbuf->lnum, wbuf->offs);
|
||||||
memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
|
memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
|
||||||
err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
|
err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
|
||||||
c->min_io_size, wbuf->dtype);
|
c->min_io_size, wbuf->dtype);
|
||||||
@@ -695,7 +698,8 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
|
|||||||
int err, rlen, overlap;
|
int err, rlen, overlap;
|
||||||
struct ubifs_ch *ch = buf;
|
struct ubifs_ch *ch = buf;
|
||||||
|
|
||||||
dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
|
dbg_io("LEB %d:%d, %s, length %d, jhead %d", lnum, offs,
|
||||||
|
dbg_ntype(type), len, wbuf->jhead);
|
||||||
ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
|
ubifs_assert(wbuf && lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
|
||||||
ubifs_assert(!(offs & 7) && offs < c->leb_size);
|
ubifs_assert(!(offs & 7) && offs < c->leb_size);
|
||||||
ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
|
ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
|
||||||
@@ -819,13 +823,12 @@ out:
|
|||||||
* @c: UBIFS file-system description object
|
* @c: UBIFS file-system description object
|
||||||
* @wbuf: write-buffer to initialize
|
* @wbuf: write-buffer to initialize
|
||||||
*
|
*
|
||||||
* This function initializes write buffer. Returns zero in case of success
|
* This function initializes write-buffer. Returns zero in case of success
|
||||||
* %-ENOMEM in case of failure.
|
* %-ENOMEM in case of failure.
|
||||||
*/
|
*/
|
||||||
int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
|
int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
|
||||||
{
|
{
|
||||||
size_t size;
|
size_t size;
|
||||||
ktime_t hardlimit;
|
|
||||||
|
|
||||||
wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL);
|
wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL);
|
||||||
if (!wbuf->buf)
|
if (!wbuf->buf)
|
||||||
@@ -851,22 +854,16 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)
|
|||||||
|
|
||||||
hrtimer_init(&wbuf->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
hrtimer_init(&wbuf->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||||
wbuf->timer.function = wbuf_timer_callback_nolock;
|
wbuf->timer.function = wbuf_timer_callback_nolock;
|
||||||
/*
|
wbuf->softlimit = ktime_set(WBUF_TIMEOUT_SOFTLIMIT, 0);
|
||||||
* Make write-buffer soft limit to be 20% of the hard limit. The
|
wbuf->delta = WBUF_TIMEOUT_HARDLIMIT - WBUF_TIMEOUT_SOFTLIMIT;
|
||||||
* write-buffer timer is allowed to expire any time between the soft
|
wbuf->delta *= 1000000000ULL;
|
||||||
* and hard limits.
|
ubifs_assert(wbuf->delta <= ULONG_MAX);
|
||||||
*/
|
|
||||||
hardlimit = ktime_set(DEFAULT_WBUF_TIMEOUT_SECS, 0);
|
|
||||||
wbuf->delta = (DEFAULT_WBUF_TIMEOUT_SECS * NSEC_PER_SEC) * 2 / 10;
|
|
||||||
wbuf->softlimit = ktime_sub_ns(hardlimit, wbuf->delta);
|
|
||||||
hrtimer_set_expires_range_ns(&wbuf->timer, wbuf->softlimit,
|
|
||||||
wbuf->delta);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array.
|
* ubifs_wbuf_add_ino_nolock - add an inode number into the wbuf inode array.
|
||||||
* @wbuf: the write-buffer whereto add
|
* @wbuf: the write-buffer where to add
|
||||||
* @inum: the inode number
|
* @inum: the inode number
|
||||||
*
|
*
|
||||||
* This function adds an inode number to the inode array of the write-buffer.
|
* This function adds an inode number to the inode array of the write-buffer.
|
||||||
|
@@ -52,6 +52,25 @@ static int is_empty(void *buf, int len)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* first_non_ff - find offset of the first non-0xff byte.
|
||||||
|
* @buf: buffer to search in
|
||||||
|
* @len: length of buffer
|
||||||
|
*
|
||||||
|
* This function returns offset of the first non-0xff byte in @buf or %-1 if
|
||||||
|
* the buffer contains only 0xff bytes.
|
||||||
|
*/
|
||||||
|
static int first_non_ff(void *buf, int len)
|
||||||
|
{
|
||||||
|
uint8_t *p = buf;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
if (*p++ != 0xff)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get_master_node - get the last valid master node allowing for corruption.
|
* get_master_node - get the last valid master node allowing for corruption.
|
||||||
* @c: UBIFS file-system description object
|
* @c: UBIFS file-system description object
|
||||||
@@ -357,11 +376,7 @@ static int is_last_write(const struct ubifs_info *c, void *buf, int offs)
|
|||||||
empty_offs = ALIGN(offs + 1, c->min_io_size);
|
empty_offs = ALIGN(offs + 1, c->min_io_size);
|
||||||
check_len = c->leb_size - empty_offs;
|
check_len = c->leb_size - empty_offs;
|
||||||
p = buf + empty_offs - offs;
|
p = buf + empty_offs - offs;
|
||||||
|
return is_empty(p, check_len);
|
||||||
for (; check_len > 0; check_len--)
|
|
||||||
if (*p++ != 0xff)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -543,8 +558,8 @@ static int drop_incomplete_group(struct ubifs_scan_leb *sleb, int *offs)
|
|||||||
*
|
*
|
||||||
* This function does a scan of a LEB, but caters for errors that might have
|
* This function does a scan of a LEB, but caters for errors that might have
|
||||||
* been caused by the unclean unmount from which we are attempting to recover.
|
* been caused by the unclean unmount from which we are attempting to recover.
|
||||||
*
|
* Returns %0 in case of success, %-EUCLEAN if an unrecoverable corruption is
|
||||||
* This function returns %0 on success and a negative error code on failure.
|
* found, and a negative error code in case of failure.
|
||||||
*/
|
*/
|
||||||
struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
|
struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
|
||||||
int offs, void *sbuf, int grouped)
|
int offs, void *sbuf, int grouped)
|
||||||
@@ -643,7 +658,8 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
|
|||||||
goto corrupted;
|
goto corrupted;
|
||||||
default:
|
default:
|
||||||
dbg_err("unknown");
|
dbg_err("unknown");
|
||||||
goto corrupted;
|
err = -EINVAL;
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -652,8 +668,13 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
|
|||||||
clean_buf(c, &buf, lnum, &offs, &len);
|
clean_buf(c, &buf, lnum, &offs, &len);
|
||||||
need_clean = 1;
|
need_clean = 1;
|
||||||
} else {
|
} else {
|
||||||
ubifs_err("corrupt empty space at LEB %d:%d",
|
int corruption = first_non_ff(buf, len);
|
||||||
lnum, offs);
|
|
||||||
|
ubifs_err("corrupt empty space LEB %d:%d, corruption "
|
||||||
|
"starts at %d", lnum, offs, corruption);
|
||||||
|
/* Make sure we dump interesting non-0xFF data */
|
||||||
|
offs = corruption;
|
||||||
|
buf += corruption;
|
||||||
goto corrupted;
|
goto corrupted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -813,7 +834,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
|
|||||||
static int recover_head(const struct ubifs_info *c, int lnum, int offs,
|
static int recover_head(const struct ubifs_info *c, int lnum, int offs,
|
||||||
void *sbuf)
|
void *sbuf)
|
||||||
{
|
{
|
||||||
int len, err, need_clean = 0;
|
int len, err;
|
||||||
|
|
||||||
if (c->min_io_size > 1)
|
if (c->min_io_size > 1)
|
||||||
len = c->min_io_size;
|
len = c->min_io_size;
|
||||||
@@ -827,19 +848,7 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs,
|
|||||||
|
|
||||||
/* Read at the head location and check it is empty flash */
|
/* Read at the head location and check it is empty flash */
|
||||||
err = ubi_read(c->ubi, lnum, sbuf, offs, len);
|
err = ubi_read(c->ubi, lnum, sbuf, offs, len);
|
||||||
if (err)
|
if (err || !is_empty(sbuf, len)) {
|
||||||
need_clean = 1;
|
|
||||||
else {
|
|
||||||
uint8_t *p = sbuf;
|
|
||||||
|
|
||||||
while (len--)
|
|
||||||
if (*p++ != 0xff) {
|
|
||||||
need_clean = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_clean) {
|
|
||||||
dbg_rcvry("cleaning head at %d:%d", lnum, offs);
|
dbg_rcvry("cleaning head at %d:%d", lnum, offs);
|
||||||
if (offs == 0)
|
if (offs == 0)
|
||||||
return ubifs_leb_unmap(c, lnum);
|
return ubifs_leb_unmap(c, lnum);
|
||||||
|
@@ -837,8 +837,9 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
|
|||||||
|
|
||||||
dbg_mnt("replay log LEB %d:%d", lnum, offs);
|
dbg_mnt("replay log LEB %d:%d", lnum, offs);
|
||||||
sleb = ubifs_scan(c, lnum, offs, sbuf);
|
sleb = ubifs_scan(c, lnum, offs, sbuf);
|
||||||
if (IS_ERR(sleb)) {
|
if (IS_ERR(sleb) ) {
|
||||||
if (c->need_recovery)
|
if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
|
||||||
|
return PTR_ERR(sleb);
|
||||||
sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
|
sleb = ubifs_recover_log_leb(c, lnum, offs, sbuf);
|
||||||
if (IS_ERR(sleb))
|
if (IS_ERR(sleb))
|
||||||
return PTR_ERR(sleb);
|
return PTR_ERR(sleb);
|
||||||
@@ -957,7 +958,7 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
out_dump:
|
out_dump:
|
||||||
ubifs_err("log error detected while replying the log at LEB %d:%d",
|
ubifs_err("log error detected while replaying the log at LEB %d:%d",
|
||||||
lnum, offs + snod->offs);
|
lnum, offs + snod->offs);
|
||||||
dbg_dump_node(c, snod->node);
|
dbg_dump_node(c, snod->node);
|
||||||
ubifs_scan_destroy(sleb);
|
ubifs_scan_destroy(sleb);
|
||||||
|
@@ -238,12 +238,12 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
|
|||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
ubifs_err("corrupted data at LEB %d:%d", lnum, offs);
|
ubifs_err("corruption at LEB %d:%d", lnum, offs);
|
||||||
if (dbg_failure_mode)
|
if (dbg_failure_mode)
|
||||||
return;
|
return;
|
||||||
len = c->leb_size - offs;
|
len = c->leb_size - offs;
|
||||||
if (len > 4096)
|
if (len > 8192)
|
||||||
len = 4096;
|
len = 8192;
|
||||||
dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs);
|
dbg_err("first %d bytes from LEB %d:%d", len, lnum, offs);
|
||||||
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
|
print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 4, buf, len, 1);
|
||||||
}
|
}
|
||||||
@@ -256,7 +256,9 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
|
|||||||
* @sbuf: scan buffer (must be c->leb_size)
|
* @sbuf: scan buffer (must be c->leb_size)
|
||||||
*
|
*
|
||||||
* This function scans LEB number @lnum and returns complete information about
|
* This function scans LEB number @lnum and returns complete information about
|
||||||
* its contents. Returns an error code in case of failure.
|
* its contents. Returns the scaned information in case of success and,
|
||||||
|
* %-EUCLEAN if the LEB neads recovery, and other negative error codes in case
|
||||||
|
* of failure.
|
||||||
*/
|
*/
|
||||||
struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
|
struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
|
||||||
int offs, void *sbuf)
|
int offs, void *sbuf)
|
||||||
@@ -279,7 +281,6 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
|
|||||||
cond_resched();
|
cond_resched();
|
||||||
|
|
||||||
ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
|
ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
|
||||||
|
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
/* Padding bytes or a valid padding node */
|
/* Padding bytes or a valid padding node */
|
||||||
offs += ret;
|
offs += ret;
|
||||||
@@ -304,7 +305,8 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
|
|||||||
goto corrupted;
|
goto corrupted;
|
||||||
default:
|
default:
|
||||||
dbg_err("unknown");
|
dbg_err("unknown");
|
||||||
goto corrupted;
|
err = -EINVAL;
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ubifs_add_snod(c, sleb, buf, offs);
|
err = ubifs_add_snod(c, sleb, buf, offs);
|
||||||
@@ -317,8 +319,10 @@ struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
|
|||||||
len -= node_len;
|
len -= node_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (offs % c->min_io_size)
|
if (offs % c->min_io_size) {
|
||||||
goto corrupted;
|
ubifs_err("empty space starts at non-aligned offset %d", offs);
|
||||||
|
goto corrupted;;
|
||||||
|
}
|
||||||
|
|
||||||
ubifs_end_scan(c, sleb, lnum, offs);
|
ubifs_end_scan(c, sleb, lnum, offs);
|
||||||
|
|
||||||
|
@@ -797,7 +797,7 @@ static int alloc_wbufs(struct ubifs_info *c)
|
|||||||
* does not need to be synchronized by timer.
|
* does not need to be synchronized by timer.
|
||||||
*/
|
*/
|
||||||
c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
|
c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
|
||||||
c->jheads[GCHD].wbuf.softlimit = ktime_set(0, 0);
|
c->jheads[GCHD].wbuf.no_timer = 1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -986,7 +986,7 @@ static int ubifs_parse_options(struct ubifs_info *c, char *options,
|
|||||||
switch (token) {
|
switch (token) {
|
||||||
/*
|
/*
|
||||||
* %Opt_fast_unmount and %Opt_norm_unmount options are ignored.
|
* %Opt_fast_unmount and %Opt_norm_unmount options are ignored.
|
||||||
* We accepte them in order to be backware-compatible. But this
|
* We accept them in order to be backward-compatible. But this
|
||||||
* should be removed at some point.
|
* should be removed at some point.
|
||||||
*/
|
*/
|
||||||
case Opt_fast_unmount:
|
case Opt_fast_unmount:
|
||||||
@@ -1287,6 +1287,9 @@ static int mount_ubifs(struct ubifs_info *c)
|
|||||||
if (err)
|
if (err)
|
||||||
goto out_journal;
|
goto out_journal;
|
||||||
|
|
||||||
|
/* Calculate 'min_idx_lebs' after journal replay */
|
||||||
|
c->min_idx_lebs = ubifs_calc_min_idx_lebs(c);
|
||||||
|
|
||||||
err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only);
|
err = ubifs_mount_orphans(c, c->need_recovery, mounted_read_only);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_orphans;
|
goto out_orphans;
|
||||||
@@ -1754,10 +1757,8 @@ static void ubifs_put_super(struct super_block *sb)
|
|||||||
|
|
||||||
/* Synchronize write-buffers */
|
/* Synchronize write-buffers */
|
||||||
if (c->jheads)
|
if (c->jheads)
|
||||||
for (i = 0; i < c->jhead_cnt; i++) {
|
for (i = 0; i < c->jhead_cnt; i++)
|
||||||
ubifs_wbuf_sync(&c->jheads[i].wbuf);
|
ubifs_wbuf_sync(&c->jheads[i].wbuf);
|
||||||
hrtimer_cancel(&c->jheads[i].wbuf.timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* On fatal errors c->ro_media is set to 1, in which case we do
|
* On fatal errors c->ro_media is set to 1, in which case we do
|
||||||
@@ -1975,7 +1976,8 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
|
|||||||
err = bdi_init(&c->bdi);
|
err = bdi_init(&c->bdi);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_close;
|
goto out_close;
|
||||||
err = bdi_register(&c->bdi, NULL, "ubifs");
|
err = bdi_register(&c->bdi, NULL, "ubifs_%d_%d",
|
||||||
|
c->vi.ubi_num, c->vi.vol_id);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_bdi;
|
goto out_bdi;
|
||||||
|
|
||||||
|
@@ -95,8 +95,9 @@
|
|||||||
*/
|
*/
|
||||||
#define BGT_NAME_PATTERN "ubifs_bgt%d_%d"
|
#define BGT_NAME_PATTERN "ubifs_bgt%d_%d"
|
||||||
|
|
||||||
/* Default write-buffer synchronization timeout in seconds */
|
/* Write-buffer synchronization timeout interval in seconds */
|
||||||
#define DEFAULT_WBUF_TIMEOUT_SECS 5
|
#define WBUF_TIMEOUT_SOFTLIMIT 3
|
||||||
|
#define WBUF_TIMEOUT_HARDLIMIT 5
|
||||||
|
|
||||||
/* Maximum possible inode number (only 32-bit inodes are supported now) */
|
/* Maximum possible inode number (only 32-bit inodes are supported now) */
|
||||||
#define MAX_INUM 0xFFFFFFFF
|
#define MAX_INUM 0xFFFFFFFF
|
||||||
@@ -654,7 +655,8 @@ typedef int (*ubifs_lpt_scan_callback)(struct ubifs_info *c,
|
|||||||
* @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit
|
* @delta: hard and soft timeouts delta (the timer expire inteval is @softlimit
|
||||||
* and @softlimit + @delta)
|
* and @softlimit + @delta)
|
||||||
* @timer: write-buffer timer
|
* @timer: write-buffer timer
|
||||||
* @need_sync: it is set if its timer expired and needs sync
|
* @no_timer: non-zero if this write-buffer does not have a timer
|
||||||
|
* @need_sync: non-zero if the timer expired and the wbuf needs sync'ing
|
||||||
* @next_ino: points to the next position of the following inode number
|
* @next_ino: points to the next position of the following inode number
|
||||||
* @inodes: stores the inode numbers of the nodes which are in wbuf
|
* @inodes: stores the inode numbers of the nodes which are in wbuf
|
||||||
*
|
*
|
||||||
@@ -683,7 +685,8 @@ struct ubifs_wbuf {
|
|||||||
ktime_t softlimit;
|
ktime_t softlimit;
|
||||||
unsigned long long delta;
|
unsigned long long delta;
|
||||||
struct hrtimer timer;
|
struct hrtimer timer;
|
||||||
int need_sync;
|
unsigned int no_timer:1;
|
||||||
|
unsigned int need_sync:1;
|
||||||
int next_ino;
|
int next_ino;
|
||||||
ino_t *inodes;
|
ino_t *inodes;
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user