diff options
Diffstat (limited to 'fs/ubifs/io.c')
| -rw-r--r-- | fs/ubifs/io.c | 418 | 
1 files changed, 308 insertions, 110 deletions
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c index d82173182ee..2290d586672 100644 --- a/fs/ubifs/io.c +++ b/fs/ubifs/io.c @@ -31,6 +31,26 @@   * buffer is full or when it is not used for some time (by timer). This is   * similar to the mechanism is used by JFFS2.   * + * UBIFS distinguishes between minimum write size (@c->min_io_size) and maximum + * write size (@c->max_write_size). The latter is the maximum amount of bytes + * the underlying flash is able to program at a time, and writing in + * @c->max_write_size units should presumably be faster. Obviously, + * @c->min_io_size <= @c->max_write_size. Write-buffers are of + * @c->max_write_size bytes in size for maximum performance. However, when a + * write-buffer is flushed, only the portion of it (aligned to @c->min_io_size + * boundary) which contains data is written, not the whole write-buffer, + * because this is more space-efficient. + * + * This optimization adds few complications to the code. Indeed, on the one + * hand, we want to write in optimal @c->max_write_size bytes chunks, which + * also means aligning writes at the @c->max_write_size bytes offsets. On the + * other hand, we do not want to waste space when synchronizing the write + * buffer, so during synchronization we writes in smaller chunks. And this makes + * the next write offset to be not aligned to @c->max_write_size bytes. So the + * have to make sure that the write-buffer offset (@wbuf->offs) becomes aligned + * to @c->max_write_size bytes again. We do this by temporarily shrinking + * write-buffer size (@wbuf->size). + *   * Write-buffers are defined by 'struct ubifs_wbuf' objects and protected by   * mutexes defined inside these objects. Since sometimes upper-level code   * has to lock the write-buffer (e.g. journal space reservation code), many @@ -46,8 +66,8 @@   * UBIFS uses padding when it pads to the next min. I/O unit. In this case it   * uses padding nodes or padding bytes, if the padding node does not fit.   * - * All UBIFS nodes are protected by CRC checksums and UBIFS checks all nodes - * every time they are read from the flash media. + * All UBIFS nodes are protected by CRC checksums and UBIFS checks CRC when + * they are read from the flash media.   */  #include <linux/crc32.h> @@ -66,8 +86,124 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)  		c->no_chk_data_crc = 0;  		c->vfs_sb->s_flags |= MS_RDONLY;  		ubifs_warn("switched to read-only mode, error %d", err); -		dbg_dump_stack(); +		dump_stack(); +	} +} + +/* + * Below are simple wrappers over UBI I/O functions which include some + * additional checks and UBIFS debugging stuff. See corresponding UBI function + * for more information. + */ + +int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs, +		   int len, int even_ebadmsg) +{ +	int err; + +	err = ubi_read(c->ubi, lnum, buf, offs, len); +	/* +	 * In case of %-EBADMSG print the error message only if the +	 * @even_ebadmsg is true. +	 */ +	if (err && (err != -EBADMSG || even_ebadmsg)) { +		ubifs_err("reading %d bytes from LEB %d:%d failed, error %d", +			  len, lnum, offs, err); +		dump_stack(); +	} +	return err; +} + +int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs, +		    int len) +{ +	int err; + +	ubifs_assert(!c->ro_media && !c->ro_mount); +	if (c->ro_error) +		return -EROFS; +	if (!dbg_is_tst_rcvry(c)) +		err = ubi_leb_write(c->ubi, lnum, buf, offs, len); +	else +		err = dbg_leb_write(c, lnum, buf, offs, len); +	if (err) { +		ubifs_err("writing %d bytes to LEB %d:%d failed, error %d", +			  len, lnum, offs, err); +		ubifs_ro_mode(c, err); +		dump_stack(); +	} +	return err; +} + +int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len) +{ +	int err; + +	ubifs_assert(!c->ro_media && !c->ro_mount); +	if (c->ro_error) +		return -EROFS; +	if (!dbg_is_tst_rcvry(c)) +		err = ubi_leb_change(c->ubi, lnum, buf, len); +	else +		err = dbg_leb_change(c, lnum, buf, len); +	if (err) { +		ubifs_err("changing %d bytes in LEB %d failed, error %d", +			  len, lnum, err); +		ubifs_ro_mode(c, err); +		dump_stack(); +	} +	return err; +} + +int ubifs_leb_unmap(struct ubifs_info *c, int lnum) +{ +	int err; + +	ubifs_assert(!c->ro_media && !c->ro_mount); +	if (c->ro_error) +		return -EROFS; +	if (!dbg_is_tst_rcvry(c)) +		err = ubi_leb_unmap(c->ubi, lnum); +	else +		err = dbg_leb_unmap(c, lnum); +	if (err) { +		ubifs_err("unmap LEB %d failed, error %d", lnum, err); +		ubifs_ro_mode(c, err); +		dump_stack(); +	} +	return err; +} + +int ubifs_leb_map(struct ubifs_info *c, int lnum) +{ +	int err; + +	ubifs_assert(!c->ro_media && !c->ro_mount); +	if (c->ro_error) +		return -EROFS; +	if (!dbg_is_tst_rcvry(c)) +		err = ubi_leb_map(c->ubi, lnum); +	else +		err = dbg_leb_map(c, lnum); +	if (err) { +		ubifs_err("mapping LEB %d failed, error %d", lnum, err); +		ubifs_ro_mode(c, err); +		dump_stack(); +	} +	return err; +} + +int ubifs_is_mapped(const struct ubifs_info *c, int lnum) +{ +	int err; + +	err = ubi_is_mapped(c->ubi, lnum); +	if (err < 0) { +		ubifs_err("ubi_is_mapped failed for LEB %d, error %d", +			  lnum, err); +		dump_stack();  	} +	return err;  }  /** @@ -88,8 +224,12 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)   * This function may skip data nodes CRC checking if @c->no_chk_data_crc is   * true, which is controlled by corresponding UBIFS mount option. However, if   * @must_chk_crc is true, then @c->no_chk_data_crc is ignored and CRC is - * checked. Similarly, if @c->always_chk_crc is true, @c->no_chk_data_crc is - * ignored and CRC is checked. + * checked. Similarly, if @c->mounting or @c->remounting_rw is true (we are + * mounting or re-mounting to R/W mode), @c->no_chk_data_crc is ignored and CRC + * is checked. This is because during mounting or re-mounting from R/O mode to + * R/W mode we may read journal nodes (when replying the journal or doing the + * recovery) and the journal nodes may potentially be corrupted, so checking is + * required.   *   * This function returns zero in case of success and %-EUCLEAN in case of bad   * CRC or magic. @@ -131,8 +271,8 @@ int ubifs_check_node(const struct ubifs_info *c, const void *buf, int lnum,  		   node_len > c->ranges[type].max_len)  		goto out_len; -	if (!must_chk_crc && type == UBIFS_DATA_NODE && !c->always_chk_crc && -	     c->no_chk_data_crc) +	if (!must_chk_crc && type == UBIFS_DATA_NODE && !c->mounting && +	    !c->remounting_rw && c->no_chk_data_crc)  		return 0;  	crc = crc32(UBIFS_CRC32_INIT, buf + 8, node_len - 8); @@ -153,8 +293,8 @@ out_len:  out:  	if (!quiet) {  		ubifs_err("bad node at LEB %d:%d", lnum, offs); -		dbg_dump_node(c, buf); -		dbg_dump_stack(); +		ubifs_dump_node(c, buf); +		dump_stack();  	}  	return err;  } @@ -343,11 +483,17 @@ static void cancel_wbuf_timer_nolock(struct ubifs_wbuf *wbuf)   *   * This function synchronizes write-buffer @buf and returns zero in case of   * success or a negative error code in case of failure. + * + * Note, although write-buffers are of @c->max_write_size, this function does + * not necessarily writes all @c->max_write_size bytes to the flash. Instead, + * if the write-buffer is only partially filled with data, only the used part + * of the write-buffer (aligned on @c->min_io_size boundary) is synchronized. + * This way we waste less space.   */  int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)  {  	struct ubifs_info *c = wbuf->c; -	int err, dirt; +	int err, dirt, sync_len;  	cancel_wbuf_timer_nolock(wbuf);  	if (!wbuf->used || wbuf->lnum == -1) @@ -357,27 +503,48 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)  	dbg_io("LEB %d:%d, %d bytes, jhead %s",  	       wbuf->lnum, wbuf->offs, wbuf->used, dbg_jhead(wbuf->jhead));  	ubifs_assert(!(wbuf->avail & 7)); -	ubifs_assert(wbuf->offs + c->min_io_size <= c->leb_size); +	ubifs_assert(wbuf->offs + wbuf->size <= c->leb_size); +	ubifs_assert(wbuf->size >= c->min_io_size); +	ubifs_assert(wbuf->size <= c->max_write_size); +	ubifs_assert(wbuf->size % c->min_io_size == 0);  	ubifs_assert(!c->ro_media && !c->ro_mount); +	if (c->leb_size - wbuf->offs >= c->max_write_size) +		ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size));  	if (c->ro_error)  		return -EROFS; -	ubifs_pad(c, wbuf->buf + wbuf->used, wbuf->avail); -	err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, -			    c->min_io_size, wbuf->dtype); -	if (err) { -		ubifs_err("cannot write %d bytes to LEB %d:%d", -			  c->min_io_size, wbuf->lnum, wbuf->offs); -		dbg_dump_stack(); +	/* +	 * Do not write whole write buffer but write only the minimum necessary +	 * amount of min. I/O units. +	 */ +	sync_len = ALIGN(wbuf->used, c->min_io_size); +	dirt = sync_len - wbuf->used; +	if (dirt) +		ubifs_pad(c, wbuf->buf + wbuf->used, dirt); +	err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len); +	if (err)  		return err; -	} - -	dirt = wbuf->avail;  	spin_lock(&wbuf->lock); -	wbuf->offs += c->min_io_size; -	wbuf->avail = c->min_io_size; +	wbuf->offs += sync_len; +	/* +	 * Now @wbuf->offs is not necessarily aligned to @c->max_write_size. +	 * But our goal is to optimize writes and make sure we write in +	 * @c->max_write_size chunks and to @c->max_write_size-aligned offset. +	 * Thus, if @wbuf->offs is not aligned to @c->max_write_size now, make +	 * sure that @wbuf->offs + @wbuf->size is aligned to +	 * @c->max_write_size. This way we make sure that after next +	 * write-buffer flush we are again at the optimal offset (aligned to +	 * @c->max_write_size). +	 */ +	if (c->leb_size - wbuf->offs < c->max_write_size) +		wbuf->size = c->leb_size - wbuf->offs; +	else if (wbuf->offs & (c->max_write_size - 1)) +		wbuf->size = ALIGN(wbuf->offs, c->max_write_size) - wbuf->offs; +	else +		wbuf->size = c->max_write_size; +	wbuf->avail = wbuf->size;  	wbuf->used = 0;  	wbuf->next_ino = 0;  	spin_unlock(&wbuf->lock); @@ -393,14 +560,12 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)   * @wbuf: write-buffer   * @lnum: logical eraseblock number to seek to   * @offs: logical eraseblock offset to seek to - * @dtype: data type   *   * 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 - * success and a negative error code in case of failure. + * The write-buffer has to be empty. Returns zero in case of success and a + * negative error code in case of failure.   */ -int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs, -			   int dtype) +int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs)  {  	const struct ubifs_info *c = wbuf->c; @@ -409,21 +574,20 @@ int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,  	ubifs_assert(offs >= 0 && offs <= c->leb_size);  	ubifs_assert(offs % c->min_io_size == 0 && !(offs & 7));  	ubifs_assert(lnum != wbuf->lnum); - -	if (wbuf->used > 0) { -		int err = ubifs_wbuf_sync_nolock(wbuf); - -		if (err) -			return err; -	} +	ubifs_assert(wbuf->used == 0);  	spin_lock(&wbuf->lock);  	wbuf->lnum = lnum;  	wbuf->offs = offs; -	wbuf->avail = c->min_io_size; +	if (c->leb_size - wbuf->offs < c->max_write_size) +		wbuf->size = c->leb_size - wbuf->offs; +	else if (wbuf->offs & (c->max_write_size - 1)) +		wbuf->size = ALIGN(wbuf->offs, c->max_write_size) - wbuf->offs; +	else +		wbuf->size = c->max_write_size; +	wbuf->avail = wbuf->size;  	wbuf->used = 0;  	spin_unlock(&wbuf->lock); -	wbuf->dtype = dtype;  	return 0;  } @@ -500,8 +664,9 @@ out_timers:   *   * This function writes data to flash via write-buffer @wbuf. This means that   * the last piece of the node won't reach the flash media immediately if it - * does not take whole minimal I/O unit. Instead, the node will sit in RAM - * until the write-buffer is synchronized (e.g., by timer). + * does not take whole max. write unit (@c->max_write_size). Instead, the node + * will sit in RAM until the write-buffer is synchronized (e.g., by timer, or + * because more data are appended to the write-buffer).   *   * This function returns zero in case of success and a negative error code in   * case of failure. If the node cannot be written because there is no more @@ -510,7 +675,7 @@ out_timers:  int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)  {  	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);  	dbg_io("%d bytes (%s) to jhead %s wbuf at LEB %d:%d", len,  	       dbg_ntype(((struct ubifs_ch *)buf)->node_type), @@ -518,9 +683,15 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)  	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 & 7) && wbuf->offs <= c->leb_size); -	ubifs_assert(wbuf->avail > 0 && wbuf->avail <= c->min_io_size); +	ubifs_assert(wbuf->avail > 0 && wbuf->avail <= wbuf->size); +	ubifs_assert(wbuf->size >= c->min_io_size); +	ubifs_assert(wbuf->size <= c->max_write_size); +	ubifs_assert(wbuf->size % c->min_io_size == 0);  	ubifs_assert(mutex_is_locked(&wbuf->io_mutex));  	ubifs_assert(!c->ro_media && !c->ro_mount); +	ubifs_assert(!c->space_fixup); +	if (c->leb_size - wbuf->offs >= c->max_write_size) +		ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size));  	if (c->leb_size - wbuf->offs - wbuf->used < aligned_len) {  		err = -ENOSPC; @@ -542,15 +713,18 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)  		if (aligned_len == wbuf->avail) {  			dbg_io("flush jhead %s wbuf to LEB %d:%d",  			       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs); -			err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, -					    wbuf->offs, c->min_io_size, -					    wbuf->dtype); +			err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, +					      wbuf->offs, wbuf->size);  			if (err)  				goto out;  			spin_lock(&wbuf->lock); -			wbuf->offs += c->min_io_size; -			wbuf->avail = c->min_io_size; +			wbuf->offs += wbuf->size; +			if (c->leb_size - wbuf->offs >= c->max_write_size) +				wbuf->size = c->max_write_size; +			else +				wbuf->size = c->leb_size - wbuf->offs; +			wbuf->avail = wbuf->size;  			wbuf->used = 0;  			wbuf->next_ino = 0;  			spin_unlock(&wbuf->lock); @@ -564,39 +738,63 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)  		goto exit;  	} -	/* -	 * The node is large enough and does not fit entirely within current -	 * minimal I/O unit. We have to fill and flush write-buffer and switch -	 * to the next min. I/O unit. -	 */ -	dbg_io("flush jhead %s wbuf to LEB %d:%d", -	       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs); -	memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail); -	err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs, -			    c->min_io_size, wbuf->dtype); -	if (err) -		goto out; +	written = 0; + +	if (wbuf->used) { +		/* +		 * The node is large enough and does not fit entirely within +		 * current available space. We have to fill and flush +		 * write-buffer and switch to the next max. write unit. +		 */ +		dbg_io("flush jhead %s wbuf to LEB %d:%d", +		       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs); +		memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail); +		err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, +				      wbuf->size); +		if (err) +			goto out; -	offs = wbuf->offs + c->min_io_size; -	len -= wbuf->avail; -	aligned_len -= wbuf->avail; -	written = wbuf->avail; +		wbuf->offs += wbuf->size; +		len -= wbuf->avail; +		aligned_len -= wbuf->avail; +		written += wbuf->avail; +	} else if (wbuf->offs & (c->max_write_size - 1)) { +		/* +		 * The write-buffer offset is not aligned to +		 * @c->max_write_size and @wbuf->size is less than +		 * @c->max_write_size. Write @wbuf->size bytes to make sure the +		 * following writes are done in optimal @c->max_write_size +		 * chunks. +		 */ +		dbg_io("write %d bytes to LEB %d:%d", +		       wbuf->size, wbuf->lnum, wbuf->offs); +		err = ubifs_leb_write(c, wbuf->lnum, buf, wbuf->offs, +				      wbuf->size); +		if (err) +			goto out; + +		wbuf->offs += wbuf->size; +		len -= wbuf->size; +		aligned_len -= wbuf->size; +		written += wbuf->size; +	}  	/* -	 * The remaining data may take more whole min. I/O units, so write the -	 * remains multiple to min. I/O unit size directly to the flash media. +	 * The remaining data may take more whole max. write units, so write the +	 * remains multiple to max. write unit size directly to the flash media.  	 * We align node length to 8-byte boundary because we anyway flash wbuf  	 * if the remaining space is less than 8 bytes.  	 */ -	n = aligned_len >> c->min_io_shift; +	n = aligned_len >> c->max_write_shift;  	if (n) { -		n <<= c->min_io_shift; -		dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum, offs); -		err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written, offs, n, -				    wbuf->dtype); +		n <<= c->max_write_shift; +		dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum, +		       wbuf->offs); +		err = ubifs_leb_write(c, wbuf->lnum, buf + written, +				      wbuf->offs, n);  		if (err)  			goto out; -		offs += n; +		wbuf->offs += n;  		aligned_len -= n;  		len -= n;  		written += n; @@ -606,14 +804,17 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)  	if (aligned_len)  		/*  		 * And now we have what's left and what does not take whole -		 * min. I/O unit, so write it to the write-buffer and we are +		 * max. write unit, so write it to the write-buffer and we are  		 * done.  		 */  		memcpy(wbuf->buf, buf + written, len); -	wbuf->offs = offs; +	if (c->leb_size - wbuf->offs >= c->max_write_size) +		wbuf->size = c->max_write_size; +	else +		wbuf->size = c->leb_size - wbuf->offs; +	wbuf->avail = wbuf->size - aligned_len;  	wbuf->used = aligned_len; -	wbuf->avail = c->min_io_size - aligned_len;  	wbuf->next_ino = 0;  	spin_unlock(&wbuf->lock); @@ -634,9 +835,9 @@ exit:  out:  	ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",  		  len, wbuf->lnum, wbuf->offs, err); -	dbg_dump_node(c, buf); -	dbg_dump_stack(); -	dbg_dump_leb(c, wbuf->lnum); +	ubifs_dump_node(c, buf); +	dump_stack(); +	ubifs_dump_leb(c, wbuf->lnum);  	return err;  } @@ -647,7 +848,6 @@ out:   * @len: node length   * @lnum: logical eraseblock number   * @offs: offset within the logical eraseblock - * @dtype: node life-time hint (%UBI_LONGTERM, %UBI_SHORTTERM, %UBI_UNKNOWN)   *   * This function automatically fills node magic number, assigns sequence   * number, and calculates node CRC checksum. The length of the @buf buffer has @@ -656,7 +856,7 @@ out:   * success and a negative error code in case of failure.   */  int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum, -		     int offs, int dtype) +		     int offs)  {  	int err, buf_len = ALIGN(len, c->min_io_size); @@ -666,18 +866,15 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,  	ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);  	ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);  	ubifs_assert(!c->ro_media && !c->ro_mount); +	ubifs_assert(!c->space_fixup);  	if (c->ro_error)  		return -EROFS;  	ubifs_prepare_node(c, buf, len, 1); -	err = ubi_leb_write(c->ubi, lnum, buf, offs, buf_len, dtype); -	if (err) { -		ubifs_err("cannot write %d bytes to LEB %d:%d, error %d", -			  buf_len, lnum, offs, err); -		dbg_dump_node(c, buf); -		dbg_dump_stack(); -	} +	err = ubifs_leb_write(c, lnum, buf, offs, buf_len); +	if (err) +		ubifs_dump_node(c, buf);  	return err;  } @@ -729,13 +926,9 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,  	if (rlen > 0) {  		/* Read everything that goes before write-buffer */ -		err = ubi_read(c->ubi, lnum, buf, offs, rlen); -		if (err && err != -EBADMSG) { -			ubifs_err("failed to read node %d from LEB %d:%d, " -				  "error %d", type, lnum, offs, err); -			dbg_dump_stack(); +		err = ubifs_leb_read(c, lnum, buf, offs, rlen, 0); +		if (err && err != -EBADMSG)  			return err; -		}  	}  	if (type != ch->node_type) { @@ -760,8 +953,8 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,  out:  	ubifs_err("bad node at LEB %d:%d", lnum, offs); -	dbg_dump_node(c, buf); -	dbg_dump_stack(); +	ubifs_dump_node(c, buf); +	dump_stack();  	return -EINVAL;  } @@ -790,38 +983,37 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,  	ubifs_assert(!(offs & 7) && offs < c->leb_size);  	ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT); -	err = ubi_read(c->ubi, lnum, buf, offs, len); -	if (err && err != -EBADMSG) { -		ubifs_err("cannot read node %d from LEB %d:%d, error %d", -			  type, lnum, offs, err); +	err = ubifs_leb_read(c, lnum, buf, offs, len, 0); +	if (err && err != -EBADMSG)  		return err; -	}  	if (type != ch->node_type) { -		ubifs_err("bad node type (%d but expected %d)", -			  ch->node_type, type); +		ubifs_errc(c, "bad node type (%d but expected %d)", +			   ch->node_type, type);  		goto out;  	}  	err = ubifs_check_node(c, buf, lnum, offs, 0, 0);  	if (err) { -		ubifs_err("expected node type %d", type); +		ubifs_errc(c, "expected node type %d", type);  		return err;  	}  	l = le32_to_cpu(ch->len);  	if (l != len) { -		ubifs_err("bad node length %d, expected %d", l, len); +		ubifs_errc(c, "bad node length %d, expected %d", l, len);  		goto out;  	}  	return 0;  out: -	ubifs_err("bad node at LEB %d:%d, LEB mapping status %d", lnum, offs, -		  ubi_is_mapped(c->ubi, lnum)); -	dbg_dump_node(c, buf); -	dbg_dump_stack(); +	ubifs_errc(c, "bad node at LEB %d:%d, LEB mapping status %d", lnum, +		   offs, ubi_is_mapped(c->ubi, lnum)); +	if (!c->probing) { +		ubifs_dump_node(c, buf); +		dump_stack(); +	}  	return -EINVAL;  } @@ -837,11 +1029,11 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)  {  	size_t size; -	wbuf->buf = kmalloc(c->min_io_size, GFP_KERNEL); +	wbuf->buf = kmalloc(c->max_write_size, GFP_KERNEL);  	if (!wbuf->buf)  		return -ENOMEM; -	size = (c->min_io_size / UBIFS_CH_SZ + 1) * sizeof(ino_t); +	size = (c->max_write_size / UBIFS_CH_SZ + 1) * sizeof(ino_t);  	wbuf->inodes = kmalloc(size, GFP_KERNEL);  	if (!wbuf->inodes) {  		kfree(wbuf->buf); @@ -851,8 +1043,14 @@ int ubifs_wbuf_init(struct ubifs_info *c, struct ubifs_wbuf *wbuf)  	wbuf->used = 0;  	wbuf->lnum = wbuf->offs = -1; -	wbuf->avail = c->min_io_size; -	wbuf->dtype = UBI_UNKNOWN; +	/* +	 * If the LEB starts at the max. write size aligned address, then +	 * write-buffer size has to be set to @c->max_write_size. Otherwise, +	 * set it to something smaller so that it ends at the closest max. +	 * write size boundary. +	 */ +	size = c->max_write_size - (c->leb_start % c->max_write_size); +	wbuf->avail = wbuf->size = size;  	wbuf->sync_callback = NULL;  	mutex_init(&wbuf->io_mutex);  	spin_lock_init(&wbuf->lock);  | 
