linux-generate-struct-vnode-dyanmically-from-kernel-headers-instead-of-by-perverting...
authorDerek Atkins <warlord@mit.edu>
Mon, 1 Oct 2001 23:58:59 +0000 (23:58 +0000)
committerDerrick Brashear <shadow@dementia.org>
Mon, 1 Oct 2001 23:58:59 +0000 (23:58 +0000)
hopefully this will be the end
(at least for a while) of problems where every linux version requires a new
openafs release. the struct vnode is now dynamically generated by parsing the
linux/fs.h file and pulling out the struct inode, then rewriting osi_vfs.h

Makefile.in
NEWS
acconfig.h
configure-libafs.in
configure.in
src/afs/LINUX/osi_vfs.h [deleted file]
src/afs/LINUX/osi_vfs.hin [new file with mode: 0644]
src/cf/linux-test2.m4
src/config/make_vnode.pl [new file with mode: 0644]

index 37ddfb1..17f4263 100644 (file)
@@ -368,6 +368,11 @@ libafs_tree: libafs_setup ${KERNELDIR}
        ${INSTALL} -c src/config/Makefile.${SYS_NAME}.in libafs_tree/config
        ${INSTALL} -c src/config/afsconfig.h.in libafs_tree/config
        ${INSTALL} -c -f -ns configure-libafs libafs_tree/configure
+       case ${SYS_NAME} in \
+       *linux*) \
+               ${INSTALL} -c src/config/make_vnode.pl libafs_tree/config ; \
+               ${INSTALL} -c src/afs/LINUX/osi_vfs.hin libafs_tree/afs ;; \
+       esac
 
 libuafs: libuafs_setup ${UKERNELDIR}
        set -x; \
diff --git a/NEWS b/NEWS
index 734e71e..2a2c3ec 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,11 @@ Openafs News -- history of user Visible changes. September 17, 2001
    of partitions and will attach and display accordingly. Creating the file
    "AlwaysAttach" in the /vicepX directory is used as the trigger to attach it.
 
+** Linux builds no longer require source changes every time the kernel
+   inode structure changes; the OpenAFS sources will now configure
+   itself to the actual inode structure as defined in the kernel
+   sources.
+
 * Changes incorporated in OpenAFS 1.2.1
 
 ** vfsck on Digital UNIX and Solaris will now refuse to fsck mounted
index 38198b4..e02e143 100644 (file)
@@ -30,13 +30,6 @@ static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg }
 
 #undef INODE_SETATTR_NOT_VOID
 #undef STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK
-#undef STRUCT_INODE_HAS_I_BYTES
-#undef STRUCT_INODE_HAS_I_CDEV
-#undef STRUCT_INODE_HAS_I_DEVICES
-#undef STRUCT_INODE_HAS_I_DIRTY_DATA_BUFFERS
-#undef STRUCT_INODE_HAS_I_MAPPING_OVERLOAD
-#undef STRUCT_INODE_HAS_I_MMAP_SHARED
-#undef STRUCT_INODE_HAS_I_TRUNCATE_SEM
 
 /* glue for RedHat kernel bug */
 #undef ENABLE_REDHAT_BUILDSYS
index f337340..83bc926 100644 (file)
@@ -112,41 +112,14 @@ case $system in
                fi
                AC_MSG_RESULT(linux)
                if test "x$enable_kernel_module" = "xyes"; then
-                LINUX_FS_STRUCT_INODE_HAS_I_BYTES
+                LINUX_BUILD_VNODE_FROM_INODE(config,afs)
                 LINUX_FS_STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK
