8.4 JFFS2

I have already described JFFS2's features in Chapter 3. One caveat I have not covered yet is JFFS2's behavior when full. Because of its architecture, JFFS2 implements garbage collection on MTD blocks. This scheme works fine in most cases. When the filesystem approaches its limits, however, JFFS2 spends an increasing amount of time garbage collecting. Furthermore, as the filesystem reaches its limits, the system is unable to truncate or move files and the access to files is slowed down. If you are using JFFS2, make sure your application's data does not grow to fill the entire filesystem. In other words, make sure your applications check for available filesystem space before writing to it in order to avoid severe slowdown and system crashes. Also, try running benchmarks on your target to determine the threshold at which JFFS2 starts misbehaving.

With that in mind, let us now concentrate on the creation and installation of a JFFS2 filesystem image. Mainly, we will use the mkfs.jffs2 utility installed in the previous chapter as part of the MTD utilities installation.

The creation of a JFFS2 image is fairly simple:

$ cd ${PRJROOT}
$ mkfs.jffs2 -r rootfs/ -o images/rootfs-jffs2.img

We use the -r option to specify the location of the directory containing the root filesystem, and the -o option to specify the name of the output file where the filesystem image should be stored. In addition to these options, we could use -l or -b to create little endian or big endian images, respectively. The JFFS2 compression ratio is much smaller than CRAMFS. For a root filesystem containing 7840 KB, for example, the resulting JFFS2 image is 6850 KB in size. The compression ratio is a little above 10%.

Once you create the JFFS2 image, you can write it to its designated MTD device. If this device is accessible on the host, you can carry out the appropriate commands directly on the host. Otherwise, follow the instructions in Section 8.2: boot your target with an NFS-mounted root filesystem, place the JFFS2 image on that filesystem, and issue the commands on the target to write the image to the designated MTD device. Regardless of your setup, you first need to erase the MTD device where the image will be placed:

# eraseall /dev/mtd5
Erased 8192 Kibyte @ 0 -- 100% complete.

Obviously, the space available on the MTD storage device must be equal to or larger than the JFFS2 image you are placing on it. With the MTD device erased, copy the JFFS2 image to the MTD partition:

# cat images/rootfs-jffs2.img > /dev/mtd5

Now, mount the copied filesystem to take a look at it:

# mount -t jffs2 /dev/mtdblock5 /mnt
# mount
/dev/mtdblock5 on /mnt type jffs2 (rw)
# ls mnt
bin      etc      linuxrc  sbin     usr
dev      lib      proc     tmp      var 
# umount mnt

Unlike disk filesystems, JFFS2 cannot be mounted on loopback using a mount -o loop ... command to view its content. Instead, it must be mounted from a real MTD device as done above. If you have no real MTD device on your host, such as CFI flash, you could use the virtual memory MTD device presented in Chapter 3. You could also use the jffs2reader command introduced in the previous chapter to view the image's content.

If your target had previously been using an NFS-mounted root filesystem, you are now ready to boot it using the JFFS2 filesystem as its root filesystem.