@@ -48,22 +48,32 @@ struct configfs_buffer {
48
48
};
49
49
};
50
50
51
+ static inline struct configfs_fragment * to_frag (struct file * file )
52
+ {
53
+ struct configfs_dirent * sd = file -> f_path .dentry -> d_fsdata ;
54
+
55
+ return sd -> s_frag ;
56
+ }
51
57
52
- static int fill_read_buffer (struct configfs_buffer * buffer )
58
+ static int fill_read_buffer (struct file * file , struct configfs_buffer * buffer )
53
59
{
54
- ssize_t count ;
60
+ struct configfs_fragment * frag = to_frag (file );
61
+ ssize_t count = - ENOENT ;
55
62
56
63
if (!buffer -> page )
57
64
buffer -> page = (char * ) get_zeroed_page (GFP_KERNEL );
58
65
if (!buffer -> page )
59
66
return - ENOMEM ;
60
67
61
- count = buffer -> attr -> show (buffer -> item , buffer -> page );
68
+ down_read (& frag -> frag_sem );
69
+ if (!frag -> frag_dead )
70
+ count = buffer -> attr -> show (buffer -> item , buffer -> page );
71
+ up_read (& frag -> frag_sem );
72
+
62
73
if (count < 0 )
63
74
return count ;
64
75
if (WARN_ON_ONCE (count > (ssize_t )SIMPLE_ATTR_SIZE ))
65
76
return - EIO ;
66
-
67
77
buffer -> needs_read_fill = 0 ;
68
78
buffer -> count = count ;
69
79
return 0 ;
@@ -96,7 +106,7 @@ configfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *pp
96
106
97
107
mutex_lock (& buffer -> mutex );
98
108
if (buffer -> needs_read_fill ) {
99
- retval = fill_read_buffer (buffer );
109
+ retval = fill_read_buffer (file , buffer );
100
110
if (retval )
101
111
goto out ;
102
112
}
@@ -133,6 +143,7 @@ static ssize_t
133
143
configfs_read_bin_file (struct file * file , char __user * buf ,
134
144
size_t count , loff_t * ppos )
135
145
{
146
+ struct configfs_fragment * frag = to_frag (file );
136
147
struct configfs_buffer * buffer = file -> private_data ;
137
148
ssize_t retval = 0 ;
138
149
ssize_t len = min_t (size_t , count , PAGE_SIZE );
@@ -148,7 +159,12 @@ configfs_read_bin_file(struct file *file, char __user *buf,
148
159
149
160
if (buffer -> needs_read_fill ) {
150
161
/* perform first read with buf == NULL to get extent */
151
- len = buffer -> bin_attr -> read (buffer -> item , NULL , 0 );
162
+ down_read (& frag -> frag_sem );
163
+ if (!frag -> frag_dead )
164
+ len = buffer -> bin_attr -> read (buffer -> item , NULL , 0 );
165
+ else
166
+ len = - ENOENT ;
167
+ up_read (& frag -> frag_sem );
152
168
if (len <= 0 ) {
153
169
retval = len ;
154
170
goto out ;
@@ -168,8 +184,13 @@ configfs_read_bin_file(struct file *file, char __user *buf,
168
184
buffer -> bin_buffer_size = len ;
169
185
170
186
/* perform second read to fill buffer */
171
- len = buffer -> bin_attr -> read (buffer -> item ,
172
- buffer -> bin_buffer , len );
187
+ down_read (& frag -> frag_sem );
188
+ if (!frag -> frag_dead )
189
+ len = buffer -> bin_attr -> read (buffer -> item ,
190
+ buffer -> bin_buffer , len );
191
+ else
192
+ len = - ENOENT ;
193
+ up_read (& frag -> frag_sem );
173
194
if (len < 0 ) {
174
195
retval = len ;
175
196
vfree (buffer -> bin_buffer );
@@ -220,9 +241,16 @@ fill_write_buffer(struct configfs_buffer * buffer, const char __user * buf, size
220
241
}
221
242
222
243
static int
223
- flush_write_buffer (struct configfs_buffer * buffer , size_t count )
244
+ flush_write_buffer (struct file * file , struct configfs_buffer * buffer , size_t count )
224
245
{
225
- return buffer -> attr -> store (buffer -> item , buffer -> page , count );
246
+ struct configfs_fragment * frag = to_frag (file );
247
+ int res = - ENOENT ;
248
+
249
+ down_read (& frag -> frag_sem );
250
+ if (!frag -> frag_dead )
251
+ res = buffer -> attr -> store (buffer -> item , buffer -> page , count );
252
+ up_read (& frag -> frag_sem );
253
+ return res ;
226
254
}
227
255
228
256
@@ -252,7 +280,7 @@ configfs_write_file(struct file *file, const char __user *buf, size_t count, lof
252
280
mutex_lock (& buffer -> mutex );
253
281
len = fill_write_buffer (buffer , buf , count );
254
282
if (len > 0 )
255
- len = flush_write_buffer (buffer , len );
283
+ len = flush_write_buffer (file , buffer , len );
256
284
if (len > 0 )
257
285
* ppos += len ;
258
286
mutex_unlock (& buffer -> mutex );
@@ -328,6 +356,7 @@ configfs_write_bin_file(struct file *file, const char __user *buf,
328
356
static int __configfs_open_file (struct inode * inode , struct file * file , int type )
329
357
{
330
358
struct dentry * dentry = file -> f_path .dentry ;
359
+ struct configfs_fragment * frag = to_frag (file );
331
360
struct configfs_attribute * attr ;
332
361
struct configfs_buffer * buffer ;
333
362
int error ;
@@ -337,8 +366,13 @@ static int __configfs_open_file(struct inode *inode, struct file *file, int type
337
366
if (!buffer )
338
367
goto out ;
339
368
369
+ error = - ENOENT ;
370
+ down_read (& frag -> frag_sem );
371
+ if (unlikely (frag -> frag_dead ))
372
+ goto out_free_buffer ;
373
+
340
374
error = - EINVAL ;
341
- buffer -> item = configfs_get_config_item (dentry -> d_parent );
375
+ buffer -> item = to_item (dentry -> d_parent );
342
376
if (!buffer -> item )
343
377
goto out_free_buffer ;
344
378
@@ -396,13 +430,15 @@ static int __configfs_open_file(struct inode *inode, struct file *file, int type
396
430
buffer -> read_in_progress = false;
397
431
buffer -> write_in_progress = false;
398
432
file -> private_data = buffer ;
433
+ up_read (& frag -> frag_sem );
399
434
return 0 ;
400
435
401
436
out_put_module :
402
437
module_put (buffer -> owner );
403
438
out_put_item :
404
439
config_item_put (buffer -> item );
405
440
out_free_buffer :
441
+ up_read (& frag -> frag_sem );
406
442
kfree (buffer );
407
443
out :
408
444
return error ;
@@ -412,8 +448,6 @@ static int configfs_release(struct inode *inode, struct file *filp)
412
448
{
413
449
struct configfs_buffer * buffer = filp -> private_data ;
414
450
415
- if (buffer -> item )
416
- config_item_put (buffer -> item );
417
451
module_put (buffer -> owner );
418
452
if (buffer -> page )
419
453
free_page ((unsigned long )buffer -> page );
@@ -439,12 +473,17 @@ static int configfs_release_bin_file(struct inode *inode, struct file *file)
439
473
buffer -> read_in_progress = false;
440
474
441
475
if (buffer -> write_in_progress ) {
476
+ struct configfs_fragment * frag = to_frag (file );
442
477
buffer -> write_in_progress = false;
443
478
444
- /* result of ->release() is ignored */
445
- buffer -> bin_attr -> write (buffer -> item , buffer -> bin_buffer ,
446
- buffer -> bin_buffer_size );
447
-
479
+ down_read (& frag -> frag_sem );
480
+ if (!frag -> frag_dead ) {
481
+ /* result of ->release() is ignored */
482
+ buffer -> bin_attr -> write (buffer -> item ,
483
+ buffer -> bin_buffer ,
484
+ buffer -> bin_buffer_size );
485
+ }
486
+ up_read (& frag -> frag_sem );
448
487
/* vfree on NULL is safe */
449
488
vfree (buffer -> bin_buffer );
450
489
buffer -> bin_buffer = NULL ;
0 commit comments