aboutsummaryrefslogtreecommitdiffstats
path: root/fs/9p
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2015-04-14 17:42:49 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2015-05-10 22:18:19 -0400
commit90e4fc8890daecea72ef73ac8047050e3e8d32db (patch)
tree41920d19c3f34c94218ba9910b783047b187cca2 /fs/9p
parentb46c267e4756a88593c4a08de869e70d3907637f (diff)
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: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/9p')
-rw-r--r--fs/9p/v9fs.h2
-rw-r--r--fs/9p/vfs_inode.c93
-rw-r--r--fs/9p/vfs_inode_dotl.c31
3 files changed, 26 insertions, 100 deletions
diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h
index fb9ffcb43277..0923f2cf3c80 100644
--- a/fs/9p/v9fs.h
+++ b/fs/9p/v9fs.h
@@ -149,8 +149,6 @@ extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d);
149extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d); 149extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d);
150extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, 150extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
151 struct inode *new_dir, struct dentry *new_dentry); 151 struct inode *new_dir, struct dentry *new_dentry);
152extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd,
153 void *p);
154extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses, 152extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses,
155 struct p9_fid *fid, 153 struct p9_fid *fid,
156 struct super_block *sb, int new); 154 struct super_block *sb, int new);
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index cda68f70d757..0ba11712b388 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1224,103 +1224,46 @@ ino_t v9fs_qid2ino(struct p9_qid *qid)
1224} 1224}
1225 1225
1226/** 1226/**
1227 * v9fs_readlink - read a symlink's location (internal version) 1227 * v9fs_vfs_follow_link - follow a symlink path
1228 * @dentry: dentry for symlink 1228 * @dentry: dentry for symlink
1229 * @buffer: buffer to load symlink location into 1229 * @nd: nameidata
1230 * @buflen: length of buffer
1231 * 1230 *
1232 */ 1231 */
1233 1232
1234static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) 1233static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1235{ 1234{
1236 int retval; 1235 struct v9fs_session_info *v9ses = v9fs_dentry2v9ses(dentry);
1237 1236 struct p9_fid *fid = v9fs_fid_lookup(dentry);
1238 struct v9fs_session_info *v9ses;
1239 struct p9_fid *fid;
1240 struct p9_wstat *st; 1237 struct p9_wstat *st;
1241 1238
1242 p9_debug(P9_DEBUG_VFS, " %pd\n", dentry); 1239 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
1243 retval = -EPERM; 1240
1244 v9ses = v9fs_dentry2v9ses(dentry);
1245 fid = v9fs_fid_lookup(dentry);
1246 if (IS_ERR(fid)) 1241 if (IS_ERR(fid))
1247 return PTR_ERR(fid); 1242 return ERR_CAST(fid);
1248 1243
1249 if (!v9fs_proto_dotu(v9ses)) 1244 if (!v9fs_proto_dotu(v9ses))
1250 return -EBADF; 1245 return ERR_PTR(-EBADF);
1251 1246
1252 st = p9_client_stat(fid); 1247 st = p9_client_stat(fid);
1253 if (IS_ERR(st)) 1248 if (IS_ERR(st))
1254 return PTR_ERR(st); 1249 return ERR_CAST(st);
1255 1250
1256 if (!(st->mode & P9_DMSYMLINK)) { 1251 if (!(st->mode & P9_DMSYMLINK)) {
1257 retval = -EINVAL; 1252 p9stat_free(st);
1258 goto done; 1253 kfree(st);
1254 return ERR_PTR(-EINVAL);
1259 } 1255 }
1256 if (strlen(st->extension) >= PATH_MAX)
1257 st->extension[PATH_MAX - 1] = '\0';
1260 1258
1261 /* copy extension buffer into buffer */ 1259 nd_set_link(nd, st->extension);
1262 retval = min(strlen(st->extension)+1, (size_t)buflen); 1260 st->extension = NULL;
1263 memcpy(buffer, st->extension, retval);
1264
1265 p9_debug(P9_DEBUG_VFS, "%pd -> %s (%.*s)\n",
1266 dentry, st->extension, buflen, buffer);
1267
1268done:
1269 p9stat_free(st); 1261 p9stat_free(st);
1270 kfree(st); 1262 kfree(st);
1271 return retval;
1272}
1273
1274/**
1275 * v9fs_vfs_follow_link - follow a symlink path
1276 * @dentry: dentry for symlink
1277 * @nd: nameidata
1278 *
1279 */
1280
1281static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd)
1282{
1283 int len = 0;
1284 char *link = __getname();
1285
1286 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
1287
1288 if (!link)
1289 link = ERR_PTR(-ENOMEM);
1290 else {
1291 len = v9fs_readlink(dentry, link, PATH_MAX);
1292
1293 if (len < 0) {
1294 __putname(link);
1295 link = ERR_PTR(len);
1296 } else
1297 link[min(len, PATH_MAX-1)] = 0;
1298 }
1299 nd_set_link(nd, link);
1300
1301 return NULL; 1263 return NULL;
1302} 1264}
1303 1265
1304/** 1266/**
1305 * v9fs_vfs_put_link - release a symlink path
1306 * @dentry: dentry for symlink
1307 * @nd: nameidata
1308 * @p: unused
1309 *
1310 */
1311
1312void
1313v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p)
1314{
1315 char *s = nd_get_link(nd);
1316
1317 p9_debug(P9_DEBUG_VFS, " %pd %s\n",
1318 dentry, IS_ERR(s) ? "<error>" : s);
1319 if (!IS_ERR(s))
1320 __putname(s);
1321}
1322
1323/**
1324 * v9fs_vfs_mkspecial - create a special file 1267 * v9fs_vfs_mkspecial - create a special file
1325 * @dir: inode to create special file in 1268 * @dir: inode to create special file in
1326 * @dentry: dentry to create 1269 * @dentry: dentry to create
@@ -1514,7 +1457,7 @@ static const struct inode_operations v9fs_file_inode_operations = {
1514static const struct inode_operations v9fs_symlink_inode_operations = { 1457static const struct inode_operations v9fs_symlink_inode_operations = {
1515 .readlink = generic_readlink, 1458 .readlink = generic_readlink,
1516 .follow_link = v9fs_vfs_follow_link, 1459 .follow_link = v9fs_vfs_follow_link,
1517 .put_link = v9fs_vfs_put_link, 1460 .put_link = kfree_put_link,
1518 .getattr = v9fs_vfs_getattr, 1461 .getattr = v9fs_vfs_getattr,
1519 .setattr = v9fs_vfs_setattr, 1462 .setattr = v9fs_vfs_setattr,
1520}; 1463};
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index 9861c7c951a6..bc2a91f2b910 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -912,33 +912,18 @@ error:
912static void * 912static void *
913v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) 913v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd)
914{ 914{
915 int retval; 915 struct p9_fid *fid = v9fs_fid_lookup(dentry);
916 struct p9_fid *fid;
917 char *link = __getname();
918 char *target; 916 char *target;
917 int retval;
919 918
920 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); 919 p9_debug(P9_DEBUG_VFS, "%pd\n", dentry);
921 920
922 if (!link) { 921 if (IS_ERR(fid))
923 link = ERR_PTR(-ENOMEM); 922 return ERR_CAST(fid);
924 goto ndset;
925 }
926 fid = v9fs_fid_lookup(dentry);
927 if (IS_ERR(fid)) {
928 __putname(link);
929 link = ERR_CAST(fid);
930 goto ndset;
931 }
932 retval = p9_client_readlink(fid, &target); 923 retval = p9_client_readlink(fid, &target);
933 if (!retval) { 924 if (retval)
934 strcpy(link, target); 925 return ERR_PTR(retval);
935 kfree(target); 926 nd_set_link(nd, target);
936 goto ndset;
937 }
938 __putname(link);
939 link = ERR_PTR(retval);
940ndset:
941 nd_set_link(nd, link);
942 return NULL; 927 return NULL;
943} 928}
944 929
@@ -1006,7 +991,7 @@ const struct inode_operations v9fs_file_inode_operations_dotl = {
1006const struct inode_operations v9fs_symlink_inode_operations_dotl = { 991const struct inode_operations v9fs_symlink_inode_operations_dotl = {
1007 .readlink = generic_readlink, 992 .readlink = generic_readlink,
1008 .follow_link = v9fs_vfs_follow_link_dotl, 993 .follow_link = v9fs_vfs_follow_link_dotl,
1009 .put_link = v9fs_vfs_put_link, 994 .put_link = kfree_put_link,
1010 .getattr = v9fs_vfs_getattr_dotl, 995 .getattr = v9fs_vfs_getattr_dotl,
1011 .setattr = v9fs_vfs_setattr_dotl, 996 .setattr = v9fs_vfs_setattr_dotl,
1012 .setxattr = generic_setxattr, 997 .setxattr = generic_setxattr,