Blame view

fs/configfs/file.c 14.3 KB
328970de0   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
7063fbf22   Joel Becker   [PATCH] configfs:...
2
3
4
5
6
  /* -*- mode: c; c-basic-offset: 8; -*-
   * vim: noexpandtab sw=8 ts=8 sts=0:
   *
   * file.c - operations for regular (text) files.
   *
7063fbf22   Joel Becker   [PATCH] configfs:...
7
8
9
10
11
12
13
14
   * Based on sysfs:
   * 	sysfs is Copyright (C) 2001, 2002, 2003 Patrick Mochel
   *
   * configfs Copyright (C) 2005 Oracle.  All rights reserved.
   */
  
  #include <linux/fs.h>
  #include <linux/module.h>
7063fbf22   Joel Becker   [PATCH] configfs:...
15
  #include <linux/slab.h>
6d748924b   Johannes Berg   [PATCH] configsfs...
16
  #include <linux/mutex.h>
03607ace8   Pantelis Antoniou   configfs: impleme...
17
  #include <linux/vmalloc.h>
7c0f6ba68   Linus Torvalds   Replace <asm/uacc...
18
  #include <linux/uaccess.h>
7063fbf22   Joel Becker   [PATCH] configfs:...
19
20
21
  
  #include <linux/configfs.h>
  #include "configfs_internal.h"
b23cdde4c   Joel Becker   configfs: consist...
22
23
24
25
26
27
28
  /*
   * A simple attribute can only be 4096 characters.  Why 4k?  Because the
   * original code limited it to PAGE_SIZE.  That's a bad idea, though,
   * because an attribute of 16k on ia64 won't work on x86.  So we limit to
   * 4k, our minimum common page size.
   */
  #define SIMPLE_ATTR_SIZE 4096
7063fbf22   Joel Becker   [PATCH] configfs:...
29
30
31
32
33
34
  
  struct configfs_buffer {
  	size_t			count;
  	loff_t			pos;
  	char			* page;
  	struct configfs_item_operations	* ops;
6d748924b   Johannes Berg   [PATCH] configsfs...
35
  	struct mutex		mutex;
7063fbf22   Joel Becker   [PATCH] configfs:...
36
  	int			needs_read_fill;
03607ace8   Pantelis Antoniou   configfs: impleme...
37
38
39
40
  	bool			read_in_progress;
  	bool			write_in_progress;
  	char			*bin_buffer;
  	int			bin_buffer_size;
ff4dd0819   Al Viro   configfs: stash t...
41
42
43
44
45
46
47
  	int			cb_max_size;
  	struct config_item	*item;
  	struct module		*owner;
  	union {
  		struct configfs_attribute	*attr;
  		struct configfs_bin_attribute	*bin_attr;
  	};
7063fbf22   Joel Becker   [PATCH] configfs:...
48
  };
b0841eefd   Al Viro   configfs: provide...
49
50
51
52
53
54
  static inline struct configfs_fragment *to_frag(struct file *file)
  {
  	struct configfs_dirent *sd = file->f_path.dentry->d_fsdata;
  
  	return sd->s_frag;
  }
7063fbf22   Joel Becker   [PATCH] configfs:...
55

b0841eefd   Al Viro   configfs: provide...
56
  static int fill_read_buffer(struct file *file, struct configfs_buffer *buffer)
