diff options
Diffstat (limited to 'fs/9p/vfs_inode.c')
-rw-r--r-- | fs/9p/vfs_inode.c | 329 |
1 files changed, 164 insertions, 165 deletions
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index b82423a72f68..4d1a4a8d9277 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * linux/fs/9p/vfs_inode.c - * * This file contains vfs inode ops for the 9P2000 protocol. * * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> @@ -49,6 +47,7 @@ static const struct inode_operations v9fs_symlink_inode_operations; static u32 unixmode2p9mode(struct v9fs_session_info *v9ses, umode_t mode) { int res; + res = mode & 0777; if (S_ISDIR(mode)) res |= P9_DMDIR; @@ -110,7 +109,7 @@ static int p9mode2perm(struct v9fs_session_info *v9ses, static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses, struct p9_wstat *stat, dev_t *rdev) { - int res; + int res, r; u32 mode = stat->mode; *rdev = 0; @@ -128,11 +127,16 @@ static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses, res |= S_IFIFO; else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses)) && (v9ses->nodev == 0)) { - char type = 0, ext[32]; + char type = 0; int major = -1, minor = -1; - strlcpy(ext, stat->extension, sizeof(ext)); - sscanf(ext, "%c %i %i", &type, &major, &minor); + r = sscanf(stat->extension, "%c %i %i", &type, &major, &minor); + if (r != 3) { + p9_debug(P9_DEBUG_ERROR, + "invalid device string, umode will be bogus: %s\n", + stat->extension); + return res; + } switch (type) { case 'c': res |= S_IFCHR; @@ -143,7 +147,7 @@ static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses, default: p9_debug(P9_DEBUG_ERROR, "Unknown special type %c %s\n", type, stat->extension); - }; + } *rdev = MKDEV(major, minor); } else res |= S_IFREG; @@ -218,28 +222,24 @@ v9fs_blank_wstat(struct p9_wstat *wstat) /** * v9fs_alloc_inode - helper function to allocate an inode - * + * @sb: The superblock to allocate the inode from */ struct inode *v9fs_alloc_inode(struct super_block *sb) { struct v9fs_inode *v9inode; - v9inode = (struct v9fs_inode *)kmem_cache_alloc(v9fs_inode_cache, - GFP_KERNEL); + + v9inode = alloc_inode_sb(sb, v9fs_inode_cache, GFP_KERNEL); if (!v9inode) return NULL; -#ifdef CONFIG_9P_FSCACHE - v9inode->fscache = NULL; - mutex_init(&v9inode->fscache_lock); -#endif v9inode->writeback_fid = NULL; v9inode->cache_validity = 0; mutex_init(&v9inode->v_mutex); - return &v9inode->vfs_inode; + return &v9inode->netfs.inode; } /** * v9fs_free_inode - destroy an inode - * + * @inode: The inode to be freed */ void v9fs_free_inode(struct inode *inode) @@ -247,16 +247,26 @@ void v9fs_free_inode(struct inode *inode) kmem_cache_free(v9fs_inode_cache, V9FS_I(inode)); } +/* + * Set parameters for the netfs library + */ +static void v9fs_set_netfs_context(struct inode *inode) +{ + struct v9fs_inode *v9inode = V9FS_I(inode); + netfs_inode_init(&v9inode->netfs, &v9fs_req_ops); +} + int v9fs_init_inode(struct v9fs_session_info *v9ses, struct inode *inode, umode_t mode, dev_t rdev) { int err = 0; - inode_init_owner(inode, NULL, mode); + inode_init_owner(&init_user_ns, inode, NULL, mode); inode->i_blocks = 0; inode->i_rdev = rdev; inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode); inode->i_mapping->a_ops = &v9fs_addr_operations; + inode->i_private = NULL; switch (mode & S_IFMT) { case S_IFIFO: @@ -334,6 +344,8 @@ int v9fs_init_inode(struct v9fs_session_info *v9ses, err = -EINVAL; goto error; } + + v9fs_set_netfs_context(inode); error: return err; @@ -343,7 +355,7 @@ error: * v9fs_get_inode - helper function to setup an inode * @sb: superblock * @mode: mode to setup inode with - * + * @rdev: The device numbers to set */ struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t rdev) @@ -368,78 +380,27 @@ struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t rdev) return inode; } -/* -static struct v9fs_fid* -v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) -{ - int err; - int nfid; - struct v9fs_fid *ret; - struct v9fs_fcall *fcall; - - nfid = v9fs_get_idpool(&v9ses->fidpool); - if (nfid < 0) { - eprintk(KERN_WARNING, "no free fids available\n"); - return ERR_PTR(-ENOSPC); - } - - err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name, - &fcall); - - if (err < 0) { - if (fcall && fcall->id == RWALK) - goto clunk_fid; - - PRINT_FCALL_ERROR("walk error", fcall); - v9fs_put_idpool(nfid, &v9ses->fidpool); - goto error; - } - - kfree(fcall); - fcall = NULL; - ret = v9fs_fid_create(v9ses, nfid); - if (!ret) { - err = -ENOMEM; - goto clunk_fid; - } - - err = v9fs_fid_insert(ret, dentry); - if (err < 0) { - v9fs_fid_destroy(ret); - goto clunk_fid; - } - - return ret; - -clunk_fid: - v9fs_t_clunk(v9ses, nfid); - -error: - kfree(fcall); - return ERR_PTR(err); -} -*/ - - /** - * v9fs_clear_inode - release an inode + * v9fs_evict_inode - Remove an inode from the inode cache * @inode: inode to release * */ void v9fs_evict_inode(struct inode *inode) { struct v9fs_inode *v9inode = V9FS_I(inode); + __le32 version; truncate_inode_pages_final(&inode->i_data); + version = cpu_to_le32(v9inode->qid.version); + fscache_clear_inode_writeback(v9fs_inode_cookie(v9inode), inode, + &version); clear_inode(inode); filemap_fdatawrite(&inode->i_data); - v9fs_cache_inode_put_cookie(inode); + fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false); /* clunk the fid stashed in writeback_fid */ - if (v9inode->writeback_fid) { - p9_client_clunk(v9inode->writeback_fid); - v9inode->writeback_fid = NULL; - } + p9_fid_put(v9inode->writeback_fid); + v9inode->writeback_fid = NULL; } static int v9fs_test_inode(struct inode *inode, void *data) @@ -452,7 +413,7 @@ static int v9fs_test_inode(struct inode *inode, void *data) umode = p9mode2unixmode(v9ses, st, &rdev); /* don't match inode of different type */ - if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) + if (inode_wrong_type(inode, umode)) return 0; /* compare qid details */ @@ -493,7 +454,7 @@ static struct inode *v9fs_qid_iget(struct super_block *sb, unsigned long i_ino; struct inode *inode; struct v9fs_session_info *v9ses = sb->s_fs_info; - int (*test)(struct inode *, void *); + int (*test)(struct inode *inode, void *data); if (new) test = v9fs_test_new_inode; @@ -552,8 +513,10 @@ v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, static int v9fs_at_to_dotl_flags(int flags) { int rflags = 0; + if (flags & AT_REMOVEDIR) rflags |= P9_DOTL_AT_REMOVEDIR; + return rflags; } @@ -604,6 +567,7 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags) if (v9fs_proto_dotl(v9ses)) retval = p9_client_unlinkat(dfid, dentry->d_name.name, v9fs_at_to_dotl_flags(flags)); + p9_fid_put(dfid); if (retval == -EOPNOTSUPP) { /* Try the one based on path */ v9fid = v9fs_fid_clone(dentry); @@ -624,6 +588,10 @@ static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags) v9fs_invalidate_inode_attr(inode); v9fs_invalidate_inode_attr(dir); + + /* invalidate all fids associated with dentry */ + /* NOTE: This will not include open fids */ + dentry->d_op->d_release(dentry); } return retval; } @@ -644,14 +612,12 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, { int err; const unsigned char *name; - struct p9_fid *dfid, *ofid, *fid; + struct p9_fid *dfid, *ofid = NULL, *fid = NULL; struct inode *inode; p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry); err = 0; - ofid = NULL; - fid = NULL; name = dentry->d_name.name; dfid = v9fs_parent_fid(dentry); if (IS_ERR(dfid)) { @@ -665,7 +631,7 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, if (IS_ERR(ofid)) { err = PTR_ERR(ofid); p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); - return ERR_PTR(err); + goto error; } err = p9_client_fcreate(ofid, name, perm, mode, extension); @@ -681,7 +647,6 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, err = PTR_ERR(fid); p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); - fid = NULL; goto error; } /* @@ -694,35 +659,34 @@ v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, "inode creation failed %d\n", err); goto error; } - v9fs_fid_add(dentry, fid); + v9fs_fid_add(dentry, &fid); d_instantiate(dentry, inode); } + p9_fid_put(dfid); return ofid; error: - if (ofid) - p9_client_clunk(ofid); - - if (fid) - p9_client_clunk(fid); - + p9_fid_put(dfid); + p9_fid_put(ofid); + p9_fid_put(fid); return ERR_PTR(err); } /** * v9fs_vfs_create - VFS hook to create a regular file + * @mnt_userns: The user namespace of the mount + * @dir: The parent directory + * @dentry: The name of file to be created + * @mode: The UNIX file mode to set + * @excl: True if the file must not yet exist * * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open(). This is only called * for mknod(2). * - * @dir: directory inode that is being created - * @dentry: dentry that is being deleted - * @mode: create permissions - * */ static int -v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, - bool excl) +v9fs_vfs_create(struct user_namespace *mnt_userns, struct inode *dir, + struct dentry *dentry, umode_t mode, bool excl) { struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); u32 perm = unixmode2p9mode(v9ses, mode); @@ -734,20 +698,22 @@ v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, return PTR_ERR(fid); v9fs_invalidate_inode_attr(dir); - p9_client_clunk(fid); + p9_fid_put(fid); return 0; } /** * v9fs_vfs_mkdir - VFS mkdir hook to create a directory + * @mnt_userns: The user namespace of the mount * @dir: inode that is being unlinked * @dentry: dentry that is being unlinked * @mode: mode for new directory * */ -static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +static int v9fs_vfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir, + struct dentry *dentry, umode_t mode) { int err; u32 perm; @@ -768,7 +734,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode } if (fid) - p9_client_clunk(fid); + p9_fid_put(fid); return err; } @@ -809,6 +775,7 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, */ name = dentry->d_name.name; fid = p9_client_walk(dfid, 1, &name, 1); + p9_fid_put(dfid); if (fid == ERR_PTR(-ENOENT)) inode = NULL; else if (IS_ERR(fid)) @@ -827,18 +794,18 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, res = d_splice_alias(inode, dentry); if (!IS_ERR(fid)) { if (!res) - v9fs_fid_add(dentry, fid); + v9fs_fid_add(dentry, &fid); else if (!IS_ERR(res)) - v9fs_fid_add(res, fid); + v9fs_fid_add(res, &fid); else - p9_client_clunk(fid); + p9_fid_put(fid); } return res; } static int v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, - struct file *file, unsigned flags, umode_t mode) + struct file *file, unsigned int flags, umode_t mode) { int err; u32 perm; @@ -846,6 +813,7 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, struct v9fs_session_info *v9ses; struct p9_fid *fid, *inode_fid; struct dentry *res = NULL; + struct inode *inode; if (d_in_lookup(dentry)) { res = v9fs_vfs_lookup(dir, dentry, 0); @@ -869,12 +837,12 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, v9fs_proto_dotu(v9ses))); if (IS_ERR(fid)) { err = PTR_ERR(fid); - fid = NULL; goto error; } v9fs_invalidate_inode_attr(dir); - v9inode = V9FS_I(d_inode(dentry)); + inode = d_inode(dentry); + v9inode = V9FS_I(inode); mutex_lock(&v9inode->v_mutex); if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) && !v9inode->writeback_fid && @@ -901,7 +869,9 @@ v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, file->private_data = fid; if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) - v9fs_cache_inode_set_cookie(d_inode(dentry), file); + fscache_use_cookie(v9fs_inode_cookie(v9inode), + file->f_mode & FMODE_WRITE); + v9fs_open_fid_add(inode, &fid); file->f_mode |= FMODE_CREATED; out: @@ -909,8 +879,7 @@ out: return err; error: - if (fid) - p9_client_clunk(fid); + p9_fid_put(fid); goto out; } @@ -940,25 +909,27 @@ int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) /** * v9fs_vfs_rename - VFS hook to rename an inode + * @mnt_userns: The user namespace of the mount * @old_dir: old dir inode * @old_dentry: old dentry * @new_dir: new dir inode * @new_dentry: new dentry + * @flags: RENAME_* flags * */ int -v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry, - unsigned int flags) +v9fs_vfs_rename(struct user_namespace *mnt_userns, struct inode *old_dir, + struct dentry *old_dentry, struct inode *new_dir, + struct dentry *new_dentry, unsigned int flags) { int retval; struct inode *old_inode; struct inode *new_inode; struct v9fs_session_info *v9ses; - struct p9_fid *oldfid; - struct p9_fid *olddirfid; - struct p9_fid *newdirfid; + struct p9_fid *oldfid = NULL, *dfid = NULL; + struct p9_fid *olddirfid = NULL; + struct p9_fid *newdirfid = NULL; struct p9_wstat wstat; if (flags) @@ -973,16 +944,24 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, if (IS_ERR(oldfid)) return PTR_ERR(oldfid); - olddirfid = clone_fid(v9fs_parent_fid(old_dentry)); + dfid = v9fs_parent_fid(old_dentry); + olddirfid = clone_fid(dfid); + p9_fid_put(dfid); + dfid = NULL; + if (IS_ERR(olddirfid)) { retval = PTR_ERR(olddirfid); - goto done; + goto error; } - newdirfid = clone_fid(v9fs_parent_fid(new_dentry)); + dfid = v9fs_parent_fid(new_dentry); + newdirfid = clone_fid(dfid); + p9_fid_put(dfid); + dfid = NULL; + if (IS_ERR(newdirfid)) { retval = PTR_ERR(newdirfid); - goto clunk_olddir; + goto error; } down_write(&v9ses->rename_sem); @@ -993,7 +972,7 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, retval = p9_client_rename(oldfid, newdirfid, new_dentry->d_name.name); if (retval != -EOPNOTSUPP) - goto clunk_newdir; + goto error_locked; } if (old_dentry->d_parent != new_dentry->d_parent) { /* @@ -1002,14 +981,14 @@ v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n"); retval = -EXDEV; - goto clunk_newdir; + goto error_locked; } v9fs_blank_wstat(&wstat); wstat.muid = v9ses->uname; wstat.name = new_dentry->d_name.name; retval = p9_client_wstat(oldfid, &wstat); -clunk_newdir: +error_locked: if (!retval) { if (new_inode) { if (S_ISDIR(new_inode->i_mode)) @@ -1030,17 +1009,17 @@ clunk_newdir: d_move(old_dentry, new_dentry); } up_write(&v9ses->rename_sem); - p9_client_clunk(newdirfid); -clunk_olddir: - p9_client_clunk(olddirfid); - -done: +error: + p9_fid_put(newdirfid); + p9_fid_put(olddirfid); + p9_fid_put(oldfid); return retval; } /** * v9fs_vfs_getattr - retrieve file metadata + * @mnt_userns: The user namespace of the mount * @path: Object to query * @stat: metadata structure to populate * @request_mask: Mask of STATX_xxx flags indicating the caller's interests @@ -1049,8 +1028,8 @@ done: */ static int -v9fs_vfs_getattr(const struct path *path, struct kstat *stat, - u32 request_mask, unsigned int flags) +v9fs_vfs_getattr(struct user_namespace *mnt_userns, const struct path *path, + struct kstat *stat, u32 request_mask, unsigned int flags) { struct dentry *dentry = path->dentry; struct v9fs_session_info *v9ses; @@ -1060,7 +1039,7 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat, p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); v9ses = v9fs_dentry2v9ses(dentry); if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - generic_fillattr(d_inode(dentry), stat); + generic_fillattr(&init_user_ns, d_inode(dentry), stat); return 0; } fid = v9fs_fid_lookup(dentry); @@ -1068,11 +1047,12 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat, return PTR_ERR(fid); st = p9_client_stat(fid); + p9_fid_put(fid); if (IS_ERR(st)) return PTR_ERR(st); v9fs_stat2inode(st, d_inode(dentry), dentry->d_sb, 0); - generic_fillattr(d_inode(dentry), stat); + generic_fillattr(&init_user_ns, d_inode(dentry), stat); p9stat_free(st); kfree(st); @@ -1081,27 +1061,38 @@ v9fs_vfs_getattr(const struct path *path, struct kstat *stat, /** * v9fs_vfs_setattr - set file metadata + * @mnt_userns: The user namespace of the mount * @dentry: file whose metadata to set * @iattr: metadata assignment structure * */ -static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) +static int v9fs_vfs_setattr(struct user_namespace *mnt_userns, + struct dentry *dentry, struct iattr *iattr) { - int retval; + int retval, use_dentry = 0; + struct inode *inode = d_inode(dentry); + struct v9fs_inode *v9inode = V9FS_I(inode); struct v9fs_session_info *v9ses; - struct p9_fid *fid; + struct p9_fid *fid = NULL; struct p9_wstat wstat; p9_debug(P9_DEBUG_VFS, "\n"); - retval = setattr_prepare(dentry, iattr); + retval = setattr_prepare(&init_user_ns, dentry, iattr); if (retval) return retval; retval = -EPERM; v9ses = v9fs_dentry2v9ses(dentry); - fid = v9fs_fid_lookup(dentry); - if(IS_ERR(fid)) + if (iattr->ia_valid & ATTR_FILE) { + fid = iattr->ia_file->private_data; + WARN_ON(!fid); + } + if (!fid) { + fid = v9fs_fid_lookup(dentry); + use_dentry = 1; + } + if (IS_ERR(fid)) return PTR_ERR(fid); v9fs_blank_wstat(&wstat); @@ -1127,20 +1118,26 @@ static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) /* Write all dirty data */ if (d_is_reg(dentry)) - filemap_write_and_wait(d_inode(dentry)->i_mapping); + filemap_write_and_wait(inode->i_mapping); retval = p9_client_wstat(fid, &wstat); + + if (use_dentry) + p9_fid_put(fid); + if (retval < 0) return retval; if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(d_inode(dentry))) - truncate_setsize(d_inode(dentry), iattr->ia_size); + iattr->ia_size != i_size_read(inode)) { + truncate_setsize(inode, iattr->ia_size); + fscache_resize_cookie(v9fs_inode_cookie(v9inode), iattr->ia_size); + } - v9fs_invalidate_inode_attr(d_inode(dentry)); + v9fs_invalidate_inode_attr(inode); - setattr_copy(d_inode(dentry), iattr); - mark_inode_dirty(d_inode(dentry)); + setattr_copy(&init_user_ns, inode, iattr); + mark_inode_dirty(inode); return 0; } @@ -1158,9 +1155,6 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, struct super_block *sb, unsigned int flags) { umode_t mode; - char ext[32]; - char tag_name[14]; - unsigned int i_nlink; struct v9fs_session_info *v9ses = sb->s_fs_info; struct v9fs_inode *v9inode = V9FS_I(inode); @@ -1178,18 +1172,18 @@ v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, inode->i_gid = stat->n_gid; } if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) { - if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) { + if (v9fs_proto_dotu(v9ses)) { + unsigned int i_nlink; /* - * Hadlink support got added later to - * to the .u extension. So there can be - * server out there that doesn't support - * this even with .u extension. So check - * for non NULL stat->extension + * Hadlink support got added later to the .u extension. + * So there can be a server out there that doesn't + * support this even with .u extension. That would + * just leave us with stat->extension being an empty + * string, though. */ - strlcpy(ext, stat->extension, sizeof(ext)); /* HARDLINKCOUNT %u */ - sscanf(ext, "%13s %u", tag_name, &i_nlink); - if (!strncmp(tag_name, "HARDLINKCOUNT", 13)) + if (sscanf(stat->extension, + " HARDLINKCOUNT %u", &i_nlink) == 1) set_nlink(inode, i_nlink); } } @@ -1244,16 +1238,17 @@ static const char *v9fs_vfs_get_link(struct dentry *dentry, return ERR_PTR(-ECHILD); v9ses = v9fs_dentry2v9ses(dentry); - fid = v9fs_fid_lookup(dentry); + if (!v9fs_proto_dotu(v9ses)) + return ERR_PTR(-EBADF); + p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); + fid = v9fs_fid_lookup(dentry); if (IS_ERR(fid)) return ERR_CAST(fid); - if (!v9fs_proto_dotu(v9ses)) - return ERR_PTR(-EBADF); - st = p9_client_stat(fid); + p9_fid_put(fid); if (IS_ERR(st)) return ERR_CAST(st); @@ -1300,12 +1295,13 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, return PTR_ERR(fid); v9fs_invalidate_inode_attr(dir); - p9_client_clunk(fid); + p9_fid_put(fid); return 0; } /** * v9fs_vfs_symlink - helper function to create symlinks + * @mnt_userns: The user namespace of the mount * @dir: directory inode containing symlink * @dentry: dentry for symlink * @symname: symlink data @@ -1315,7 +1311,8 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, */ static int -v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) +v9fs_vfs_symlink(struct user_namespace *mnt_userns, struct inode *dir, + struct dentry *dentry, const char *symname) { p9_debug(P9_DEBUG_VFS, " %lu,%pd,%s\n", dir->i_ino, dentry, symname); @@ -1354,12 +1351,13 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, v9fs_refresh_inode(oldfid, d_inode(old_dentry)); v9fs_invalidate_inode_attr(dir); } - p9_client_clunk(oldfid); + p9_fid_put(oldfid); return retval; } /** * v9fs_vfs_mknod - create a special file + * @mnt_userns: The user namespace of the mount * @dir: inode destination for new link * @dentry: dentry for file * @mode: mode for creation @@ -1368,14 +1366,15 @@ v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, */ static int -v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) +v9fs_vfs_mknod(struct user_namespace *mnt_userns, struct inode *dir, + struct dentry *dentry, umode_t mode, dev_t rdev) { struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); int retval; char name[2 + U32_MAX_DIGITS + 1 + U32_MAX_DIGITS + 1]; u32 perm; - p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n", + p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %x MAJOR: %u MINOR: %u\n", dir->i_ino, dentry, mode, MAJOR(rdev), MINOR(rdev)); @@ -1409,7 +1408,7 @@ int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) * Don't update inode if the file type is different */ umode = p9mode2unixmode(v9ses, st, &rdev); - if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) + if (inode_wrong_type(inode, umode)) goto out; /* |