-                LINUX_FS_STRUCT_INODE_HAS_I_CDEV
-                LINUX_FS_STRUCT_INODE_HAS_I_DEVICES
-                LINUX_FS_STRUCT_INODE_HAS_I_TRUNCATE_SEM
-                LINUX_FS_STRUCT_INODE_HAS_I_DIRTY_DATA_BUFFERS
-                LINUX_FS_STRUCT_INODE_HAS_I_MAPPING_OVERLOAD
-                LINUX_FS_STRUCT_INODE_HAS_I_MMAP_SHARED
                 LINUX_INODE_SETATTR_RETURN_TYPE
                 LINUX_NEED_RHCONFIG
                 LINUX_WHICH_MODULES
                 if test "x$ac_cv_linux_func_inode_setattr_returns_int" = "xyes" ; then
                  AC_DEFINE(INODE_SETATTR_NOT_VOID)
                 fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_dirty_data_buffers" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_DIRTY_DATA_BUFFERS)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_mmap_shared" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_MMAP_SHARED)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_mapping_overload" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_MAPPING_OVERLOAD)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_devices" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_DEVICES)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_cdev" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_CDEV)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_truncate_sem" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_TRUNCATE_SEM)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_bytes" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_BYTES)
-                fi
                 if test "x$ac_cv_linux_fs_struct_address_space_has_page_lock" = "xyes"; then 
                  AC_DEFINE(STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK)
                 fi
index aaeb6e4..797286a 100644 (file)
@@ -112,41 +112,14 @@ case $system in
                fi
                AC_MSG_RESULT(linux)
                if test "x$enable_kernel_module" = "xyes"; then
-                LINUX_FS_STRUCT_INODE_HAS_I_BYTES
+                LINUX_BUILD_VNODE_FROM_INODE(src/config,src/afs/LINUX)
                 LINUX_FS_STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK
-                LINUX_FS_STRUCT_INODE_HAS_I_CDEV
-                LINUX_FS_STRUCT_INODE_HAS_I_DEVICES
-                LINUX_FS_STRUCT_INODE_HAS_I_TRUNCATE_SEM
-                LINUX_FS_STRUCT_INODE_HAS_I_DIRTY_DATA_BUFFERS
-                LINUX_FS_STRUCT_INODE_HAS_I_MAPPING_OVERLOAD
-                LINUX_FS_STRUCT_INODE_HAS_I_MMAP_SHARED
                 LINUX_INODE_SETATTR_RETURN_TYPE
                 LINUX_NEED_RHCONFIG
                 LINUX_WHICH_MODULES
                 if test "x$ac_cv_linux_func_inode_setattr_returns_int" = "xyes" ; then
                  AC_DEFINE(INODE_SETATTR_NOT_VOID)
                 fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_dirty_data_buffers" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_DIRTY_DATA_BUFFERS)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_mmap_shared" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_MMAP_SHARED)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_mapping_overload" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_MAPPING_OVERLOAD)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_devices" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_DEVICES)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_cdev" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_CDEV)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_truncate_sem" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_TRUNCATE_SEM)
-                fi
-                if test "x$ac_cv_linux_fs_struct_inode_has_i_bytes" = "xyes"; then 
-                 AC_DEFINE(STRUCT_INODE_HAS_I_BYTES)
-                fi
                 if test "x$ac_cv_linux_fs_struct_address_space_has_page_lock" = "xyes"; then 
                  AC_DEFINE(STRUCT_ADDRESS_SPACE_HAS_PAGE_LOCK)
                 fi