7063fbf22   Joel Becker   [PATCH] configfs:...
57
  {
b0841eefd   Al Viro   configfs: provide...
58
59
  	struct configfs_fragment *frag = to_frag(file);
  	ssize_t count = -ENOENT;
7063fbf22   Joel Becker   [PATCH] configfs:...
60
61
62
63
64
  
  	if (!buffer->page)
  		buffer->page = (char *) get_zeroed_page(GFP_KERNEL);
  	if (!buffer->page)
  		return -ENOMEM;
b0841eefd   Al Viro   configfs: provide...
65
66
67
68
  	down_read(&frag->frag_sem);
  	if (!frag->frag_dead)
  		count = buffer->attr->show(buffer->item, buffer->page);
  	up_read(&frag->frag_sem);
ff4dd0819   Al Viro   configfs: stash t...
69
70
71
72
  	if (count < 0)
  		return count;
  	if (WARN_ON_ONCE(count > (ssize_t)SIMPLE_ATTR_SIZE))
  		return -EIO;
ff4dd0819   Al Viro   configfs: stash t...
73
74
75
  	buffer->needs_read_fill = 0;
  	buffer->count = count;
  	return 0;
7063fbf22   Joel Becker   [PATCH] configfs:...
76
  }
7063fbf22   Joel Becker   [PATCH] configfs:...
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  /**
   *	configfs_read_file - read an attribute.
   *	@file:	file pointer.
   *	@buf:	buffer to fill.
   *	@count:	number of bytes to read.
   *	@ppos:	starting offset in file.
   *
   *	Userspace wants to read an attribute file. The attribute descriptor
   *	is in the file's ->d_fsdata. The target item is in the directory's
   *	->d_fsdata.
   *
   *	We call fill_read_buffer() to allocate and fill the buffer from the
   *	item's show() method exactly once (if the read is happening from
   *	the beginning of the file). That should fill the entire buffer with
   *	all the data the item has to offer for that attribute.
   *	We then call flush_read_buffer() to copy the buffer to userspace
   *	in the increments specified.
   */
  
  static ssize_t
  configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos)
  {
ff4dd0819   Al Viro   configfs: stash t...
99
  	struct configfs_buffer *buffer = file->private_data;
7063fbf22   Joel Becker   [PATCH] configfs:...
100
  	ssize_t retval = 0;
6d748924b   Johannes Berg   [PATCH] configsfs...
101
  	mutex_lock(&buffer->mutex);
7063fbf22   Joel Becker   [PATCH] configfs:...
102
  	if (buffer->needs_read_fill) {
b0841eefd   Al Viro   configfs: provide...
103
  		retval = fill_read_buffer(file, buffer);
ff4dd0819   Al Viro   configfs: stash t...
104
  		if (retval)
7063fbf22   Joel Becker   [PATCH] configfs:...
105
106
  			goto out;
  	}
4779efca1   Zach Brown   [PATCH] pr_debug:...
107
108
  	pr_debug("%s: count = %zd, ppos = %lld, buf = %s
  ",
8e24eea72   Harvey Harrison   fs: replace remai...
109
  		 __func__, count, *ppos, buffer->page);
92f4c701a   Akinobu Mita   use simple_read_f...
110
111
  	retval = simple_read_from_buffer(buf, count, ppos, buffer->page,
  					 buffer->count);
7063fbf22   Joel Becker   [PATCH] configfs:...
112
  out:
6d748924b   Johannes Berg   [PATCH] configsfs...
113
  	mutex_unlock(&buffer->mutex);
7063fbf22   Joel Becker   [PATCH] configfs:...
114
115
  	return retval;
  }
