@@ -95,13 +95,31 @@ static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode)
95
95
return - ENOMEM ;
96
96
97
97
if (mode == DBGFS_GET_SHORT ) {
98
- fsd -> real_fops = NULL ;
99
- fsd -> short_fops = (void * )((unsigned long )d_fsd &
100
- ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT );
98
+ const struct debugfs_short_fops * ops ;
99
+ ops = (void * )((unsigned long )d_fsd &
100
+ ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT );
101
+ fsd -> short_fops = ops ;
102
+ if (ops -> llseek )
103
+ fsd -> methods |= HAS_LSEEK ;
104
+ if (ops -> read )
105
+ fsd -> methods |= HAS_READ ;
106
+ if (ops -> write )
107
+ fsd -> methods |= HAS_WRITE ;
101
108
} else {
102
- fsd -> real_fops = (void * )((unsigned long )d_fsd &
103
- ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT );
104
- fsd -> short_fops = NULL ;
109
+ const struct file_operations * ops ;
110
+ ops = (void * )((unsigned long )d_fsd &
111
+ ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT );
112
+ fsd -> real_fops = ops ;
113
+ if (ops -> llseek )
114
+ fsd -> methods |= HAS_LSEEK ;
115
+ if (ops -> read )
116
+ fsd -> methods |= HAS_READ ;
117
+ if (ops -> write )
118
+ fsd -> methods |= HAS_WRITE ;
119
+ if (ops -> unlocked_ioctl )
120
+ fsd -> methods |= HAS_IOCTL ;
121
+ if (ops -> poll )
122
+ fsd -> methods |= HAS_POLL ;
105
123
}
106
124
refcount_set (& fsd -> active_users , 1 );
107
125
init_completion (& fsd -> active_users_drained );
@@ -322,13 +340,16 @@ const struct file_operations debugfs_open_proxy_file_operations = {
322
340
#define PROTO (args ...) args
323
341
#define ARGS (args ...) args
324
342
325
- #define FULL_PROXY_FUNC (name , ret_type , filp , proto , args ) \
343
+ #define FULL_PROXY_FUNC (name , ret_type , filp , proto , args , bit , ret ) \
326
344
static ret_type full_proxy_ ## name(proto) \
327
345
{ \
328
- struct dentry *dentry = F_DENTRY(filp); \
346
+ struct dentry *dentry = F_DENTRY(filp); \
347
+ struct debugfs_fsdata *fsd = dentry->d_fsdata; \
329
348
const struct file_operations *real_fops; \
330
349
ret_type r; \
331
350
\
351
+ if (!(fsd->methods & bit)) \
352
+ return ret; \
332
353
r = debugfs_file_get(dentry); \
333
354
if (unlikely(r)) \
334
355
return r; \
@@ -338,17 +359,18 @@ static ret_type full_proxy_ ## name(proto) \
338
359
return r; \
339
360
}
340
361
341
- #define FULL_PROXY_FUNC_BOTH (name , ret_type , filp , proto , args ) \
362
+ #define FULL_PROXY_FUNC_BOTH (name , ret_type , filp , proto , args , bit , ret ) \
342
363
static ret_type full_proxy_ ## name(proto) \
343
364
{ \
344
365
struct dentry *dentry = F_DENTRY(filp); \
345
- struct debugfs_fsdata *fsd; \
366
+ struct debugfs_fsdata *fsd = dentry->d_fsdata; \
346
367
ret_type r; \
347
368
\
369
+ if (!(fsd->methods & bit)) \
370
+ return ret; \
348
371
r = debugfs_file_get(dentry); \
349
372
if (unlikely(r)) \
350
373
return r; \
351
- fsd = dentry->d_fsdata; \
352
374
if (fsd->real_fops) \
353
375
r = fsd->real_fops->name(args); \
354
376
else \
@@ -359,29 +381,32 @@ static ret_type full_proxy_ ## name(proto) \
359
381
360
382
FULL_PROXY_FUNC_BOTH (llseek , loff_t , filp ,
361
383
PROTO (struct file * filp , loff_t offset , int whence ),
362
- ARGS (filp , offset , whence ));
384
+ ARGS (filp , offset , whence ), HAS_LSEEK , - ESPIPE );
363
385
364
386
FULL_PROXY_FUNC_BOTH (read , ssize_t , filp ,
365
387
PROTO (struct file * filp , char __user * buf , size_t size ,
366
388
loff_t * ppos ),
367
- ARGS (filp , buf , size , ppos ));
389
+ ARGS (filp , buf , size , ppos ), HAS_READ , - EINVAL );
368
390
369
391
FULL_PROXY_FUNC_BOTH (write , ssize_t , filp ,
370
392
PROTO (struct file * filp , const char __user * buf ,
371
393
size_t size , loff_t * ppos ),
372
- ARGS (filp , buf , size , ppos ));
394
+ ARGS (filp , buf , size , ppos ), HAS_WRITE , - EINVAL );
373
395
374
396
FULL_PROXY_FUNC (unlocked_ioctl , long , filp ,
375
397
PROTO (struct file * filp , unsigned int cmd , unsigned long arg ),
376
- ARGS (filp , cmd , arg ));
398
+ ARGS (filp , cmd , arg ), HAS_IOCTL , - ENOTTY );
377
399
378
400
static __poll_t full_proxy_poll (struct file * filp ,
379
401
struct poll_table_struct * wait )
380
402
{
381
403
struct dentry * dentry = F_DENTRY (filp );
404
+ struct debugfs_fsdata * fsd = dentry -> d_fsdata ;
382
405
__poll_t r = 0 ;
383
406
const struct file_operations * real_fops ;
384
407
408
+ if (!(fsd -> methods & HAS_POLL ))
409
+ return DEFAULT_POLLMASK ;
385
410
if (debugfs_file_get (dentry ))
386
411
return EPOLLHUP ;
387
412
@@ -393,9 +418,7 @@ static __poll_t full_proxy_poll(struct file *filp,
393
418
394
419
static int full_proxy_release (struct inode * inode , struct file * filp )
395
420
{
396
- const struct dentry * dentry = F_DENTRY (filp );
397
421
const struct file_operations * real_fops = debugfs_real_fops (filp );
398
- const struct file_operations * proxy_fops = filp -> f_op ;
399
422
int r = 0 ;
400
423
401
424
/*
@@ -407,42 +430,15 @@ static int full_proxy_release(struct inode *inode, struct file *filp)
407
430
if (real_fops && real_fops -> release )
408
431
r = real_fops -> release (inode , filp );
409
432
410
- replace_fops (filp , d_inode (dentry )-> i_fop );
411
- kfree (proxy_fops );
412
433
fops_put (real_fops );
413
434
return r ;
414
435
}
415
436
416
- static void __full_proxy_fops_init (struct file_operations * proxy_fops ,
417
- struct debugfs_fsdata * fsd )
418
- {
419
- proxy_fops -> release = full_proxy_release ;
420
-
421
- if ((fsd -> real_fops && fsd -> real_fops -> llseek ) ||
422
- (fsd -> short_fops && fsd -> short_fops -> llseek ))
423
- proxy_fops -> llseek = full_proxy_llseek ;
424
-
425
- if ((fsd -> real_fops && fsd -> real_fops -> read ) ||
426
- (fsd -> short_fops && fsd -> short_fops -> read ))
427
- proxy_fops -> read = full_proxy_read ;
428
-
429
- if ((fsd -> real_fops && fsd -> real_fops -> write ) ||
430
- (fsd -> short_fops && fsd -> short_fops -> write ))
431
- proxy_fops -> write = full_proxy_write ;
432
-
433
- if (fsd -> real_fops && fsd -> real_fops -> poll )
434
- proxy_fops -> poll = full_proxy_poll ;
435
-
436
- if (fsd -> real_fops && fsd -> real_fops -> unlocked_ioctl )
437
- proxy_fops -> unlocked_ioctl = full_proxy_unlocked_ioctl ;
438
- }
439
-
440
437
static int full_proxy_open (struct inode * inode , struct file * filp ,
441
438
enum dbgfs_get_mode mode )
442
439
{
443
440
struct dentry * dentry = F_DENTRY (filp );
444
441
const struct file_operations * real_fops ;
445
- struct file_operations * proxy_fops = NULL ;
446
442
struct debugfs_fsdata * fsd ;
447
443
int r ;
448
444
@@ -472,34 +468,20 @@ static int full_proxy_open(struct inode *inode, struct file *filp,
472
468
goto out ;
473
469
}
474
470
475
- proxy_fops = kzalloc (sizeof (* proxy_fops ), GFP_KERNEL );
476
- if (!proxy_fops ) {
477
- r = - ENOMEM ;
478
- goto free_proxy ;
479
- }
480
- __full_proxy_fops_init (proxy_fops , fsd );
481
- replace_fops (filp , proxy_fops );
482
-
483
471
if (!real_fops || real_fops -> open ) {
484
472
if (real_fops )
485
473
r = real_fops -> open (inode , filp );
486
474
else
487
475
r = simple_open (inode , filp );
488
476
if (r ) {
489
- replace_fops (filp , d_inode (dentry )-> i_fop );
490
- goto free_proxy ;
491
- } else if (filp -> f_op != proxy_fops ) {
477
+ fops_put (real_fops );
478
+ } else if (filp -> f_op != & debugfs_full_proxy_file_operations ) {
492
479
/* No protection against file removal anymore. */
493
480
WARN (1 , "debugfs file owner replaced proxy fops: %pd" ,
494
481
dentry );
495
- goto free_proxy ;
482
+ fops_put ( real_fops ) ;
496
483
}
497
484
}
498
-
499
- goto out ;
500
- free_proxy :
501
- kfree (proxy_fops );
502
- fops_put (real_fops );
503
485
out :
504
486
debugfs_file_put (dentry );
505
487
return r ;
@@ -512,6 +494,12 @@ static int full_proxy_open_regular(struct inode *inode, struct file *filp)
512
494
513
495
const struct file_operations debugfs_full_proxy_file_operations = {
514
496
.open = full_proxy_open_regular ,
497
+ .release = full_proxy_release ,
498
+ .llseek = full_proxy_llseek ,
499
+ .read = full_proxy_read ,
500
+ .write = full_proxy_write ,
501
+ .poll = full_proxy_poll ,
502
+ .unlocked_ioctl = full_proxy_unlocked_ioctl
515
503
};
516
504
517
505
static int full_proxy_open_short (struct inode * inode , struct file * filp )
@@ -521,6 +509,9 @@ static int full_proxy_open_short(struct inode *inode, struct file *filp)
521
509
522
510
const struct file_operations debugfs_full_short_proxy_file_operations = {
523
511
.open = full_proxy_open_short ,
512
+ .llseek = full_proxy_llseek ,
513
+ .read = full_proxy_read ,
514
+ .write = full_proxy_write ,
524
515
};
525
516
526
517
ssize_t debugfs_attr_read (struct file * file , char __user * buf ,
0 commit comments