diff --git a/src/afs/LINUX/osi_vfs.h b/src/afs/LINUX/osi_vfs.h
deleted file mode 100644 (file)
index 962e3b1..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Copyright 2000, International Business Machines Corporation and others.
- * All Rights Reserved.
- * 
- * This software has been released under the terms of the IBM Public
- * License.  For details, see the LICENSE file in the top-level source
- * directory or online at http://www.openafs.org/dl/license10.html
- */
-
-/*
- * Linux interpretations of vnode and vfs structs.
- *
- * The Linux "inode" has been abstracted to the fs independent part to avoid
- * wasting 100+bytes per vnode.
- */
-
-#ifndef OSI_VFS_H_
-#define OSI_VFS_H_
-
-/* The vnode should match the current implementation of the fs independent
- * part of the Linux inode.
- */
-/* The first cut is to continue to use a separate vnode pool. */
-typedef struct vnode {
-       struct list_head        i_hash;
-       struct list_head        i_list;
-       struct list_head        i_dentry;
-#if defined(AFS_LINUX24_ENV)
-        struct list_head        i_dirty_buffers;
-#endif
-#if defined(STRUCT_INODE_HAS_I_DIRTY_DATA_BUFFERS)
-        struct list_head        i_dirty_data_buffers;
-#endif
-       unsigned long           i_ino;
-       unsigned int            i_count;
-       kdev_t                  i_dev;
-       umode_t                 i_mode;
-       nlink_t                 i_nlink;
-       uid_t                   i_uid;
-       gid_t                   i_gid;
-       kdev_t                  i_rdev;
-#if defined(AFS_LINUX24_ENV) || defined(pgoff2loff) 
-        loff_t                  i_size;
-#else
-       off_t                   i_size;
-#endif
-       time_t                  i_atime;
-       time_t                  i_mtime;
-       time_t                  i_ctime;
-       unsigned long           i_blksize;
-       unsigned long           i_blocks;
-       unsigned long           i_version;
-#if !defined(AFS_LINUX24_ENV)
-       unsigned long           i_nrpages;
-#endif
-#ifdef STRUCT_INODE_HAS_I_BYTES
-        unsigned short          i_bytes;
-#endif
-       struct semaphore        i_sem;
-#ifdef STRUCT_INODE_HAS_I_TRUNCATE_SEM
-        struct rw_semaphore     i_truncate_sem;
-#endif
-#if defined(AFS_LINUX24_ENV)
-        struct semaphore        i_zombie;
-#else
-       struct semaphore        i_atomic_write;
-#endif
-       struct inode_operations *i_op;
-#if defined(AFS_LINUX24_ENV)
-        struct file_operations  *i_fop;
-#endif
-       struct super_block      *i_sb;
-#if defined(AFS_LINUX24_ENV)
-        wait_queue_head_t       i_wait;
-#else
-       struct wait_queue       *i_wait;
-#endif
-       struct file_lock        *i_flock;
-#if defined(AFS_LINUX24_ENV)
-        struct address_space    *i_mapping;
-        struct address_space    i_data;
-#else
-       struct vm_area_struct   *i_mmap;
-#if defined(STRUCT_INODE_HAS_I_MMAP_SHARED)
-        struct vm_area_struct   *i_mmap_shared;
-#endif
-       struct page             *i_pages;
-#endif
-#if defined(STRUCT_INODE_HAS_I_MAPPING_OVERLOAD)
-        int                     i_mapping_overload;
-#endif
-       struct dquot            *i_dquot[MAXQUOTAS];
-#if defined(AFS_LINUX24_ENV)
-#if defined(STRUCT_INODE_HAS_I_DEVICES)
-        struct list_head        i_devices;
-#endif
-        struct pipe_inode_info  *i_pipe;
-        struct block_device     *i_bdev;
-#if defined(STRUCT_INODE_HAS_I_CDEV)
-        struct char_device      *i_cdev;
-#endif
-        unsigned long           i_dnotify_mask;
-        struct dnotify_struct   *i_dnotify;
-#endif
-
-       unsigned long           i_state;
-
-       unsigned int            i_flags;
-#if !defined(AFS_LINUX24_ENV)
-       unsigned char           i_pipe;
-#endif
-       unsigned char           i_sock;
-
-#if defined(AFS_LINUX24_ENV)
-        atomic_t                i_writecount;
-#else
-       int                     i_writecount;
-#endif
-       unsigned int            i_attr_flags;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,2,10)
-       __u32                   i_generation;
-#endif
-#ifdef notdef
-       union {
-               struct pipe_inode_info          pipe_i;
-               struct minix_inode_info         minix_i;
-               struct ext2_inode_info          ext2_i;
-               struct hpfs_inode_info          hpfs_i;
-               struct ntfs_inode_info          ntfs_i;
-               struct msdos_inode_info         msdos_i;
-               struct umsdos_inode_info        umsdos_i;
-               struct iso_inode_info           isofs_i;
-               struct nfs_inode_info           nfs_i;
-               struct sysv_inode_info          sysv_i;
-               struct affs_inode_info          affs_i;
-               struct ufs_inode_info           ufs_i;
-               struct romfs_inode_info         romfs_i;
-               struct coda_inode_info          coda_i;
-               struct smb_inode_info           smbfs_i;
-               struct hfs_inode_info           hfs_i;
-               struct adfs_inode_info          adfs_i;
-               struct qnx4_inode_info          qnx4_i;    
-               struct socket                   socket_i;
-               void                            *generic_ip;
-       } u;
-#endif
-} vnode_t;
-
-/* Map vnode fields to inode fields. */
-#define i_number       i_ino
-#define v_count                i_count
-#define v_op           i_op
-#if defined(AFS_LINUX24_ENV)
-#define v_fop           i_fop
-#endif
-#define v_type         i_mode
-#define v_vfsp         i_sb
-#define vfs_vnodecovered s_covered
-
-/* v_type bits map to mode bits: */
-#define VNON 0
-#define VREG S_IFREG
-#define VDIR S_IFDIR
-#define VBLK S_IFBLK
-#define VCHR S_IFCHR
-#define VLNK S_IFLNK
-#define VSOCK S_IFSOCK
-
-/* vcexcl - used only by afs_create */
-enum vcexcl { EXCL, NONEXCL } ;
-
-/* afs_open and afs_close needs to distinguish these cases */
-#define FWRITE O_WRONLY|O_RDWR|O_APPEND
-#define FTRUNC O_TRUNC
-
-
-#define IO_APPEND O_APPEND
-#define FSYNC O_SYNC
-
-#define VTOI(V)  ((struct inode*)V)
-#define VN_HOLD(V) ((vnode_t*)V)->i_count++;
-#define VN_RELE(V) osi_iput((struct inode *)V);
-#define VFS_STATFS(V, S) ((V)->s_op->statfs)((V), (S), sizeof(*(S)))
-
-
-
-/* Various mode bits */
-#define VWRITE S_IWUSR
-#define VREAD  S_IRUSR
-#define VEXEC  S_IXUSR
-#define VSUID  S_ISUID
-#define VSGID  S_ISGID
-
-
-#define vfs super_block
-
-typedef struct vattr {
-    int                va_type;        /* One of v_types above. */
-    size_t     va_size;
-    unsigned long va_blocks;
-    unsigned long va_blocksize;
-    int                va_mask;        /* AT_xxx operation to perform. */
-    umode_t    va_mode;        /* mode bits. */
-    uid_t      va_uid;
-    gid_t      va_gid;
-    int                va_fsid;        /* Not used? */
-    dev_t      va_rdev;
-    ino_t      va_nodeid;      /* Inode number */
-    nlink_t    va_nlink;       /* link count for file. */
-    struct timeval va_atime;
-    struct timeval va_mtime;
-    struct timeval va_ctime;
-} vattr_t;
-
-#define VATTR_NULL(A) memset(A, 0, sizeof(struct vattr))
-
-
-/* va_masks - these should match their respective ATTR_xxx #defines in fs.h.
- * afs_notify_change has to use the attr bits in both the Linux and AFS
- * meanings. The glue layer code uses the ATTR_xxx style names.
- */
-#define AT_SIZE                ATTR_SIZE
-#define AT_MODE                ATTR_MODE
-#define AT_UID         ATTR_UID
-#define AT_GID         ATTR_GID
-#define AT_MTIME       ATTR_MTIME
-
-
-#define vnodeops inode_operations
-
-#endif /* OSI_VFS_H_ */
diff --git a/src/afs/LINUX/osi_vfs.hin b/src/afs/LINUX/osi_vfs.hin
new file mode 100644 (file)
index 0000000..99d8e3f
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
+
+/*
+ * Linux interpretations of vnode and vfs structs.
+ *
+ * The Linux "inode" has been abstracted to the fs independent part to avoid
+ * wasting 100+bytes per vnode.
+ */
+
+#ifndef OSI_VFS_H_
+#define OSI_VFS_H_
+
+/* The vnode should match the current implementation of the fs independent
+ * part of the Linux inode.
+ */
+/* The first cut is to continue to use a separate vnode pool. */
+/* LINUX VNODE INCLUDED BELOW -- DO NOT MODIFY */
+
+typedef struct vnode vnode_t;
+
+/* Map vnode fields to inode fields. */
+#define i_number       i_ino
+#define v_count                i_count
+#define v_op           i_op
+#if defined(AFS_LINUX24_ENV)
+#define v_fop           i_fop
+#endif
+#define v_type         i_mode
+#define v_vfsp         i_sb
+#define vfs_vnodecovered s_covered
+
+/* v_type bits map to mode bits: */
+#define VNON 0
+#define VREG S_IFREG
+#define VDIR S_IFDIR
+#define VBLK S_IFBLK
+#define VCHR S_IFCHR
+#define VLNK S_IFLNK
+#define VSOCK S_IFSOCK
+
+/* vcexcl - used only by afs_create */
+enum vcexcl { EXCL, NONEXCL } ;
+
+/* afs_open and afs_close needs to distinguish these cases */
+#define FWRITE O_WRONLY|O_RDWR|O_APPEND
+#define FTRUNC O_TRUNC
+
+
+#define IO_APPEND O_APPEND
+#define FSYNC O_SYNC
+
+#define VTOI(V)  ((struct inode*)V)
+#define VN_HOLD(V) ((vnode_t*)V)->i_count++;
+#define VN_RELE(V) osi_iput((struct inode *)V);
+#define VFS_STATFS(V, S) ((V)->s_op->statfs)((V), (S), sizeof(*(S)))
+
+
+
+/* Various mode bits */
+#define VWRITE S_IWUSR
+#define VREAD  S_IRUSR
+#define VEXEC  S_IXUSR
+#define VSUID  S_ISUID
+#define VSGID  S_ISGID
+
+
+#define vfs super_block
+
+typedef struct vattr {
+    int                va_type;        /* One of v_types above. */
+    size_t     va_size;
+    unsigned long va_blocks;
+    unsigned long va_blocksize;
+    int                va_mask;        /* AT_xxx operation to perform. */
+    umode_t    va_mode;        /* mode bits. */
+    uid_t      va_uid;
+    gid_t      va_gid;
+    int                va_fsid;        /* Not used? */
+    dev_t      va_rdev;
+    ino_t      va_nodeid;      /* Inode number */
+    nlink_t    va_nlink;       /* link count for file. */
+    struct timeval va_atime;
+    struct timeval va_mtime;
+    struct timeval va_ctime;
+} vattr_t;
+
+#define VATTR_NULL(A) memset(A, 0, sizeof(struct vattr))
+
+
+/* va_masks - these should match their respective ATTR_xxx #defines in fs.h.
+ * afs_notify_change has to use the attr bits in both the Linux and AFS
+ * meanings. The glue layer code uses the ATTR_xxx style names.
+ */
+#define AT_SIZE                ATTR_SIZE
+#define AT_MODE                ATTR_MODE
+#define AT_UID         ATTR_UID
+#define AT_GID         ATTR_GID
+#define AT_MTIME       ATTR_MTIME
+
+
+#define vnodeops inode_operations
+
+#endif /* OSI_VFS_H_ */
index beefbae..8e0753b 100644 (file)
@@ -28,3 +28,14 @@ ac_cv_linux_fs_struct_address_space_has_page_lock=no)])
 AC_MSG_RESULT($ac_cv_linux_fs_struct_address_space_has_page_lock)
 CPPFLAGS="$save_CPPFLAGS"])
 
