diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 7e51d2cec64b..bee3dd3be323 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -92,60 +92,39 @@ __uml_setup("hostfs=", hostfs_args, ); #endif -static char *__dentry_name(struct dentry *dentry, char *name) +static char *dentry_name(struct dentry *dentry, char *name) { - char *p = dentry_path_raw(dentry, name, PATH_MAX); - char *root; - size_t len; - struct hostfs_fs_info *fsi; + struct hostfs_fs_info *fsi = dentry->d_sb->s_fs_info; + char *root = fsi->host_root_path; + size_t len = strlen(root); + char *p; - fsi = dentry->d_sb->s_fs_info; - root = fsi->host_root_path; - len = strlen(root); - if (IS_ERR(p)) { - __putname(name); + if (!name) return NULL; - } - - /* - * This function relies on the fact that dentry_path_raw() will place - * the path name at the end of the provided buffer. - */ - BUG_ON(p + strlen(p) + 1 != name + PATH_MAX); - strscpy(name, root, PATH_MAX); - if (len > p - name) { - __putname(name); + p = dentry_path_raw(dentry, name, PATH_MAX); + if (IS_ERR(p)) return NULL; - } - - if (p > name + len) - strcpy(name + len, p); - return name; -} - -static char *dentry_name(struct dentry *dentry) -{ - char *name = __getname(); - if (!name) + if (len > p - name) return NULL; - return __dentry_name(dentry, name); + memcpy(p - len, root, len); + return p - len; } -static char *inode_name(struct inode *ino) -{ - struct dentry *dentry; - char *name; +DEFINE_FREE(__putname, void *, if (_T) __putname(_T)) +#define NAME_BUFFER(name) void *name __free(__putname) = __getname() - dentry = d_find_alias(ino); - if (!dentry) - return NULL; - - name = dentry_name(dentry); +static char *inode_name(struct inode *ino, char *buf) +{ + char *name = NULL; + struct dentry *dentry = d_find_alias(ino); - dput(dentry); + if (dentry) { + name = dentry_name(dentry, buf); + dput(dentry); + } return name; } @@ -284,16 +263,16 @@ static const struct super_operations hostfs_sbops = { static int hostfs_readdir(struct file *file, struct dir_context *ctx) { void *dir; + NAME_BUFFER(buf); char *name; unsigned long long next, ino; int error, len; unsigned int type; - name = dentry_name(file->f_path.dentry); + name = dentry_name(file->f_path.dentry, buf); if (name == NULL) return -ENOMEM; dir = open_dir(name, &error); - __putname(name); if (dir == NULL) return -error; next = ctx->pos; @@ -320,6 +299,8 @@ static int hostfs_open(struct inode *ino, struct file *file) mode |= HOSTFS_I(ino)->mode; + NAME_BUFFER(buf); + retry: r = w = 0; @@ -328,12 +309,11 @@ static int hostfs_open(struct inode *ino, struct file *file) if (mode & FMODE_WRITE) r = w = 1; - name = dentry_name(file_dentry(file)); + name = dentry_name(file_dentry(file), buf); if (name == NULL) return -ENOMEM; fd = open_file(name, r, w, append); - __putname(name); if (fd < 0) return fd; @@ -607,22 +587,20 @@ static struct inode *hostfs_iget(struct super_block *sb, char *name) static int hostfs_create(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode, bool excl) { + NAME_BUFFER(buf); struct inode *inode; char *name; int fd; - name = dentry_name(dentry); + name = dentry_name(dentry, buf); if (name == NULL) return -ENOMEM; fd = file_create(name, mode & 0777); - if (fd < 0) { - __putname(name); + if (fd < 0) return fd; - } inode = hostfs_iget(dir->i_sb, name); - __putname(name); if (IS_ERR(inode)) return PTR_ERR(inode); @@ -635,15 +613,15 @@ static int hostfs_create(struct mnt_idmap *idmap, struct inode *dir, static struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, unsigned int flags) { - struct inode *inode = NULL; + struct inode *inode; + NAME_BUFFER(buf); char *name; - name = dentry_name(dentry); + name = dentry_name(dentry, buf); if (name == NULL) return ERR_PTR(-ENOMEM); inode = hostfs_iget(ino->i_sb, name); - __putname(name); if (inode == ERR_PTR(-ENOENT)) inode = NULL; @@ -653,95 +631,77 @@ static struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry, static int hostfs_link(struct dentry *to, struct inode *ino, struct dentry *from) { - char *from_name, *to_name; - int err; + NAME_BUFFER(from_buf); + NAME_BUFFER(to_buf); + char *from_name = dentry_name(from, from_buf); + char *to_name = dentry_name(to, to_buf); - if ((from_name = dentry_name(from)) == NULL) - return -ENOMEM; - to_name = dentry_name(to); - if (to_name == NULL) { - __putname(from_name); + if (!from_name || !to_name) return -ENOMEM; - } - err = link_file(to_name, from_name); - __putname(from_name); - __putname(to_name); - return err; + return link_file(to_name, from_name); } static int hostfs_unlink(struct inode *ino, struct dentry *dentry) { - char *file; - int err; - if (append) return -EPERM; - if ((file = dentry_name(dentry)) == NULL) - return -ENOMEM; + NAME_BUFFER(buf); + char *file = dentry_name(dentry, buf); - err = unlink_file(file); - __putname(file); - return err; + if (!file) + return -ENOMEM; + return unlink_file(file); } static int hostfs_symlink(struct mnt_idmap *idmap, struct inode *ino, struct dentry *dentry, const char *to) { - char *file; - int err; + NAME_BUFFER(buf); + char *file = dentry_name(dentry, buf); - if ((file = dentry_name(dentry)) == NULL) + if (!file) return -ENOMEM; - err = make_symlink(file, to); - __putname(file); - return err; + return make_symlink(file, to); } static int hostfs_mkdir(struct mnt_idmap *idmap, struct inode *ino, struct dentry *dentry, umode_t mode) { - char *file; - int err; + NAME_BUFFER(buf); + char *file = dentry_name(dentry, buf); - if ((file = dentry_name(dentry)) == NULL) + if (!file) return -ENOMEM; - err = do_mkdir(file, mode); - __putname(file); - return err; + return do_mkdir(file, mode); } static int hostfs_rmdir(struct inode *ino, struct dentry *dentry) { - char *file; - int err; + NAME_BUFFER(buf); + char *file = dentry_name(dentry, buf); - if ((file = dentry_name(dentry)) == NULL) + if (!file) return -ENOMEM; - err = hostfs_do_rmdir(file); - __putname(file); - return err; + return hostfs_do_rmdir(file); } static int hostfs_mknod(struct mnt_idmap *idmap, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) { + NAME_BUFFER(buf); + char *name = dentry_name(dentry, buf); struct inode *inode; - char *name; int err; - name = dentry_name(dentry); if (name == NULL) return -ENOMEM; err = do_mknod(name, mode, MAJOR(dev), MINOR(dev)); - if (err) { - __putname(name); + if (err) return err; - } inode = hostfs_iget(dir->i_sb, name); - __putname(name); if (IS_ERR(inode)) return PTR_ERR(inode); @@ -754,28 +714,21 @@ static int hostfs_rename2(struct mnt_idmap *idmap, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) { - char *old_name, *new_name; - int err; + NAME_BUFFER(old_buf); + NAME_BUFFER(new_buf); + char *old_name = dentry_name(old_dentry, old_buf); + char *new_name = dentry_name(new_dentry, new_buf); if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE)) return -EINVAL; - old_name = dentry_name(old_dentry); - if (old_name == NULL) + if (!old_name || !new_name) return -ENOMEM; - new_name = dentry_name(new_dentry); - if (new_name == NULL) { - __putname(old_name); - return -ENOMEM; - } + if (!flags) - err = rename_file(old_name, new_name); + return rename_file(old_name, new_name); else - err = rename2_file(old_name, new_name, flags); - - __putname(old_name); - __putname(new_name); - return err; + return rename2_file(old_name, new_name, flags); } static int hostfs_permission(struct mnt_idmap *idmap, @@ -790,7 +743,10 @@ static int hostfs_permission(struct mnt_idmap *idmap, if (desired & MAY_READ) r = 1; if (desired & MAY_WRITE) w = 1; if (desired & MAY_EXEC) x = 1; - name = inode_name(ino); + + NAME_BUFFER(buf); + + name = inode_name(ino, buf); if (name == NULL) return -ENOMEM; @@ -799,7 +755,6 @@ static int hostfs_permission(struct mnt_idmap *idmap, err = 0; else err = access_file(name, r, w, x); - __putname(name); if (!err) err = generic_permission(&nop_mnt_idmap, ino, desired); return err; @@ -860,11 +815,13 @@ static int hostfs_setattr(struct mnt_idmap *idmap, if (attr->ia_valid & ATTR_MTIME_SET) { attrs.ia_valid |= HOSTFS_ATTR_MTIME_SET; } - name = dentry_name(dentry); + + NAME_BUFFER(buf); + + name = dentry_name(dentry, buf); if (name == NULL) return -ENOMEM; err = set_attr(name, &attrs, fd); - __putname(name); if (err) return err; @@ -905,13 +862,13 @@ static const char *hostfs_get_link(struct dentry *dentry, return ERR_PTR(-ECHILD); link = kmalloc(PATH_MAX, GFP_KERNEL); if (link) { - char *path = dentry_name(dentry); + NAME_BUFFER(buf); + char *path = dentry_name(dentry, buf); int err = -ENOMEM; if (path) { err = hostfs_do_readlink(path, link, PATH_MAX); if (err == PATH_MAX) err = -E2BIG; - __putname(path); } if (err < 0) { kfree(link);