aboutsummaryrefslogtreecommitdiffstats
path: root/fs/kernfs/dir.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-10-14 15:18:50 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-10-14 15:18:50 -0400
commitf34d3606f76a8121b9d4940d2dd436bebeb2f9d7 (patch)
tree61a9deb6a950568df274580fbbd44a7015af9f7c /fs/kernfs/dir.c
parentb6daa51b9a6a02a644dcf6b880fd50c1f70ec07f (diff)
parentbbb427e342495df1cda10051d0566388697499c0 (diff)
Merge branch 'for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup
Pull cgroup updates from Tejun Heo: - tracepoints for basic cgroup management operations added - kernfs and cgroup path formatting functions updated to behave in the style of strlcpy() - non-critical bug fixes * 'for-4.9' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: blkcg: Unlock blkcg_pol_mutex only once when cpd == NULL cgroup: fix error handling regressions in proc_cgroup_show() and cgroup_release_agent() cpuset: fix error handling regression in proc_cpuset_show() cgroup: add tracepoints for basic operations cgroup: make cgroup_path() and friends behave in the style of strlcpy() kernfs: remove kernfs_path_len() kernfs: make kernfs_path*() behave in the style of strlcpy() kernfs: add dummy implementation of kernfs_path_from_node()
Diffstat (limited to 'fs/kernfs/dir.c')
-rw-r--r--fs/kernfs/dir.c84
1 files changed, 17 insertions, 67 deletions
diff --git a/fs/kernfs/dir.c b/fs/kernfs/dir.c
index dcd96aac02f5..cf4c636ff4da 100644
--- a/fs/kernfs/dir.c
+++ b/fs/kernfs/dir.c
@@ -110,8 +110,9 @@ static struct kernfs_node *kernfs_common_ancestor(struct kernfs_node *a,
110 * kn_to: /n1/n2/n3 [depth=3] 110 * kn_to: /n1/n2/n3 [depth=3]
111 * result: /../.. 111 * result: /../..
112 * 112 *
113 * return value: length of the string. If greater than buflen, 113 * Returns the length of the full path. If the full length is equal to or
114 * then contents of buf are undefined. On error, -1 is returned. 114 * greater than @buflen, @buf contains the truncated path with the trailing
115 * '\0'. On error, -errno is returned.
115 */ 116 */
116static int kernfs_path_from_node_locked(struct kernfs_node *kn_to, 117static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
117 struct kernfs_node *kn_from, 118 struct kernfs_node *kn_from,
@@ -119,9 +120,8 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
119{ 120{
120 struct kernfs_node *kn, *common; 121 struct kernfs_node *kn, *common;
121 const char parent_str[] = "/.."; 122 const char parent_str[] = "/..";
122 size_t depth_from, depth_to, len = 0, nlen = 0; 123 size_t depth_from, depth_to, len = 0;
123 char *p; 124 int i, j;
124 int i;
125 125
126 if (!kn_from) 126 if (!kn_from)
127 kn_from = kernfs_root(kn_to)->kn; 127 kn_from = kernfs_root(kn_to)->kn;
@@ -131,7 +131,7 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
131 131
132 common = kernfs_common_ancestor(kn_from, kn_to); 132 common = kernfs_common_ancestor(kn_from, kn_to);
133 if (WARN_ON(!common)) 133 if (WARN_ON(!common))
134 return -1; 134 return -EINVAL;
135 135
136 depth_to = kernfs_depth(common, kn_to); 136 depth_to = kernfs_depth(common, kn_to);
137 depth_from = kernfs_depth(common, kn_from); 137 depth_from = kernfs_depth(common, kn_from);
@@ -144,22 +144,16 @@ static int kernfs_path_from_node_locked(struct kernfs_node *kn_to,
144 len < buflen ? buflen - len : 0); 144 len < buflen ? buflen - len : 0);
145 145
146 /* Calculate how many bytes we need for the rest */ 146 /* Calculate how many bytes we need for the rest */
147 for (kn = kn_to; kn != common; kn = kn->parent) 147 for (i = depth_to - 1; i >= 0; i--) {
148 nlen += strlen(kn->name) + 1; 148 for (kn = kn_to, j = 0; j < i; j++)
149 149 kn = kn->parent;
150 if (len + nlen >= buflen) 150 len += strlcpy(buf + len, "/",
151 return len + nlen; 151 len < buflen ? buflen - len : 0);
152 152 len += strlcpy(buf + len, kn->name,
153 p = buf + len + nlen; 153 len < buflen ? buflen - len : 0);
154 *p = '\0';
155 for (kn = kn_to; kn != common; kn = kn->parent) {
156 size_t tmp = strlen(kn->name);
157 p -= tmp;
158 memcpy(p, kn->name, tmp);
159 *(--p) = '/';
160 } 154 }
161 155
162 return len + nlen; 156 return len;
163} 157}
164 158
165/** 159/**
@@ -186,29 +180,6 @@ int kernfs_name(struct kernfs_node *kn, char *buf, size_t buflen)
186} 180}
187 181
188/** 182/**
189 * kernfs_path_len - determine the length of the full path of a given node
190 * @kn: kernfs_node of interest
191 *
192 * The returned length doesn't include the space for the terminating '\0'.
193 */
194size_t kernfs_path_len(struct kernfs_node *kn)
195{
196 size_t len = 0;
197 unsigned long flags;
198
199 spin_lock_irqsave(&kernfs_rename_lock, flags);
200
201 do {
202 len += strlen(kn->name) + 1;
203 kn = kn->parent;
204 } while (kn && kn->parent);
205
206 spin_unlock_irqrestore(&kernfs_rename_lock, flags);
207
208 return len;
209}
210
211/**
212 * kernfs_path_from_node - build path of node @to relative to @from. 183 * kernfs_path_from_node - build path of node @to relative to @from.
213 * @from: parent kernfs_node relative to which we need to build the path 184 * @from: parent kernfs_node relative to which we need to build the path
214 * @to: kernfs_node of interest 185 * @to: kernfs_node of interest
@@ -220,8 +191,9 @@ size_t kernfs_path_len(struct kernfs_node *kn)
220 * path (which includes '..'s) as needed to reach from @from to @to is 191 * path (which includes '..'s) as needed to reach from @from to @to is
221 * returned. 192 * returned.
222 * 193 *
223 * If @buf isn't long enough, the return value will be greater than @buflen 194 * Returns the length of the full path. If the full length is equal to or
224 * and @buf contents are undefined. 195 * greater than @buflen, @buf contains the truncated path with the trailing
196 * '\0'. On error, -errno is returned.
225 */ 197 */
226int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from, 198int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,
227 char *buf, size_t buflen) 199 char *buf, size_t buflen)
@@ -237,28 +209,6 @@ int kernfs_path_from_node(struct kernfs_node *to, struct kernfs_node *from,
237EXPORT_SYMBOL_GPL(kernfs_path_from_node); 209EXPORT_SYMBOL_GPL(kernfs_path_from_node);
238 210
239/** 211/**
240 * kernfs_path - build full path of a given node
241 * @kn: kernfs_node of interest
242 * @buf: buffer to copy @kn's name into
243 * @buflen: size of @buf
244 *
245 * Builds and returns the full path of @kn in @buf of @buflen bytes. The
246 * path is built from the end of @buf so the returned pointer usually
247 * doesn't match @buf. If @buf isn't long enough, @buf is nul terminated
248 * and %NULL is returned.
249 */
250char *kernfs_path(struct kernfs_node *kn, char *buf, size_t buflen)
251{
252 int ret;
253
254 ret = kernfs_path_from_node(kn, NULL, buf, buflen);
255 if (ret < 0 || ret >= buflen)
256 return NULL;
257 return buf;
258}
259EXPORT_SYMBOL_GPL(kernfs_path);
260
261/**
262 * pr_cont_kernfs_name - pr_cont name of a kernfs_node 212 * pr_cont_kernfs_name - pr_cont name of a kernfs_node
263 * @kn: kernfs_node of interest 213 * @kn: kernfs_node of interest
264 * 214 *