Filesystems/ubifs
UBI (Unsorted Block Images) filesystem is a filesystem for flash memory devices. Unlike traditional filesystem, UBI filesystem does not work on top of block devices such as /dev/mtdblock0. It was designed to work on top of raw flash device like /dev/mtd0. UBI filesystem doesn't access raw flash devices directly, rather there is an additional layer called UBI between UBI filesystem and raw flash devices. UBI is a volume management system which manages multiple logical volumes on a single physical flash device and spreads the I/O across whole flash chip (wear-leveling).
Contents |
Source Codes
UBI (Unsorted Block Images): drivers/mtd/ubi
I/O
High level I/O: ubi_read() and ubi_write()
Low level I/O: ubi_io_read() and ubi_io_write(). Thse functions make use of read and write method provided by MTD character device layer.
In include/linux/mtd/ubi.h
static inline int ubi_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, int len) { return ubi_leb_read(desc, lnum, buf, offset, len, 0); } static inline int ubi_write(struct ubi_volume_desc *desc, int lnum, const void *buf, int offset, int len) { return ubi_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN); }
In drivers/mtd/ubi/kapi.c
int ubi_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset, int len, int check) { ....... err = ubi_eba_read_leb(ubi, vol, lnum, buf, offset, len, check); ....... } int ubi_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf, int offset, int len, int dtype) { ....... return ubi_eba_write_leb(ubi, vol, lnum, buf, offset, len, dtype); ....... }
In drivers/mtd/ubi/eba.c
int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, void *buf, int offset, int len, int check) { ....... err = ubi_io_read_vid_hdr(ubi, pnum, vid_hdr, 1); ....... err = ubi_io_read_data(ubi, buf, pnum, offset, len); ....... } int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, const void *buf, int offset, int len, int dtype) { ....... err = ubi_io_write_data(ubi, buf, pnum, offset, len); ....... err = ubi_io_write_vid_hdr(ubi, pnum, vid_hdr); ....... }
In drivers/mtd/ubi/ubi.h
static inline int ubi_io_read_data(const struct ubi_device *ubi, void *buf, int pnum, int offset, int len) { ubi_assert(offset >= 0); return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len); } static inline int ubi_io_write_data(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len) { ubi_assert(offset >= 0); return ubi_io_write(ubi, buf, pnum, offset + ubi->leb_start, len); }
In drivers/mtd/ubi/io.c
int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, struct ubi_vid_hdr *vid_hdr, int verbose) { ....... read_err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); ....... } int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, struct ubi_vid_hdr *vid_hdr) { ....... err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, ubi->vid_hdr_alsize); ....... } int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, struct ubi_ec_hdr *ec_hdr, int verbose) { ....... read_err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); ....... } int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, struct ubi_ec_hdr *ec_hdr) { ....... err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize); ....... }
Eventually all I/O requests are processed by following functions in drivers/mtd/ubi/io.c.
int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, int len) { ....... err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf); ....... } int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, int len) { ....... err = ubi->mtd->write(ubi->mtd, addr, len, &written, buf); ....... }
UBI Filesystem: fs/ubifs
Test
# flash_eraseall /dev/mtd0 # modprobe ubi mtd=0 # ubimkvol /dev/ubi0 -N test -s 100MiB # mount -t ubifs ubi0:test /mnt/ubifs