diff -Naur kernel-source-subfs-0.9.orig/subfs.c kernel-source-subfs-0.9/subfs.c --- kernel-source-subfs-0.9.orig/subfs.c 2009-04-28 10:02:33.000000000 +0400 +++ kernel-source-subfs-0.9/subfs.c 2010-09-05 11:46:10.755440525 +0400 @@ -17,16 +17,33 @@ #include #include #include + +#include "subfs.h" + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) +#include +#include +#endif +#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 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27) +#include +#else #include +#endif #include #include #include +#include -#include "subfs.h" MODULE_LICENSE("GPL"); MODULE_AUTHOR("Eugene S. Weiss"); @@ -47,7 +64,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 +93,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 +122,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; } @@ -111,14 +139,20 @@ */ static void add_procuid(struct subfs_mount *sfs_mnt) { - struct task_struct *task = current; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) + uid_t uid = current->cred->uid; + gid_t gid = current->cred->gid; +#else + uid_t uid = current->uid; + gid_t gid = current->gid; +#endif char *o = kmalloc(strlen(sfs_mnt->options) + 1 + 32 + 1, GFP_KERNEL); if (sfs_mnt->options[0] == '\0') - sprintf(o, "uid=%d,gid=%d", task->uid, task->gid); + sprintf(o, "uid=%d,gid=%d", uid, gid); else - sprintf(o, "%s,uid=%d,gid=%d", sfs_mnt->options, task->uid, task->gid); + sprintf(o, "%s,uid=%d,gid=%d", sfs_mnt->options, uid, gid); kfree(sfs_mnt->options); sfs_mnt->options = o; @@ -137,14 +171,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 +262,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 +312,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 +324,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 +354,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 +452,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 -Naur kernel-source-subfs-0.9.orig/subfs.h kernel-source-subfs-0.9/subfs.h --- kernel-source-subfs-0.9.orig/subfs.h 2009-04-28 10:02:08.000000000 +0400 +++ kernel-source-subfs-0.9/subfs.h 2010-09-05 11:47:21.362640898 +0400 @@ -7,6 +7,11 @@ * or above. */ +#include +#include +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,32) +#include +#endif #define SUBFS_MAGIC 0x2c791058 @@ -33,8 +38,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 +61,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 = {