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

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
...@@ -149,8 +149,6 @@ extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d); ...@@ -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_rmdir(struct inode *i, struct dentry *d);
extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
struct inode *new_dir, struct dentry *new_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, extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
struct p9_fid *fid, struct p9_fid *fid,
struct super_block *sb, int new); struct super_block *sb, int new);
......
...@@ -1224,102 +1224,45 @@ ino_t v9fs_qid2ino(struct p9_qid *qid) ...@@ -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 * @dentry: dentry for symlink
* @buffer: buffer to load symlink location into * @nd: nameidata
* @buflen: length of buffer
* *
*/ */
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 = v9fs_dentry2v9ses(dentry);
struct p9_fid *fid = v9fs_fid_lookup(dentry);
struct v9fs_session_info *v9ses;
struct p9_fid *fid;
struct p9_wstat *st; struct p9_wstat *st;
p9_debug(P9_DEBUG_VFS, " %pd\n", dentry); p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
retval = -EPERM;
v9ses = v9fs_dentry2v9ses(dentry);
fid = v9fs_fid_lookup(dentry);
if (IS_ERR(fid)) if (IS_ERR(fid))
return PTR_ERR(fid); return ERR_CAST(fid);
if (!v9fs_proto_dotu(v9ses)) if (!v9fs_proto_dotu(v9ses))
return -EBADF; return ERR_PTR(-EBADF);
st = p9_client_stat(fid); st = p9_client_stat(fid);
if (IS_ERR(st)) if (IS_ERR(st))
return PTR_ERR(st); return ERR_CAST(st);
if (!(st->mode & P9_DMSYMLINK)) { 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); p9stat_free(st);
kfree(st); kfree(st);
return retval; return ERR_PTR(-EINVAL);
}
/**
* 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); if (strlen(st->extension) >= PATH_MAX)
st->extension[PATH_MAX - 1] = '\0';
nd_set_link(nd, st->extension);
st->extension = NULL;
p9stat_free(st);
kfree(st);
return NULL; 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 * v9fs_vfs_mkspecial - create a special file
* @dir: inode to create special file in * @dir: inode to create special file in
...@@ -1514,7 +1457,7 @@ static const struct inode_operations v9fs_file_inode_operations = { ...@@ -1514,7 +1457,7 @@ static const struct inode_operations v9fs_file_inode_operations = {
static const struct inode_operations v9fs_symlink_inode_operations = { static const struct inode_operations v9fs_symlink_inode_operations = {
.readlink = generic_readlink, .readlink = generic_readlink,
.follow_link = v9fs_vfs_follow_link, .follow_link = v9fs_vfs_follow_link,
.put_link = v9fs_vfs_put_link, .put_link = kfree_put_link,
.getattr = v9fs_vfs_getattr, .getattr = v9fs_vfs_getattr,
.setattr = v9fs_vfs_setattr, .setattr = v9fs_vfs_setattr,
}; };
......
...@@ -912,33 +912,18 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, ...@@ -912,33 +912,18 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
static void * static void *
v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
{ {
int retval; struct p9_fid *fid = v9fs_fid_lookup(dentry);
struct p9_fid *fid;
char *link = __getname();
char *target; char *target;
int retval;
p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
if (!link) { if (IS_ERR(fid))
link = ERR_PTR(-ENOMEM); return ERR_CAST(fid);
goto ndset;
}
fid = v9fs_fid_lookup(dentry);
if (IS_ERR(fid)) {
__putname(link);
link = ERR_CAST(fid);
goto ndset;
}
retval = p9_client_readlink(fid, &target); retval = p9_client_readlink(fid, &target);
if (!retval) { if (retval)
strcpy(link, target); return ERR_PTR(retval);
kfree(target); nd_set_link(nd, target);
goto ndset;
}
__putname(link);
link = ERR_PTR(retval);
ndset:
nd_set_link(nd, link);
return NULL; return NULL;
} }
...@@ -1006,7 +991,7 @@ const struct inode_operations v9fs_file_inode_operations_dotl = { ...@@ -1006,7 +991,7 @@ const struct inode_operations v9fs_file_inode_operations_dotl = {
const struct inode_operations v9fs_symlink_inode_operations_dotl = { const struct inode_operations v9fs_symlink_inode_operations_dotl = {
.readlink = generic_readlink, .readlink = generic_readlink,
.follow_link = v9fs_vfs_follow_link_dotl, .follow_link = v9fs_vfs_follow_link_dotl,
.put_link = v9fs_vfs_put_link, .put_link = kfree_put_link,
.getattr = v9fs_vfs_getattr_dotl, .getattr = v9fs_vfs_getattr_dotl,
.setattr = v9fs_vfs_setattr_dotl, .setattr = v9fs_vfs_setattr_dotl,
.setxattr = generic_setxattr, .setxattr = generic_setxattr,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment