aboutsummaryrefslogtreecommitdiffstats
path: root/fs/sysfs
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2013-11-28 14:54:35 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-11-29 21:08:39 -0500
commit2072f1afddfe9fa00c1c0c79f8986707324ec65b (patch)
tree636f5f2e0c44082afcded77328bcbcdb62b58f51 /fs/sysfs
parent414985ae23c031efbd6d16d484dea8b5de28b8f7 (diff)
sysfs, kernfs: move symlink core code to fs/kernfs/symlink.c
Move core symlink code to fs/kernfs/symlink.c. fs/sysfs/symlink.c now only contains sysfs wrappers around kernfs interfaces. The respective declarations in fs/sysfs/sysfs.h are moved to fs/kernfs/kernfs-internal.h. This is pure relocation. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/sysfs')
-rw-r--r--fs/sysfs/symlink.c137
-rw-r--r--fs/sysfs/sysfs.h1
2 files changed, 0 insertions, 138 deletions
diff --git a/fs/sysfs/symlink.c b/fs/sysfs/symlink.c
index b137aa3a486c..6797c9c2e43a 100644
--- a/fs/sysfs/symlink.c
+++ b/fs/sysfs/symlink.c
@@ -11,53 +11,13 @@
11 */ 11 */
12 12
13#include <linux/fs.h> 13#include <linux/fs.h>
14#include <linux/gfp.h>
15#include <linux/mount.h>
16#include <linux/module.h> 14#include <linux/module.h>
17#include <linux/kobject.h> 15#include <linux/kobject.h>
18#include <linux/namei.h>
19#include <linux/mutex.h> 16#include <linux/mutex.h>
20#include <linux/security.h> 17#include <linux/security.h>
21 18
22#include "sysfs.h" 19#include "sysfs.h"
23 20
24/**
25 * kernfs_create_link - create a symlink
26 * @parent: directory to create the symlink in
27 * @name: name of the symlink
28 * @target: target node for the symlink to point to
29 *
30 * Returns the created node on success, ERR_PTR() value on error.
31 */
32struct sysfs_dirent *kernfs_create_link(struct sysfs_dirent *parent,
33 const char *name,
34 struct sysfs_dirent *target)
35{
36 struct sysfs_dirent *sd;
37 struct sysfs_addrm_cxt acxt;
38 int error;
39
40 sd = sysfs_new_dirent(name, S_IFLNK|S_IRWXUGO, SYSFS_KOBJ_LINK);
41 if (!sd)
42 return ERR_PTR(-ENOMEM);
43
44 if (parent->s_flags & SYSFS_FLAG_NS)
45 sd->s_ns = target->s_ns;
46 sd->s_symlink.target_sd = target;
47 kernfs_get(target); /* ref owned by symlink */
48
49 sysfs_addrm_start(&acxt);
50 error = sysfs_add_one(&acxt, sd, parent);
51 sysfs_addrm_finish(&acxt);
52
53 if (!error)
54 return sd;
55
56 kernfs_put(sd);
57 return ERR_PTR(error);
58}
59
60
61static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd, 21static int sysfs_do_create_link_sd(struct sysfs_dirent *parent_sd,
62 struct kobject *target, 22 struct kobject *target,
63 const char *name, int warn) 23 const char *name, int warn)
@@ -235,100 +195,3 @@ out:
235 return result; 195 return result;
236} 196}
237EXPORT_SYMBOL_GPL(sysfs_rename_link_ns); 197EXPORT_SYMBOL_GPL(sysfs_rename_link_ns);
238
239static int sysfs_get_target_path(struct sysfs_dirent *parent_sd,
240 struct sysfs_dirent *target_sd, char *path)
241{
242 struct sysfs_dirent *base, *sd;
243 char *s = path;
244 int len = 0;
245
246 /* go up to the root, stop at the base */
247 base = parent_sd;
248 while (base->s_parent) {
249 sd = target_sd->s_parent;
250 while (sd->s_parent && base != sd)
251 sd = sd->s_parent;
252
253 if (base == sd)
254 break;
255
256 strcpy(s, "../");
257 s += 3;
258 base = base->s_parent;
259 }
260
261 /* determine end of target string for reverse fillup */
262 sd = target_sd;
263 while (sd->s_parent && sd != base) {
264 len += strlen(sd->s_name) + 1;
265 sd = sd->s_parent;
266 }
267
268 /* check limits */
269 if (len < 2)
270 return -EINVAL;
271 len--;
272 if ((s - path) + len > PATH_MAX)
273 return -ENAMETOOLONG;
274
275 /* reverse fillup of target string from target to base */
276 sd = target_sd;
277 while (sd->s_parent && sd != base) {
278 int slen = strlen(sd->s_name);
279
280 len -= slen;
281 strncpy(s + len, sd->s_name, slen);
282 if (len)
283 s[--len] = '/';
284
285 sd = sd->s_parent;
286 }
287
288 return 0;
289}
290
291static int sysfs_getlink(struct dentry *dentry, char *path)
292{
293 struct sysfs_dirent *sd = dentry->d_fsdata;
294 struct sysfs_dirent *parent_sd = sd->s_parent;
295 struct sysfs_dirent *target_sd = sd->s_symlink.target_sd;
296 int error;
297
298 mutex_lock(&sysfs_mutex);
299 error = sysfs_get_target_path(parent_sd, target_sd, path);
300 mutex_unlock(&sysfs_mutex);
301
302 return error;
303}
304
305static void *sysfs_follow_link(struct dentry *dentry, struct nameidata *nd)
306{
307 int error = -ENOMEM;
308 unsigned long page = get_zeroed_page(GFP_KERNEL);
309 if (page) {
310 error = sysfs_getlink(dentry, (char *) page);
311 if (error < 0)
312 free_page((unsigned long)page);
313 }
314 nd_set_link(nd, error ? ERR_PTR(error) : (char *)page);
315 return NULL;
316}
317
318static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd,
319 void *cookie)
320{
321 char *page = nd_get_link(nd);
322 if (!IS_ERR(page))
323 free_page((unsigned long)page);
324}
325
326const struct inode_operations sysfs_symlink_inode_operations = {
327 .setxattr = sysfs_setxattr,
328 .readlink = generic_readlink,
329 .follow_link = sysfs_follow_link,
330 .put_link = sysfs_put_link,
331 .setattr = sysfs_setattr,
332 .getattr = sysfs_getattr,
333 .permission = sysfs_permission,
334};
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 4b8b60d834cc..6d0dcead2d6a 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -50,7 +50,6 @@ int sysfs_add_file_mode_ns(struct sysfs_dirent *dir_sd,
50/* 50/*
51 * symlink.c 51 * symlink.c
52 */ 52 */
53extern const struct inode_operations sysfs_symlink_inode_operations;
54int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target, 53int sysfs_create_link_sd(struct sysfs_dirent *sd, struct kobject *target,
55 const char *name); 54 const char *name);
56 55