Commit 90e4fc88 authored by Al Viro's avatar Al Viro
Browse files

9p: don't bother with __getname() in ->follow_link()



We copy there a kmalloc'ed string and proceed to kfree that string immediately
after that.  Easier to just feed that string to nd_set_link() and _not_
kfree it until ->put_link() (which becomes kfree_put_link() in that case).

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent b46c267e
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -149,8 +149,6 @@ extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
			struct inode *new_dir, struct dentry *new_dentry);
extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd,
			void *p);
extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
					 struct p9_fid *fid,
					 struct super_block *sb, int new);
+18 −75
Original line number Diff line number Diff line
@@ -1224,102 +1224,45 @@ ino_t v9fs_qid2ino(struct p9_qid *qid)
}

/**
 * v9fs_readlink - read a symlink's location (internal version)
 * v9fs_vfs_follow_link - follow a symlink path
 * @dentry: dentry for symlink
 * @buffer: buffer to load symlink location into
 * @buflen: length of buffer
 * @nd: nameidata
 *
 */

static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen)
static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	int retval;

	struct v9fs_session_info *v9ses;
	struct p9_fid *fid;
	struct v9fs_session_info *v9ses = v9fs_dentry2v9ses(dentry);
	struct p9_fid *fid = v9fs_fid_lookup(dentry);
	struct p9_wstat *st;

	p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
	retval = -EPERM;
	v9ses = v9fs_dentry2v9ses(dentry);
	fid = v9fs_fid_lookup(dentry);

	if (IS_ERR(fid))
		return PTR_ERR(fid);
		return ERR_CAST(fid);

	if (!v9fs_proto_dotu(v9ses))
		return -EBADF;
		return ERR_PTR(-EBADF);

	st = p9_client_stat(fid);
	if (IS_ERR(st))
		return PTR_ERR(st);
		return ERR_CAST(st);

	if (!(st->mode & P9_DMSYMLINK)) {
		retval = -EINVAL;
		goto done;
	}

	/* copy extension buffer into buffer */
	retval = min(strlen(st->extension)+1, (size_t)buflen);
	memcpy(buffer, st->extension, retval);

	p9_debug(P9_DEBUG_VFS, "%pd -> %s (%.*s)\n",
		 dentry, st->extension, buflen, buffer);

done:
		p9stat_free(st);
		kfree(st);
	return retval;
		return ERR_PTR(-EINVAL);
	}
	if (strlen(st->extension) >= PATH_MAX)
		st->extension[PATH_MAX - 1] = '\0';

/**
 * v9fs_vfs_follow_link - follow a symlink path
 * @dentry: dentry for symlink
 * @nd: nameidata
 *
 */

static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
	int len = 0;
	char *link = __getname();

	p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);

	if (!link)
		link = ERR_PTR(-ENOMEM);
	else {
		len = v9fs_readlink(dentry, link, PATH_MAX);

		if (len < 0) {
			__putname(link);
			link = ERR_PTR(len);
		} else
			link[min(len, PATH_MAX-1)] = 0;
	}
	nd_set_link(nd, link);

	nd_set_link(nd, st->extension);
	st->extension = NULL;
	p9stat_free(st);
	kfree(st);
	return NULL;
}

/**
 * v9fs_vfs_put_link - release a symlink path
 * @dentry: dentry for symlink
 * @nd: nameidata
 * @p: unused
 *
 */

void
v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
{
	char *s = nd_get_link(nd);

	p9_debug(P9_DEBUG_VFS, " %pd %s\n",
		 dentry, IS_ERR(s) ? "<error>" : s);
	if (!IS_ERR(s))
		__putname(s);
}

/**
 * v9fs_vfs_mkspecial - create a special file
 * @dir: inode to create special file in
@@ -1514,7 +1457,7 @@ static const struct inode_operations v9fs_file_inode_operations = {
static const struct inode_operations v9fs_symlink_inode_operations = {
	.readlink = generic_readlink,
	.follow_link = v9fs_vfs_follow_link,
	.put_link = v9fs_vfs_put_link,
	.put_link = kfree_put_link,
	.getattr = v9fs_vfs_getattr,
	.setattr = v9fs_vfs_setattr,
};
+8 −23
Original line number Diff line number Diff line
@@ -912,33 +912,18 @@ error:
static void *
v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
{
	int retval;
	struct p9_fid *fid;
	char *link = __getname();
	struct p9_fid *fid = v9fs_fid_lookup(dentry);
	char *target;
	int retval;

	p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);

	if (!link) {
		link = ERR_PTR(-ENOMEM);
		goto ndset;
	}
	fid = v9fs_fid_lookup(dentry);
	if (IS_ERR(fid)) {
		__putname(link);
		link = ERR_CAST(fid);
		goto ndset;
	}
	if (IS_ERR(fid))
		return ERR_CAST(fid);
	retval = p9_client_readlink(fid, &target);
	if (!retval) {
		strcpy(link, target);
		kfree(target);
		goto ndset;
	}
	__putname(link);
	link = ERR_PTR(retval);
ndset:
	nd_set_link(nd, link);
	if (retval)
		return ERR_PTR(retval);
	nd_set_link(nd, target);
	return NULL;
}

@@ -1006,7 +991,7 @@ const struct inode_operations v9fs_file_inode_operations_dotl = {
const struct inode_operations v9fs_symlink_inode_operations_dotl = {
	.readlink = generic_readlink,
	.follow_link = v9fs_vfs_follow_link_dotl,
	.put_link = v9fs_vfs_put_link,
	.put_link = kfree_put_link,
	.getattr = v9fs_vfs_getattr_dotl,
	.setattr = v9fs_vfs_setattr_dotl,
	.setxattr = generic_setxattr,