Blame view

fs/sysfs/symlink.c 4.79 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
  /*
6d66f5cd2   Tejun Heo   sysfs: add copyri...
2
3
4
5
6
7
8
9
10
   * fs/sysfs/symlink.c - sysfs symlink implementation
   *
   * Copyright (c) 2001-3 Patrick Mochel
   * Copyright (c) 2007 SUSE Linux Products GmbH
   * Copyright (c) 2007 Tejun Heo <teheo@suse.de>
   *
   * This file is released under the GPLv2.
   *
   * Please see Documentation/filesystems/sysfs.txt for more information.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
   */
  
  #include <linux/fs.h>
  #include <linux/module.h>
  #include <linux/kobject.h>
869512ab5   Dave Young   sysfs: cleanup se...
16
  #include <linux/mutex.h>
ddd29ec65   David P. Quigley   sysfs: Add labeli...
17
  #include <linux/security.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
18
19
  
  #include "sysfs.h"
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
20
21
  static int sysfs_do_create_link_sd(struct kernfs_node *parent,
  				   struct kobject *target_kobj,
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
22
  				   const char *name, int warn)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
23
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
24
  	struct kernfs_node *kn, *target = NULL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
25

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
26
  	BUG_ON(!name || !parent);
2b29ac252   Tejun Heo   sysfs: reimplemen...
27

0cae60f91   Tejun Heo   sysfs: rename sys...
28
  	/*
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
29
  	 * We don't own @target_kobj and it may be removed at any time.
0cae60f91   Tejun Heo   sysfs: rename sys...
30
31
  	 * Synchronize using sysfs_symlink_target_lock.  See
  	 * sysfs_remove_dir() for details.
2b29ac252   Tejun Heo   sysfs: reimplemen...
32
  	 */
0cae60f91   Tejun Heo   sysfs: rename sys...
33
  	spin_lock(&sysfs_symlink_target_lock);
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
34
35
36
  	if (target_kobj->sd) {
  		target = target_kobj->sd;
  		kernfs_get(target);
ccf73cf33   Tejun Heo   sysfs, kernfs: in...
37
  	}
0cae60f91   Tejun Heo   sysfs: rename sys...
38
  	spin_unlock(&sysfs_symlink_target_lock);
2b29ac252   Tejun Heo   sysfs: reimplemen...
39

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
40
  	if (!target)
5d0e26bb5   Tejun Heo   sysfs, kernfs: in...
41
  		return -ENOENT;
a1da4dfe3   Tejun Heo   sysfs: kill an ex...
42

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
43
44
  	kn = kernfs_create_link(parent, name, target);
  	kernfs_put(target);
967e35dcc   Tejun Heo   sysfs: cosmetic c...
45

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
46
  	if (!IS_ERR(kn))
5d0e26bb5   Tejun Heo   sysfs, kernfs: in...
47
  		return 0;
fb6896da3   Tejun Heo   sysfs: restructur...
48

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
49
50
51
  	if (warn && PTR_ERR(kn) == -EEXIST)
  		sysfs_warn_dup(parent, name);
  	return PTR_ERR(kn);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
52
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
53
  /**
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
54
   *	sysfs_create_link_sd - create symlink to a given object.
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
55
   *	@kn:		directory we're creating the link in.
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
56
57
58
   *	@target:	object we're pointing to.
   *	@name:		name of the symlink.
   */
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
59
  int sysfs_create_link_sd(struct kernfs_node *kn, struct kobject *target,
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
60
61
  			 const char *name)
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
62
  	return sysfs_do_create_link_sd(kn, target, name, 1);
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
63
64
65
66
67
  }
  
  static int sysfs_do_create_link(struct kobject *kobj, struct kobject *target,
  				const char *name, int warn)
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
68
  	struct kernfs_node *parent = NULL;
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
69
70
  
  	if (!kobj)
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
71
  		parent = sysfs_root_kn;
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
72
  	else
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
73
  		parent = kobj->sd;
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
74

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
75
  	if (!parent)
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
76
  		return -EFAULT;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
77
  	return sysfs_do_create_link_sd(parent, target, name, warn);
0bb8f3d6a   Rafael J. Wysocki   sysfs: Functions ...
78
79
80
  }
  
  /**
36ce6dad6   Cornelia Huck   driver core: Supp...
81
82
83
84
85
86
87
88
89
90
   *	sysfs_create_link - create symlink between two objects.
   *	@kobj:	object whose directory we're creating the link in.
   *	@target:	object we're pointing to.
   *	@name:		name of the symlink.
   */
  int sysfs_create_link(struct kobject *kobj, struct kobject *target,
  		      const char *name)
  {
  	return sysfs_do_create_link(kobj, target, name, 1);
  }
1b866757f   Greg Kroah-Hartman   sysfs: fix placem...
91
  EXPORT_SYMBOL_GPL(sysfs_create_link);