03607ace8   Pantelis Antoniou   configfs: impleme...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  /**
   *	configfs_read_bin_file - read a binary attribute.
   *	@file:	file pointer.
   *	@buf:	buffer to fill.
   *	@count:	number of bytes to read.
   *	@ppos:	starting offset in file.
   *
   *	Userspace wants to read a binary attribute file. The attribute
   *	descriptor is in the file's ->d_fsdata. The target item is in the
   *	directory's ->d_fsdata.
   *
   *	We check whether we need to refill the buffer. If so we will
   *	call the attributes' attr->read() twice. The first time we
   *	will pass a NULL as a buffer pointer, which the attributes' method
   *	will use to return the size of the buffer required. If no error
   *	occurs we will allocate the buffer using vmalloc and call
   *	attr->read() again passing that buffer as an argument.
   *	Then we just copy to user-space using simple_read_from_buffer.
   */
  
  static ssize_t
  configfs_read_bin_file(struct file *file, char __user *buf,
  		       size_t count, loff_t *ppos)
  {
b0841eefd   Al Viro   configfs: provide...
140
  	struct configfs_fragment *frag = to_frag(file);
03607ace8   Pantelis Antoniou   configfs: impleme...
141
  	struct configfs_buffer *buffer = file->private_data;
03607ace8   Pantelis Antoniou   configfs: impleme...
142
143
144
145
146
147
148
149
150
151
  	ssize_t retval = 0;
  	ssize_t len = min_t(size_t, count, PAGE_SIZE);
  
  	mutex_lock(&buffer->mutex);
  
  	/* we don't support switching read/write modes */
  	if (buffer->write_in_progress) {
  		retval = -ETXTBSY;
  		goto out;
  	}
3f6928c34   Thomas Meyer   configfs: Fix boo...
152
  	buffer->read_in_progress = true;
03607ace8   Pantelis Antoniou   configfs: impleme...
153
154
155
  
  	if (buffer->needs_read_fill) {
  		/* perform first read with buf == NULL to get extent */
b0841eefd   Al Viro   configfs: provide...
156
157
158
159
160
161
  		down_read(&frag->frag_sem);
  		if (!frag->frag_dead)
  			len = buffer->bin_attr->read(buffer->item, NULL, 0);
  		else
  			len = -ENOENT;
  		up_read(&frag->frag_sem);
03607ace8   Pantelis Antoniou   configfs: impleme...
162
163
164
165
166
167
  		if (len <= 0) {
  			retval = len;
  			goto out;
  		}
  
  		/* do not exceed the maximum value */
ff4dd0819   Al Viro   configfs: stash t...
168
  		if (buffer->cb_max_size && len > buffer->cb_max_size) {
03607ace8   Pantelis Antoniou   configfs: impleme...
169
170
171
172
173
174
175
176
177
178
179
180
  			retval = -EFBIG;
  			goto out;
  		}
  
  		buffer->bin_buffer = vmalloc(len);
  		if (buffer->bin_buffer == NULL) {
  			retval = -ENOMEM;
  			goto out;
  		}
  		buffer->bin_buffer_size = len;
  
  		/* perform second read to fill buffer */
b0841eefd   Al Viro   configfs: provide...
181
182
183
184
185
186
187
  		down_read(&frag->frag_sem);
  		if (!frag->frag_dead)
  			len = buffer->bin_attr->read(buffer->item,
  						     buffer->bin_buffer, len);
  		else
  			len = -ENOENT;
  		up_read(&frag->frag_sem);
03607ace8   Pantelis Antoniou   configfs: impleme...
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
  		if (len < 0) {
  			retval = len;
  			vfree(buffer->bin_buffer);
  			buffer->bin_buffer_size = 0;
  			buffer->bin_buffer = NULL;
  			goto out;
  		}
  
  		buffer->needs_read_fill = 0;
  	}
  
  	retval = simple_read_from_buffer(buf, count, ppos, buffer->bin_buffer,
  					buffer->bin_buffer_size);
  out:
  	mutex_unlock(&buffer->mutex);
  	return retval;
  }
