@@ -95,13 +95,31 @@ static int __debugfs_file_get(struct dentry *dentry, enum dbgfs_get_mode mode)
9595 return - ENOMEM ;
9696
9797 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 ;
101108 } 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 ;
105123 }
106124 refcount_set (& fsd -> active_users , 1 );
107125 init_completion (& fsd -> active_users_drained );
@@ -322,13 +340,16 @@ const struct file_operations debugfs_open_proxy_file_operations = {
322340#define PROTO (args ...) args
323341#define ARGS (args ...) args
324342
325- #define FULL_PROXY_FUNC (name , ret_type , filp , proto , args ) \
343+ #define FULL_PROXY_FUNC (name , ret_type , filp , proto , args , bit , ret ) \
326344static ret_type full_proxy_ ## name(proto) \
327345{ \
328- struct dentry *dentry = F_DENTRY(filp); \
346+ struct dentry *dentry = F_DENTRY(filp); \
347+ struct debugfs_fsdata *fsd = dentry->d_fsdata; \
329348 const struct file_operations *real_fops; \
330349 ret_type r; \
331350 \
351+ if (!(fsd->methods & bit)) \
352+ return ret; \
332353 r = debugfs_file_get(dentry); \
333354 if (unlikely(r)) \
334355 return r; \
@@ -338,17 +359,18 @@ static ret_type full_proxy_ ## name(proto) \
338359 return r; \
339360}
340361
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 ) \
342363static ret_type full_proxy_ ## name(proto) \
343364{ \
344365 struct dentry *dentry = F_DENTRY(filp); \
345- struct debugfs_fsdata *fsd; \
366+ struct debugfs_fsdata *fsd = dentry->d_fsdata; \
346367 ret_type r; \
347368 \
369+ if (!(fsd->methods & bit)) \
370+ return ret; \
348371 r = debugfs_file_get(dentry); \
349372 if (unlikely(r)) \
350373 return r; \
351- fsd = dentry->d_fsdata; \
352374 if (fsd->real_fops) \
353375 r = fsd->real_fops->name(args); \
354376 else \
@@ -359,29 +381,32 @@ static ret_type full_proxy_ ## name(proto) \
359381
360382FULL_PROXY_FUNC_BOTH (llseek , loff_t , filp ,
361383 PROTO (struct file * filp , loff_t offset , int whence ),
362- ARGS (filp , offset , whence ));
384+ ARGS (filp , offset , whence ), HAS_LSEEK , - ESPIPE );
363385
364386FULL_PROXY_FUNC_BOTH (read , ssize_t , filp ,
365387 PROTO (struct file * filp , char __user * buf , size_t size ,
366388 loff_t * ppos ),
367- ARGS (filp , buf , size , ppos ));
389+ ARGS (filp , buf , size , ppos ), HAS_READ , - EINVAL );
368390
369391FULL_PROXY_FUNC_BOTH (write , ssize_t , filp ,
370392 PROTO (struct file * filp , const char __user * buf ,
371393 size_t size , loff_t * ppos ),
372- ARGS (filp , buf , size , ppos ));
394+ ARGS (filp , buf , size , ppos ), HAS_WRITE , - EINVAL );
373395
374396FULL_PROXY_FUNC (unlocked_ioctl , long , filp ,
375397 PROTO (struct file * filp , unsigned int cmd , unsigned long arg ),
376- ARGS (filp , cmd , arg ));
398+ ARGS (filp , cmd , arg ), HAS_IOCTL , - ENOTTY );
377399
378400static __poll_t full_proxy_poll (struct file * filp ,
379401 struct poll_table_struct * wait )
380402{
381403 struct dentry * dentry = F_DENTRY (filp );
404+ struct debugfs_fsdata * fsd = dentry -> d_fsdata ;
382405 __poll_t r = 0 ;
383406 const struct file_operations * real_fops ;
384407
408+ if (!(fsd -> methods & HAS_POLL ))
409+ return DEFAULT_POLLMASK ;
385410 if (debugfs_file_get (dentry ))
386411 return EPOLLHUP ;
387412
@@ -393,9 +418,7 @@ static __poll_t full_proxy_poll(struct file *filp,
393418
394419static int full_proxy_release (struct inode * inode , struct file * filp )
395420{
396- const struct dentry * dentry = F_DENTRY (filp );
397421 const struct file_operations * real_fops = debugfs_real_fops (filp );
398- const struct file_operations * proxy_fops = filp -> f_op ;
399422 int r = 0 ;
400423
401424 /*
@@ -407,42 +430,15 @@ static int full_proxy_release(struct inode *inode, struct file *filp)
407430 if (real_fops && real_fops -> release )
408431 r = real_fops -> release (inode , filp );
409432
410- replace_fops (filp , d_inode (dentry )-> i_fop );
411- kfree (proxy_fops );
412433 fops_put (real_fops );
413434 return r ;
414435}
415436
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-
440437static int full_proxy_open (struct inode * inode , struct file * filp ,
441438 enum dbgfs_get_mode mode )
442439{
443440 struct dentry * dentry = F_DENTRY (filp );
444441 const struct file_operations * real_fops ;
445- struct file_operations * proxy_fops = NULL ;
446442 struct debugfs_fsdata * fsd ;
447443 int r ;
448444
@@ -472,34 +468,20 @@ static int full_proxy_open(struct inode *inode, struct file *filp,
472468 goto out ;
473469 }
474470
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-
483471 if (!real_fops || real_fops -> open ) {
484472 if (real_fops )
485473 r = real_fops -> open (inode , filp );
486474 else
487475 r = simple_open (inode , filp );
488476 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 ) {
492479 /* No protection against file removal anymore. */
493480 WARN (1 , "debugfs file owner replaced proxy fops: %pd" ,
494481 dentry );
495- goto free_proxy ;
482+ fops_put ( real_fops ) ;
496483 }
497484 }
498-
499- goto out ;
500- free_proxy :
501- kfree (proxy_fops );
502- fops_put (real_fops );
503485out :
504486 debugfs_file_put (dentry );
505487 return r ;
@@ -512,6 +494,12 @@ static int full_proxy_open_regular(struct inode *inode, struct file *filp)
512494
513495const struct file_operations debugfs_full_proxy_file_operations = {
514496 .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
515503};
516504
517505static 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)
521509
522510const struct file_operations debugfs_full_short_proxy_file_operations = {
523511 .open = full_proxy_open_short ,
512+ .llseek = full_proxy_llseek ,
513+ .read = full_proxy_read ,
514+ .write = full_proxy_write ,
524515};
525516
526517ssize_t debugfs_attr_read (struct file * file , char __user * buf ,
0 commit comments