8 .8  Linux2.4文件系统的移植问题

Linux 内核源代码2.2.x版本及2.4.x版本之间有一定的变化,我们把 2.2.x版本叫旧版,把2.4.x叫新版。下面给出文件系统的变化:

1.模块处理方式发生了变化

模块的初始化方式有所变化,在旧版本中的初始化方式如下(我们把某个文件系统叫做myfs):

 

   static struct file_system_type myfs_fs_type =

         { "myfs", FS_REQUIRES_DEV, myfs_read_super, NULL };

 

   __initfunc(int init_myfs_fs(void)) {

      return register_filesystem(&myfs_fs_type);

   }

 

      #ifdef MODULE

     EXPORT_NO_SYMBOLS;

 

      int init_module(void) {

         return init_myfs_fs();

     }

 

     void cleanup_module(void) {

         unregister_filesystem(&myfs_fs_type);

     }

     #endif

  另外,MOD_INC_USE_COUN宏在文件系统的read_super()中被调用,而MOD_DEC_USE_COUNT宏在put_super()中被调用。新版中的初始化方法如下:

 

   static DECLARE_FSTYPE_DEV(myfs_fs_type, "myfs", myfs_read_super);

 

   static int __init init_myfs_fs(void) {

      return register_filesystem(&myfs_fs_type);

   }

 

   static void __exit exit_myfs_fs(void) {

      unregister_filesystem(&myfs_fs_type);

   }

 

   EXPORT_NO_SYMBOLS;

   module_init(init_myfs_fs);

   module_exit(exit_myfs_fs);

 

MOD_XXX_USE_COUNT现在由VFS文件系统在注册时进行处理。从代码可以看出,新版本的处理方式更具可读性,而本质上并没有多大变化。

2 大文件的支持(Large File SupportLFS

  VFS现在支持64位文件(仅适用于x86 Sparc平台):

·      使用64位类型loff_t

·      但内核还不支持64位的getrlimit()setrlimit()系统调用。

·      glibc库支持getrlimit64() setrlimit64()

 

  3.新的错误处理方式

     旧版中错误处理如下:

      if (!dir || !dir->i_nlink) {

                  *err = -EPERM;

                  return NULL;

             }

     在新版中,对错误的处理调用了ERR_PTR(), PTR_ERR() IS_ERR()函数:

     if (!dir || !dir->i_nlink)

                  return ERR_PTR(-EPERM);

     这几个错误处理函数定义于include/linux/fs.h中:

       static inline void *ERR_PTR(long error)

{

         return (void *) error;

}

 

 static inline long PTR_ERR(const void *ptr)

 {

         return (long) ptr;

 }

 

 static inline long IS_ERR(const void *ptr)

 {

         return (unsigned long)ptr > (unsigned long)-1000L;

}

4inode结构

  在旧版中,file_operationsinode_operations结构中定义,而在新版中已移到inode结构中,即:

 

    struct file_operations *i_fop;

   其引用形式为:inode->i_fop

   另外,inodecount类型的定义也有所改变:

 

   旧版:  int i_count;

   新版: atomic_t i_count;

   这种类型的定义是与体系结构独立的,因此,对这些变量的访问就是原子操作,例如对变量v的读和设置函数为:

   atomic_read(v);

   atomic_set(v, value);

  这种形式也应用于file 结构 dentry 结构。

5. dentry 高速缓存

    在旧版中,删除一个dentry 的函数形式为:

                    void (*d_delete)(struct dentry *);

     在新版中,删除一个dentry 的函数形式为:

             int (*d_delete)(struct dentry *);

    返回一个整数表示删除的成功与否。

    在旧版中,分配一个根目录项的函数形式为:

  struct dentry *d_alloc_root(struct inode *, struct dentry *);

    在新版中,分配一个根目录项的函数形式为:

           struct dentry *d_alloc_root(struct inode *);

 6.VFS 操作

   在旧版中,filldir帮助函数的形式为:

typedef int (*filldir_t)(void *, const char *, int, off_t, ino_t);

   在新版中,filldir帮助函数的形式为:

            typedef int (*filldir_t)(void *, const char *, int, off_t, ino_t, unsigned);

   新增加的参数表示文件类型,其定义于fs.h

      /*

     * File types

     */

 #define DT_UNKNOWN      0

 #define DT_FIFO         1

 #define DT_CHR          2

 #define DT_DIR          4

 #define DT_BLK          6

 #define DT_REG          8

 #define DT_LNK          10

 #define DT_SOCK         12

 #define DT_WHT          14

7.各种操作结构的指定方式发生变化

   所有操作结构的指定方式发生了变化,旧版中的形式为:

 

   struct file_operations myfs_file_operations = {

      myfs_file_lseek,

      generic_file_read,

      generic_file_write,

      NULL,

      NULL,

      myfs_ioctl,

      NULL,

   };

 

  新版中的形式为:

   struct file_operations myfs_file_operations = {

      llseek: myfs_file_lseek,

      read: generic_file_read,

      write: generic_file_write,

      ioctl: myfs_ioctl,

   };

   这种形式使用了GNU C语言的扩展形式,符合ISO C99标准,C99标准指定的初始化者的形式为:

 

 

   struct foo {

      int foo;

      long bar;

   };

 

   struct foo x = { .bar = 3, .foo = 4 };

 

8VFSfile_operations

   fsync()函数中增加了一个新的参数;如果这个参数被设置,则不干预对时间标记的刷新:

   旧版:  int (*fsync) (struct file *, struct dentry *);

   新版:  int (*fsync) (struct file *, struct dentry *, int);

 

   另外,原来file_operations中的两个操作:

 

int (*check_media_change) (kdev_t dev);

             int (*revalidate) (kdev_t dev);

  被移到一个新的结构block_device_operations

 

   struct block_device_operations {

      int (*open) (struct inode *, struct file *);

      int (*release) (struct inode *, struct file *);

      int (*ioctl)(struct inode *, struct file *, unsigned, unsigned long);

      int (*check_media_change)(kdev_t);

      int (*revalidate) (kdev_t);

   };

   这个新的结构成为inode结构中一个新的域:

 

   新版:  struct block_device *i_bdev;

   于是在block_device中有一个指向这个操作结构的指针:

 

   struct block_device {

      struct list_head bd_hash;

      atomic_t bd_count;

      dev_t bd_dev;

      atomic_t bd_openers;

      const struct

      block_device_operations *bd_op;

      struct semaphore bd_sem;

   };

 

另外,file_operations()中还增加了以下两个函数。在不用保持大内核锁的情况下,所有文件系统都可以调用这两个函数。这两个函数还实现了readv() writev()系统调用。

 

     ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *);

     ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *);

 

