mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
Merge branch 'afs-proc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull AFS updates from Al Viro: "Assorted AFS stuff - ended up in vfs.git since most of that consists of David's AFS-related followups to Christoph's procfs series" * 'afs-proc' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: afs: Optimise callback breaking by not repeating volume lookup afs: Display manually added cells in dynamic root mount afs: Enable IPv6 DNS lookups afs: Show all of a server's addresses in /proc/fs/afs/servers afs: Handle CONFIG_PROC_FS=n proc: Make inline name size calculation automatic afs: Implement network namespacing afs: Mark afs_net::ws_cell as __rcu and set using rcu functions afs: Fix a Sparse warning in xdr_decode_AFSFetchStatus() proc: Add a way to make network proc files writable afs: Rearrange fs/afs/proc.c to remove remaining predeclarations. afs: Rearrange fs/afs/proc.c to move the show routines up afs: Rearrange fs/afs/proc.c by moving fops and open functions down afs: Move /proc management functions to the end of the file
This commit is contained in:
commit
35773c9381
22 changed files with 892 additions and 645 deletions
|
|
@ -409,7 +409,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
|
|||
if (!ent)
|
||||
goto out;
|
||||
|
||||
if (qstr.len + 1 <= sizeof(ent->inline_name)) {
|
||||
if (qstr.len + 1 <= SIZEOF_PDE_INLINE_NAME) {
|
||||
ent->name = ent->inline_name;
|
||||
} else {
|
||||
ent->name = kmalloc(qstr.len + 1, GFP_KERNEL);
|
||||
|
|
@ -740,3 +740,27 @@ void *PDE_DATA(const struct inode *inode)
|
|||
return __PDE_DATA(inode);
|
||||
}
|
||||
EXPORT_SYMBOL(PDE_DATA);
|
||||
|
||||
/*
|
||||
* Pull a user buffer into memory and pass it to the file's write handler if
|
||||
* one is supplied. The ->write() method is permitted to modify the
|
||||
* kernel-side buffer.
|
||||
*/
|
||||
ssize_t proc_simple_write(struct file *f, const char __user *ubuf, size_t size,
|
||||
loff_t *_pos)
|
||||
{
|
||||
struct proc_dir_entry *pde = PDE(file_inode(f));
|
||||
char *buf;
|
||||
int ret;
|
||||
|
||||
if (!pde->write)
|
||||
return -EACCES;
|
||||
if (size == 0 || size > PAGE_SIZE - 1)
|
||||
return -EINVAL;
|
||||
buf = memdup_user_nul(ubuf, size);
|
||||
if (IS_ERR(buf))
|
||||
return PTR_ERR(buf);
|
||||
ret = pde->write(f, buf, size);
|
||||
kfree(buf);
|
||||
return ret == 0 ? size : ret;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,9 +105,8 @@ void __init proc_init_kmemcache(void)
|
|||
kmem_cache_create("pde_opener", sizeof(struct pde_opener), 0,
|
||||
SLAB_ACCOUNT|SLAB_PANIC, NULL);
|
||||
proc_dir_entry_cache = kmem_cache_create_usercopy(
|
||||
"proc_dir_entry", sizeof(struct proc_dir_entry), 0, SLAB_PANIC,
|
||||
offsetof(struct proc_dir_entry, inline_name),
|
||||
sizeof_field(struct proc_dir_entry, inline_name), NULL);
|
||||
"proc_dir_entry", SIZEOF_PDE_SLOT, 0, SLAB_PANIC,
|
||||
OFFSETOF_PDE_NAME, SIZEOF_PDE_INLINE_NAME, NULL);
|
||||
}
|
||||
|
||||
static int proc_show_options(struct seq_file *seq, struct dentry *root)
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@ struct proc_dir_entry {
|
|||
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;
|
||||
|
|
@ -61,14 +62,20 @@ struct proc_dir_entry {
|
|||
char *name;
|
||||
umode_t mode;
|
||||
u8 namelen;
|
||||
#ifdef CONFIG_64BIT
|
||||
#define SIZEOF_PDE_INLINE_NAME (192-155)
|
||||
#else
|
||||
#define SIZEOF_PDE_INLINE_NAME (128-95)
|
||||
#endif
|
||||
char inline_name[SIZEOF_PDE_INLINE_NAME];
|
||||
char inline_name[];
|
||||
} __randomize_layout;
|
||||
|
||||
#define OFFSETOF_PDE_NAME offsetof(struct proc_dir_entry, inline_name)
|
||||
#define SIZEOF_PDE_SLOT \
|
||||
(OFFSETOF_PDE_NAME + 34 <= 64 ? 64 : \
|
||||
OFFSETOF_PDE_NAME + 34 <= 128 ? 128 : \
|
||||
OFFSETOF_PDE_NAME + 34 <= 192 ? 192 : \
|
||||
OFFSETOF_PDE_NAME + 34 <= 256 ? 256 : \
|
||||
OFFSETOF_PDE_NAME + 34 <= 512 ? 512 : \
|
||||
0)
|
||||
|
||||
#define SIZEOF_PDE_INLINE_NAME (SIZEOF_PDE_SLOT - OFFSETOF_PDE_NAME)
|
||||
|
||||
extern struct kmem_cache *proc_dir_entry_cache;
|
||||
void pde_free(struct proc_dir_entry *pde);
|
||||
|
||||
|
|
@ -189,6 +196,7 @@ static inline bool is_empty_pde(const struct proc_dir_entry *pde)
|
|||
{
|
||||
return S_ISDIR(pde->mode) && !pde->proc_iops;
|
||||
}
|
||||
extern ssize_t proc_simple_write(struct file *, const char __user *, size_t, loff_t *);
|
||||
|
||||
/*
|
||||
* inode.c
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ static int seq_open_net(struct inode *inode, struct file *file)
|
|||
|
||||
WARN_ON_ONCE(state_size < sizeof(*p));
|
||||
|
||||
if (file->f_mode & FMODE_WRITE && !PDE(inode)->write)
|
||||
return -EACCES;
|
||||
|
||||
net = get_proc_net(inode);
|
||||
if (!net)
|
||||
return -ENXIO;
|
||||
|
|
@ -73,6 +76,7 @@ static int seq_release_net(struct inode *ino, struct file *f)
|
|||
static const struct file_operations proc_net_seq_fops = {
|
||||
.open = seq_open_net,
|
||||
.read = seq_read,
|
||||
.write = proc_simple_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release_net,
|
||||
};
|
||||
|
|
@ -93,6 +97,50 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(proc_create_net_data);
|
||||
|
||||
/**
|
||||
* proc_create_net_data_write - Create a writable net_ns-specific proc file
|
||||
* @name: The name of the file.
|
||||
* @mode: The file's access mode.
|
||||
* @parent: The parent directory in which to create.
|
||||
* @ops: The seq_file ops with which to read the file.
|
||||
* @write: The write method which which to 'modify' the file.
|
||||
* @data: Data for retrieval by PDE_DATA().
|
||||
*
|
||||
* Create a network namespaced proc file in the @parent directory with the
|
||||
* specified @name and @mode that allows reading of a file that displays a
|
||||
* series of elements and also provides for the file accepting writes that have
|
||||
* some arbitrary effect.
|
||||
*
|
||||
* The functions in the @ops table are used to iterate over items to be
|
||||
* presented and extract the readable content using the seq_file interface.
|
||||
*
|
||||
* The @write function is called with the data copied into a kernel space
|
||||
* scratch buffer and has a NUL appended for convenience. The buffer may be
|
||||
* modified by the @write function. @write should return 0 on success.
|
||||
*
|
||||
* The @data value is accessible from the @show and @write functions by calling
|
||||
* PDE_DATA() on the file inode. The network namespace must be accessed by
|
||||
* calling seq_file_net() on the seq_file struct.
|
||||
*/
|
||||
struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode,
|
||||
struct proc_dir_entry *parent,
|
||||
const struct seq_operations *ops,
|
||||
proc_write_t write,
|
||||
unsigned int state_size, void *data)
|
||||
{
|
||||
struct proc_dir_entry *p;
|
||||
|
||||
p = proc_create_reg(name, mode, &parent, data);
|
||||
if (!p)
|
||||
return NULL;
|
||||
p->proc_fops = &proc_net_seq_fops;
|
||||
p->seq_ops = ops;
|
||||
p->state_size = state_size;
|
||||
p->write = write;
|
||||
return proc_register(parent, p);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(proc_create_net_data_write);
|
||||
|
||||
static int single_open_net(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct proc_dir_entry *de = PDE(inode);
|
||||
|
|
@ -119,6 +167,7 @@ static int single_release_net(struct inode *ino, struct file *f)
|
|||
static const struct file_operations proc_net_single_fops = {
|
||||
.open = single_open_net,
|
||||
.read = seq_read,
|
||||
.write = proc_simple_write,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release_net,
|
||||
};
|
||||
|
|
@ -138,6 +187,49 @@ struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(proc_create_net_single);
|
||||
|
||||
/**
|
||||
* proc_create_net_single_write - Create a writable net_ns-specific proc file
|
||||
* @name: The name of the file.
|
||||
* @mode: The file's access mode.
|
||||
* @parent: The parent directory in which to create.
|
||||
* @show: The seqfile show method with which to read the file.
|
||||
* @write: The write method which which to 'modify' the file.
|
||||
* @data: Data for retrieval by PDE_DATA().
|
||||
*
|
||||
* Create a network-namespaced proc file in the @parent directory with the
|
||||
* specified @name and @mode that allows reading of a file that displays a
|
||||
* single element rather than a series and also provides for the file accepting
|
||||
* writes that have some arbitrary effect.
|
||||
*
|
||||
* The @show function is called to extract the readable content via the
|
||||
* seq_file interface.
|
||||
*
|
||||
* The @write function is called with the data copied into a kernel space
|
||||
* scratch buffer and has a NUL appended for convenience. The buffer may be
|
||||
* modified by the @write function. @write should return 0 on success.
|
||||
*
|
||||
* The @data value is accessible from the @show and @write functions by calling
|
||||
* PDE_DATA() on the file inode. The network namespace must be accessed by
|
||||
* calling seq_file_single_net() on the seq_file struct.
|
||||
*/
|
||||
struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mode,
|
||||
struct proc_dir_entry *parent,
|
||||
int (*show)(struct seq_file *, void *),
|
||||
proc_write_t write,
|
||||
void *data)
|
||||
{
|
||||
struct proc_dir_entry *p;
|
||||
|
||||
p = proc_create_reg(name, mode, &parent, data);
|
||||
if (!p)
|
||||
return NULL;
|
||||
p->proc_fops = &proc_net_single_fops;
|
||||
p->single_show = show;
|
||||
p->write = write;
|
||||
return proc_register(parent, p);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(proc_create_net_single_write);
|
||||
|
||||
static struct net *get_proc_task_net(struct inode *dir)
|
||||
{
|
||||
struct task_struct *task;
|
||||
|
|
|
|||
|
|
@ -204,8 +204,7 @@ struct proc_dir_entry proc_root = {
|
|||
.proc_fops = &proc_root_operations,
|
||||
.parent = &proc_root,
|
||||
.subdir = RB_ROOT,
|
||||
.name = proc_root.inline_name,
|
||||
.inline_name = "/proc",
|
||||
.name = "/proc",
|
||||
};
|
||||
|
||||
int pid_ns_prepare_proc(struct pid_namespace *ns)
|
||||
|
|
|
|||
Loading…
Reference in a new issue