Blame view

fs/kernfs/inode.c 9.2 KB
b8441ed27   Tejun Heo   sysfs, kernfs: ad...
1
2
3
4
5
6
7
8
9
  /*
   * fs/kernfs/inode.c - kernfs inode implementation
   *
   * Copyright (c) 2001-3 Patrick Mochel
   * Copyright (c) 2007 SUSE Linux Products GmbH
   * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org>
   *
   * This file is released under the GPLv2.
   */
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
10
11
12
13
14
15
16
17
18
19
  
  #include <linux/pagemap.h>
  #include <linux/backing-dev.h>
  #include <linux/capability.h>
  #include <linux/errno.h>
  #include <linux/slab.h>
  #include <linux/xattr.h>
  #include <linux/security.h>
  
  #include "kernfs-internal.h"
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
20
  static const struct address_space_operations kernfs_aops = {
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
21
22
23
24
  	.readpage	= simple_readpage,
  	.write_begin	= simple_write_begin,
  	.write_end	= simple_write_end,
  };
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
25
  static const struct inode_operations kernfs_iops = {
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
26
27
28
  	.permission	= kernfs_iop_permission,
  	.setattr	= kernfs_iop_setattr,
  	.getattr	= kernfs_iop_getattr,
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
29
  	.listxattr	= kernfs_iop_listxattr,
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
30
  };
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
31
  static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
32
  {
4afddd60a   Tejun Heo   kernfs: protect l...
33
34
  	static DEFINE_MUTEX(iattr_mutex);
  	struct kernfs_iattrs *ret;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
35
  	struct iattr *iattrs;
4afddd60a   Tejun Heo   kernfs: protect l...
36
  	mutex_lock(&iattr_mutex);
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
37
  	if (kn->iattr)
4afddd60a   Tejun Heo   kernfs: protect l...
38
  		goto out_unlock;
9a8049aff   Tejun Heo   kernfs: update sy...
39

c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
40
  	kn->iattr = kzalloc(sizeof(struct kernfs_iattrs), GFP_KERNEL);
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
41
  	if (!kn->iattr)
4afddd60a   Tejun Heo   kernfs: protect l...
42
  		goto out_unlock;
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
43
  	iattrs = &kn->iattr->ia_iattr;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
44
45
  
  	/* assign default attributes */
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
46
  	iattrs->ia_mode = kn->mode;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
47
48
  	iattrs->ia_uid = GLOBAL_ROOT_UID;
  	iattrs->ia_gid = GLOBAL_ROOT_GID;
3a3a5fece   Deepa Dinamani   fs: kernfs: Repla...
49
50
51
52
  
  	ktime_get_real_ts(&iattrs->ia_atime);
  	iattrs->ia_mtime = iattrs->ia_atime;
  	iattrs->ia_ctime = iattrs->ia_atime;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
53

adc5e8b58   Tejun Heo   kernfs: drop s_ p...
54
  	simple_xattrs_init(&kn->iattr->xattrs);
4afddd60a   Tejun Heo   kernfs: protect l...
55
56
57
58
  out_unlock:
  	ret = kn->iattr;
  	mutex_unlock(&iattr_mutex);
  	return ret;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
59
  }
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
60
  static int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
61
  {
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
62
  	struct kernfs_iattrs *attrs;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
63
64
  	struct iattr *iattrs;
  	unsigned int ia_valid = iattr->ia_valid;
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
65
  	attrs = kernfs_iattrs(kn);
9a8049aff   Tejun Heo   kernfs: update sy...
66
67
  	if (!attrs)
  		return -ENOMEM;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
68

9a8049aff   Tejun Heo   kernfs: update sy...
69
  	iattrs = &attrs->ia_iattr;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
70
71
72
73
74
75
76
77
78
79
80
81
82
  
  	if (ia_valid & ATTR_UID)
  		iattrs->ia_uid = iattr->ia_uid;
  	if (ia_valid & ATTR_GID)
  		iattrs->ia_gid = iattr->ia_gid;
  	if (ia_valid & ATTR_ATIME)
  		iattrs->ia_atime = iattr->ia_atime;
  	if (ia_valid & ATTR_MTIME)
  		iattrs->ia_mtime = iattr->ia_mtime;
  	if (ia_valid & ATTR_CTIME)
  		iattrs->ia_ctime = iattr->ia_ctime;
  	if (ia_valid & ATTR_MODE) {
  		umode_t mode = iattr->ia_mode;
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
83
  		iattrs->ia_mode = kn->mode = mode;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
84
85
86
87
88
89
  	}
  	return 0;
  }
  
  /**
   * kernfs_setattr - set iattr on a node
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
90
   * @kn: target node
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
91
92
93
94
   * @iattr: iattr to set
   *
   * Returns 0 on success, -errno on failure.
   */
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
95
  int kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
