1 /* -*- mode: c; c-basic-offset: 8; -*-
2 * vim: noexpandtab sw=8 ts=8 sts=0:
4 * symlink.c - operations for configfs symlinks.
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.
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.
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.
22 * sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
24 * configfs Copyright (C) 2005 Oracle. All rights reserved.
28 #include <linux/module.h>
29 #include <linux/namei.h>
30 #include <linux/slab.h>
32 #include <linux/configfs.h>
33 #include "configfs_internal.h"
35 /* Protects attachments of new symlinks */
36 DEFINE_MUTEX(configfs_symlink_mutex
);
38 static int item_depth(struct config_item
* item
)
40 struct config_item
* p
= item
;
42 do { depth
++; } while ((p
= p
->ci_parent
) && !configfs_is_root(p
));
46 static int item_path_length(struct config_item
* item
)
48 struct config_item
* p
= item
;
51 length
+= strlen(config_item_name(p
)) + 1;
53 } while (p
&& !configfs_is_root(p
));
57 static void fill_item_path(struct config_item
* item
, char * buffer
, int length
)
59 struct config_item
* p
;
62 for (p
= item
; p
&& !configfs_is_root(p
); p
= p
->ci_parent
) {
63 int cur
= strlen(config_item_name(p
));
65 /* back up enough to print this bus id with '/' */
67 strncpy(buffer
+ length
,config_item_name(p
),cur
);
68 *(buffer
+ --length
) = '/';
72 static int create_link(struct config_item
*parent_item
,
73 struct config_item
*item
,
74 struct dentry
*dentry
)
76 struct configfs_dirent
*target_sd
= item
->ci_dentry
->d_fsdata
;
77 struct configfs_symlink
*sl
;
81 if (!configfs_dirent_is_ready(target_sd
))
84 sl
= kmalloc(sizeof(struct configfs_symlink
), GFP_KERNEL
);
86 sl
->sl_target
= config_item_get(item
);
87 spin_lock(&configfs_dirent_lock
);
88 if (target_sd
->s_type
& CONFIGFS_USET_DROPPING
) {
89 spin_unlock(&configfs_dirent_lock
);
90 config_item_put(item
);
94 list_add(&sl
->sl_list
, &target_sd
->s_links
);
95 spin_unlock(&configfs_dirent_lock
);
96 ret
= configfs_create_link(sl
, parent_item
->ci_dentry
,
99 spin_lock(&configfs_dirent_lock
);
100 list_del_init(&sl
->sl_list
);
101 spin_unlock(&configfs_dirent_lock
);
102 config_item_put(item
);
112 static int get_target(const char *symname
, struct path
*path
,
113 struct config_item
**target
)
117 ret
= kern_path(symname
, LOOKUP_FOLLOW
|LOOKUP_DIRECTORY
, path
);
119 if (path
->dentry
->d_sb
== configfs_sb
) {
120 *target
= configfs_get_config_item(path
->dentry
);
135 int configfs_symlink(struct inode
*dir
, struct dentry
*dentry
, const char *symname
)
139 struct configfs_dirent
*sd
;
140 struct config_item
*parent_item
;
141 struct config_item
*target_item
= NULL
;
142 struct config_item_type
*type
;
144 ret
= -EPERM
; /* What lack-of-symlink returns */
145 if (dentry
->d_parent
== configfs_sb
->s_root
)
148 sd
= dentry
->d_parent
->d_fsdata
;
150 * Fake invisibility if dir belongs to a group/default groups hierarchy
154 if (!configfs_dirent_is_ready(sd
))
157 parent_item
= configfs_get_config_item(dentry
->d_parent
);
158 type
= parent_item
->ci_type
;
161 if (!type
|| !type
->ct_item_ops
||
162 !type
->ct_item_ops
->allow_link
)
165 ret
= get_target(symname
, &path
, &target_item
);
169 ret
= type
->ct_item_ops
->allow_link(parent_item
, target_item
);
171 mutex_lock(&configfs_symlink_mutex
);
172 ret
= create_link(parent_item
, target_item
, dentry
);
173 mutex_unlock(&configfs_symlink_mutex
);
174 if (ret
&& type
->ct_item_ops
->drop_link
)
175 type
->ct_item_ops
->drop_link(parent_item
,
179 config_item_put(target_item
);
183 config_item_put(parent_item
);
189 int configfs_unlink(struct inode
*dir
, struct dentry
*dentry
)
191 struct configfs_dirent
*sd
= dentry
->d_fsdata
;
192 struct configfs_symlink
*sl
;
193 struct config_item
*parent_item
;
194 struct config_item_type
*type
;
197 ret
= -EPERM
; /* What lack-of-symlink returns */
198 if (!(sd
->s_type
& CONFIGFS_ITEM_LINK
))
201 BUG_ON(dentry
->d_parent
== configfs_sb
->s_root
);
205 parent_item
= configfs_get_config_item(dentry
->d_parent
);
206 type
= parent_item
->ci_type
;
208 spin_lock(&configfs_dirent_lock
);
209 list_del_init(&sd
->s_sibling
);
210 spin_unlock(&configfs_dirent_lock
);
211 configfs_drop_dentry(sd
, dentry
->d_parent
);
216 * drop_link() must be called before
217 * list_del_init(&sl->sl_list), so that the order of
218 * drop_link(this, target) and drop_item(target) is preserved.
220 if (type
&& type
->ct_item_ops
&&
221 type
->ct_item_ops
->drop_link
)
222 type
->ct_item_ops
->drop_link(parent_item
,
225 spin_lock(&configfs_dirent_lock
);
226 list_del_init(&sl
->sl_list
);
227 spin_unlock(&configfs_dirent_lock
);
229 /* Put reference from create_link() */
230 config_item_put(sl
->sl_target
);
233 config_item_put(parent_item
);
241 static int configfs_get_target_path(struct config_item
* item
, struct config_item
* target
,
247 depth
= item_depth(item
);
248 size
= item_path_length(target
) + depth
* 3 - 1;
250 return -ENAMETOOLONG
;
252 pr_debug("%s: depth = %d, size = %d\n", __func__
, depth
, size
);
254 for (s
= path
; depth
--; s
+= 3)
257 fill_item_path(target
, path
, size
);
258 pr_debug("%s: path = '%s'\n", __func__
, path
);
263 static int configfs_getlink(struct dentry
*dentry
, char * path
)
265 struct config_item
*item
, *target_item
;
268 item
= configfs_get_config_item(dentry
->d_parent
);
272 target_item
= configfs_get_config_item(dentry
);
274 config_item_put(item
);
278 down_read(&configfs_rename_sem
);
279 error
= configfs_get_target_path(item
, target_item
, path
);
280 up_read(&configfs_rename_sem
);
282 config_item_put(item
);
283 config_item_put(target_item
);
288 static void *configfs_follow_link(struct dentry
*dentry
, struct nameidata
*nd
)
291 unsigned long page
= get_zeroed_page(GFP_KERNEL
);
294 error
= configfs_getlink(dentry
, (char *)page
);
296 nd_set_link(nd
, (char *)page
);
301 nd_set_link(nd
, ERR_PTR(error
));
305 static void configfs_put_link(struct dentry
*dentry
, struct nameidata
*nd
,
309 unsigned long page
= (unsigned long)cookie
;
314 const struct inode_operations configfs_symlink_inode_operations
= {
315 .follow_link
= configfs_follow_link
,
316 .readlink
= generic_readlink
,
317 .put_link
= configfs_put_link
,
318 .setattr
= configfs_setattr
,