9p: don't bother with __getname() in ->follow_link()
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 14 Apr 2015 21:42:49 +0000 (17:42 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Mon, 11 May 2015 02:18:19 +0000 (22:18 -0400)
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: Al Viro <viro@zeniv.linux.org.uk>
fs/9p/v9fs.h
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c

index fb9ffcb432779b55620909090b825ead7ddbcede..0923f2cf3c80aa2fb95a7385276de6f497ea46fe 100644 (file)
@@ -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);
index cda68f70d75747f64ac553ab0cb72c1ed14ce4cb..0ba11712b38883001a76a3191061138b3e8bbfb8 100644 (file)
@@ -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);
+       p9_debug(P9_DEBUG_VFS, "%pd\n", 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;
+               p9stat_free(st);
+               kfree(st);
+               return ERR_PTR(-EINVAL);
        }
+       if (strlen(st->extension) >= PATH_MAX)
+               st->extension[PATH_MAX - 1] = '\0';
 
-       /* 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:
+       nd_set_link(nd, st->extension);
+       st->extension = NULL;
        p9stat_free(st);
        kfree(st);
-       return retval;
-}
-
-/**
- * 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);
-
        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,
 };
index 9861c7c951a6dbd293e78d84e190f0908b4a1921..bc2a91f2b910d8a258fbed6c7ad23c06020aa976 100644 (file)
@@ -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,