7063fbf22   Joel Becker   [PATCH] configfs:...
205
206
207
208
  
  /**
   *	fill_write_buffer - copy buffer from userspace.
   *	@buffer:	data buffer for file.
3d0f89bb1   Joel Becker   configfs: Add per...
209
   *	@buf:		data from user.
7063fbf22   Joel Becker   [PATCH] configfs:...
210
211
212
213
214
215
216
217
218
219
220
221
   *	@count:		number of bytes in @userbuf.
   *
   *	Allocate @buffer->page if it hasn't been already, then
   *	copy the user-supplied buffer into it.
   */
  
  static int
  fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size_t count)
  {
  	int error;
  
  	if (!buffer->page)
ff05d1c46   Joel Becker   configfs: Zero te...
222
  		buffer->page = (char *)__get_free_pages(GFP_KERNEL, 0);
7063fbf22   Joel Becker   [PATCH] configfs:...
223
224
  	if (!buffer->page)
  		return -ENOMEM;
b23cdde4c   Joel Becker   configfs: consist...
225
226
  	if (count >= SIMPLE_ATTR_SIZE)
  		count = SIMPLE_ATTR_SIZE - 1;
7063fbf22   Joel Becker   [PATCH] configfs:...
227
228
  	error = copy_from_user(buffer->page,buf,count);
  	buffer->needs_read_fill = 1;
ff05d1c46   Joel Becker   configfs: Zero te...
229
230
231
  	/* if buf is assumed to contain a string, terminate it by \0,
  	 * so e.g. sscanf() can scan the string easily */
  	buffer->page[count] = 0;
7063fbf22   Joel Becker   [PATCH] configfs:...
232
233
  	return error ? -EFAULT : count;
  }
7063fbf22   Joel Becker   [PATCH] configfs:...
234
  static int
b0841eefd   Al Viro   configfs: provide...
235
  flush_write_buffer(struct file *file, struct configfs_buffer *buffer, size_t count)
