world leader in high performance signal processing
Trace: » file_systems

File Systems

A file system is a method to describe the data layout found on some physical media. There are also things called pseudo filesystems which use the features of the file system interface to access or manage some kernel functions.

Probably one of the most excellent features of Linux is its ability to dynamically add different filesystem types to the kernel.

This means that when you plug in your USB Drive the kernel detects the device and also tries to access this by adding the correct file systems to the kernel.

Looking at Filesystems

The command cat /proc/filesystems is a good way to see what the kernel understands. The size of this list is a good indication of how much filesystems are used.

Output of 
cat /proc/filesystems
( from an X86 system )
nodev   sysfs
nodev   rootfs
nodev   bdev
nodev   proc
nodev   sockfs
nodev   futexfs
nodev   tmpfs
nodev   pipefs
nodev   eventpollfs
nodev   devpts
nodev   ramfs
nodev   hugetlbfs
nodev   nfs
nodev   mqueue
nodev   rpc_pipefs
nodev   usbfs
nodev   usbdevfs
nodev   subfs
nodev   nfsd

The nodev filesystems are pseudo filesystems that do not have direct access to some storage device.

Useful Filesystems

This is a summary of the more useful filesystems directly used by the embedded developer.

Name Description Read Write Use
ext2 Basic Linux FilesystemRW Often used as a Root File System
ext3 ext2 with journallingRW Used to provide a quick recovery after a shutdown
romfs rom based filesystem Read only often used for flash based systems
cramfs compresses rom based Read Only like romfs but file data is compressed
tmpfs ram based RW Fixed size volatile ram based file system
ramfs ram based RW Expanding , volatile ram based file system
jffs2 flash based RW Flash Journalling File System

This is a summary of filesystems often included in the kernel

Name Description Read Write Use
proc Kernel Information System RW Used to access kernel data and structures
sysfs Kernel Object Information RW procfs replacement for 2.6 kernels

Here are some more advanced file systems, some of these require patches in the kernel. Some of these are experimental and you may have to do a google search to find more information.

Name Description Read Write Use
overlayfs Overlays a read only filesystem with non volatile storage RW live cds with persistent backing store
debugfs Exposes optional debug informationRW Debugging Systems
configfsExposes configuration information RW Configuring Systems
squashfsCramfs alternativeRead Only Embedded Systems
yaffsJffs2 alternative RW Yet Another Flash File System
cloopfscompressed loop Read Only Knoppix style Live CD's
devfs Device Driver Interface RW Exposes Device Drivers ( now deprecated )

The Superblock

This is not a football move but is the core of a file system.

The first 512 bytes of a device are normally used the determine the structure of the file system contained in that device. The kernel will read this initial data and try to determine the type of filesystem contained. If needed the kernel will try to load additional modules to allow it to understand and mount the file system.

Creating a Filesystem

Not a task for beginners but Linux has a fully working example file system in the kernel. If you look at the code for ramfs ( in linux/fs/ramfs/inode.c ) you will see an example File system generated by Linus.

The key code components are:

  • register a file system
  • define how to read a superblock

Once you read a superblock you then define the file operations allowed by that file systemo The basic building block of a file system is the inode. An inode defines an entity in the file system. Typically such an entity can be

  • a regular file
  • a directory
  • a link to another entry

For each different type of inode the file system registers different methods for handling reads and writes to that particular inode. There are inode operations and file operations.

Directory inode operations include

  • create - create a file in the directory
  • mkdir - make a sub directory
  • mknod - make a special device file
  • symlink - make a link to another file
  • rename - change the name of an entry
  • unlink - delete a file ( when no longer used )

Refer to the code for more details

File System Example: Debugfs

Created by Greg Kroah-Hartman debugfs is an in-kernel filesystem which gas been designed to help kernel developers easily access debug data from userspace.

It has been designed to be easy to use and also it is optional. If you dont mount the debugfs the filesystem , and its kernel memory overhead, is not there.

Debugfs is available as a patch which also contains a few use examples.

NOTE that all the code below is in kernel space

You can create a debug directory as follows:

struct dentry *debugfs_create_dir(const char *name, struct dentry *parent);
struct dentry *mydebdir;
mydebdir = debugfs_create_dir("mydebug", NULL);

Then, for example, to export a single value mydebugch to userspace:

struct dentry *debugfs_create_u8(const char *name,
                                 mode_t mode,
                                 struct dentry *parent, u8*value);
u8 mydebugch; (also u16 , u32 )
debugfs_create_u8("mydebugch", S_IWUGO, mydebdir, &mydebugchar);

Two lines of code provide the following entry in the file system


For your own parser you will need to define a file operations table with suitable open , seek, read and write functions.

static int my_open(struct inode *inode, struct file *file)
        return 0;
static loff_t my_lseek(struct file *file, loff_t offset, int orig)
        loff_t retval = -EINVAL;
        switch(orig) {
        case 0:
                if (offset > 0) {
                        file->f_pos = offset;
                        retval = file->f_pos;
        case 1:
                if ((offset + file->f_pos) > 0) {
                        file->f_pos += offset;
                        retval = file->f_pos;
        return retval;
static ssize_t my_read(struct file *file, char __user *user_buf,
                                  size_t count, loff_t *ppos)
        char buf[32];
        u32 *val = file->private_data;
        int len;
        len = sprintf(buf,"my val is %d \n",val);
        return simple_read_from_buffer(user_buf, count, ppos, buf, len);
static ssize_t my_write(struct file *file, const char __user *user_buf,
                              size_t count, loff_t *ppos)
        char buf[32];
        int buf_size;
        int scanc;
        u32 *val = file->private_data;
        buf_size = min(count, (sizeof(buf)-1));
        if (copy_from_user(buf, user_buf, buf_size))
                return -EFAULT;
        sscanf(buf,"Set val to %d\n",val);
        return count;

Create a file using debugfs the call is

static struct file_operations my_fops = {
        .read =         my_read,
        .write =        my_write,
        .open =         my_open,
        .llseek =       my_lseek,

Then use the create_file system function to make the entry in debugfs:

struct dentry *debugfs_create_file(const char *name,
                                   mode_t mode,
                                   struct dentry *parent, void *data,
                                   struct file_operations *fops);
static int mysval;