You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
254 lines
7.2 KiB
254 lines
7.2 KiB
4 months ago
|
/*
|
||
|
* Copyright (c) Hisilicon Technologies Co., Ltd. 2020-2020. All rights reserved.
|
||
|
* Description: driver common hardware adapter layer implement.
|
||
|
* Author: Hisilicon
|
||
|
* Create: 2020-08-18
|
||
|
*/
|
||
|
|
||
|
#include <linux/proc_fs.h>
|
||
|
#include <linux/proc_ns.h>
|
||
|
#include <linux/spinlock.h>
|
||
|
#include <linux/atomic.h>
|
||
|
#include <linux/binfmts.h>
|
||
|
#include <linux/sched/coredump.h>
|
||
|
#include <linux/sched/task.h>
|
||
|
|
||
|
struct ctl_table_header;
|
||
|
struct mempolicy;
|
||
|
|
||
|
/*
|
||
|
* This is not completely implemented yet. The idea is to
|
||
|
* create an in-memory tree (like the actual /proc filesystem
|
||
|
* tree) of these proc_dir_entries, so that we can dynamically
|
||
|
* add new files to /proc.
|
||
|
*
|
||
|
* parent/subdir are used for the directory structure (every /proc file has a
|
||
|
* parent, but "subdir" is empty for all non-directory entries).
|
||
|
* subdir_node is used to build the rb tree "subdir" of the parent.
|
||
|
*/
|
||
|
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 10, 0))
|
||
|
struct proc_dir_entry {
|
||
|
/*
|
||
|
* number of callers into module in progress;
|
||
|
* negative -> it's going away RSN
|
||
|
*/
|
||
|
atomic_t in_use;
|
||
|
refcount_t refcnt;
|
||
|
struct list_head pde_openers; /* who did ->open, but not ->release */
|
||
|
/* protects ->pde_openers and all struct pde_opener instances */
|
||
|
spinlock_t pde_unload_lock;
|
||
|
struct completion *pde_unload_completion;
|
||
|
const struct inode_operations *proc_iops;
|
||
|
union {
|
||
|
const struct proc_ops *proc_ops;
|
||
|
const struct file_operations *proc_dir_ops;
|
||
|
};
|
||
|
const struct dentry_operations *proc_dops;
|
||
|
union {
|
||
|
const struct seq_operations *seq_ops;
|
||
|
int (*single_show)(struct seq_file *, void *);
|
||
|
};
|
||
|
proc_write_t write;
|
||
|
void *data;
|
||
|
unsigned int state_size;
|
||
|
unsigned int low_ino;
|
||
|
nlink_t nlink;
|
||
|
kuid_t uid;
|
||
|
kgid_t gid;
|
||
|
loff_t size;
|
||
|
struct proc_dir_entry *parent;
|
||
|
struct rb_root subdir;
|
||
|
struct rb_node subdir_node;
|
||
|
char *name;
|
||
|
umode_t mode;
|
||
|
u8 flags;
|
||
|
u8 namelen;
|
||
|
char inline_name[];
|
||
|
} __randomize_layout;
|
||
|
|
||
|
union proc_op {
|
||
|
int (*proc_get_link)(struct dentry *, struct path *);
|
||
|
int (*proc_show)(struct seq_file *m,
|
||
|
struct pid_namespace *ns, struct pid *pid,
|
||
|
struct task_struct *task);
|
||
|
const char *lsm;
|
||
|
};
|
||
|
|
||
|
struct proc_inode {
|
||
|
struct pid *pid;
|
||
|
unsigned int fd;
|
||
|
union proc_op op;
|
||
|
struct proc_dir_entry *pde;
|
||
|
struct ctl_table_header *sysctl;
|
||
|
struct ctl_table *sysctl_entry;
|
||
|
struct hlist_node sibling_inodes;
|
||
|
const struct proc_ns_operations *ns_ops;
|
||
|
struct inode vfs_inode;
|
||
|
} __randomize_layout;
|
||
|
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
|
||
|
struct proc_dir_entry {
|
||
|
/*
|
||
|
* number of callers into module in progress;
|
||
|
* negative -> it's going away RSN
|
||
|
*/
|
||
|
atomic_t in_use;
|
||
|
refcount_t refcnt;
|
||
|
struct list_head pde_openers; /* who did ->open, but not ->release */
|
||
|
/* protects ->pde_openers and all struct pde_opener instances */
|
||
|
spinlock_t pde_unload_lock;
|
||
|
struct completion *pde_unload_completion;
|
||
|
const struct inode_operations *proc_iops;
|
||
|
const struct file_operations *proc_fops;
|
||
|
const struct dentry_operations *proc_dops;
|
||
|
union {
|
||
|
const struct seq_operations *seq_ops;
|
||
|
int (*single_show)(struct seq_file *, void *);
|
||
|
};
|
||
|
proc_write_t write;
|
||
|
void *data;
|
||
|
unsigned int state_size;
|
||
|
unsigned int low_ino;
|
||
|
nlink_t nlink;
|
||
|
kuid_t uid;
|
||
|
kgid_t gid;
|
||
|
loff_t size;
|
||
|
struct proc_dir_entry *parent;
|
||
|
struct rb_root subdir;
|
||
|
struct rb_node subdir_node;
|
||
|
char *name;
|
||
|
umode_t mode;
|
||
|
u8 namelen;
|
||
|
char inline_name[];
|
||
|
} __randomize_layout;
|
||
|
|
||
|
union proc_op {
|
||
|
int (*proc_get_link)(struct dentry *, struct path *);
|
||
|
int (*proc_show)(struct seq_file *m,
|
||
|
struct pid_namespace *ns, struct pid *pid,
|
||
|
struct task_struct *task);
|
||
|
const char *lsm;
|
||
|
};
|
||
|
|
||
|
struct proc_inode {
|
||
|
struct pid *pid;
|
||
|
unsigned int fd;
|
||
|
union proc_op op;
|
||
|
struct proc_dir_entry *pde;
|
||
|
struct ctl_table_header *sysctl;
|
||
|
struct ctl_table *sysctl_entry;
|
||
|
struct hlist_node sysctl_inodes;
|
||
|
const struct proc_ns_operations *ns_ops;
|
||
|
struct inode vfs_inode;
|
||
|
} __randomize_layout;
|
||
|
#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 19, 0))
|
||
|
struct proc_dir_entry {
|
||
|
/*
|
||
|
* number of callers into module in progress;
|
||
|
* negative -> it's going away RSN
|
||
|
*/
|
||
|
atomic_t in_use;
|
||
|
refcount_t refcnt;
|
||
|
struct list_head pde_openers; /* who did ->open, but not ->release */
|
||
|
/* protects ->pde_openers and all struct pde_opener instances */
|
||
|
spinlock_t pde_unload_lock;
|
||
|
struct completion *pde_unload_completion;
|
||
|
const struct inode_operations *proc_iops;
|
||
|
const struct file_operations *proc_fops;
|
||
|
const struct dentry_operations *proc_dops;
|
||
|
union {
|
||
|
const struct seq_operations *seq_ops;
|
||
|
int (*single_show)(struct seq_file *, void *);
|
||
|
};
|
||
|
proc_write_t write;
|
||
|
void *data;
|
||
|
unsigned int state_size;
|
||
|
unsigned int low_ino;
|
||
|
nlink_t nlink;
|
||
|
kuid_t uid;
|
||
|
kgid_t gid;
|
||
|
loff_t size;
|
||
|
struct proc_dir_entry *parent;
|
||
|
struct rb_root subdir;
|
||
|
struct rb_node subdir_node;
|
||
|
char *name;
|
||
|
umode_t mode;
|
||
|
u8 namelen;
|
||
|
char inline_name[];
|
||
|
} __randomize_layout;
|
||
|
|
||
|
union proc_op {
|
||
|
int (*proc_get_link)(struct dentry *, struct path *);
|
||
|
int (*proc_show)(struct seq_file *m,
|
||
|
struct pid_namespace *ns, struct pid *pid,
|
||
|
struct task_struct *task);
|
||
|
};
|
||
|
|
||
|
struct proc_inode {
|
||
|
struct pid *pid;
|
||
|
unsigned int fd;
|
||
|
union proc_op op;
|
||
|
struct proc_dir_entry *pde;
|
||
|
struct ctl_table_header *sysctl;
|
||
|
struct ctl_table *sysctl_entry;
|
||
|
struct hlist_node sysctl_inodes;
|
||
|
const struct proc_ns_operations *ns_ops;
|
||
|
struct inode vfs_inode;
|
||
|
} __randomize_layout;
|
||
|
#else
|
||
|
struct proc_dir_entry {
|
||
|
unsigned int low_ino;
|
||
|
umode_t mode;
|
||
|
nlink_t nlink;
|
||
|
kuid_t uid;
|
||
|
kgid_t gid;
|
||
|
loff_t size;
|
||
|
const struct inode_operations *proc_iops;
|
||
|
const struct file_operations *proc_fops;
|
||
|
struct proc_dir_entry *parent;
|
||
|
struct rb_root_cached subdir;
|
||
|
struct rb_node subdir_node;
|
||
|
void *data;
|
||
|
atomic_t count; /* use count */
|
||
|
atomic_t in_use; /* number of callers into module in progress; */
|
||
|
/* negative -> it's going away RSN */
|
||
|
struct completion *pde_unload_completion;
|
||
|
struct list_head pde_openers; /* who did ->open, but not ->release */
|
||
|
spinlock_t pde_unload_lock; /* proc_fops checks and pde_users bumps */
|
||
|
u8 namelen;
|
||
|
char name[];
|
||
|
} __randomize_layout;
|
||
|
|
||
|
union proc_op {
|
||
|
int (*proc_get_link)(struct dentry *, struct path *);
|
||
|
int (*proc_show)(struct seq_file *m,
|
||
|
struct pid_namespace *ns, struct pid *pid,
|
||
|
struct task_struct *task);
|
||
|
};
|
||
|
|
||
|
struct proc_inode {
|
||
|
struct pid *pid;
|
||
|
unsigned int fd;
|
||
|
union proc_op op;
|
||
|
struct proc_dir_entry *pde;
|
||
|
struct ctl_table_header *sysctl;
|
||
|
struct ctl_table *sysctl_entry;
|
||
|
struct hlist_node sysctl_inodes;
|
||
|
const struct proc_ns_operations *ns_ops;
|
||
|
struct inode vfs_inode;
|
||
|
} __randomize_layout;
|
||
|
#endif
|
||
|
|
||
|
/*
|
||
|
* General functions
|
||
|
*/
|
||
|
static inline struct proc_inode *proc_i(const struct inode *inode)
|
||
|
{
|
||
|
return container_of(inode, struct proc_inode, vfs_inode);
|
||
|
}
|
||
|
|
||
|
static inline struct proc_dir_entry *pde(const struct inode *inode)
|
||
|
{
|
||
|
return proc_i(inode)->pde;
|
||
|
}
|
||
|
|