diff options
author | Jack Cummings <jack@mudshark.org> | 2012-10-22 13:43:36 -0700 |
---|---|---|
committer | David Guibert <david.guibert@gmail.com> | 2012-11-15 07:41:11 +0100 |
commit | b61ed12ea35c48cec7f8ef593af83f608f4d707f (patch) | |
tree | cc92ce13ebfe7ccaa4e32ba300310656ce6bf619 /pkgs/os-specific | |
parent | 0611a8b223d76b917059c7267bb7c1d8a5d8e172 (diff) | |
download | nixlib-b61ed12ea35c48cec7f8ef593af83f608f4d707f.tar nixlib-b61ed12ea35c48cec7f8ef593af83f608f4d707f.tar.gz nixlib-b61ed12ea35c48cec7f8ef593af83f608f4d707f.tar.bz2 nixlib-b61ed12ea35c48cec7f8ef593af83f608f4d707f.tar.lz nixlib-b61ed12ea35c48cec7f8ef593af83f608f4d707f.tar.xz nixlib-b61ed12ea35c48cec7f8ef593af83f608f4d707f.tar.zst nixlib-b61ed12ea35c48cec7f8ef593af83f608f4d707f.zip |
Add missing patch
Diffstat (limited to 'pkgs/os-specific')
-rw-r--r-- | pkgs/os-specific/linux/spl/linux-3.6.patch | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/pkgs/os-specific/linux/spl/linux-3.6.patch b/pkgs/os-specific/linux/spl/linux-3.6.patch new file mode 100644 index 000000000000..6b92cdd61ac9 --- /dev/null +++ b/pkgs/os-specific/linux/spl/linux-3.6.patch @@ -0,0 +1,251 @@ +commit bcb15891ab394e11615eee08bba1fd85ac32e158 +Author: Yuxuan Shui <yshuiv7@gmail.com> +Date: Thu Oct 11 22:41:33 2012 +0800 + + Linux 3.6 compat, kern_path_locked() added + + The kern_path_parent() function was removed from Linux 3.6 because + it was observed that all the callers just want the parent dentry. + The simpler kern_path_locked() function replaces kern_path_parent() + and does the lookup while holding the ->i_mutex lock. + + This is good news for the vn implementation because it removes the + need for us to handle the locking. However, it makes it harder to + implement a single readable vn_remove()/vn_rename() function which + is usually what we prefer. + + Therefore, we implement a new version of vn_remove()/vn_rename() + for Linux 3.6 and newer kernels. This allows us to leave the + existing working implementation untouched, and to add a simpler + version for newer kernels. + + Long term I would very much like to see all of the vn code removed + since what this code enabled is generally frowned upon in the kernel. + But that can't happen util we either abondon the zpool.cache file + or implement alternate infrastructure to update is correctly in + user space. + + Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com> + Signed-off-by: Richard Yao <ryao@cs.stonybrook.edu> + Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> + Closes #154 + +diff --git a/config/spl-build.m4 b/config/spl-build.m4 +index 0c7a03c..eb644a1 100644 +--- a/config/spl-build.m4 ++++ b/config/spl-build.m4 +@@ -86,6 +86,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ + SPL_AC_SHRINK_ICACHE_MEMORY + SPL_AC_KERN_PATH_PARENT_HEADER + SPL_AC_KERN_PATH_PARENT_SYMBOL ++ SPL_AC_KERN_PATH_LOCKED + SPL_AC_2ARGS_ZLIB_DEFLATE_WORKSPACESIZE + SPL_AC_SHRINK_CONTROL_STRUCT + SPL_AC_RWSEM_SPINLOCK_IS_RAW +@@ -2188,6 +2189,21 @@ AC_DEFUN([SPL_AC_KERN_PATH_PARENT_SYMBOL], + ]) + + dnl # ++dnl # 3.6 API compat, ++dnl # The kern_path_parent() function was replaced by the kern_path_locked() ++dnl # function to eliminate all struct nameidata usage outside fs/namei.c. ++dnl # ++AC_DEFUN([SPL_AC_KERN_PATH_LOCKED], [ ++ SPL_CHECK_SYMBOL_HEADER( ++ [kern_path_locked], ++ [struct dentry \*kern_path_locked(const char \*, struct path \*)], ++ [include/linux/namei.h], ++ [AC_DEFINE(HAVE_KERN_PATH_LOCKED, 1, ++ [kern_path_locked() is available])], ++ []) ++]) ++ ++dnl # + dnl # 2.6.39 API compat, + dnl # The function zlib_deflate_workspacesize() now take 2 arguments. + dnl # This was done to avoid always having to allocate the maximum size +diff --git a/include/linux/file_compat.h b/include/linux/file_compat.h +index 2b5b7d2..27819d5 100644 +--- a/include/linux/file_compat.h ++++ b/include/linux/file_compat.h +@@ -83,6 +83,12 @@ extern kern_path_parent_t kern_path_parent_fn; + # define spl_kern_path_parent(path, nd) path_lookup(path, LOOKUP_PARENT, nd) + #endif /* HAVE_KERN_PATH_PARENT_HEADER */ + ++#ifdef HAVE_KERN_PATH_LOCKED ++typedef struct dentry * (*kern_path_locked_t)(const char *, struct path *); ++extern kern_path_locked_t kern_path_locked_fn; ++# define spl_kern_path_locked(name, path) kern_path_locked_fn(name, path) ++#endif /* HAVE_KERN_PATH_LOCKED */ ++ + #ifndef HAVE_CLEAR_CLOSE_ON_EXEC + #define __clear_close_on_exec(fd, fdt) FD_CLR(fd, fdt->close_on_exec) + #endif +diff --git a/module/spl/spl-vnode.c b/module/spl/spl-vnode.c +index f5fc65d..a0fed32 100644 +--- a/module/spl/spl-vnode.c ++++ b/module/spl/spl-vnode.c +@@ -50,6 +50,10 @@ EXPORT_SYMBOL(kern_path_parent_fn); + #endif /* HAVE_KERN_PATH_PARENT_SYMBOL */ + #endif /* HAVE_KERN_PATH_PARENT_HEADER */ + ++#ifdef HAVE_KERN_PATH_LOCKED ++kern_path_locked_t kern_path_locked_fn = SYMBOL_POISON; ++#endif /* HAVE_KERN_PATH_LOCKED */ ++ + vtype_t + vn_mode_to_vtype(mode_t mode) + { +@@ -298,6 +302,128 @@ vn_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, void *ct) + } + EXPORT_SYMBOL(vn_seek); + ++#ifdef HAVE_KERN_PATH_LOCKED ++/* Based on do_unlinkat() from linux/fs/namei.c */ ++int ++vn_remove(const char *path, uio_seg_t seg, int flags) ++{ ++ struct dentry *dentry; ++ struct path parent; ++ struct inode *inode = NULL; ++ int rc = 0; ++ SENTRY; ++ ++ ASSERT(seg == UIO_SYSSPACE); ++ ASSERT(flags == RMFILE); ++ ++ dentry = spl_kern_path_locked(path, &parent); ++ rc = PTR_ERR(dentry); ++ if (!IS_ERR(dentry)) { ++ if (parent.dentry->d_name.name[parent.dentry->d_name.len]) ++ SGOTO(slashes, rc = 0); ++ ++ inode = dentry->d_inode; ++ if (!inode) ++ SGOTO(slashes, rc = 0); ++ ++ if (inode) ++ ihold(inode); ++ ++ rc = vfs_unlink(parent.dentry->d_inode, dentry); ++exit1: ++ dput(dentry); ++ } ++ ++ spl_inode_unlock(parent.dentry->d_inode); ++ if (inode) ++ iput(inode); /* truncate the inode here */ ++ ++ path_put(&parent); ++ SRETURN(-rc); ++ ++slashes: ++ rc = !dentry->d_inode ? -ENOENT : ++ S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR; ++ SGOTO(exit1, rc); ++} /* vn_remove() */ ++EXPORT_SYMBOL(vn_remove); ++ ++/* Based on do_rename() from linux/fs/namei.c */ ++int ++vn_rename(const char *oldname, const char *newname, int x1) ++{ ++ struct dentry *old_dir, *new_dir; ++ struct dentry *old_dentry, *new_dentry; ++ struct dentry *trap; ++ struct path old_parent, new_parent; ++ int rc = 0; ++ SENTRY; ++ ++ old_dentry = spl_kern_path_locked(oldname, &old_parent); ++ if (IS_ERR(old_dentry)) ++ SGOTO(exit, rc = PTR_ERR(old_dentry)); ++ ++ spl_inode_unlock(old_parent.dentry->d_inode); ++ ++ new_dentry = spl_kern_path_locked(newname, &new_parent); ++ if (IS_ERR(new_dentry)) ++ SGOTO(exit2, rc = PTR_ERR(new_dentry)); ++ ++ spl_inode_unlock(new_parent.dentry->d_inode); ++ ++ rc = -EXDEV; ++ if (old_parent.mnt != new_parent.mnt) ++ SGOTO(exit3, rc); ++ ++ old_dir = old_parent.dentry; ++ new_dir = new_parent.dentry; ++ trap = lock_rename(new_dir, old_dir); ++ ++ /* source should not be ancestor of target */ ++ rc = -EINVAL; ++ if (old_dentry == trap) ++ SGOTO(exit4, rc); ++ ++ /* target should not be an ancestor of source */ ++ rc = -ENOTEMPTY; ++ if (new_dentry == trap) ++ SGOTO(exit4, rc); ++ ++ /* source must exist */ ++ rc = -ENOENT; ++ if (!old_dentry->d_inode) ++ SGOTO(exit4, rc); ++ ++ /* unless the source is a directory trailing slashes give -ENOTDIR */ ++ if (!S_ISDIR(old_dentry->d_inode->i_mode)) { ++ rc = -ENOTDIR; ++ if (old_dentry->d_name.name[old_dentry->d_name.len]) ++ SGOTO(exit4, rc); ++ if (new_dentry->d_name.name[new_dentry->d_name.len]) ++ SGOTO(exit4, rc); ++ } ++ ++#ifdef HAVE_4ARGS_VFS_RENAME ++ rc = vfs_rename(old_dir->d_inode, old_dentry, ++ new_dir->d_inode, new_dentry); ++#else ++ rc = vfs_rename(old_dir->d_inode, old_dentry, oldnd.nd_mnt, ++ new_dir->d_inode, new_dentry, newnd.nd_mnt); ++#endif /* HAVE_4ARGS_VFS_RENAME */ ++exit4: ++ unlock_rename(new_dir, old_dir); ++exit3: ++ dput(new_dentry); ++ path_put(&new_parent); ++exit2: ++ dput(old_dentry); ++ path_put(&old_parent); ++exit: ++ SRETURN(-rc); ++} ++EXPORT_SYMBOL(vn_rename); ++ ++#else + static struct dentry * + vn_lookup_hash(struct nameidata *nd) + { +@@ -458,6 +584,7 @@ exit: + SRETURN(-rc); + } + EXPORT_SYMBOL(vn_rename); ++#endif /* HAVE_KERN_PATH_LOCKED */ + + int + vn_getattr(vnode_t *vp, vattr_t *vap, int flags, void *x3, void *x4) +@@ -862,6 +989,15 @@ int spl_vn_init_kallsyms_lookup(void) + #endif /* HAVE_KERN_PATH_PARENT_SYMBOL */ + #endif /* HAVE_KERN_PATH_PARENT_HEADER */ + ++#ifdef HAVE_KERN_PATH_LOCKED ++ kern_path_locked_fn = (kern_path_locked_t) ++ spl_kallsyms_lookup_name("kern_path_locked"); ++ if (!kern_path_locked_fn) { ++ printk(KERN_ERR "Error: Unknown symbol kern_path_locked\n"); ++ return -EFAULT; ++ } ++#endif ++ + return (0); + } + |