+
+dnl LINUX_BUILD_VNODE_FROM_INODE (configdir, outputdir)
+dnl            defaults: (src/config, src/afs/LINUX)
+
+AC_DEFUN(LINUX_BUILD_VNODE_FROM_INODE, [
+AC_MSG_CHECKING(whether to build osi_vfs.h)
+configdir=ifelse([$1], ,src/config,$1)
+outputdir=ifelse([$2], ,src/afs/LINUX,$2)
+chmod +x $configdir/make_vnode.pl
+$configdir/make_vnode.pl -i $LINUX_KERNEL_PATH -o $outputdir
+])
diff --git a/src/config/make_vnode.pl b/src/config/make_vnode.pl
new file mode 100644 (file)
index 0000000..c020861
--- /dev/null
@@ -0,0 +1,113 @@
+#!/usr/bin/perl
+#
+# Make VNODE structure from INODE structure
+#
+# Created By:  Derek Atkins <warlord@MIT.EDU>
+#
+
+$linux_header_dir="/usr/src/linux";
+$outdir="./src/afs/LINUX";
+
+$sepline="/* LINUX VNODE INCLUDED BELOW -- DO NOT MODIFY */\n";
+
+# makeVfs (fs.h, vfs.hin, vfs.out)
+sub makeVfs {
+    my ($in,$base,$out) = @_;
+    my ($seplinefound);
+
+    open (IN, "$in") || die "Cannot open $in for reading";
+    open (BASE, "$base" ) || die "Cannot open base file $base";
+    open (OUT, ">$out") || die "Cannot open tempfile $out";
+
+    while (<BASE>) {
+       print OUT;
+       if ($_ eq $sepline) {
+           $seplinefound = 1;
+           last;
+       }
+    }
+
+    print OUT $sepline if !$seplinefound;
+
+    my ($state) = 0;
+    while (<IN>) {
+
+       # Look for 'struct inode' definition
+       if ($state == 0) {
+           next unless m/^struct\s+inode\s*\{/;
+           $state++;
+           s/inode/vnode/;
+           # Fallthrough
+       }
+
+       # Look for 'union {' -- print otherwise
+       if ($state == 1) {
+           if (m/^\s*union\s*\{/) {
+               $state++;
+               print OUT "#ifdef notdef\n";
+           }
+           print OUT;
+           next;
+       }
+
+       # Look for the end of the union -- ignore otherwise
+       if ($state == 2) {
+           print OUT;
+           next unless (m/^\s+\}\s*u;/);
+           $state++;
+           print OUT "#endif /* notdef */\n";
+           next;
+       }
+
+       # Look for end brace -- print until we find it
+       if ($state == 3) {
+           print OUT;
+           if (m/^\s*\};/) { $state++ }
+       }
+    }
+
+    while (<BASE>) { print OUT; }
+
+    close (IN);
+    close (BASE);
+    close (OUT);
+}
+
+sub usage {
+    print "usage: $0 [-i linux_header_dir] [-o output_dir] [-h]\n";
+    exit 1;
+}
+
+sub testArg {
+    my ($arg) = @_;
+    return $arg if ($arg && $arg ne "");
+    usage;
+}
+
+while ($_ = shift @ARGV) {
+    if (m/^-i/) { $linux_header_dir = testArg(shift @ARGV); next; }
+    if (m/^-o/) { $outdir = testArg(shift @ARGV); next; }
+    usage;
+}
+
+$linux_fs_h="$linux_header_dir/include/linux/fs.h";
+$vfs_h="$outdir/osi_vfs.h";
+$vfs_hin="$outdir/osi_vfs.hin";
+
+makeVfs ($linux_fs_h, $vfs_hin, "$vfs_h.new");
+
+system ("cmp", "-s", $vfs_h, "$vfs_h.new");
+$exit_value = $? >> 8;
+$signal_num = $? & 127;
+$core_dump  = $? & 128;
+
+if ($exit_value == 0 || $signal_num > 0) {
+    unlink "$vfs_h.new";
+    print "nothing to do... $vfs_h not changed.\n"
+} else {
+    unlink "$vfs_h";
+    rename ("$vfs_h.new", $vfs_h);
+    print "wrote $vfs_h\n";
+}
+
+exit 0;