1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* -*- mode: c; c-basic-offset: 8; -*-
3 * vim: noexpandtab sw=8 ts=8 sts=0:
5 * symlink.c - operations for configfs symlinks.
8 * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
10 * configfs Copyright (C) 2005 Oracle. All rights reserved.
14 #include <linux/module.h>
15 #include <linux/namei.h>
16 #include <linux/slab.h>
18 #include <linux/configfs.h>
19 #include "configfs_internal.h"
21 /* Protects attachments of new symlinks */
22 DEFINE_MUTEX(configfs_symlink_mutex
);
24 static int item_depth(struct config_item
* item
)
26 struct config_item
* p
= item
;
28 do { depth
++; } while ((p
= p
->ci_parent
) && !configfs_is_root(p
));
32 static int item_path_length(struct config_item
* item
)
34 struct config_item
* p
= item
;
37 length
+= strlen(config_item_name(p
)) + 1;
39 } while (p
&& !configfs_is_root(p
));
43 static void fill_item_path(struct config_item
* item
, char * buffer
, int length
)
45 struct config_item
* p
;
48 for (p
= item
; p
&& !configfs_is_root(p
); p
= p
->ci_parent
) {
49 int cur
= strlen(config_item_name(p
));
51 /* back up enough to print this bus id with '/' */
53 memcpy(buffer
+ length
, config_item_name(p
), cur
);
54 *(buffer
+ --length
) = '/';
58 static int create_link(struct config_item
*parent_item
,
59 struct config_item
*item
,
60 struct dentry
*dentry
)
62 struct configfs_dirent
*target_sd
= item
->ci_dentry
->d_fsdata
;
63 struct configfs_symlink
*sl
;
67 if (!configfs_dirent_is_ready(target_sd
))
70 sl
= kmalloc(sizeof(struct configfs_symlink
), GFP_KERNEL
);
72 spin_lock(&configfs_dirent_lock
);
73 if (target_sd
->s_type
& CONFIGFS_USET_DROPPING
) {
74 spin_unlock(&configfs_dirent_lock
);
78 sl
->sl_target
= config_item_get(item
);
79 list_add(&sl
->sl_list
, &target_sd
->s_links
);
80 spin_unlock(&configfs_dirent_lock
);
81 ret
= configfs_create_link(sl
, parent_item
->ci_dentry
,
84 spin_lock(&configfs_dirent_lock
);
85 list_del_init(&sl
->sl_list
);
86 spin_unlock(&configfs_dirent_lock
);
87 config_item_put(item
);
97 static int get_target(const char *symname
, struct path
*path
,
98 struct config_item
**target
, struct super_block
*sb
)
102 ret
= kern_path(symname
, LOOKUP_FOLLOW
|LOOKUP_DIRECTORY
, path
);
104 if (path
->dentry
->d_sb
== sb
) {
105 *target
= configfs_get_config_item(path
->dentry
);
120 int configfs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symname
)
124 struct configfs_dirent
*sd
;
125 struct config_item
*parent_item
;
126 struct config_item
*target_item
= NULL
;
127 const struct config_item_type
*type
;
129 sd
= dentry
->d_parent
->d_fsdata
;
131 * Fake invisibility if dir belongs to a group/default groups hierarchy
135 if (!configfs_dirent_is_ready(sd
))
138 parent_item
= configfs_get_config_item(dentry
->d_parent
);
139 type
= parent_item
->ci_type
;
142 if (!type
|| !type
->ct_item_ops
||
143 !type
->ct_item_ops
->allow_link
)
146 ret
= get_target(symname
, &path
, &target_item
, dentry
->d_sb
);
150 ret
= type
->ct_item_ops
->allow_link(parent_item
, target_item
);
152 mutex_lock(&configfs_symlink_mutex
);
153 ret
= create_link(parent_item
, target_item
, dentry
);
154 mutex_unlock(&configfs_symlink_mutex
);
155 if (ret
&& type
->ct_item_ops
->drop_link
)
156 type
->ct_item_ops
->drop_link(parent_item
,
160 config_item_put(target_item
);
164 config_item_put(parent_item
);
170 int configfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
172 struct configfs_dirent
*sd
= dentry
->d_fsdata
;
173 struct configfs_symlink
*sl
;
174 struct config_item
*parent_item
;
175 const struct config_item_type
*type
;
178 ret
= -EPERM
; /* What lack-of-symlink returns */
179 if (!(sd
->s_type
& CONFIGFS_ITEM_LINK
))
184 parent_item
= configfs_get_config_item(dentry
->d_parent
);
185 type
= parent_item
->ci_type
;
187 spin_lock(&configfs_dirent_lock
);
188 list_del_init(&sd
->s_sibling
);
189 spin_unlock(&configfs_dirent_lock
);
190 configfs_drop_dentry(sd
, dentry
->d_parent
);
195 * drop_link() must be called before
196 * list_del_init(&sl->sl_list), so that the order of
197 * drop_link(this, target) and drop_item(target) is preserved.
199 if (type
&& type
->ct_item_ops
&&
200 type
->ct_item_ops
->drop_link
)
201 type
->ct_item_ops
->drop_link(parent_item
,
204 spin_lock(&configfs_dirent_lock
);
205 list_del_init(&sl
->sl_list
);
206 spin_unlock(&configfs_dirent_lock
);
208 /* Put reference from create_link() */
209 config_item_put(sl
->sl_target
);
212 config_item_put(parent_item
);
220 static int configfs_get_target_path(struct config_item
* item
, struct config_item
* target
,
226 depth
= item_depth(item
);
227 size
= item_path_length(target
) + depth
* 3 - 1;
229 return -ENAMETOOLONG
;
231 pr_debug("%s: depth = %d, size = %d\n", __func__
, depth
, size
);
233 for (s
= path
; depth
--; s
+= 3)
236 fill_item_path(target
, path
, size
);
237 pr_debug("%s: path = '%s'\n", __func__
, path
);
242 static int configfs_getlink(struct dentry
*dentry
, char * path
)
244 struct config_item
*item
, *target_item
;
247 item
= configfs_get_config_item(dentry
->d_parent
);
251 target_item
= configfs_get_config_item(dentry
);
253 config_item_put(item
);
257 down_read(&configfs_rename_sem
);
258 error
= configfs_get_target_path(item
, target_item
, path
);
259 up_read(&configfs_rename_sem
);
261 config_item_put(item
);
262 config_item_put(target_item
);
267 static const char *configfs_get_link(struct dentry
*dentry
,
269 struct delayed_call
*done
)
275 return ERR_PTR(-ECHILD
);
277 body
= kzalloc(PAGE_SIZE
, GFP_KERNEL
);
279 return ERR_PTR(-ENOMEM
);
281 error
= configfs_getlink(dentry
, body
);
283 set_delayed_call(done
, kfree_link
, body
);
288 return ERR_PTR(error
);
291 const struct inode_operations configfs_symlink_inode_operations
= {
292 .get_link
= configfs_get_link
,
293 .setattr
= configfs_setattr
,