96
97
  {
  	int ret;
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
98
  	mutex_lock(&kernfs_mutex);
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
99
  	ret = __kernfs_setattr(kn, iattr);
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
100
  	mutex_unlock(&kernfs_mutex);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
101
102
  	return ret;
  }
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
103
  int kernfs_iop_setattr(struct dentry *dentry, struct iattr *iattr)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
104
  {
2b0143b5c   David Howells   VFS: normal files...
105
  	struct inode *inode = d_inode(dentry);
319ba91d3   Shaohua Li   kernfs: don't set...
106
  	struct kernfs_node *kn = inode->i_private;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
107
  	int error;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
108
  	if (!kn)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
109
  		return -EINVAL;
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
110
  	mutex_lock(&kernfs_mutex);
31051c85b   Jan Kara   fs: Give dentry t...
111
  	error = setattr_prepare(dentry, iattr);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
112
113
  	if (error)
  		goto out;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
114
  	error = __kernfs_setattr(kn, iattr);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
115
116
117
118
119
120
121
  	if (error)
  		goto out;
  
  	/* this ignores size changes */
  	setattr_copy(inode, iattr);
  
  out:
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
122
  	mutex_unlock(&kernfs_mutex);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
123
124
  	return error;
  }
e72a1a8b3   Andreas Gruenbacher   kernfs: Switch to...
125
  static int kernfs_node_setsecdata(struct kernfs_iattrs *attrs, void **secdata,
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
126
  				  u32 *secdata_len)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
127
  {
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
128
129
  	void *old_secdata;
  	size_t old_secdata_len;
9a8049aff   Tejun Heo   kernfs: update sy...
130
131
  	old_secdata = attrs->ia_secdata;
  	old_secdata_len = attrs->ia_secdata_len;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
132

9a8049aff   Tejun Heo   kernfs: update sy...
133
134
  	attrs->ia_secdata = *secdata;
  	attrs->ia_secdata_len = *secdata_len;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
135
136
137
138
139
  
  	*secdata = old_secdata;
  	*secdata_len = old_secdata_len;
  	return 0;
  }
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
140
  ssize_t kernfs_iop_listxattr(struct dentry *dentry, char *buf, size_t size)
2322392b0   Tejun Heo   kernfs: implement...
141
  {
319ba91d3   Shaohua Li   kernfs: don't set...
142
  	struct kernfs_node *kn = kernfs_dentry_node(dentry);
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
143
  	struct kernfs_iattrs *attrs;
2322392b0   Tejun Heo   kernfs: implement...
144

c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
145
  	attrs = kernfs_iattrs(kn);
2322392b0   Tejun Heo   kernfs: implement...
146
147
  	if (!attrs)
  		return -ENOMEM;
786534b92   Andreas Gruenbacher   tmpfs: listxattr ...
148
  	return simple_xattr_list(d_inode(dentry), &attrs->xattrs, buf, size);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
149
150
151
152
153
  }
  
  static inline void set_default_inode_attr(struct inode *inode, umode_t mode)
  {
  	inode->i_mode = mode;
3a3a5fece   Deepa Dinamani   fs: kernfs: Repla...
154
  	inode->i_atime = inode->i_mtime =
c2050a454   Deepa Dinamani   fs: Replace curre...
155
  		inode->i_ctime = current_time(inode);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
156
157
158
159
  }
  
  static inline void set_inode_attr(struct inode *inode, struct iattr *iattr)
  {
3a3a5fece   Deepa Dinamani   fs: kernfs: Repla...
160
  	struct super_block *sb = inode->i_sb;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
161
162
  	inode->i_uid = iattr->ia_uid;
  	inode->i_gid = iattr->ia_gid;
3a3a5fece   Deepa Dinamani   fs: kernfs: Repla...
163
164
165
  	inode->i_atime = timespec_trunc(iattr->ia_atime, sb->s_time_gran);
  	inode->i_mtime = timespec_trunc(iattr->ia_mtime, sb->s_time_gran);
  	inode->i_ctime = timespec_trunc(iattr->ia_ctime, sb->s_time_gran);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
166
  }
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
167
  static void kernfs_refresh_inode(struct kernfs_node *kn, struct inode *inode)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
