diff -urN kernel-source-subfs-0.9.orig/subfs.c kernel-source-subfs-0.9/subfs.c --- kernel-source-subfs-0.9.orig/subfs.c 2008-02-14 03:36:44 +0200 +++ kernel-source-subfs-0.9/subfs.c 2008-05-25 03:51:09 +0300 @@ -7,6 +7,7 @@ * or above. */ +#include #include #include #include @@ -17,7 +18,13 @@ #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) +#include +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +#include +#else #include +#endif #include #include #include @@ -25,6 +32,7 @@ #include #include #include +#include #include "subfs.h" @@ -47,7 +56,11 @@ /* Get the head of the global mount list from the init process. */ /* Is there a better way? */ init_fs = init_task.fs; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) + head = &init_fs->root.mnt->mnt_list; +#else head = &init_fs->rootmnt->mnt_list; +#endif /* Go through the list and look for a superblock pointer match. */ list_for_each_safe(entry, lh, head) { @@ -72,10 +85,17 @@ struct vfsmount *old_pwdmnt; write_lock(&fs->lock); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) + old_pwd = fs->pwd.dentry; + old_pwdmnt = fs->pwd.mnt; + fs->pwd.mnt = mntget(mnt); + fs->pwd.dentry = dget(dentry); +#else old_pwd = fs->pwd; old_pwdmnt = fs->pwdmnt; fs->pwdmnt = mntget(mnt); fs->pwd = dget(dentry); +#endif write_unlock(&fs->lock); if (old_pwd) { @@ -94,11 +114,11 @@ struct task_struct *task = current; int signal = SIGCONT; - read_lock(&tasklist_lock); + rcu_read_lock(); spin_lock_irq(&task->sighand->siglock); sigaddset(&task->pending.signal, signal); spin_unlock_irq(&task->sighand->siglock); - read_unlock(&tasklist_lock); + rcu_read_unlock(); set_tsk_thread_flag(task, TIF_SIGPENDING); return; } @@ -137,14 +157,21 @@ char *envp[2] = { "HOME=/", NULL }; char *path_buf; int result, len = 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) + struct path p; +#endif argv[1] = sfs_mnt->device; path_buf = (char *) __get_free_page(GFP_KERNEL); if (!path_buf) return -ENOMEM; - argv[2] = - d_path(sfs_mnt->mount->mnt_mountpoint, - sfs_mnt->mount->mnt_parent, path_buf, PAGE_SIZE); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) + p.mnt = sfs_mnt->mount; + p.dentry = p.mnt->mnt_root; + argv[2] = d_path(&p, path_buf, PAGE_SIZE); +#else + argv[2] = d_path(sfs_mnt->mount->mnt_mountpoint, sfs_mnt->mount->mnt_parent, path_buf, PAGE_SIZE); +#endif argv[3] = sfs_mnt->req_fs; if (!(argv[4] = kmalloc(17, GFP_KERNEL))) { free_page((unsigned long) path_buf); @@ -221,18 +248,35 @@ struct vfsmount *child; /* This is ugly, but prevents a lockup during mount. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) + mutex_unlock(&dir->i_mutex); +#else up(&dir->i_sem); +#endif if (down_interruptible(&sfs_mnt->sem)) { - down(&dir->i_sem);/*put the dir sem back down if interrupted*/ + /*put the dir sem back down if interrupted*/ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) + mutex_lock(&dir->i_mutex); +#else + down(&dir->i_sem); +#endif return ERR_PTR(-ERESTARTSYS); } child = get_child_mount(sfs_mnt); up(&sfs_mnt->sem); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) + mutex_lock(&dir->i_mutex); +#else down(&dir->i_sem); +#endif if (IS_ERR(child)) return (void *) child; subfs_send_signal(); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) + if (sfs_mnt->mount == current->fs->pwd.mnt) +#else if (sfs_mnt->mount == current->fs->pwdmnt) +#endif subfs_set_fs_pwd(current->fs, child, child->mnt_root); return ERR_PTR(-ERESTARTSYS); } @@ -254,7 +298,11 @@ if (IS_ERR(child)) return PTR_ERR(child); subfs_send_signal(); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) + if (sfs_mnt->mount == current->fs->pwd.mnt) +#else if (sfs_mnt->mount == current->fs->pwdmnt) +#endif subfs_set_fs_pwd(current->fs, child, child->mnt_root); return -ERESTARTSYS; } @@ -262,9 +310,15 @@ /* Implements the statfs method so df and such will work on the mountpoint. */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17) +static int subfs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct subfs_mount *sfs_mnt = dentry->d_sb->s_fs_info; +#else static int subfs_statfs(struct super_block *sb, struct kstatfs *buf) { struct subfs_mount *sfs_mnt = sb->s_fs_info; +#endif struct vfsmount *child; if (down_interruptible(&sfs_mnt->sem)) return -ERESTARTSYS; @@ -286,7 +340,9 @@ if (ret) { ret->i_mode = mode; ret->i_uid = ret->i_gid = 0; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) ret->i_blksize = PAGE_CACHE_SIZE; +#endif ret->i_blocks = 0; ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME; ret->i_fop = &subfs_file_ops; @@ -382,33 +438,61 @@ * subfs_mount structure is pointed to by the s_fs_info field of the * superblock structure. */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17) +static int subfs_get_super(struct file_system_type *fst, + int flags, const char *devname, void *data, + struct vfsmount *mnt) +#else static struct super_block *subfs_get_super(struct file_system_type *fst, int flags, const char *devname, void *data) +#endif { char *device; struct subfs_mount *newmount; int ret; - if (!(newmount = kmalloc(sizeof(struct subfs_mount), GFP_KERNEL))) - return ERR_PTR(-ENOMEM); + if (!(newmount = kmalloc(sizeof(struct subfs_mount), GFP_KERNEL))) { + ret = -ENOMEM; + goto err; + } newmount->req_fs = NULL; newmount->sb = NULL; newmount->mount = NULL; newmount->procuid = 0; sema_init(&newmount->sem, 1); - if (!(device = kmalloc((strlen(devname) + 1), GFP_KERNEL))) - return ERR_PTR(-ENOMEM); + if (!(device = kmalloc((strlen(devname) + 1), GFP_KERNEL))) { + ret = -ENOMEM; + goto err; + } strcpy(device, devname); newmount->device = device; if (!(newmount->helper_prog = - kmalloc(sizeof(SUBMOUNTD_PATH), GFP_KERNEL))) - return ERR_PTR(-ENOMEM); + kmalloc(sizeof(SUBMOUNTD_PATH), GFP_KERNEL))) { + ret = -ENOMEM; + goto err; + } strcpy(newmount->helper_prog, SUBMOUNTD_PATH); if ((ret = proc_opts(newmount, data))) - return ERR_PTR(ret); + goto err; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17) + ret = get_sb_nodev(fst, flags, data, subfs_fill_super, mnt); + if (ret) + goto err; + newmount->sb = mnt->mnt_sb; + newmount->sb->s_fs_info = newmount; + return ret; +#else newmount->sb = get_sb_nodev(fst, flags, data, subfs_fill_super); newmount->sb->s_fs_info = newmount; return newmount->sb; +#endif + +err: +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17) + return ret; +#else + return ERR_PTR(ret); +#endif } diff -urN kernel-source-subfs-0.9.orig/subfs.h kernel-source-subfs-0.9/subfs.h --- kernel-source-subfs-0.9.orig/subfs.h 2008-02-14 03:36:44 +0200 +++ kernel-source-subfs-0.9/subfs.h 2008-05-25 03:51:05 +0300 @@ -7,6 +7,7 @@ * or above. */ +#include #define SUBFS_MAGIC 0x2c791058 @@ -33,8 +34,17 @@ static void subfs_kill_super(struct super_block *sb); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17) +static int subfs_get_super(struct file_system_type *fst, + int flags, const char *devname, void *data, struct vfsmount *mnt); +static int subfs_statfs(struct dentry *dentry, struct kstatfs *buf); +#else static struct super_block *subfs_get_super(struct file_system_type *fst, int flags, const char *devname, void *data); +static int subfs_statfs(struct super_block *sb, struct kstatfs *buf); +#endif + static struct vfsmount *get_subfs_vfsmount(struct super_block *sb); static int subfs_fill_super(struct super_block *sb, void *data, int silent); @@ -47,7 +57,6 @@ static void subfs_send_signal(void); static void subfs_set_fs_pwd(struct fs_struct *fs, struct vfsmount *mnt, struct dentry *dentry); -static int subfs_statfs(struct super_block *sb, struct kstatfs *buf); static struct file_system_type subfs_type = {