Geert reported that my previous short fops debugfs changes
broke m68k, because it only has mandatory alignement of two,
so we can't stash the "is it short" information into the
pointer (as we already did with the "is it real" bit.)
Instead, exploit the fact that debugfs_file_get() called on
an already open file will already find that the fsdata is
no longer the real fops but rather the allocated data that
already distinguishes full/short ops, so only open() needs
to be able to distinguish. We can achieve that by using two
different open functions.
Unfortunately this requires another set of full file ops,
increasing the size by 536 bytes (x86-64), but that's still
a reasonable trade-off given that only converting some of
the wireless stack gained over 28k. This brings the total
cost of this to around 1k, for wins of 28k (all x86-64).
Reported-and-tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
Link: https://lore.kernel.org/CAMuHMdWu_9-L2Te101w8hU7H_2yobJFPXSwwUmGHSJfaPWDKiQ@mail.gmail.com
Fixes: 8dc6d81c6b
("debugfs: add small file operations for most files")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
Link: https://lore.kernel.org/r/20241129121536.30989-2-johannes@sipsolutions.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
59 lines
1.6 KiB
C
59 lines
1.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* internal.h - declarations internal to debugfs
|
|
*
|
|
* Copyright (C) 2016 Nicolai Stange <nicstange@gmail.com>
|
|
*/
|
|
|
|
#ifndef _DEBUGFS_INTERNAL_H_
|
|
#define _DEBUGFS_INTERNAL_H_
|
|
#include <linux/list.h>
|
|
|
|
struct file_operations;
|
|
|
|
/* declared over in file.c */
|
|
extern const struct file_operations debugfs_noop_file_operations;
|
|
extern const struct file_operations debugfs_open_proxy_file_operations;
|
|
extern const struct file_operations debugfs_full_proxy_file_operations;
|
|
extern const struct file_operations debugfs_full_short_proxy_file_operations;
|
|
|
|
struct debugfs_fsdata {
|
|
const struct file_operations *real_fops;
|
|
const struct debugfs_short_fops *short_fops;
|
|
union {
|
|
/* automount_fn is used when real_fops is NULL */
|
|
debugfs_automount_t automount;
|
|
struct {
|
|
refcount_t active_users;
|
|
struct completion active_users_drained;
|
|
|
|
/* protect cancellations */
|
|
struct mutex cancellations_mtx;
|
|
struct list_head cancellations;
|
|
};
|
|
};
|
|
};
|
|
|
|
/*
|
|
* 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)
|
|
|
|
/* Access BITS */
|
|
#define DEBUGFS_ALLOW_API BIT(0)
|
|
#define DEBUGFS_ALLOW_MOUNT BIT(1)
|
|
|
|
#ifdef CONFIG_DEBUG_FS_ALLOW_ALL
|
|
#define DEFAULT_DEBUGFS_ALLOW_BITS (DEBUGFS_ALLOW_MOUNT | DEBUGFS_ALLOW_API)
|
|
#endif
|
|
#ifdef CONFIG_DEBUG_FS_DISALLOW_MOUNT
|
|
#define DEFAULT_DEBUGFS_ALLOW_BITS (DEBUGFS_ALLOW_API)
|
|
#endif
|
|
#ifdef CONFIG_DEBUG_FS_ALLOW_NONE
|
|
#define DEFAULT_DEBUGFS_ALLOW_BITS (0)
|
|
#endif
|
|
|
|
#endif /* _DEBUGFS_INTERNAL_H_ */
|