7063fbf22   Joel Becker   [PATCH] configfs:...
236
  {
b0841eefd   Al Viro   configfs: provide...
237
238
239
240
241
242
243
244
  	struct configfs_fragment *frag = to_frag(file);
  	int res = -ENOENT;
  
  	down_read(&frag->frag_sem);
  	if (!frag->frag_dead)
  		res = buffer->attr->store(buffer->item, buffer->page, count);
  	up_read(&frag->frag_sem);
  	return res;
7063fbf22   Joel Becker   [PATCH] configfs:...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  }
  
  
  /**
   *	configfs_write_file - write an attribute.
   *	@file:	file pointer
   *	@buf:	data to write
   *	@count:	number of bytes
   *	@ppos:	starting offset
   *
   *	Similar to configfs_read_file(), though working in the opposite direction.
   *	We allocate and fill the data from the user in fill_write_buffer(),
   *	then push it to the config_item in flush_write_buffer().
   *	There is no easy way for us to know if userspace is only doing a partial
   *	write, so we don't support them. We expect the entire buffer to come
   *	on the first write.
ce9bebe68   Randy Dunlap   fs: configfs: del...
261
   *	Hint: if you're writing a value, first read the file, modify only
7063fbf22   Joel Becker   [PATCH] configfs:...
262
263
264
265
266
267
   *	the value you're changing, then write entire buffer back.
   */
  
  static ssize_t
  configfs_write_file(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
  {
ff4dd0819   Al Viro   configfs: stash t...
268
  	struct configfs_buffer *buffer = file->private_data;
3d0f89bb1   Joel Becker   configfs: Add per...
269
  	ssize_t len;
7063fbf22   Joel Becker   [PATCH] configfs:...
270

6d748924b   Johannes Berg   [PATCH] configsfs...
271
  	mutex_lock(&buffer->mutex);
3d0f89bb1   Joel Becker   configfs: Add per...
272
273
  	len = fill_write_buffer(buffer, buf, count);
  	if (len > 0)
b0841eefd   Al Viro   configfs: provide...
274
  		len = flush_write_buffer(file, buffer, len);
3d0f89bb1   Joel Becker   configfs: Add per...
275
276
  	if (len > 0)
  		*ppos += len;
6d748924b   Johannes Berg   [PATCH] configsfs...
277
  	mutex_unlock(&buffer->mutex);
3d0f89bb1   Joel Becker   configfs: Add per...
278
  	return len;
7063fbf22   Joel Becker   [PATCH] configfs:...
279
  }
03607ace8   Pantelis Antoniou   configfs: impleme...
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
  /**
   *	configfs_write_bin_file - write a binary attribute.
   *	@file:	file pointer
   *	@buf:	data to write
   *	@count:	number of bytes
   *	@ppos:	starting offset
   *
   *	Writing to a binary attribute file is similar to a normal read.
   *	We buffer the consecutive writes (binary attribute files do not
   *	support lseek) in a continuously growing buffer, but we don't
   *	commit until the close of the file.
   */
  
  static ssize_t
  configfs_write_bin_file(struct file *file, const char __user *buf,
  			size_t count, loff_t *ppos)
  {
  	struct configfs_buffer *buffer = file->private_data;
03607ace8   Pantelis Antoniou   configfs: impleme...
298
299
300
301
302
303
304
305
306
307
  	void *tbuf = NULL;
  	ssize_t len;
  
  	mutex_lock(&buffer->mutex);
  
  	/* we don't support switching read/write modes */
  	if (buffer->read_in_progress) {
  		len = -ETXTBSY;
  		goto out;
  	}
3f6928c34   Thomas Meyer   configfs: Fix boo...
308
  	buffer->write_in_progress = true;
03607ace8   Pantelis Antoniou   configfs: impleme...
309
310
311
  
  	/* buffer grows? */
  	if (*ppos + count > buffer->bin_buffer_size) {
ff4dd0819   Al Viro   configfs: stash t...
312
313
  		if (buffer->cb_max_size &&
  			*ppos + count > buffer->cb_max_size) {
03607ace8   Pantelis Antoniou   configfs: impleme...
314
  			len = -EFBIG;
42857cf51   Phil Turnbull   configfs: Return ...
315
  			goto out;
03607ace8   Pantelis Antoniou   configfs: impleme...
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
  		}
  
  		tbuf = vmalloc(*ppos + count);
  		if (tbuf == NULL) {
  			len = -ENOMEM;
  			goto out;
  		}
  
  		/* copy old contents */
  		if (buffer->bin_buffer) {
  			memcpy(tbuf, buffer->bin_buffer,
  				buffer->bin_buffer_size);
  			vfree(buffer->bin_buffer);
  		}
  
  		/* clear the new area */
  		memset(tbuf + buffer->bin_buffer_size, 0,
  			*ppos + count - buffer->bin_buffer_size);
  		buffer->bin_buffer = tbuf;
  		buffer->bin_buffer_size = *ppos + count;
  	}
  
  	len = simple_write_to_buffer(buffer->bin_buffer,
  			buffer->bin_buffer_size, ppos, buf, count);
03607ace8   Pantelis Antoniou   configfs: impleme...
340
341
342
343
  out:
  	mutex_unlock(&buffer->mutex);
  	return len;
  }
ff4dd0819   Al Viro   configfs: stash t...
344
  static int __configfs_open_file(struct inode *inode, struct file *file, int type)
7063fbf22   Joel Becker   [PATCH] configfs:...
345
  {
ff4dd0819   Al Viro   configfs: stash t...
346
  	struct dentry *dentry = file->f_path.dentry;
b0841eefd   Al Viro   configfs: provide...
347
  	struct configfs_fragment *frag = to_frag(file);
ff4dd0819   Al Viro   configfs: stash t...
348
349
350
  	struct configfs_attribute *attr;
  	struct configfs_buffer *buffer;
  	int error;
7063fbf22   Joel Becker   [PATCH] configfs:...
351

ff4dd0819   Al Viro   configfs: stash t...
352
353
354
355
  	error = -ENOMEM;
  	buffer = kzalloc(sizeof(struct configfs_buffer), GFP_KERNEL);
  	if (!buffer)
  		goto out;
7063fbf22   Joel Becker   [PATCH] configfs:...
356

b0841eefd   Al Viro   configfs: provide...
357
358
359
360
  	error = -ENOENT;
  	down_read(&frag->frag_sem);
  	if (unlikely(frag->frag_dead))
  		goto out_free_buffer;
ff4dd0819   Al Viro   configfs: stash t...
361
  	error = -EINVAL;
b0841eefd   Al Viro   configfs: provide...
362
  	buffer->item = to_item(dentry->d_parent);
ff4dd0819   Al Viro   configfs: stash t...
363
364
365
366
367
368
369
370
371
372
373
374
375
  	if (!buffer->item)
  		goto out_free_buffer;
  
  	attr = to_attr(dentry);
  	if (!attr)
  		goto out_put_item;
  
  	if (type & CONFIGFS_ITEM_BIN_ATTR) {
  		buffer->bin_attr = to_bin_attr(dentry);
  		buffer->cb_max_size = buffer->bin_attr->cb_max_size;
  	} else {
  		buffer->attr = attr;
  	}
03607ace8   Pantelis Antoniou   configfs: impleme...
376

ff4dd0819   Al Viro   configfs: stash t...
377
  	buffer->owner = attr->ca_owner;
7063fbf22   Joel Becker   [PATCH] configfs:...
378
  	/* Grab the module reference for this attribute if we have one */
ff4dd0819   Al Viro   configfs: stash t...
379
380
381
  	error = -ENODEV;
  	if (!try_module_get(buffer->owner))
  		goto out_put_item;
7063fbf22   Joel Becker   [PATCH] configfs:...
382

ff4dd0819   Al Viro   configfs: stash t...
383
384
385
386
387
  	error = -EACCES;
  	if (!buffer->item->ci_type)
  		goto out_put_module;
  
  	buffer->ops = buffer->item->ci_type->ct_item_ops;
7063fbf22   Joel Becker   [PATCH] configfs:...
388
389
390
391
392
393
  
  	/* File needs write support.
  	 * The inode's perms must say it's ok,
  	 * and we must have a store method.
  	 */
  	if (file->f_mode & FMODE_WRITE) {
03607ace8   Pantelis Antoniou   configfs: impleme...
394
  		if (!(inode->i_mode & S_IWUGO))
ff4dd0819   Al Viro   configfs: stash t...
395
  			goto out_put_module;
03607ace8   Pantelis Antoniou   configfs: impleme...
396
  		if ((type & CONFIGFS_ITEM_ATTR) && !attr->store)
ff4dd0819   Al Viro   configfs: stash t...
397
398
399
  			goto out_put_module;
  		if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->write)
  			goto out_put_module;
7063fbf22   Joel Becker   [PATCH] configfs:...
400
401
402
403
404
405
406
  	}
  
  	/* File needs read support.
  	 * The inode's perms must say it's ok, and we there
  	 * must be a show method for it.
  	 */
  	if (file->f_mode & FMODE_READ) {
03607ace8   Pantelis Antoniou   configfs: impleme...
407
  		if (!(inode->i_mode & S_IRUGO))
ff4dd0819   Al Viro   configfs: stash t...
408
  			goto out_put_module;
03607ace8   Pantelis Antoniou   configfs: impleme...
409
  		if ((type & CONFIGFS_ITEM_ATTR) && !attr->show)
ff4dd0819   Al Viro   configfs: stash t...
410
411
412
  			goto out_put_module;
  		if ((type & CONFIGFS_ITEM_BIN_ATTR) && !buffer->bin_attr->read)
  			goto out_put_module;
7063fbf22   Joel Becker   [PATCH] configfs:...
413
  	}
6d748924b   Johannes Berg   [PATCH] configsfs...
414
  	mutex_init(&buffer->mutex);
559c9ac39   Chandra Seetharaman   configfs: handle ...
415
  	buffer->needs_read_fill = 1;
3f6928c34   Thomas Meyer   configfs: Fix boo...
416
417
  	buffer->read_in_progress = false;
  	buffer->write_in_progress = false;
559c9ac39   Chandra Seetharaman   configfs: handle ...
418
  	file->private_data = buffer;
b0841eefd   Al Viro   configfs: provide...
419
  	up_read(&frag->frag_sem);
ff4dd0819   Al Viro   configfs: stash t...
420
  	return 0;
7063fbf22   Joel Becker   [PATCH] configfs:...
421

ff4dd0819   Al Viro   configfs: stash t...
422
423
424
425
426
  out_put_module:
  	module_put(buffer->owner);
  out_put_item:
  	config_item_put(buffer->item);
  out_free_buffer:
b0841eefd   Al Viro   configfs: provide...
427
  	up_read(&frag->frag_sem);
ff4dd0819   Al Viro   configfs: stash t...
428
429
  	kfree(buffer);
  out:
7063fbf22   Joel Becker   [PATCH] configfs:...
430
431
  	return error;
  }
