hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/fs/configfs/symlink.c
....@@ -1,22 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* -*- mode: c; c-basic-offset: 8; -*-
23 * vim: noexpandtab sw=8 ts=8 sts=0:
34 *
45 * symlink.c - operations for configfs symlinks.
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public
8
- * License as published by the Free Software Foundation; either
9
- * version 2 of the License, or (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful,
12
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
- * General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public
17
- * License along with this program; if not, write to the
18
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19
- * Boston, MA 021110-1307, USA.
206 *
217 * Based on sysfs:
228 * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
....@@ -69,41 +55,63 @@
6955 }
7056 }
7157
58
+static int configfs_get_target_path(struct config_item *item,
59
+ struct config_item *target, char *path)
60
+{
61
+ int depth, size;
62
+ char *s;
63
+
64
+ depth = item_depth(item);
65
+ size = item_path_length(target) + depth * 3 - 1;
66
+ if (size > PATH_MAX)
67
+ return -ENAMETOOLONG;
68
+
69
+ pr_debug("%s: depth = %d, size = %d\n", __func__, depth, size);
70
+
71
+ for (s = path; depth--; s += 3)
72
+ strcpy(s,"../");
73
+
74
+ fill_item_path(target, path, size);
75
+ pr_debug("%s: path = '%s'\n", __func__, path);
76
+ return 0;
77
+}
78
+
7279 static int create_link(struct config_item *parent_item,
7380 struct config_item *item,
7481 struct dentry *dentry)
7582 {
7683 struct configfs_dirent *target_sd = item->ci_dentry->d_fsdata;
77
- struct configfs_symlink *sl;
84
+ char *body;
7885 int ret;
7986
80
- ret = -ENOENT;
8187 if (!configfs_dirent_is_ready(target_sd))
82
- goto out;
83
- ret = -ENOMEM;
84
- sl = kmalloc(sizeof(struct configfs_symlink), GFP_KERNEL);
85
- if (sl) {
86
- spin_lock(&configfs_dirent_lock);
87
- if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
88
- spin_unlock(&configfs_dirent_lock);
89
- kfree(sl);
90
- return -ENOENT;
91
- }
92
- sl->sl_target = config_item_get(item);
93
- list_add(&sl->sl_list, &target_sd->s_links);
94
- spin_unlock(&configfs_dirent_lock);
95
- ret = configfs_create_link(sl, parent_item->ci_dentry,
96
- dentry);
97
- if (ret) {
98
- spin_lock(&configfs_dirent_lock);
99
- list_del_init(&sl->sl_list);
100
- spin_unlock(&configfs_dirent_lock);
101
- config_item_put(item);
102
- kfree(sl);
103
- }
104
- }
88
+ return -ENOENT;
10589
106
-out:
90
+ body = kzalloc(PAGE_SIZE, GFP_KERNEL);
91
+ if (!body)
92
+ return -ENOMEM;
93
+
94
+ configfs_get(target_sd);
95
+ spin_lock(&configfs_dirent_lock);
96
+ if (target_sd->s_type & CONFIGFS_USET_DROPPING) {
97
+ spin_unlock(&configfs_dirent_lock);
98
+ configfs_put(target_sd);
99
+ kfree(body);
100
+ return -ENOENT;
101
+ }
102
+ target_sd->s_links++;
103
+ spin_unlock(&configfs_dirent_lock);
104
+ ret = configfs_get_target_path(parent_item, item, body);
105
+ if (!ret)
106
+ ret = configfs_create_link(target_sd, parent_item->ci_dentry,
107
+ dentry, body);
108
+ if (ret) {
109
+ spin_lock(&configfs_dirent_lock);
110
+ target_sd->s_links--;
111
+ spin_unlock(&configfs_dirent_lock);
112
+ configfs_put(target_sd);
113
+ kfree(body);
114
+ }
107115 return ret;
108116 }
109117
....@@ -145,9 +153,8 @@
145153 * Fake invisibility if dir belongs to a group/default groups hierarchy
146154 * being attached
147155 */
148
- ret = -ENOENT;
149156 if (!configfs_dirent_is_ready(sd))
150
- goto out;
157
+ return -ENOENT;
151158
152159 parent_item = configfs_get_config_item(dentry->d_parent);
153160 type = parent_item->ci_type;
....@@ -207,15 +214,12 @@
207214
208215 out_put:
209216 config_item_put(parent_item);
210
-
211
-out:
212217 return ret;
213218 }
214219
215220 int configfs_unlink(struct inode *dir, struct dentry *dentry)
216221 {
217
- struct configfs_dirent *sd = dentry->d_fsdata;
218
- struct configfs_symlink *sl;
222
+ struct configfs_dirent *sd = dentry->d_fsdata, *target_sd;
219223 struct config_item *parent_item;
220224 const struct config_item_type *type;
221225 int ret;
....@@ -224,7 +228,7 @@
224228 if (!(sd->s_type & CONFIGFS_ITEM_LINK))
225229 goto out;
226230
227
- sl = sd->s_element;
231
+ target_sd = sd->s_element;
228232
229233 parent_item = configfs_get_config_item(dentry->d_parent);
230234 type = parent_item->ci_type;
....@@ -238,21 +242,18 @@
238242
239243 /*
240244 * drop_link() must be called before
241
- * list_del_init(&sl->sl_list), so that the order of
245
+ * decrementing target's ->s_links, so that the order of
242246 * drop_link(this, target) and drop_item(target) is preserved.
243247 */
244248 if (type && type->ct_item_ops &&
245249 type->ct_item_ops->drop_link)
246250 type->ct_item_ops->drop_link(parent_item,
247
- sl->sl_target);
251
+ target_sd->s_element);
248252
249253 spin_lock(&configfs_dirent_lock);
250
- list_del_init(&sl->sl_list);
254
+ target_sd->s_links--;
251255 spin_unlock(&configfs_dirent_lock);
252
-
253
- /* Put reference from create_link() */
254
- config_item_put(sl->sl_target);
255
- kfree(sl);
256
+ configfs_put(target_sd);
256257
257258 config_item_put(parent_item);
258259
....@@ -262,79 +263,8 @@
262263 return ret;
263264 }
264265
265
-static int configfs_get_target_path(struct config_item * item, struct config_item * target,
266
- char *path)
267
-{
268
- char * s;
269
- int depth, size;
270
-
271
- depth = item_depth(item);
272
- size = item_path_length(target) + depth * 3 - 1;
273
- if (size > PATH_MAX)
274
- return -ENAMETOOLONG;
275
-
276
- pr_debug("%s: depth = %d, size = %d\n", __func__, depth, size);
277
-
278
- for (s = path; depth--; s += 3)
279
- strcpy(s,"../");
280
-
281
- fill_item_path(target, path, size);
282
- pr_debug("%s: path = '%s'\n", __func__, path);
283
-
284
- return 0;
285
-}
286
-
287
-static int configfs_getlink(struct dentry *dentry, char * path)
288
-{
289
- struct config_item *item, *target_item;
290
- int error = 0;
291
-
292
- item = configfs_get_config_item(dentry->d_parent);
293
- if (!item)
294
- return -EINVAL;
295
-
296
- target_item = configfs_get_config_item(dentry);
297
- if (!target_item) {
298
- config_item_put(item);
299
- return -EINVAL;
300
- }
301
-
302
- down_read(&configfs_rename_sem);
303
- error = configfs_get_target_path(item, target_item, path);
304
- up_read(&configfs_rename_sem);
305
-
306
- config_item_put(item);
307
- config_item_put(target_item);
308
- return error;
309
-
310
-}
311
-
312
-static const char *configfs_get_link(struct dentry *dentry,
313
- struct inode *inode,
314
- struct delayed_call *done)
315
-{
316
- char *body;
317
- int error;
318
-
319
- if (!dentry)
320
- return ERR_PTR(-ECHILD);
321
-
322
- body = kzalloc(PAGE_SIZE, GFP_KERNEL);
323
- if (!body)
324
- return ERR_PTR(-ENOMEM);
325
-
326
- error = configfs_getlink(dentry, body);
327
- if (!error) {
328
- set_delayed_call(done, kfree_link, body);
329
- return body;
330
- }
331
-
332
- kfree(body);
333
- return ERR_PTR(error);
334
-}
335
-
336266 const struct inode_operations configfs_symlink_inode_operations = {
337
- .get_link = configfs_get_link,
267
+ .get_link = simple_get_link,
338268 .setattr = configfs_setattr,
339269 };
340270