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
;
32 kn
= kernfs_new_node(parent
, name
, S_IFLNK
|S_IRWXUGO
, KERNFS_LINK
);
34 return ERR_PTR(-ENOMEM
);
36 if (kernfs_ns_enabled(parent
))
38 kn
->symlink
.target_kn
= target
;
39 kernfs_get(target
); /* ref owned by symlink */
41 error
= kernfs_add_one(kn
);
46 return ERR_PTR(error
);
49 static int kernfs_get_target_path(struct kernfs_node
*parent
,
50 struct kernfs_node
*target
, char *path
)
52 struct kernfs_node
*base
, *kn
;
56 /* go up to the root, stop at the base */
58 while (base
->parent
) {
60 while (kn
->parent
&& base
!= kn
)
71 /* determine end of target string for reverse fillup */
73 while (kn
->parent
&& kn
!= base
) {
74 len
+= strlen(kn
->name
) + 1;
82 if ((s
- path
) + len
> PATH_MAX
)
85 /* reverse fillup of target string from target to base */
87 while (kn
->parent
&& kn
!= base
) {
88 int slen
= strlen(kn
->name
);
91 strncpy(s
+ len
, kn
->name
, slen
);
101 static int kernfs_getlink(struct dentry
*dentry
, char *path
)
103 struct kernfs_node
*kn
= dentry
->d_fsdata
;
104 struct kernfs_node
*parent
= kn
->parent
;
105 struct kernfs_node
*target
= kn
->symlink
.target_kn
;
108 mutex_lock(&kernfs_mutex
);
109 error
= kernfs_get_target_path(parent
, target
, path
);
110 mutex_unlock(&kernfs_mutex
);
115 static const char *kernfs_iop_get_link(struct dentry
*dentry
,
117 struct delayed_call
*done
)
123 return ERR_PTR(-ECHILD
);
124 body
= kzalloc(PAGE_SIZE
, GFP_KERNEL
);
126 return ERR_PTR(-ENOMEM
);
127 error
= kernfs_getlink(dentry
, body
);
128 if (unlikely(error
< 0)) {
130 return ERR_PTR(error
);
132 set_delayed_call(done
, kfree_link
, body
);
136 const struct inode_operations kernfs_symlink_iops
= {
137 .setxattr
= kernfs_iop_setxattr
,
138 .removexattr
= kernfs_iop_removexattr
,
139 .getxattr
= kernfs_iop_getxattr
,
140 .listxattr
= kernfs_iop_listxattr
,
141 .readlink
= generic_readlink
,
142 .get_link
= kernfs_iop_get_link
,
143 .setattr
= kernfs_iop_setattr
,
144 .getattr
= kernfs_iop_getattr
,
145 .permission
= kernfs_iop_permission
,