03607ace8   Pantelis Antoniou   configfs: impleme...
432
  static int configfs_release(struct inode *inode, struct file *filp)
7063fbf22   Joel Becker   [PATCH] configfs:...
433
  {
ff4dd0819   Al Viro   configfs: stash t...
434
  	struct configfs_buffer *buffer = filp->private_data;
ff4dd0819   Al Viro   configfs: stash t...
435
436
437
438
439
  	module_put(buffer->owner);
  	if (buffer->page)
  		free_page((unsigned long)buffer->page);
  	mutex_destroy(&buffer->mutex);
  	kfree(buffer);
7063fbf22   Joel Becker   [PATCH] configfs:...
440
441
  	return 0;
  }
03607ace8   Pantelis Antoniou   configfs: impleme...
442
443
  static int configfs_open_file(struct inode *inode, struct file *filp)
  {
ff4dd0819   Al Viro   configfs: stash t...
444
  	return __configfs_open_file(inode, filp, CONFIGFS_ITEM_ATTR);
03607ace8   Pantelis Antoniou   configfs: impleme...
445
446
447
448
  }
  
  static int configfs_open_bin_file(struct inode *inode, struct file *filp)
  {
ff4dd0819   Al Viro   configfs: stash t...
449
  	return __configfs_open_file(inode, filp, CONFIGFS_ITEM_BIN_ATTR);
03607ace8   Pantelis Antoniou   configfs: impleme...
450
  }
