By liran bh | 5/16/2016 | Linux Kernel & Internals

Simple File System

Simple File System (Old kernel 2.6.22)

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/statfs.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <asm/errno.h>
#include <linux/buffer_head.h>
#include <linux/pagemap.h>    /* unlock_page */
 
#define RKFS_MAGIC 0xabcd
#define FILE_INODE_NUMBER 2
 
/* file_system_type */
/* get_sb */
static int rkfs_get_sb (struct file_system_type *fs_type,
                    int flags, const char *dev_name,
                    void *data, struct vfsmount *mnt);
/* kill_sb */
static void rkfs_kill_sb (struct super_block *);
 
/* super_operations */
/* read_inode */
static void rkfs_super_read_inode (struct inode *inode);
/* write_inode */
static int rkfs_super_write_inode (struct inode *inode, int sync);
 
/* inode_operations */
/* lookup */
static struct dentry *rkfs_inode_lookup (struct inode *parent_inode,
                     struct dentry *dentry,
                     struct nameidata *);
 
/* file_operations */
static int rkfs_file_open (struct inode *, struct file *);
/* readdir */
static int
rkfs_file_readdir (struct file *file, void *dirent, filldir_t filldir);
/* release */
static int rkfs_file_release (struct inode *, struct file *);
 
/* Address Space Operations */
/* writepage */
static int rkfs_writepage (struct page *page, struct writeback_control *wbc);
/* readpage */
static int rkfs_readpage (struct file *file, struct page *page);
/* prepare_write */
static int
rkfs_prepare_write (struct file *file, struct page *page,
            unsigned from, unsigned to);
/* commit_write */
static int
rkfs_commit_write (struct file *file, struct page *page,
           unsigned from, unsigned to);
 
/* readpage */
 
/*
 * Data declarations
 */
 
static struct super_operations rkfs_sops = {
      read_inode:rkfs_super_read_inode,
      statfs:simple_statfs,    /* handler from libfs */
      write_inode:&rkfs_super_write_inode
};
 
static struct inode_operations rkfs_iops = {
      lookup:rkfs_inode_lookup
};
 
#if 0
static struct file_operations rkfs_fops = {
      open:rkfs_file_open,
      read:&generic_file_read,
      readdir:&rkfs_file_readdir,
      write:&generic_file_write,
      release:&rkfs_file_release,
      fsync:simple_sync_file
};
#else
static struct file_operations rkfs_fops = {
      open:rkfs_file_open,
      read:&do_sync_read,
      aio_read: generic_file_aio_read,
      aio_write: generic_file_aio_write,
      readdir:&rkfs_file_readdir,
      write:&do_sync_write,
      release:&rkfs_file_release,
      fsync:simple_sync_file
};
#endif
 
static struct file_system_type rkfs = {
      name:"rkfs",
      get_sb:rkfs_get_sb,
      kill_sb:rkfs_kill_sb,
      owner:THIS_MODULE
};
 
static struct address_space_operations rkfs_aops = {
    .readpage = rkfs_readpage,
    .writepage = rkfs_writepage,
    .prepare_write = rkfs_prepare_write,
    .commit_write = rkfs_commit_write
};
 
static struct inode *rkfs_root_inode;
 
static char file_buf[PAGE_SIZE] = "Hello World\n";
static int file_size = 12;
 
/*
 * File-System Operations
 */
 
static int
rkfs_fill_super (struct super_block *sb, void *data, int silent)
{
    printk ("RKFS: rkfs_fill_super\n");
    sb->s_blocksize = 1024;
    sb->s_blocksize_bits = 10;
    sb->s_magic = RKFS_MAGIC;
    sb->s_op = &rkfs_sops;    // super block operations
    sb->s_type = &rkfs;    // file_system_type
 
    rkfs_root_inode = iget (sb, 1);    // allocate an inode
    rkfs_root_inode->i_op = &rkfs_iops;    // set the inode ops
    rkfs_root_inode->i_mode = S_IFDIR | S_IRWXU;
    rkfs_root_inode->i_fop = &rkfs_fops;
 
    if (!(sb->s_root = d_alloc_root (rkfs_root_inode)))
      {
          iput (rkfs_root_inode);
          return -ENOMEM;
      }
 
    return 0;
}
 
static int
rkfs_get_sb (struct file_system_type *fs_type,
         int flags, const char *dev_name, void *data,
         struct vfsmount *mnt)
{
    /* rkfs_fill_super this will be called to fill the superblock */
    return get_sb_single (fs_type, flags, data, rkfs_fill_super, mnt);
}
 
static void
rkfs_kill_sb (struct super_block *super)
{
    kill_anon_super (super);
}
 
/*
 * Super-Block Operations
 */
 
static void
rkfs_super_read_inode (struct inode *inode)
{
    printk ("RKFS: rkfs_super_read_inode\n");
    inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
    inode->i_mapping->a_ops = &rkfs_aops;
}
 
static int
rkfs_super_write_inode (struct inode *inode, int wait)
{
    printk ("RKFS: rkfs_super_write_inode (i_ino = %d) = %d\n",
        (int) inode->i_ino, (int) i_size_read (inode));
    if (inode->i_ino == FILE_INODE_NUMBER)
      {
          file_size = i_size_read (inode);
      }
    return 0;
}
 
/*
 * Inode Operations
 */
 
static char filename[] = "hello.txt";
static int filename_len = sizeof (filename) - 1;
static struct dentry *
rkfs_inode_lookup (struct inode *parent_inode, struct dentry *dentry,
           struct nameidata *nameidata)
{
    struct inode *file_inode;
    printk ("RKFS: rkfs_inode_lookup\n");
    if (parent_inode->i_ino != rkfs_root_inode->i_ino ||
        dentry->d_name.len != filename_len ||
        strncmp (dentry->d_name.name, filename, dentry->d_name.len))
      {
          d_add (dentry, NULL);
          goto out;
      }
 