36ce6dad6   Cornelia Huck   driver core: Supp...
92
93
94
95
96
97
98
  
  /**
   *	sysfs_create_link_nowarn - create symlink between two objects.
   *	@kobj:	object whose directory we're creating the link in.
   *	@target:	object we're pointing to.
   *	@name:		name of the symlink.
   *
6f1cbd4a2   Robert P. J. Day   sysfs: Fix commen...
99
   *	This function does the same as sysfs_create_link(), but it
36ce6dad6   Cornelia Huck   driver core: Supp...
100
101
102
103
104
105
106
107
108
   *	doesn't warn if the link already exists.
   */
  int sysfs_create_link_nowarn(struct kobject *kobj, struct kobject *target,
  			     const char *name)
  {
  	return sysfs_do_create_link(kobj, target, name, 0);
  }
  
  /**
746edb7ae   Eric W. Biederman   sysfs: Implement ...
109
110
111
112
113
114
115
116
117
118
119
120
   *	sysfs_delete_link - remove symlink in object's directory.
   *	@kobj:	object we're acting for.
   *	@targ:	object we're pointing to.
   *	@name:	name of the symlink to remove.
   *
   *	Unlike sysfs_remove_link sysfs_delete_link has enough information
   *	to successfully delete symlinks in tagged directories.
   */
  void sysfs_delete_link(struct kobject *kobj, struct kobject *targ,
  			const char *name)
  {
  	const void *ns = NULL;
0cae60f91   Tejun Heo   sysfs: rename sys...
121
122
123
124
125
126
127
  
  	/*
  	 * We don't own @target and it may be removed at any time.
  	 * Synchronize using sysfs_symlink_target_lock.  See
  	 * sysfs_remove_dir() for details.
  	 */
  	spin_lock(&sysfs_symlink_target_lock);
ac9bba031   Tejun Heo   sysfs, kernfs: im...
128
  	if (targ->sd && kernfs_ns_enabled(kobj->sd))
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
129
  		ns = targ->sd->ns;
0cae60f91   Tejun Heo   sysfs: rename sys...
130
  	spin_unlock(&sysfs_symlink_target_lock);
879f40d19   Tejun Heo   sysfs, kernfs: in...
131
  	kernfs_remove_by_name_ns(kobj->sd, name, ns);
746edb7ae   Eric W. Biederman   sysfs: Implement ...
132
133
134
  }
  
  /**
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
137
138
   *	sysfs_remove_link - remove symlink in object's directory.
   *	@kobj:	object we're acting for.
   *	@name:	name of the symlink to remove.
   */
1b18dc2be   Greg Kroah-Hartman   sysfs: fix up spa...
139
  void sysfs_remove_link(struct kobject *kobj, const char *name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
140
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
141
  	struct kernfs_node *parent = NULL;
a839c5afc   Mark Fasheh   sysfs: Allow remo...
142
143
  
  	if (!kobj)
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
144
  		parent = sysfs_root_kn;
a839c5afc   Mark Fasheh   sysfs: Allow remo...
145
  	else
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
146
  		parent = kobj->sd;
a839c5afc   Mark Fasheh   sysfs: Allow remo...
147

324a56e16   Tejun Heo   kernfs: s/sysfs_d...
148
  	kernfs_remove_by_name(parent, name);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
149
  }
1b866757f   Greg Kroah-Hartman   sysfs: fix placem...
150
  EXPORT_SYMBOL_GPL(sysfs_remove_link);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
151

7cb32942d   Eric W. Biederman   sysfs: Implement ...
152
  /**
4b30ee58e   Tejun Heo   sysfs: remove kty...
153
   *	sysfs_rename_link_ns - rename symlink in object's directory.
7cb32942d   Eric W. Biederman   sysfs: Implement ...
154
155
156
157
   *	@kobj:	object we're acting for.
   *	@targ:	object we're pointing to.
   *	@old:	previous name of the symlink.
   *	@new:	new name of the symlink.
4b30ee58e   Tejun Heo   sysfs: remove kty...
158
   *	@new_ns: new namespace of the symlink.
7cb32942d   Eric W. Biederman   sysfs: Implement ...
159
160
161
   *
   *	A helper function for the common rename symlink idiom.
   */
4b30ee58e   Tejun Heo   sysfs: remove kty...
162
163
  int sysfs_rename_link_ns(struct kobject *kobj, struct kobject *targ,
  			 const char *old, const char *new, const void *new_ns)
7cb32942d   Eric W. Biederman   sysfs: Implement ...
164
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
165
  	struct kernfs_node *parent, *kn = NULL;
4b30ee58e   Tejun Heo   sysfs: remove kty...
166
  	const void *old_ns = NULL;
7cb32942d   Eric W. Biederman   sysfs: Implement ...
167
168
169
  	int result;
  
  	if (!kobj)
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
170
  		parent = sysfs_root_kn;
7cb32942d   Eric W. Biederman   sysfs: Implement ...
171
  	else
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
172
  		parent = kobj->sd;
7cb32942d   Eric W. Biederman   sysfs: Implement ...
173

3ff195b01   Eric W. Biederman   sysfs: Implement ...
174
  	if (targ->sd)
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
175
  		old_ns = targ->sd->ns;
3ff195b01   Eric W. Biederman   sysfs: Implement ...
176

7cb32942d   Eric W. Biederman   sysfs: Implement ...
177
  	result = -ENOENT;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
178
179
  	kn = kernfs_find_and_get_ns(parent, old, old_ns);
  	if (!kn)
7cb32942d   Eric W. Biederman   sysfs: Implement ...
180
181
182
  		goto out;
  
  	result = -EINVAL;
df23fc39b   Tejun Heo   kernfs: s/sysfs/k...
183
  	if (kernfs_type(kn) != KERNFS_LINK)
7cb32942d   Eric W. Biederman   sysfs: Implement ...
184
  		goto out;
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
185
  	if (kn->symlink.target_kn->priv != targ)
7cb32942d   Eric W. Biederman   sysfs: Implement ...
186
  		goto out;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
187
  	result = kernfs_rename_ns(kn, parent, new, new_ns);
7cb32942d   Eric W. Biederman   sysfs: Implement ...
188
189
  
  out:
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
190
  	kernfs_put(kn);
7cb32942d   Eric W. Biederman   sysfs: Implement ...
191
192
  	return result;
  }
4b30ee58e   Tejun Heo   sysfs: remove kty...
193
  EXPORT_SYMBOL_GPL(sysfs_rename_link_ns);