ff4dd0819   Al Viro   configfs: stash t...
451
  static int configfs_release_bin_file(struct inode *inode, struct file *file)
03607ace8   Pantelis Antoniou   configfs: impleme...
452
  {
ff4dd0819   Al Viro   configfs: stash t...
453
  	struct configfs_buffer *buffer = file->private_data;
03607ace8   Pantelis Antoniou   configfs: impleme...
454

3f6928c34   Thomas Meyer   configfs: Fix boo...
455
  	buffer->read_in_progress = false;
03607ace8   Pantelis Antoniou   configfs: impleme...
456
457
  
  	if (buffer->write_in_progress) {
b0841eefd   Al Viro   configfs: provide...
458
  		struct configfs_fragment *frag = to_frag(file);
3f6928c34   Thomas Meyer   configfs: Fix boo...
459
  		buffer->write_in_progress = false;
03607ace8   Pantelis Antoniou   configfs: impleme...
460

b0841eefd   Al Viro   configfs: provide...
461
462
463
464
465
466
467
468
  		down_read(&frag->frag_sem);
  		if (!frag->frag_dead) {
  			/* result of ->release() is ignored */
  			buffer->bin_attr->write(buffer->item,
  					buffer->bin_buffer,
  					buffer->bin_buffer_size);
  		}
  		up_read(&frag->frag_sem);
03607ace8   Pantelis Antoniou   configfs: impleme...
469
470
471
472
473
474
  		/* vfree on NULL is safe */
  		vfree(buffer->bin_buffer);
  		buffer->bin_buffer = NULL;
  		buffer->bin_buffer_size = 0;
  		buffer->needs_read_fill = 1;
  	}
ff4dd0819   Al Viro   configfs: stash t...
475
476
  	configfs_release(inode, file);
  	return 0;
03607ace8   Pantelis Antoniou   configfs: impleme...
477
  }
