Loading fs/debugfs/file.c +50 −60 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ #include <linux/slab.h> #include <linux/atomic.h> #include <linux/device.h> #include <linux/srcu.h> #include <asm/poll.h> #include "internal.h" Loading @@ -48,59 +47,21 @@ const struct file_operations debugfs_noop_file_operations = { .llseek = noop_llseek, }; /** * debugfs_use_file_start - mark the beginning of file data access * @dentry: the dentry object whose data is being accessed. * @srcu_idx: a pointer to some memory to store a SRCU index in. * * Up to a matching call to debugfs_use_file_finish(), any * successive call into the file removing functions debugfs_remove() * and debugfs_remove_recursive() will block. Since associated private * file data may only get freed after a successful return of any of * the removal functions, you may safely access it after a successful * call to debugfs_use_file_start() without worrying about * lifetime issues. * * If -%EIO is returned, the file has already been removed and thus, * it is not safe to access any of its data. If, on the other hand, * it is allowed to access the file data, zero is returned. * * Regardless of the return code, any call to * debugfs_use_file_start() must be followed by a matching call * to debugfs_use_file_finish(). */ int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) __acquires(&debugfs_srcu) { *srcu_idx = srcu_read_lock(&debugfs_srcu); barrier(); if (d_unlinked(dentry)) return -EIO; return 0; } EXPORT_SYMBOL_GPL(debugfs_use_file_start); /** * debugfs_use_file_finish - mark the end of file data access * @srcu_idx: the SRCU index "created" by a former call to * debugfs_use_file_start(). * * Allow any ongoing concurrent call into debugfs_remove() or * debugfs_remove_recursive() blocked by a former call to * debugfs_use_file_start() to proceed and return to its caller. */ void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) { srcu_read_unlock(&debugfs_srcu, srcu_idx); } EXPORT_SYMBOL_GPL(debugfs_use_file_finish); #define F_DENTRY(filp) ((filp)->f_path.dentry) const struct file_operations *debugfs_real_fops(const struct file *filp) { struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata; if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) { /* * Urgh, we've been called w/o a protecting * debugfs_file_get(). */ WARN_ON(1); return NULL; } return fsd->real_fops; } EXPORT_SYMBOL_GPL(debugfs_real_fops); Loading @@ -122,9 +83,35 @@ EXPORT_SYMBOL_GPL(debugfs_real_fops); */ int debugfs_file_get(struct dentry *dentry) { struct debugfs_fsdata *fsd = dentry->d_fsdata; struct debugfs_fsdata *fsd; void *d_fsd; d_fsd = READ_ONCE(dentry->d_fsdata); if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) { fsd = d_fsd; } else { fsd = kmalloc(sizeof(*fsd), GFP_KERNEL); if (!fsd) return -ENOMEM; fsd->real_fops = (void *)((unsigned long)d_fsd & ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); refcount_set(&fsd->active_users, 1); init_completion(&fsd->active_users_drained); if (cmpxchg(&dentry->d_fsdata, d_fsd, fsd) != d_fsd) { kfree(fsd); fsd = READ_ONCE(dentry->d_fsdata); } } /* Avoid starvation of removers. */ /* * In case of a successful cmpxchg() above, this check is * strictly necessary and must follow it, see the comment in * __debugfs_remove_file(). * OTOH, if the cmpxchg() hasn't been executed or wasn't * successful, this serves the purpose of not starving * removers. */ if (d_unlinked(dentry)) return -EIO; Loading @@ -146,7 +133,7 @@ EXPORT_SYMBOL_GPL(debugfs_file_get); */ void debugfs_file_put(struct dentry *dentry) { struct debugfs_fsdata *fsd = dentry->d_fsdata; struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata); if (refcount_dec_and_test(&fsd->active_users)) complete(&fsd->active_users_drained); Loading @@ -157,10 +144,11 @@ static int open_proxy_open(struct inode *inode, struct file *filp) { struct dentry *dentry = F_DENTRY(filp); const struct file_operations *real_fops = NULL; int r = 0; int r; if (debugfs_file_get(dentry)) return -ENOENT; r = debugfs_file_get(dentry); if (r) return r == -EIO ? -ENOENT : r; real_fops = debugfs_real_fops(filp); real_fops = fops_get(real_fops); Loading Loading @@ -192,13 +180,13 @@ const struct file_operations debugfs_open_proxy_file_operations = { static ret_type full_proxy_ ## name(proto) \ { \ struct dentry *dentry = F_DENTRY(filp); \ const struct file_operations *real_fops = \ debugfs_real_fops(filp); \ const struct file_operations *real_fops; \ ret_type r; \ \ r = debugfs_file_get(dentry); \ if (unlikely(r)) \ return r; \ real_fops = debugfs_real_fops(filp); \ r = real_fops->name(args); \ debugfs_file_put(dentry); \ return r; \ Loading @@ -225,13 +213,14 @@ FULL_PROXY_FUNC(unlocked_ioctl, long, filp, static unsigned int full_proxy_poll(struct file *filp, struct poll_table_struct *wait) { const struct file_operations *real_fops = debugfs_real_fops(filp); struct dentry *dentry = F_DENTRY(filp); unsigned int r = 0; const struct file_operations *real_fops; if (debugfs_file_get(dentry)) return POLLHUP; real_fops = debugfs_real_fops(filp); r = real_fops->poll(filp, wait); debugfs_file_put(dentry); return r; Loading Loading @@ -280,10 +269,11 @@ static int full_proxy_open(struct inode *inode, struct file *filp) struct dentry *dentry = F_DENTRY(filp); const struct file_operations *real_fops = NULL; struct file_operations *proxy_fops = NULL; int r = 0; int r; if (debugfs_file_get(dentry)) return -ENOENT; r = debugfs_file_get(dentry); if (r) return r == -EIO ? -ENOENT : r; real_fops = debugfs_real_fops(filp); real_fops = fops_get(real_fops); Loading fs/debugfs/inode.c +19 −24 Original line number Diff line number Diff line Loading @@ -27,14 +27,11 @@ #include <linux/parser.h> #include <linux/magic.h> #include <linux/slab.h> #include <linux/srcu.h> #include "internal.h" #define DEBUGFS_DEFAULT_MODE 0700 DEFINE_SRCU(debugfs_srcu); static struct vfsmount *debugfs_mount; static int debugfs_mount_count; static bool debugfs_registered; Loading Loading @@ -187,6 +184,9 @@ static const struct super_operations debugfs_super_operations = { static void debugfs_release_dentry(struct dentry *dentry) { void *fsd = dentry->d_fsdata; if (!((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) kfree(dentry->d_fsdata); } Loading Loading @@ -347,35 +347,25 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode, { struct dentry *dentry; struct inode *inode; struct debugfs_fsdata *fsd; fsd = kmalloc(sizeof(*fsd), GFP_KERNEL); if (!fsd) return NULL; if (!(mode & S_IFMT)) mode |= S_IFREG; BUG_ON(!S_ISREG(mode)); dentry = start_creating(name, parent); if (IS_ERR(dentry)) { kfree(fsd); if (IS_ERR(dentry)) return NULL; } inode = debugfs_get_inode(dentry->d_sb); if (unlikely(!inode)) { kfree(fsd); if (unlikely(!inode)) return failed_creating(dentry); } inode->i_mode = mode; inode->i_private = data; inode->i_fop = proxy_fops; fsd->real_fops = real_fops; refcount_set(&fsd->active_users, 1); dentry->d_fsdata = fsd; dentry->d_fsdata = (void *)((unsigned long)real_fops | DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); d_instantiate(dentry, inode); fsnotify_create(d_inode(dentry->d_parent), dentry); Loading Loading @@ -638,8 +628,17 @@ static void __debugfs_remove_file(struct dentry *dentry, struct dentry *parent) simple_unlink(d_inode(parent), dentry); d_delete(dentry); fsd = dentry->d_fsdata; init_completion(&fsd->active_users_drained); /* * Paired with the closing smp_mb() implied by a successful * cmpxchg() in debugfs_file_get(): either * debugfs_file_get() must see a dead dentry or we must see a * debugfs_fsdata instance at ->d_fsdata here (or both). */ smp_mb(); fsd = READ_ONCE(dentry->d_fsdata); if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) return; if (!refcount_dec_and_test(&fsd->active_users)) wait_for_completion(&fsd->active_users_drained); } Loading Loading @@ -693,8 +692,6 @@ void debugfs_remove(struct dentry *dentry) inode_unlock(d_inode(parent)); if (!ret) simple_release_fs(&debugfs_mount, &debugfs_mount_count); synchronize_srcu(&debugfs_srcu); } EXPORT_SYMBOL_GPL(debugfs_remove); Loading Loading @@ -768,8 +765,6 @@ void debugfs_remove_recursive(struct dentry *dentry) if (!__debugfs_remove(child, parent)) simple_release_fs(&debugfs_mount, &debugfs_mount_count); inode_unlock(d_inode(parent)); synchronize_srcu(&debugfs_srcu); } EXPORT_SYMBOL_GPL(debugfs_remove_recursive); Loading fs/debugfs/internal.h +8 −0 Original line number Diff line number Diff line Loading @@ -25,4 +25,12 @@ struct debugfs_fsdata { struct completion active_users_drained; }; /* * A dentry's ->d_fsdata either points to the real fops or to a * dynamically allocated debugfs_fsdata instance. * In order to distinguish between these two cases, a real fops * pointer gets its lowest bit set. */ #define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0) #endif /* _DEBUGFS_INTERNAL_H_ */ include/linux/debugfs.h +0 −19 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ struct device; struct file_operations; struct srcu_struct; struct debugfs_blob_wrapper { void *data; Loading @@ -43,8 +42,6 @@ struct debugfs_regset32 { extern struct dentry *arch_debugfs_dir; extern struct srcu_struct debugfs_srcu; #define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ static int __fops ## _open(struct inode *inode, struct file *file) \ { \ Loading Loading @@ -90,11 +87,6 @@ struct dentry *debugfs_create_automount(const char *name, void debugfs_remove(struct dentry *dentry); void debugfs_remove_recursive(struct dentry *dentry); int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) __acquires(&debugfs_srcu); void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu); const struct file_operations *debugfs_real_fops(const struct file *filp); int debugfs_file_get(struct dentry *dentry); Loading Loading @@ -227,17 +219,6 @@ static inline void debugfs_remove(struct dentry *dentry) static inline void debugfs_remove_recursive(struct dentry *dentry) { } static inline int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) __acquires(&debugfs_srcu) { return 0; } static inline void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) { } static inline int debugfs_file_get(struct dentry *dentry) { return 0; Loading kernel/trace/ipc_logging_debug.c +10 −8 Original line number Diff line number Diff line /* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -78,17 +78,18 @@ static ssize_t debug_read_helper(struct file *file, char __user *buff, struct dentry *d = file->f_path.dentry; char *buffer; int bsize; int srcu_idx; int r; r = debugfs_use_file_start(d, &srcu_idx); if (!r) { r = debugfs_file_get(d); if (r) return r; ilctxt = file->private_data; r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO; } debugfs_use_file_finish(srcu_idx); if (r) if (r) { debugfs_file_put(d); return r; } buffer = kmalloc(count, GFP_KERNEL); if (!buffer) { Loading @@ -110,6 +111,7 @@ static ssize_t debug_read_helper(struct file *file, char __user *buff, done: ipc_log_context_put(ilctxt); debugfs_file_put(d); return bsize; } Loading Loading
fs/debugfs/file.c +50 −60 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ #include <linux/slab.h> #include <linux/atomic.h> #include <linux/device.h> #include <linux/srcu.h> #include <asm/poll.h> #include "internal.h" Loading @@ -48,59 +47,21 @@ const struct file_operations debugfs_noop_file_operations = { .llseek = noop_llseek, }; /** * debugfs_use_file_start - mark the beginning of file data access * @dentry: the dentry object whose data is being accessed. * @srcu_idx: a pointer to some memory to store a SRCU index in. * * Up to a matching call to debugfs_use_file_finish(), any * successive call into the file removing functions debugfs_remove() * and debugfs_remove_recursive() will block. Since associated private * file data may only get freed after a successful return of any of * the removal functions, you may safely access it after a successful * call to debugfs_use_file_start() without worrying about * lifetime issues. * * If -%EIO is returned, the file has already been removed and thus, * it is not safe to access any of its data. If, on the other hand, * it is allowed to access the file data, zero is returned. * * Regardless of the return code, any call to * debugfs_use_file_start() must be followed by a matching call * to debugfs_use_file_finish(). */ int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) __acquires(&debugfs_srcu) { *srcu_idx = srcu_read_lock(&debugfs_srcu); barrier(); if (d_unlinked(dentry)) return -EIO; return 0; } EXPORT_SYMBOL_GPL(debugfs_use_file_start); /** * debugfs_use_file_finish - mark the end of file data access * @srcu_idx: the SRCU index "created" by a former call to * debugfs_use_file_start(). * * Allow any ongoing concurrent call into debugfs_remove() or * debugfs_remove_recursive() blocked by a former call to * debugfs_use_file_start() to proceed and return to its caller. */ void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) { srcu_read_unlock(&debugfs_srcu, srcu_idx); } EXPORT_SYMBOL_GPL(debugfs_use_file_finish); #define F_DENTRY(filp) ((filp)->f_path.dentry) const struct file_operations *debugfs_real_fops(const struct file *filp) { struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata; if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) { /* * Urgh, we've been called w/o a protecting * debugfs_file_get(). */ WARN_ON(1); return NULL; } return fsd->real_fops; } EXPORT_SYMBOL_GPL(debugfs_real_fops); Loading @@ -122,9 +83,35 @@ EXPORT_SYMBOL_GPL(debugfs_real_fops); */ int debugfs_file_get(struct dentry *dentry) { struct debugfs_fsdata *fsd = dentry->d_fsdata; struct debugfs_fsdata *fsd; void *d_fsd; d_fsd = READ_ONCE(dentry->d_fsdata); if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) { fsd = d_fsd; } else { fsd = kmalloc(sizeof(*fsd), GFP_KERNEL); if (!fsd) return -ENOMEM; fsd->real_fops = (void *)((unsigned long)d_fsd & ~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); refcount_set(&fsd->active_users, 1); init_completion(&fsd->active_users_drained); if (cmpxchg(&dentry->d_fsdata, d_fsd, fsd) != d_fsd) { kfree(fsd); fsd = READ_ONCE(dentry->d_fsdata); } } /* Avoid starvation of removers. */ /* * In case of a successful cmpxchg() above, this check is * strictly necessary and must follow it, see the comment in * __debugfs_remove_file(). * OTOH, if the cmpxchg() hasn't been executed or wasn't * successful, this serves the purpose of not starving * removers. */ if (d_unlinked(dentry)) return -EIO; Loading @@ -146,7 +133,7 @@ EXPORT_SYMBOL_GPL(debugfs_file_get); */ void debugfs_file_put(struct dentry *dentry) { struct debugfs_fsdata *fsd = dentry->d_fsdata; struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata); if (refcount_dec_and_test(&fsd->active_users)) complete(&fsd->active_users_drained); Loading @@ -157,10 +144,11 @@ static int open_proxy_open(struct inode *inode, struct file *filp) { struct dentry *dentry = F_DENTRY(filp); const struct file_operations *real_fops = NULL; int r = 0; int r; if (debugfs_file_get(dentry)) return -ENOENT; r = debugfs_file_get(dentry); if (r) return r == -EIO ? -ENOENT : r; real_fops = debugfs_real_fops(filp); real_fops = fops_get(real_fops); Loading Loading @@ -192,13 +180,13 @@ const struct file_operations debugfs_open_proxy_file_operations = { static ret_type full_proxy_ ## name(proto) \ { \ struct dentry *dentry = F_DENTRY(filp); \ const struct file_operations *real_fops = \ debugfs_real_fops(filp); \ const struct file_operations *real_fops; \ ret_type r; \ \ r = debugfs_file_get(dentry); \ if (unlikely(r)) \ return r; \ real_fops = debugfs_real_fops(filp); \ r = real_fops->name(args); \ debugfs_file_put(dentry); \ return r; \ Loading @@ -225,13 +213,14 @@ FULL_PROXY_FUNC(unlocked_ioctl, long, filp, static unsigned int full_proxy_poll(struct file *filp, struct poll_table_struct *wait) { const struct file_operations *real_fops = debugfs_real_fops(filp); struct dentry *dentry = F_DENTRY(filp); unsigned int r = 0; const struct file_operations *real_fops; if (debugfs_file_get(dentry)) return POLLHUP; real_fops = debugfs_real_fops(filp); r = real_fops->poll(filp, wait); debugfs_file_put(dentry); return r; Loading Loading @@ -280,10 +269,11 @@ static int full_proxy_open(struct inode *inode, struct file *filp) struct dentry *dentry = F_DENTRY(filp); const struct file_operations *real_fops = NULL; struct file_operations *proxy_fops = NULL; int r = 0; int r; if (debugfs_file_get(dentry)) return -ENOENT; r = debugfs_file_get(dentry); if (r) return r == -EIO ? -ENOENT : r; real_fops = debugfs_real_fops(filp); real_fops = fops_get(real_fops); Loading
fs/debugfs/inode.c +19 −24 Original line number Diff line number Diff line Loading @@ -27,14 +27,11 @@ #include <linux/parser.h> #include <linux/magic.h> #include <linux/slab.h> #include <linux/srcu.h> #include "internal.h" #define DEBUGFS_DEFAULT_MODE 0700 DEFINE_SRCU(debugfs_srcu); static struct vfsmount *debugfs_mount; static int debugfs_mount_count; static bool debugfs_registered; Loading Loading @@ -187,6 +184,9 @@ static const struct super_operations debugfs_super_operations = { static void debugfs_release_dentry(struct dentry *dentry) { void *fsd = dentry->d_fsdata; if (!((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) kfree(dentry->d_fsdata); } Loading Loading @@ -347,35 +347,25 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode, { struct dentry *dentry; struct inode *inode; struct debugfs_fsdata *fsd; fsd = kmalloc(sizeof(*fsd), GFP_KERNEL); if (!fsd) return NULL; if (!(mode & S_IFMT)) mode |= S_IFREG; BUG_ON(!S_ISREG(mode)); dentry = start_creating(name, parent); if (IS_ERR(dentry)) { kfree(fsd); if (IS_ERR(dentry)) return NULL; } inode = debugfs_get_inode(dentry->d_sb); if (unlikely(!inode)) { kfree(fsd); if (unlikely(!inode)) return failed_creating(dentry); } inode->i_mode = mode; inode->i_private = data; inode->i_fop = proxy_fops; fsd->real_fops = real_fops; refcount_set(&fsd->active_users, 1); dentry->d_fsdata = fsd; dentry->d_fsdata = (void *)((unsigned long)real_fops | DEBUGFS_FSDATA_IS_REAL_FOPS_BIT); d_instantiate(dentry, inode); fsnotify_create(d_inode(dentry->d_parent), dentry); Loading Loading @@ -638,8 +628,17 @@ static void __debugfs_remove_file(struct dentry *dentry, struct dentry *parent) simple_unlink(d_inode(parent), dentry); d_delete(dentry); fsd = dentry->d_fsdata; init_completion(&fsd->active_users_drained); /* * Paired with the closing smp_mb() implied by a successful * cmpxchg() in debugfs_file_get(): either * debugfs_file_get() must see a dead dentry or we must see a * debugfs_fsdata instance at ->d_fsdata here (or both). */ smp_mb(); fsd = READ_ONCE(dentry->d_fsdata); if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) return; if (!refcount_dec_and_test(&fsd->active_users)) wait_for_completion(&fsd->active_users_drained); } Loading Loading @@ -693,8 +692,6 @@ void debugfs_remove(struct dentry *dentry) inode_unlock(d_inode(parent)); if (!ret) simple_release_fs(&debugfs_mount, &debugfs_mount_count); synchronize_srcu(&debugfs_srcu); } EXPORT_SYMBOL_GPL(debugfs_remove); Loading Loading @@ -768,8 +765,6 @@ void debugfs_remove_recursive(struct dentry *dentry) if (!__debugfs_remove(child, parent)) simple_release_fs(&debugfs_mount, &debugfs_mount_count); inode_unlock(d_inode(parent)); synchronize_srcu(&debugfs_srcu); } EXPORT_SYMBOL_GPL(debugfs_remove_recursive); Loading
fs/debugfs/internal.h +8 −0 Original line number Diff line number Diff line Loading @@ -25,4 +25,12 @@ struct debugfs_fsdata { struct completion active_users_drained; }; /* * A dentry's ->d_fsdata either points to the real fops or to a * dynamically allocated debugfs_fsdata instance. * In order to distinguish between these two cases, a real fops * pointer gets its lowest bit set. */ #define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0) #endif /* _DEBUGFS_INTERNAL_H_ */
include/linux/debugfs.h +0 −19 Original line number Diff line number Diff line Loading @@ -23,7 +23,6 @@ struct device; struct file_operations; struct srcu_struct; struct debugfs_blob_wrapper { void *data; Loading @@ -43,8 +42,6 @@ struct debugfs_regset32 { extern struct dentry *arch_debugfs_dir; extern struct srcu_struct debugfs_srcu; #define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt) \ static int __fops ## _open(struct inode *inode, struct file *file) \ { \ Loading Loading @@ -90,11 +87,6 @@ struct dentry *debugfs_create_automount(const char *name, void debugfs_remove(struct dentry *dentry); void debugfs_remove_recursive(struct dentry *dentry); int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) __acquires(&debugfs_srcu); void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu); const struct file_operations *debugfs_real_fops(const struct file *filp); int debugfs_file_get(struct dentry *dentry); Loading Loading @@ -227,17 +219,6 @@ static inline void debugfs_remove(struct dentry *dentry) static inline void debugfs_remove_recursive(struct dentry *dentry) { } static inline int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx) __acquires(&debugfs_srcu) { return 0; } static inline void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu) { } static inline int debugfs_file_get(struct dentry *dentry) { return 0; Loading
kernel/trace/ipc_logging_debug.c +10 −8 Original line number Diff line number Diff line /* Copyright (c) 2012-2015, 2017, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -78,17 +78,18 @@ static ssize_t debug_read_helper(struct file *file, char __user *buff, struct dentry *d = file->f_path.dentry; char *buffer; int bsize; int srcu_idx; int r; r = debugfs_use_file_start(d, &srcu_idx); if (!r) { r = debugfs_file_get(d); if (r) return r; ilctxt = file->private_data; r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO; } debugfs_use_file_finish(srcu_idx); if (r) if (r) { debugfs_file_put(d); return r; } buffer = kmalloc(count, GFP_KERNEL); if (!buffer) { Loading @@ -110,6 +111,7 @@ static ssize_t debug_read_helper(struct file *file, char __user *buff, done: ipc_log_context_put(ilctxt); debugfs_file_put(d); return bsize; } Loading