diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2015-04-14 17:42:49 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2015-05-10 22:18:19 -0400 |
commit | 90e4fc8890daecea72ef73ac8047050e3e8d32db (patch) | |
tree | 41920d19c3f34c94218ba9910b783047b187cca2 /fs/9p | |
parent | b46c267e4756a88593c4a08de869e70d3907637f (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.h | 2 | ||||
-rw-r--r-- | fs/9p/vfs_inode.c | 93 | ||||
-rw-r--r-- | fs/9p/vfs_inode_dotl.c | 31 |
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); | |||
149 | extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d); | 149 | extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d); |
150 | extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, | 150 | extern 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); |
152 | extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, | ||
153 | void *p); | ||
154 | extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses, | 152 | extern 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 | ||
1234 | static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) | 1233 | static 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 | |||
1268 | done: | ||
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 | |||
1281 | static 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 | |||
1312 | void | ||
1313 | v9fs_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 = { | |||
1514 | static const struct inode_operations v9fs_symlink_inode_operations = { | 1457 | static 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: | |||
912 | static void * | 912 | static void * |
913 | v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) | 913 | v9fs_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); | ||
940 | ndset: | ||
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 = { | |||
1006 | const struct inode_operations v9fs_symlink_inode_operations_dotl = { | 991 | const 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, |