4b6f5d20b   Arjan van de Ven   [PATCH] Make most...
478
  const struct file_operations configfs_file_operations = {
7063fbf22   Joel Becker   [PATCH] configfs:...
479
480
481
482
483
484
  	.read		= configfs_read_file,
  	.write		= configfs_write_file,
  	.llseek		= generic_file_llseek,
  	.open		= configfs_open_file,
  	.release	= configfs_release,
  };
03607ace8   Pantelis Antoniou   configfs: impleme...
485
486
487
488
489
490
491
  const struct file_operations configfs_bin_file_operations = {
  	.read		= configfs_read_bin_file,
  	.write		= configfs_write_bin_file,
  	.llseek		= NULL,		/* bin file is not seekable */
  	.open		= configfs_open_bin_file,
  	.release	= configfs_release_bin_file,
  };
7063fbf22   Joel Becker   [PATCH] configfs:...
492
493
494
495
496
497
498
499
  /**
   *	configfs_create_file - create an attribute file for an item.
   *	@item:	item we're creating for.
   *	@attr:	atrribute descriptor.
   */
  
  int configfs_create_file(struct config_item * item, const struct configfs_attribute * attr)
  {
28444a2bd   Al Viro   configfs_add_file...
500
501
502
503
  	struct dentry *dir = item->ci_dentry;
  	struct configfs_dirent *parent_sd = dir->d_fsdata;
  	umode_t mode = (attr->ca_mode & S_IALLUGO) | S_IFREG;
  	int error = 0;
7063fbf22   Joel Becker   [PATCH] configfs:...
504

5955102c9   Al Viro   wrappers for ->i_...
505
  	inode_lock_nested(d_inode(dir), I_MUTEX_NORMAL);
28444a2bd   Al Viro   configfs_add_file...
506
  	error = configfs_make_dirent(parent_sd, NULL, (void *) attr, mode,
47320fbe1   Al Viro   configfs: new obj...
507
  				     CONFIGFS_ITEM_ATTR, parent_sd->s_frag);
5955102c9   Al Viro   wrappers for ->i_...
508
  	inode_unlock(d_inode(dir));
28444a2bd   Al Viro   configfs_add_file...
509
510
  
  	return error;
7063fbf22   Joel Becker   [PATCH] configfs:...
511
  }
03607ace8   Pantelis Antoniou   configfs: impleme...
512
513
514
515
516
517
518
519
520
521
522
523
524
  /**
   *	configfs_create_bin_file - create a binary attribute file for an item.
   *	@item:	item we're creating for.
   *	@attr:	atrribute descriptor.
   */
  
  int configfs_create_bin_file(struct config_item *item,
  		const struct configfs_bin_attribute *bin_attr)
  {
  	struct dentry *dir = item->ci_dentry;
  	struct configfs_dirent *parent_sd = dir->d_fsdata;
  	umode_t mode = (bin_attr->cb_attr.ca_mode & S_IALLUGO) | S_IFREG;
  	int error = 0;
5955102c9   Al Viro   wrappers for ->i_...
525
  	inode_lock_nested(dir->d_inode, I_MUTEX_NORMAL);
03607ace8   Pantelis Antoniou   configfs: impleme...
526
  	error = configfs_make_dirent(parent_sd, NULL, (void *) bin_attr, mode,
47320fbe1   Al Viro   configfs: new obj...
527
  				     CONFIGFS_ITEM_BIN_ATTR, parent_sd->s_frag);
5955102c9   Al Viro   wrappers for ->i_...
528
  	inode_unlock(dir->d_inode);
03607ace8   Pantelis Antoniou   configfs: impleme...
529
530
531
  
  	return error;
  }