This article, which is a part of the series on Linux device drivers, takes the next step towards developing a file system module by exploring how to write a formatting application for your real pen drive.
Thanks, friends, for your confidence in Shweta, and not trying to help her figure out the issues with her code. She indeed figured out and fixed the following issues on her own:
sfs_read() and sfs_write() need to check for the read and write file permissions before proceeding to read and write, respectively.
sfs_write() should free any previously allocated blocks, as write is always over-write.
Moreover, the earlier written sfs_remove() also now needs to free up the allocated blocks.
SFS format for a real partition
Thereafter, Pugs took the lead and slightly modified Shweta’s format_sfs.c and sfs_ds.h files to format a real pen drive’s partition. The key change was that instead of creating the default regular file .sfsf to format, it would now be operating on an existing block device file corresponding to an underlying partition, say, something like /dev/sdb1. So:
It would get the partition’s size from the partition’s block device file itself, rather than taking it as a command-line argument.
Accordingly, it would now expect the partition’s block device file name instead of size, as main()’s first argument.
Also, it would not need mark_data_block() to grow the file to equal the partition’s size.
The ioctl command BLKGETSIZE64 gets the 64-bit size of the underlying block device partition, in bytes. Then, it is divided by the block size (SIMULA_FS_BLOCK_SIZE) to get the partition’s size in block units. Here is the corresponding modified snippet of the main() function in format_sfs.c, along with the required typedef in sfs_ds.h:
typedef unsigned long long uint8_t;
sfs_handle = open(argv, O_RDWR);
if (sfs_handle == -1)
fprintf(stderr, “Error formatting %s: %s\n”, argv, strerror(errno));
if (ioctl(sfs_handle, BLKGETSIZE64, &size) == -1)
fprintf(stderr, “Error getting size of %s: %s\n”, argv, strerror(errno));
sb.partition_size = size / SIMULA_FS_BLOCK_SIZE;
As per the above code, various additional header files would be needed, as follows:
#include <errno.h> /* For errno */
#include <string.h> /* For strerror() */
#include <sys/ioctl.h> /* For ioctl() */
#include <linux/fs.h> /* For BLKGETSIZE64 */
With all the above changes compiled into format_sfs, Pugs plugged in his pen drive, the partition of which was auto-mounted. Then, he took a backup of its contents, and unmounted it, ready for a real SFS formatting of the partition.
Caution: Take a backup of your pen drive’s contents,you are formatting it for real. Be careful in choosing the right partition of your pen drive. Otherwise, you may forever lose data from your hard disk, or even make your system unbootable. You have been warned!
Figure 1 demonstrates all of the above, except the backup steps, at the root prompt (#). Instead, you may use sudo, as well. Note that Pugs got his pen drive partition mounted at /media/10AC-BF1C, and the corresponding device file is /dev/sdb1 (/dev/sdb being the complete pen drive). Both these may be different in your case, so take the subsequent steps accordingly. Also, note that the SFS formatting is then started using the following command:
# ./format_sfs /dev/sdb1
And then, there is a ^C (Ctrl-C) immediately after that, which basically terminates the formatting. Aha! Did Pugs realise there was something important on the pen drive? Not really, as his pen drive is already empty. Actually, what happened is that formatting was going on for quite some time so Pugs had some doubts about his code changes and terminated the run. Reviewing his code didn’t yield much, so he reissued the format command, this time with the time command, to figure out exactly how much time the formatting takes and then maybe debug or fix that. And finally… the formatting completed after a whopping 430.88 seconds (7+ minutes!). time basically shows the real time taken (including the time when other processes have been running after the context switch), the time executed in user space, and the time executed in kernel space. That’s a lot something obviously needs optimisation. And it didn’t take much time for a close review to determine the issue. The code at fault is the clear_file_entries() function, which clears file entries by writing 64-byte-sized file entries one by one which is pretty non-optimal. A better approach would be to fill up a block with such entries, and then write these blocks one by one. In case of a 512-byte block (i.e., SIMULA_FS_BLOCK_SIZE defined as 512), that would mean 8 file entries in a 512-byte block, and then writing these 512-byte blocks, one by one. So, Pugs changed the clear_file_entries() function to do that, and voilà! Formatting completed in a little less than 26 seconds. Here’s the re-written clear_file_entries() function:
void clear_file_entries(int sfs_handle, sfs_super_block_t *sb)
for (i = 0; i < sb->block_size / sb->entry_size; i++)
memcpy(block + i * sb->entry_size, &fe, sizeof(fe));
for (i = 0; i < sb->entry_table_size; i++)
write(sfs_handle, block, sizeof(block));
Now, you may plug out and plug in the pen drive again. It is neither auto-mounted, nor are you able to mount it. That’s expected it has been formatted with a file system for which there is no (kernel) module to decode. So, coding would be the ultimate step to get everything working like with any other existing file system (vfat, ext3,). To get your pen drive usable again, re-format it with the FAT32 (vfat) file system (as the root, or with sudo), as follows:
# mkfs.vfat /dev/sdb1 # Be careful with the correct partition device file
Then, unplug and reinsert it to get it auto-mounted. But Pugs, being a cool carefree guy, instead went ahead to try browsing the Simula file system created on the pen drive partition.
Browsing the pen drive partition
Obviously, there were slight modifications to the browse_sfs.c application as well, in line with the changes to format_sfs.c. The major one was to compulsorily take the partition device file to browse as a command-line argument, instead of browsing the default regular file .sfsf.
All the updated files (sfs_ds.h, format_sfs.c, browse_sfs.c and Makefile) are available at http://linuxforu.com/article_source_code/aug12/rfs_code.tar.bz2.
. However, the coolest browsing would be done the same way as with all other file systems, using the shell commands cd, ls, Yes, and for that, we would need the SFS module in place. Keep following what Pugs is up to, to get that in place.