    file_inode = iget (parent_inode->i_sb, FILE_INODE_NUMBER);
    if (!file_inode)
        return ERR_PTR (-EACCES);
    file_inode->i_size = file_size;
    file_inode->i_mode = S_IFREG | S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
    file_inode->i_fop = &rkfs_fops;
    //  file_inode->i_fop
    d_add (dentry, file_inode);
 
      out:
    return NULL;
}
 
/*
 * File Operations
 */
 
static int
rkfs_file_open (struct inode *inode, struct file *file)
{
    printk ("RKFS: @rkfs_file_open max_readahead = %d (size = %d)\n",
        (int) file->f_ra.ra_pages, file_size);
    file->f_ra.ra_pages = 0;    /* No read-ahead */
    return generic_file_open (inode, file);
}
 
static int
rkfs_file_release (struct inode *ino, struct file *file)
{
    struct dentry *dentry;
    dentry = file->f_dentry;
    return 0;
}
 
static int
rkfs_file_readdir (struct file *file, void *dirent, filldir_t filldir)
{
    struct dentry *de = file->f_dentry;
 
    if (file->f_pos > 2)
        return 1;
    if (filldir
        (dirent, ".", 1, file->f_pos++, de->d_inode->i_ino, DT_DIR))
        return 0;
    if (filldir
        (dirent, "..", 2, file->f_pos++, de->d_parent->d_inode->i_ino,
         DT_DIR))
        return 0;
    if (filldir
        (dirent, filename, filename_len, file->f_pos++, FILE_INODE_NUMBER,
         DT_REG))
        return 0;
    return 1;
}
 
/* address_space_operations */
static int
rkfs_writepage (struct page *page, struct writeback_control *wbc)
{
    void *page_addr = kmap (page);
    printk ("[RKFS] offset = %d\n", (int) page->index);
    printk ("RKFS: WritePage: [%s] [%s] [%s] [%s]\n",
        PageUptodate (page) ? "Uptodate" : "Not Uptodate",
        PageDirty (page) ? "Dirty" : "Not Dirty",
        PageWriteback (page) ? "PageWriteback Set" :
        "PageWriteback Cleared",
        PageLocked (page) ? "Locked" : "Unlocked");
    memcpy (file_buf, page_addr, PAGE_SIZE);
    ClearPageDirty (page);
    if (PageLocked (page))
        unlock_page (page);
    kunmap (page);
    return 0;
}
 
static int
rkfs_readpage (struct file *file, struct page *page)
{
    void *page_addr;
    printk ("RKFS: readpage called for page index=[%d]\n",
        (int) page->index);
    if (page->index > 0)
      {
          return -ENOSPC;
      }
 
    printk ("RKFS: Page: [%s] [%s] [%s] [%s]\n",
        PageUptodate (page) ? "Uptodate" : "Not Uptodate",
        PageDirty (page) ? "Dirty" : "Not Dirty",
        PageWriteback (page) ? "PageWriteback Set" :
        "PageWriteback Cleared",
        PageLocked (page) ? "Locked" : "Unlocked");
    SetPageUptodate (page);
    page_addr = kmap (page);
    if (page_addr)
        memcpy (page_addr, file_buf, PAGE_SIZE);
    if (PageLocked (page))
        unlock_page (page);
    kunmap (page);
    return 0;
}
 
static int
rkfs_prepare_write (struct file *file, struct page *page,
            unsigned from, unsigned to)
{
    return 0;
}
 
/* modified from generic_commit_write. generic_commit_write calls the
 * block device layer to write set up buffer heads for I/O.
 */
static int
rkfs_commit_write (struct file *file, struct page *page,
           unsigned from, unsigned to)
{
    struct inode *inode = page->mapping->host;
    void *page_addr = kmap (page);
    loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + to;
 
    printk ("RKFS: commit_write: [%s] [%s] [%s] \n",
        PageUptodate (page) ? "Uptodate" : "Not Uptodate",
        PageDirty (page) ? "Dirty" : "Not Dirty",
        PageLocked (page) ? "Locked" : "Unlocked");
 
    if (page->index == 0)
      {
          memcpy (file_buf, page_addr, PAGE_SIZE);
          ClearPageDirty (page);
      }
 
    SetPageUptodate (page);
    kunmap (page);
 
    /*
     * No need to use i_size_read() here, the i_size
     * cannot change under us because we hold i_sem.
     */
    if (pos > inode->i_size)
      {
          i_size_write (inode, pos);
          mark_inode_dirty (inode);
      }
 
    return 0;
}
 
static int
rkfs_init_module (void)
{
    int err;
 
    err = register_filesystem (&rkfs);
    return err;
}
 
static void
rkfs_cleanup_module (void)
{
    unregister_filesystem (&rkfs);
}
 
module_init (rkfs_init_module);
module_exit (rkfs_cleanup_module);
 
MODULE_LICENSE ("GPL");

{{CommentsModel.TotalCount}} Comments

Your Comment

{{CommentsModel.Message}}

Recent Stories

Top DiscoverSDK Experts

User photo
3355
Ashton Torrence
Web and Windows developer
GUI | Web and 11 more
View Profile
User photo
3220
Mendy Bennett
Experienced with Ad network & Ad servers.
Mobile | Ad Networks and 1 more
View Profile
User photo
3060
Karen Fitzgerald
7 years in Cross-Platform development.
Mobile | Cross Platform Frameworks
View Profile
Show All
X

Compare Products

Select up to three two products to compare by clicking on the compare icon () of each product.

{{compareToolModel.Error}}

Now comparing:

{{product.ProductName | createSubstring:25}} X
Compare Now