9VFSinode_operations

file_operations指针从inode_operations结构移到inode结构。

    inode_operations 结构中,follow_link()函数的形式也发生了变化:

    

旧版中:  struct dentry * (*follow_link) (struct dentry *, struct dentry *, unsigned int);

      新版中:  int (*follow_link) (struct dentry *, struct nameidata *);

 

     从调用形式可以看出,第一个参数仍然相同,新版参数的nameidata结构中包含了旧版中的最后两个参数:

 

    struct nameidata {

      struct dentry *dentry;

      struct vfsmount *mnt;

      struct qstr last;

      unsigned int flags;

      int last_type;

    };

    

   inode_operations结构中还增加了以下两个函数:

             int (*setattr) (struct dentry *, struct iattr *);

             int (*getattr) (struct dentry *, struct iattr *);

   这两个函数(实际上仅仅是setattr())取代了旧版中superblock操作中的notify_change()函数。另外,下列五个函数已经全部被取消:

 

    int (*readpage) (struct file *, struct page *);

    int (*writepage) (struct file *, struct page *);

    int (*updatepage) (struct file *, struct page *, unsigned long, unsigned int, int);

int (*bmap) (struct inode *,int);

    int (*smap) (struct inode *,int);

10VFSsuper_operations

   super_operations结构中,write_inode()函数的形式有所变化:

 

旧版中:  void (*write_inode) (struct inode *);

    新版中:  void (*write_inode) (struct inode *, int);

 

    新增加的参数是一个布尔标志,用来决定是否把inode同步地写到磁盘。

 

    相反, statfs() 函数中少一个参数,因为statfs 结构的大小是没有必要的。

      旧版中:  int (*statfs) (struct super_block *, struct statfs *, int);

      新版中:  int (*statfs) (struct super_block *, struct statfs *);

最后,notify_change()函数被以getattr()setattr()函数取代。