2 * fs/kernfs/symlink.c - kernfs symlink implementation
4 * Copyright (c) 2001-3 Patrick Mochel
5 * Copyright (c) 2007 SUSE Linux Products GmbH
6 * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org>
8 * This file is released under the GPLv2.
12 #include <linux/gfp.h>
13 #include <linux/namei.h>
15 #include "kernfs-internal.h"
18 * kernfs_create_link - create a symlink
19 * @parent: directory to create the symlink in
20 * @name: name of the symlink
21 * @target: target node for the symlink to point to
23 * Returns the created node on success, ERR_PTR() value on error.
25 struct kernfs_node
*kernfs_create_link(struct kernfs_node
*parent
,
27 struct kernfs_node
*target
)
29 struct kernfs_node
*kn
;
30 struct kernfs_addrm_cxt acxt
;
33 kn
= sysfs_new_dirent(kernfs_root(parent
), name
, S_IFLNK
|S_IRWXUGO
,
36 return ERR_PTR(-ENOMEM
);
38 if (kernfs_ns_enabled(parent
))
40 kn
->symlink
.target_kn
= target
;
41 kernfs_get(target
); /* ref owned by symlink */
43 sysfs_addrm_start(&acxt
);
44 error
= sysfs_add_one(&acxt
, kn
, parent
);
45 sysfs_addrm_finish(&acxt
);
51 return ERR_PTR(error
);
54 static int sysfs_get_target_path(struct kernfs_node
*parent
,
55 struct kernfs_node
*target
, char *path
)
57 struct kernfs_node
*base
, *kn
;
61 /* go up to the root, stop at the base */
63 while (base
->parent
) {
65 while (kn
->parent
&& base
!= kn
)
76 /* determine end of target string for reverse fillup */
78 while (kn
->parent
&& kn
!= base
) {
79 len
+= strlen(kn
->name
) + 1;
87 if ((s
- path
) + len
> PATH_MAX
)
90 /* reverse fillup of target string from target to base */
92 while (kn
->parent
&& kn
!= base
) {
93 int slen
= strlen(kn
->name
);
96 strncpy(s
+ len
, kn
->name
, slen
);
106 static int sysfs_getlink(struct dentry
*dentry
, char *path
)
108 struct kernfs_node
*kn
= dentry
->d_fsdata
;
109 struct kernfs_node
*parent
= kn
->parent
;
110 struct kernfs_node
*target
= kn
->symlink
.target_kn
;
113 mutex_lock(&sysfs_mutex
);
114 error
= sysfs_get_target_path(parent
, target
, path
);
115 mutex_unlock(&sysfs_mutex
);
120 static void *sysfs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
123 unsigned long page
= get_zeroed_page(GFP_KERNEL
);
125 error
= sysfs_getlink(dentry
, (char *) page
);
127 free_page((unsigned long)page
);
129 nd_set_link(nd
, error
? ERR_PTR(error
) : (char *)page
);
133 static void sysfs_put_link(struct dentry
*dentry
, struct nameidata
*nd
,
136 char *page
= nd_get_link(nd
);
138 free_page((unsigned long)page
);
141 const struct inode_operations sysfs_symlink_inode_operations
= {
142 .setxattr
= sysfs_setxattr
,
143 .removexattr
= sysfs_removexattr
,
144 .getxattr
= sysfs_getxattr
,
145 .listxattr
= sysfs_listxattr
,
146 .readlink
= generic_readlink
,
147 .follow_link
= sysfs_follow_link
,
148 .put_link
= sysfs_put_link
,
149 .setattr
= sysfs_setattr
,
150 .getattr
= sysfs_getattr
,
151 .permission
= sysfs_permission
,