From 28c7cb9dfeb5d473d2b6cbe9b396b4bfc3f1f5af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arkadiusz=20Buba=C5=82a?= Date: Fri, 8 Sep 2017 12:14:29 +0200 Subject: [PATCH] Introduced spl_dirname function. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 8bcb77fabd7cbabcad49f58750be8683febee92b in kernel tree the logic for getting parent path doesn't work. The parent points to the file itself instead of its parent path. This results that the cache file for pool is never removed. The new function returns parent directory where the file is placed. Then kern_path is executed with the parent directory name and the LOOKUP_DIR flag. Returned parent structure will point to correct parent path. Signed-off-by: Arkadiusz BubaƂa --- module/spl/spl-vnode.c | 52 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/module/spl/spl-vnode.c b/module/spl/spl-vnode.c index 346e63c0..734c53a3 100644 --- a/module/spl/spl-vnode.c +++ b/module/spl/spl-vnode.c @@ -328,12 +328,56 @@ spl_basename(const char *s, const char **str, int *len) *len = end + 1; } +/* + * spl_dirname() takes a NULL-terminated string s as input containing a path. + * Returns pointer to a string containing the directory name or NULL + * on allocation failure. Returned pointer must be freed after use. + */ + +static char * +spl_dirname(const char *name) +{ + size_t i; + + char *dirname = kmalloc(strlen(name), kmem_flags_convert(KM_SLEEP)); + if (!dirname) + return dirname; + + if (!name || !*name) { + dirname[0] = '.'; + dirname[1] = '\0'; + return dirname; + } + + i = strlen(name) - 1; + + while (i && name[i--] != '/'); + + if (i == 0) { + dirname[0] = '/'; + dirname[1] = '\0'; + return dirname; + } + + ++i; + + dirname[i] = '\0'; + while(i) { + --i; + dirname[i] = name[i]; + } + + return dirname; +} + + static struct dentry * spl_kern_path_locked(const char *name, struct path *path) { struct path parent; struct dentry *dentry; const char *basename; + char *dirname; int len; int rc; @@ -347,10 +391,16 @@ spl_kern_path_locked(const char *name, struct path *path) if (len == 1 || basename[1] == '.') return (ERR_PTR(-EACCES)); - rc = kern_path(name, LOOKUP_PARENT, &parent); + dirname = spl_dirname(name); + if (!dirname) + return (ERR_PTR(-ENOMEM)); + + rc = kern_path(dirname, LOOKUP_DIR, &parent); if (rc) return (ERR_PTR(rc)); + kfree(dirname); + /* use I_MUTEX_PARENT because vfs_unlink needs it */ spl_inode_lock_nested(parent.dentry->d_inode, I_MUTEX_PARENT);