168
  {
c525aaddc   Tejun Heo   kernfs: s/sysfs/k...
169
  	struct kernfs_iattrs *attrs = kn->iattr;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
170

adc5e8b58   Tejun Heo   kernfs: drop s_ p...
171
  	inode->i_mode = kn->mode;
9a8049aff   Tejun Heo   kernfs: update sy...
172
  	if (attrs) {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
173
174
175
  		/*
  		 * kernfs_node has non-default attributes get them from
  		 * persistent copy in kernfs_node.
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
176
  		 */
9a8049aff   Tejun Heo   kernfs: update sy...
177
178
179
  		set_inode_attr(inode, &attrs->ia_iattr);
  		security_inode_notifysecctx(inode, attrs->ia_secdata,
  					    attrs->ia_secdata_len);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
180
  	}
df23fc39b   Tejun Heo   kernfs: s/sysfs/k...
181
  	if (kernfs_type(kn) == KERNFS_DIR)
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
182
  		set_nlink(inode, kn->dir.subdirs + 2);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
183
  }
a528d35e8   David Howells   statx: Add a syst...
184
185
  int kernfs_iop_getattr(const struct path *path, struct kstat *stat,
  		       u32 request_mask, unsigned int query_flags)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
186
  {
a528d35e8   David Howells   statx: Add a syst...
187
  	struct inode *inode = d_inode(path->dentry);
319ba91d3   Shaohua Li   kernfs: don't set...
188
  	struct kernfs_node *kn = inode->i_private;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
189

a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
190
  	mutex_lock(&kernfs_mutex);
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
191
  	kernfs_refresh_inode(kn, inode);
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
192
  	mutex_unlock(&kernfs_mutex);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
193
194
195
196
  
  	generic_fillattr(inode, stat);
  	return 0;
  }
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
197
  static void kernfs_init_inode(struct kernfs_node *kn, struct inode *inode)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
198
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
199
200
  	kernfs_get(kn);
  	inode->i_private = kn;
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
201
  	inode->i_mapping->a_ops = &kernfs_aops;
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
202
  	inode->i_op = &kernfs_iops;
c53cd490b   Shaohua Li   kernfs: introduce...
203
  	inode->i_generation = kn->id.generation;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
204

adc5e8b58   Tejun Heo   kernfs: drop s_ p...
205
  	set_default_inode_attr(inode, kn->mode);
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
206
  	kernfs_refresh_inode(kn, inode);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
207
208
  
  	/* initialize inode according to type */
df23fc39b   Tejun Heo   kernfs: s/sysfs/k...
209
210
  	switch (kernfs_type(kn)) {
  	case KERNFS_DIR:
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
211
212
  		inode->i_op = &kernfs_dir_iops;
  		inode->i_fop = &kernfs_dir_fops;
ea015218f   Eric W. Biederman   kernfs: Add suppo...
213
214
  		if (kn->flags & KERNFS_EMPTY_DIR)
  			make_empty_dir_inode(inode);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
215
  		break;
df23fc39b   Tejun Heo   kernfs: s/sysfs/k...
216
  	case KERNFS_FILE:
adc5e8b58   Tejun Heo   kernfs: drop s_ p...
217
  		inode->i_size = kn->attr.size;
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
218
  		inode->i_fop = &kernfs_file_fops;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
219
  		break;
df23fc39b   Tejun Heo   kernfs: s/sysfs/k...
220
  	case KERNFS_LINK:
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
221
  		inode->i_op = &kernfs_symlink_iops;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
222
223
224
225
226
227
228
229
230
  		break;
  	default:
  		BUG();
  	}
  
  	unlock_new_inode(inode);
  }
  
  /**
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
231
   *	kernfs_get_inode - get inode for kernfs_node
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
232
   *	@sb: super block
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
233
   *	@kn: kernfs_node to allocate inode for
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
234
   *
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
235
236
237
   *	Get inode for @kn.  If such inode doesn't exist, a new inode is
   *	allocated and basics are initialized.  New inode is returned
   *	locked.
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
238
239
240
241
242
243
244
   *
   *	LOCKING:
   *	Kernel thread context (may sleep).
   *
   *	RETURNS:
   *	Pointer to allocated inode on success, NULL on failure.
   */
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
245
  struct inode *kernfs_get_inode(struct super_block *sb, struct kernfs_node *kn)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
246
247
  {
  	struct inode *inode;
c53cd490b   Shaohua Li   kernfs: introduce...
248
  	inode = iget_locked(sb, kn->id.ino);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
249
  	if (inode && (inode->i_state & I_NEW))
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
250
  		kernfs_init_inode(kn, inode);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
251
252
253
254
255
  
  	return inode;
  }
  
  /*
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
256
257
258
   * The kernfs_node serves as both an inode and a directory entry for
   * kernfs.  To prevent the kernfs inode numbers from being freed
   * prematurely we take a reference to kernfs_node from the kernfs inode.  A
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
259
260
261
   * super_operations.evict_inode() implementation is needed to drop that
   * reference upon inode destruction.
   */
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
262
  void kernfs_evict_inode(struct inode *inode)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
