1 // SPDX-License-Identifier: GPL-2.0-only
3 * fs/kernfs/symlink.c - kernfs symlink implementation
5 * Copyright (c) 2001-3 Patrick Mochel
6 * Copyright (c) 2007 SUSE Linux Products GmbH
7 * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org>
11 #include <linux/gfp.h>
12 #include <linux/namei.h>
14 #include "kernfs-internal.h"
17 * kernfs_create_link - create a symlink
18 * @parent: directory to create the symlink in
19 * @name: name of the symlink
20 * @target: target node for the symlink to point to
22 * Return: the created node on success, ERR_PTR() value on error.
23 * Ownership of the link matches ownership of the target.
25 struct kernfs_node
*kernfs_create_link(struct kernfs_node
*parent
,
27 struct kernfs_node
*target
)
29 struct kernfs_node
*kn
;
31 kuid_t uid
= GLOBAL_ROOT_UID
;
32 kgid_t gid
= GLOBAL_ROOT_GID
;
35 uid
= target
->iattr
->ia_uid
;
36 gid
= target
->iattr
->ia_gid
;
39 kn
= kernfs_new_node(parent
, name
, S_IFLNK
|0777, uid
, gid
, KERNFS_LINK
);
41 return ERR_PTR(-ENOMEM
);
43 if (kernfs_ns_enabled(parent
))
45 kn
->symlink
.target_kn
= target
;
46 kernfs_get(target
); /* ref owned by symlink */
48 error
= kernfs_add_one(kn
);
53 return ERR_PTR(error
);
56 static int kernfs_get_target_path(struct kernfs_node
*parent
,
57 struct kernfs_node
*target
, char *path
)
59 struct kernfs_node
*base
, *kn
;
63 /* go up to the root, stop at the base */
65 while (base
->parent
) {
67 while (kn
->parent
&& base
!= kn
)
73 if ((s
- path
) + 3 >= PATH_MAX
)
81 /* determine end of target string for reverse fillup */
83 while (kn
->parent
&& kn
!= base
) {
84 len
+= strlen(kn
->name
) + 1;
92 if ((s
- path
) + len
>= PATH_MAX
)
95 /* reverse fillup of target string from target to base */
97 while (kn
->parent
&& kn
!= base
) {
98 int slen
= strlen(kn
->name
);
101 memcpy(s
+ len
, kn
->name
, slen
);
111 static int kernfs_getlink(struct inode
*inode
, char *path
)
113 struct kernfs_node
*kn
= inode
->i_private
;
114 struct kernfs_node
*parent
= kn
->parent
;
115 struct kernfs_node
*target
= kn
->symlink
.target_kn
;
116 struct kernfs_root
*root
= kernfs_root(parent
);
119 down_read(&root
->kernfs_rwsem
);
120 error
= kernfs_get_target_path(parent
, target
, path
);
121 up_read(&root
->kernfs_rwsem
);
126 static const char *kernfs_iop_get_link(struct dentry
*dentry
,
128 struct delayed_call
*done
)
134 return ERR_PTR(-ECHILD
);
135 body
= kzalloc(PAGE_SIZE
, GFP_KERNEL
);
137 return ERR_PTR(-ENOMEM
);
138 error
= kernfs_getlink(inode
, body
);
139 if (unlikely(error
< 0)) {
141 return ERR_PTR(error
);
143 set_delayed_call(done
, kfree_link
, body
);
147 const struct inode_operations kernfs_symlink_iops
= {
148 .listxattr
= kernfs_iop_listxattr
,
149 .get_link
= kernfs_iop_get_link
,
150 .setattr
= kernfs_iop_setattr
,
151 .getattr
= kernfs_iop_getattr
,
152 .permission
= kernfs_iop_permission
,