diff options
author | Jeff Layton <jlayton@kernel.org> | 2019-04-29 12:13:14 -0400 |
---|---|---|
committer | Ilya Dryomov <idryomov@gmail.com> | 2019-05-07 13:22:37 -0400 |
commit | f77f21bb28367d0ac4861a24da1db118bba850e6 (patch) | |
tree | 09381ee5d6fac1e444a8795da70eb08fe4ce551d | |
parent | 964fff7491e4923e18ff08f2a254c4b94e3f83d6 (diff) |
ceph: use __getname/__putname in ceph_mdsc_build_path
Al suggested we get rid of the kmalloc here and just use __getname
and __putname to get a full PATH_MAX pathname buffer.
Since we build the path in reverse, we continue to return a pointer
to the beginning of the string and the length, and add a new helper
to free the thing at the end.
Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Reviewed-by: "Yan, Zheng" <zyan@redhat.com>
Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r-- | fs/ceph/debugfs.c | 4 | ||||
-rw-r--r-- | fs/ceph/mds_client.c | 65 | ||||
-rw-r--r-- | fs/ceph/mds_client.h | 6 |
3 files changed, 36 insertions, 39 deletions
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c index 777f6ceb5259..b014fc7d4e3c 100644 --- a/fs/ceph/debugfs.c +++ b/fs/ceph/debugfs.c | |||
@@ -88,7 +88,7 @@ static int mdsc_show(struct seq_file *s, void *p) | |||
88 | req->r_dentry, | 88 | req->r_dentry, |
89 | path ? path : ""); | 89 | path ? path : ""); |
90 | spin_unlock(&req->r_dentry->d_lock); | 90 | spin_unlock(&req->r_dentry->d_lock); |
91 | kfree(path); | 91 | ceph_mdsc_free_path(path, pathlen); |
92 | } else if (req->r_path1) { | 92 | } else if (req->r_path1) { |
93 | seq_printf(s, " #%llx/%s", req->r_ino1.ino, | 93 | seq_printf(s, " #%llx/%s", req->r_ino1.ino, |
94 | req->r_path1); | 94 | req->r_path1); |
@@ -108,7 +108,7 @@ static int mdsc_show(struct seq_file *s, void *p) | |||
108 | req->r_old_dentry, | 108 | req->r_old_dentry, |
109 | path ? path : ""); | 109 | path ? path : ""); |
110 | spin_unlock(&req->r_old_dentry->d_lock); | 110 | spin_unlock(&req->r_old_dentry->d_lock); |
111 | kfree(path); | 111 | ceph_mdsc_free_path(path, pathlen); |
112 | } else if (req->r_path2 && req->r_op != CEPH_MDS_OP_SYMLINK) { | 112 | } else if (req->r_path2 && req->r_op != CEPH_MDS_OP_SYMLINK) { |
113 | if (req->r_ino2.ino) | 113 | if (req->r_ino2.ino) |
114 | seq_printf(s, " #%llx/%s", req->r_ino2.ino, | 114 | seq_printf(s, " #%llx/%s", req->r_ino2.ino, |
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 7af722834348..d29f6c094f7c 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c | |||
@@ -2094,39 +2094,24 @@ char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *pbase, | |||
2094 | { | 2094 | { |
2095 | struct dentry *temp; | 2095 | struct dentry *temp; |
2096 | char *path; | 2096 | char *path; |
2097 | int len, pos; | 2097 | int pos; |
2098 | unsigned seq; | 2098 | unsigned seq; |
2099 | u64 base; | 2099 | u64 base; |
2100 | 2100 | ||
2101 | if (!dentry) | 2101 | if (!dentry) |
2102 | return ERR_PTR(-EINVAL); | 2102 | return ERR_PTR(-EINVAL); |
2103 | 2103 | ||
2104 | retry: | 2104 | path = __getname(); |
2105 | len = 0; | ||
2106 | seq = read_seqbegin(&rename_lock); | ||
2107 | rcu_read_lock(); | ||
2108 | for (temp = dentry; !IS_ROOT(temp);) { | ||
2109 | struct inode *inode = d_inode(temp); | ||
2110 | if (inode && ceph_snap(inode) == CEPH_SNAPDIR) | ||
2111 | len++; /* slash only */ | ||
2112 | else if (stop_on_nosnap && inode && | ||
2113 | ceph_snap(inode) == CEPH_NOSNAP) | ||
2114 | break; | ||
2115 | else | ||
2116 | len += 1 + temp->d_name.len; | ||
2117 | temp = temp->d_parent; | ||
2118 | } | ||
2119 | rcu_read_unlock(); | ||
2120 | if (len) | ||
2121 | len--; /* no leading '/' */ | ||
2122 | |||
2123 | path = kmalloc(len+1, GFP_NOFS); | ||
2124 | if (!path) | 2105 | if (!path) |
2125 | return ERR_PTR(-ENOMEM); | 2106 | return ERR_PTR(-ENOMEM); |
2126 | pos = len; | 2107 | retry: |
2127 | path[pos] = 0; /* trailing null */ | 2108 | pos = PATH_MAX - 1; |
2109 | path[pos] = '\0'; | ||
2110 | |||
2111 | seq = read_seqbegin(&rename_lock); | ||
2128 | rcu_read_lock(); | 2112 | rcu_read_lock(); |
2129 | for (temp = dentry; !IS_ROOT(temp) && pos != 0; ) { | 2113 | temp = dentry; |
2114 | for (;;) { | ||
2130 | struct inode *inode; | 2115 | struct inode *inode; |
2131 | 2116 | ||
2132 | spin_lock(&temp->d_lock); | 2117 | spin_lock(&temp->d_lock); |
@@ -2144,32 +2129,38 @@ retry: | |||
2144 | spin_unlock(&temp->d_lock); | 2129 | spin_unlock(&temp->d_lock); |
2145 | break; | 2130 | break; |
2146 | } | 2131 | } |
2147 | strncpy(path + pos, temp->d_name.name, | 2132 | memcpy(path + pos, temp->d_name.name, temp->d_name.len); |
2148 | temp->d_name.len); | ||
2149 | } | 2133 | } |
2150 | spin_unlock(&temp->d_lock); | 2134 | spin_unlock(&temp->d_lock); |
2151 | if (pos) | ||
2152 | path[--pos] = '/'; | ||
2153 | temp = temp->d_parent; | 2135 | temp = temp->d_parent; |
2136 | |||
2137 | /* Are we at the root? */ | ||
2138 | if (IS_ROOT(temp)) | ||
2139 | break; | ||
2140 | |||
2141 | /* Are we out of buffer? */ | ||
2142 | if (--pos < 0) | ||
2143 | break; | ||
2144 | |||
2145 | path[pos] = '/'; | ||
2154 | } | 2146 | } |
2155 | base = ceph_ino(d_inode(temp)); | 2147 | base = ceph_ino(d_inode(temp)); |
2156 | rcu_read_unlock(); | 2148 | rcu_read_unlock(); |
2157 | if (pos != 0 || read_seqretry(&rename_lock, seq)) { | 2149 | if (pos < 0 || read_seqretry(&rename_lock, seq)) { |
2158 | pr_err("build_path did not end path lookup where " | 2150 | pr_err("build_path did not end path lookup where " |
2159 | "expected, namelen is %d, pos is %d\n", len, pos); | 2151 | "expected, pos is %d\n", pos); |
2160 | /* presumably this is only possible if racing with a | 2152 | /* presumably this is only possible if racing with a |
2161 | rename of one of the parent directories (we can not | 2153 | rename of one of the parent directories (we can not |
2162 | lock the dentries above us to prevent this, but | 2154 | lock the dentries above us to prevent this, but |
2163 | retrying should be harmless) */ | 2155 | retrying should be harmless) */ |
2164 | kfree(path); | ||
2165 | goto retry; | 2156 | goto retry; |
2166 | } | 2157 | } |
2167 | 2158 | ||
2168 | *pbase = base; | 2159 | *pbase = base; |
2169 | *plen = len; | 2160 | *plen = PATH_MAX - 1 - pos; |
2170 | dout("build_path on %p %d built %llx '%.*s'\n", | 2161 | dout("build_path on %p %d built %llx '%.*s'\n", |
2171 | dentry, d_count(dentry), base, len, path); | 2162 | dentry, d_count(dentry), base, *plen, path + pos); |
2172 | return path; | 2163 | return path + pos; |
2173 | } | 2164 | } |
2174 | 2165 | ||
2175 | static int build_dentry_path(struct dentry *dentry, struct inode *dir, | 2166 | static int build_dentry_path(struct dentry *dentry, struct inode *dir, |
@@ -2376,10 +2367,10 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc, | |||
2376 | 2367 | ||
2377 | out_free2: | 2368 | out_free2: |
2378 | if (freepath2) | 2369 | if (freepath2) |
2379 | kfree((char *)path2); | 2370 | ceph_mdsc_free_path((char *)path2, pathlen2); |
2380 | out_free1: | 2371 | out_free1: |
2381 | if (freepath1) | 2372 | if (freepath1) |
2382 | kfree((char *)path1); | 2373 | ceph_mdsc_free_path((char *)path1, pathlen1); |
2383 | out: | 2374 | out: |
2384 | return msg; | 2375 | return msg; |
2385 | } | 2376 | } |
@@ -3451,7 +3442,7 @@ out_freeflocks: | |||
3451 | ceph_pagelist_encode_string(pagelist, path, pathlen); | 3442 | ceph_pagelist_encode_string(pagelist, path, pathlen); |
3452 | ceph_pagelist_append(pagelist, &rec, sizeof(rec.v1)); | 3443 | ceph_pagelist_append(pagelist, &rec, sizeof(rec.v1)); |
3453 | out_freepath: | 3444 | out_freepath: |
3454 | kfree(path); | 3445 | ceph_mdsc_free_path(path, pathlen); |
3455 | } | 3446 | } |
3456 | 3447 | ||
3457 | out_err: | 3448 | out_err: |
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 0d1f673a5689..ebcad5afc87b 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h | |||
@@ -492,6 +492,12 @@ extern int ceph_iterate_session_caps(struct ceph_mds_session *session, | |||
492 | void *arg); | 492 | void *arg); |
493 | extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); | 493 | extern void ceph_mdsc_pre_umount(struct ceph_mds_client *mdsc); |
494 | 494 | ||
495 | static inline void ceph_mdsc_free_path(char *path, int len) | ||
496 | { | ||
497 | if (path) | ||
498 | __putname(path - (PATH_MAX - 1 - len)); | ||
499 | } | ||
500 | |||
495 | extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base, | 501 | extern char *ceph_mdsc_build_path(struct dentry *dentry, int *plen, u64 *base, |
496 | int stop_on_nosnap); | 502 | int stop_on_nosnap); |
497 | 503 | ||