263
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
264
  	struct kernfs_node *kn = inode->i_private;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
265

91b0abe36   Johannes Weiner   mm + fs: store sh...
266
  	truncate_inode_pages_final(&inode->i_data);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
267
  	clear_inode(inode);
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
268
  	kernfs_put(kn);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
269
  }
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
270
  int kernfs_iop_permission(struct inode *inode, int mask)
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
271
  {
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
272
  	struct kernfs_node *kn;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
273
274
275
  
  	if (mask & MAY_NOT_BLOCK)
  		return -ECHILD;
324a56e16   Tejun Heo   kernfs: s/sysfs_d...
276
  	kn = inode->i_private;
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
277

a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
278
  	mutex_lock(&kernfs_mutex);
c637b8acb   Tejun Heo   kernfs: s/sysfs/k...
279
  	kernfs_refresh_inode(kn, inode);
a797bfc30   Tejun Heo   kernfs: s/sysfs/k...
280
  	mutex_unlock(&kernfs_mutex);
ffed24e22   Tejun Heo   sysfs, kernfs: mo...
281
282
283
  
  	return generic_permission(inode, mask);
  }
e72a1a8b3   Andreas Gruenbacher   kernfs: Switch to...
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
  
  static int kernfs_xattr_get(const struct xattr_handler *handler,
  			    struct dentry *unused, struct inode *inode,
  			    const char *suffix, void *value, size_t size)
  {
  	const char *name = xattr_full_name(handler, suffix);
  	struct kernfs_node *kn = inode->i_private;
  	struct kernfs_iattrs *attrs;
  
  	attrs = kernfs_iattrs(kn);
  	if (!attrs)
  		return -ENOMEM;
  
  	return simple_xattr_get(&attrs->xattrs, name, value, size);
  }
  
  static int kernfs_xattr_set(const struct xattr_handler *handler,
  			    struct dentry *unused, struct inode *inode,
  			    const char *suffix, const void *value,
  			    size_t size, int flags)
  {
  	const char *name = xattr_full_name(handler, suffix);
  	struct kernfs_node *kn = inode->i_private;
  	struct kernfs_iattrs *attrs;
  
  	attrs = kernfs_iattrs(kn);
  	if (!attrs)
  		return -ENOMEM;
  
  	return simple_xattr_set(&attrs->xattrs, name, value, size, flags);
  }
b5a062344   Bart Van Assche   kernfs: Declare t...
315
  static const struct xattr_handler kernfs_trusted_xattr_handler = {
e72a1a8b3   Andreas Gruenbacher   kernfs: Switch to...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
  	.prefix = XATTR_TRUSTED_PREFIX,
  	.get = kernfs_xattr_get,
  	.set = kernfs_xattr_set,
  };
  
  static int kernfs_security_xattr_set(const struct xattr_handler *handler,
  				     struct dentry *unused, struct inode *inode,
  				     const char *suffix, const void *value,
  				     size_t size, int flags)
  {
  	struct kernfs_node *kn = inode->i_private;
  	struct kernfs_iattrs *attrs;
  	void *secdata;
  	u32 secdata_len = 0;
  	int error;
  
  	attrs = kernfs_iattrs(kn);
  	if (!attrs)
  		return -ENOMEM;
  
  	error = security_inode_setsecurity(inode, suffix, value, size, flags);
  	if (error)
  		return error;
  	error = security_inode_getsecctx(inode, &secdata, &secdata_len);
  	if (error)
  		return error;
  
  	mutex_lock(&kernfs_mutex);
  	error = kernfs_node_setsecdata(attrs, &secdata, &secdata_len);
  	mutex_unlock(&kernfs_mutex);
  
  	if (secdata)
  		security_release_secctx(secdata, secdata_len);
  	return error;
  }
b5a062344   Bart Van Assche   kernfs: Declare t...
351
  static const struct xattr_handler kernfs_security_xattr_handler = {
e72a1a8b3   Andreas Gruenbacher   kernfs: Switch to...
352
353
354
355
356
357
358
359
360
361
  	.prefix = XATTR_SECURITY_PREFIX,
  	.get = kernfs_xattr_get,
  	.set = kernfs_security_xattr_set,
  };
  
  const struct xattr_handler *kernfs_xattr_handlers[] = {
  	&kernfs_trusted_xattr_handler,
  	&kernfs_security_xattr_handler,
  	NULL
  };