Skip to content

Commit d56c0d4

Browse files
Alexey Dobriyantorvalds
authored andcommitted
proc: decouple proc from VFS with "struct proc_ops"
Currently core /proc code uses "struct file_operations" for custom hooks, however, VFS doesn't directly call them. Every time VFS expands file_operations hook set, /proc code bloats for no reason. Introduce "struct proc_ops" which contains only those hooks which /proc allows to call into (open, release, read, write, ioctl, mmap, poll). It doesn't contain module pointer as well. Save ~184 bytes per usage: add/remove: 26/26 grow/shrink: 1/4 up/down: 1922/-6674 (-4752) Function old new delta sysvipc_proc_ops - 72 +72 ... config_gz_proc_ops - 72 +72 proc_get_inode 289 339 +50 proc_reg_get_unmapped_area 110 107 -3 close_pdeo 227 224 -3 proc_reg_open 289 284 -5 proc_create_data 60 53 -7 rt_cpu_seq_fops 256 - -256 ... default_affinity_proc_fops 256 - -256 Total: Before=5430095, After=5425343, chg -0.09% Link: http://lkml.kernel.org/r/20191225172228.GA13378@avx2 Signed-off-by: Alexey Dobriyan <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 0d6e24d commit d56c0d4

File tree

7 files changed

+98
-80
lines changed

7 files changed

+98
-80
lines changed

fs/proc/generic.c

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ struct proc_dir_entry *proc_mkdir_data(const char *name, umode_t mode,
473473
ent = __proc_create(&parent, name, S_IFDIR | mode, 2);
474474
if (ent) {
475475
ent->data = data;
476-
ent->proc_fops = &proc_dir_operations;
476+
ent->proc_dir_ops = &proc_dir_operations;
477477
ent->proc_iops = &proc_dir_inode_operations;
478478
ent = proc_register(parent, ent);
479479
}
@@ -503,7 +503,7 @@ struct proc_dir_entry *proc_create_mount_point(const char *name)
503503
ent = __proc_create(&parent, name, mode, 2);
504504
if (ent) {
505505
ent->data = NULL;
506-
ent->proc_fops = NULL;
506+
ent->proc_dir_ops = NULL;
507507
ent->proc_iops = NULL;
508508
ent = proc_register(parent, ent);
509509
}
@@ -533,25 +533,23 @@ struct proc_dir_entry *proc_create_reg(const char *name, umode_t mode,
533533

534534
struct proc_dir_entry *proc_create_data(const char *name, umode_t mode,
535535
struct proc_dir_entry *parent,
536-
const struct file_operations *proc_fops, void *data)
536+
const struct proc_ops *proc_ops, void *data)
537537
{
538538
struct proc_dir_entry *p;
539539

540-
BUG_ON(proc_fops == NULL);
541-
542540
p = proc_create_reg(name, mode, &parent, data);
543541
if (!p)
544542
return NULL;
545-
p->proc_fops = proc_fops;
543+
p->proc_ops = proc_ops;
546544
return proc_register(parent, p);
547545
}
548546
EXPORT_SYMBOL(proc_create_data);
549547

550548
struct proc_dir_entry *proc_create(const char *name, umode_t mode,
551549
struct proc_dir_entry *parent,
552-
const struct file_operations *proc_fops)
550+
const struct proc_ops *proc_ops)
553551
{
554-
return proc_create_data(name, mode, parent, proc_fops, NULL);
552+
return proc_create_data(name, mode, parent, proc_ops, NULL);
555553
}
556554
EXPORT_SYMBOL(proc_create);
557555

@@ -573,11 +571,11 @@ static int proc_seq_release(struct inode *inode, struct file *file)
573571
return seq_release(inode, file);
574572
}
575573

576-
static const struct file_operations proc_seq_fops = {
577-
.open = proc_seq_open,
578-
.read = seq_read,
579-
.llseek = seq_lseek,
580-
.release = proc_seq_release,
574+
static const struct proc_ops proc_seq_ops = {
575+
.proc_open = proc_seq_open,
576+
.proc_read = seq_read,
577+
.proc_lseek = seq_lseek,
578+
.proc_release = proc_seq_release,
581579
};
582580

583581
struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
@@ -589,7 +587,7 @@ struct proc_dir_entry *proc_create_seq_private(const char *name, umode_t mode,
589587
p = proc_create_reg(name, mode, &parent, data);
590588
if (!p)
591589
return NULL;
592-
p->proc_fops = &proc_seq_fops;
590+
p->proc_ops = &proc_seq_ops;
593591
p->seq_ops = ops;
594592
p->state_size = state_size;
595593
return proc_register(parent, p);
@@ -603,11 +601,11 @@ static int proc_single_open(struct inode *inode, struct file *file)
603601
return single_open(file, de->single_show, de->data);
604602
}
605603

606-
static const struct file_operations proc_single_fops = {
607-
.open = proc_single_open,
608-
.read = seq_read,
609-
.llseek = seq_lseek,
610-
.release = single_release,
604+
static const struct proc_ops proc_single_ops = {
605+
.proc_open = proc_single_open,
606+
.proc_read = seq_read,
607+
.proc_lseek = seq_lseek,
608+
.proc_release = single_release,
611609
};
612610

613611
struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
@@ -619,7 +617,7 @@ struct proc_dir_entry *proc_create_single_data(const char *name, umode_t mode,
619617
p = proc_create_reg(name, mode, &parent, data);
620618
if (!p)
621619
return NULL;
622-
p->proc_fops = &proc_single_fops;
620+
p->proc_ops = &proc_single_ops;
623621
p->single_show = show;
624622
return proc_register(parent, p);
625623
}

fs/proc/inode.c

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ static void close_pdeo(struct proc_dir_entry *pde, struct pde_opener *pdeo)
163163
pdeo->closing = true;
164164
spin_unlock(&pde->pde_unload_lock);
165165
file = pdeo->file;
166-
pde->proc_fops->release(file_inode(file), file);
166+
pde->proc_ops->proc_release(file_inode(file), file);
167167
spin_lock(&pde->pde_unload_lock);
168168
/* After ->release. */
169169
list_del(&pdeo->lh);
@@ -200,12 +200,12 @@ static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence)
200200
struct proc_dir_entry *pde = PDE(file_inode(file));
201201
loff_t rv = -EINVAL;
202202
if (use_pde(pde)) {
203-
typeof_member(struct file_operations, llseek) llseek;
203+
typeof_member(struct proc_ops, proc_lseek) lseek;
204204

205-
llseek = pde->proc_fops->llseek;
206-
if (!llseek)
207-
llseek = default_llseek;
208-
rv = llseek(file, offset, whence);
205+
lseek = pde->proc_ops->proc_lseek;
206+
if (!lseek)
207+
lseek = default_llseek;
208+
rv = lseek(file, offset, whence);
209209
unuse_pde(pde);
210210
}
211211
return rv;
@@ -216,9 +216,9 @@ static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count,
216216
struct proc_dir_entry *pde = PDE(file_inode(file));
217217
ssize_t rv = -EIO;
218218
if (use_pde(pde)) {
219-
typeof_member(struct file_operations, read) read;
219+
typeof_member(struct proc_ops, proc_read) read;
220220

221-
read = pde->proc_fops->read;
221+
read = pde->proc_ops->proc_read;
222222
if (read)
223223
rv = read(file, buf, count, ppos);
224224
unuse_pde(pde);
@@ -231,9 +231,9 @@ static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t
231231
struct proc_dir_entry *pde = PDE(file_inode(file));
232232
ssize_t rv = -EIO;
233233
if (use_pde(pde)) {
234-
typeof_member(struct file_operations, write) write;
234+
typeof_member(struct proc_ops, proc_write) write;
235235

236-
write = pde->proc_fops->write;
236+
write = pde->proc_ops->proc_write;
237237
if (write)
238238
rv = write(file, buf, count, ppos);
239239
unuse_pde(pde);
@@ -246,9 +246,9 @@ static __poll_t proc_reg_poll(struct file *file, struct poll_table_struct *pts)
246246
struct proc_dir_entry *pde = PDE(file_inode(file));
247247
__poll_t rv = DEFAULT_POLLMASK;
248248
if (use_pde(pde)) {
249-
typeof_member(struct file_operations, poll) poll;
249+
typeof_member(struct proc_ops, proc_poll) poll;
250250

251-
poll = pde->proc_fops->poll;
251+
poll = pde->proc_ops->proc_poll;
252252
if (poll)
253253
rv = poll(file, pts);
254254
unuse_pde(pde);
@@ -261,9 +261,9 @@ static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigne
261261
struct proc_dir_entry *pde = PDE(file_inode(file));
262262
long rv = -ENOTTY;
263263
if (use_pde(pde)) {
264-
typeof_member(struct file_operations, unlocked_ioctl) ioctl;
264+
typeof_member(struct proc_ops, proc_ioctl) ioctl;
265265

266-
ioctl = pde->proc_fops->unlocked_ioctl;
266+
ioctl = pde->proc_ops->proc_ioctl;
267267
if (ioctl)
268268
rv = ioctl(file, cmd, arg);
269269
unuse_pde(pde);
@@ -277,9 +277,9 @@ static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned
277277
struct proc_dir_entry *pde = PDE(file_inode(file));
278278
long rv = -ENOTTY;
279279
if (use_pde(pde)) {
280-
typeof_member(struct file_operations, compat_ioctl) compat_ioctl;
280+
typeof_member(struct proc_ops, proc_compat_ioctl) compat_ioctl;
281281

282-
compat_ioctl = pde->proc_fops->compat_ioctl;
282+
compat_ioctl = pde->proc_ops->proc_compat_ioctl;
283283
if (compat_ioctl)
284284
rv = compat_ioctl(file, cmd, arg);
285285
unuse_pde(pde);
@@ -293,9 +293,9 @@ static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma)
293293
struct proc_dir_entry *pde = PDE(file_inode(file));
294294
int rv = -EIO;
295295
if (use_pde(pde)) {
296-
typeof_member(struct file_operations, mmap) mmap;
296+
typeof_member(struct proc_ops, proc_mmap) mmap;
297297

298-
mmap = pde->proc_fops->mmap;
298+
mmap = pde->proc_ops->proc_mmap;
299299
if (mmap)
300300
rv = mmap(file, vma);
301301
unuse_pde(pde);
@@ -312,9 +312,9 @@ proc_reg_get_unmapped_area(struct file *file, unsigned long orig_addr,
312312
unsigned long rv = -EIO;
313313

314314
if (use_pde(pde)) {
315-
typeof_member(struct file_operations, get_unmapped_area) get_area;
315+
typeof_member(struct proc_ops, proc_get_unmapped_area) get_area;
316316

317-
get_area = pde->proc_fops->get_unmapped_area;
317+
get_area = pde->proc_ops->proc_get_unmapped_area;
318318
#ifdef CONFIG_MMU
319319
if (!get_area)
320320
get_area = current->mm->get_unmapped_area;
@@ -333,8 +333,8 @@ static int proc_reg_open(struct inode *inode, struct file *file)
333333
{
334334
struct proc_dir_entry *pde = PDE(inode);
335335
int rv = 0;
336-
typeof_member(struct file_operations, open) open;
337-
typeof_member(struct file_operations, release) release;
336+
typeof_member(struct proc_ops, proc_open) open;
337+
typeof_member(struct proc_ops, proc_release) release;
338338
struct pde_opener *pdeo;
339339

340340
/*
@@ -351,7 +351,7 @@ static int proc_reg_open(struct inode *inode, struct file *file)
351351
if (!use_pde(pde))
352352
return -ENOENT;
353353

354-
release = pde->proc_fops->release;
354+
release = pde->proc_ops->proc_release;
355355
if (release) {
356356
pdeo = kmem_cache_alloc(pde_opener_cache, GFP_KERNEL);
357357
if (!pdeo) {
@@ -360,7 +360,7 @@ static int proc_reg_open(struct inode *inode, struct file *file)
360360
}
361361
}
362362

363-
open = pde->proc_fops->open;
363+
open = pde->proc_ops->proc_open;
364364
if (open)
365365
rv = open(inode, file);
366366

@@ -468,21 +468,23 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
468468
inode->i_size = de->size;
469469
if (de->nlink)
470470
set_nlink(inode, de->nlink);
471-
WARN_ON(!de->proc_iops);
472-
inode->i_op = de->proc_iops;
473-
if (de->proc_fops) {
474-
if (S_ISREG(inode->i_mode)) {
471+
472+
if (S_ISREG(inode->i_mode)) {
473+
inode->i_op = de->proc_iops;
474+
inode->i_fop = &proc_reg_file_ops;
475475
#ifdef CONFIG_COMPAT
476-
if (!de->proc_fops->compat_ioctl)
477-
inode->i_fop =
478-
&proc_reg_file_ops_no_compat;
479-
else
480-
#endif
481-
inode->i_fop = &proc_reg_file_ops;
482-
} else {
483-
inode->i_fop = de->proc_fops;
476+
if (!de->proc_ops->proc_compat_ioctl) {
477+
inode->i_fop = &proc_reg_file_ops_no_compat;
484478
}
485-
}
479+
#endif
480+
} else if (S_ISDIR(inode->i_mode)) {
481+
inode->i_op = de->proc_iops;
482+
inode->i_fop = de->proc_dir_ops;
483+
} else if (S_ISLNK(inode->i_mode)) {
484+
inode->i_op = de->proc_iops;
485+
inode->i_fop = NULL;
486+
} else
487+
BUG();
486488
} else
487489
pde_put(de);
488490
return inode;

fs/proc/internal.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ struct proc_dir_entry {
3939
spinlock_t pde_unload_lock;
4040
struct completion *pde_unload_completion;
4141
const struct inode_operations *proc_iops;
42-
const struct file_operations *proc_fops;
42+
union {
43+
const struct proc_ops *proc_ops;
44+
const struct file_operations *proc_dir_ops;
45+
};
4346
const struct dentry_operations *proc_dops;
4447
union {
4548
const struct seq_operations *seq_ops;

fs/proc/proc_net.c

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,12 @@ static int seq_release_net(struct inode *ino, struct file *f)
9090
return 0;
9191
}
9292

93-
static const struct file_operations proc_net_seq_fops = {
94-
.open = seq_open_net,
95-
.read = seq_read,
96-
.write = proc_simple_write,
97-
.llseek = seq_lseek,
98-
.release = seq_release_net,
93+
static const struct proc_ops proc_net_seq_ops = {
94+
.proc_open = seq_open_net,
95+
.proc_read = seq_read,
96+
.proc_write = proc_simple_write,
97+
.proc_lseek = seq_lseek,
98+
.proc_release = seq_release_net,
9999
};
100100

101101
struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
@@ -108,7 +108,7 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
108108
if (!p)
109109
return NULL;
110110
pde_force_lookup(p);
111-
p->proc_fops = &proc_net_seq_fops;
111+
p->proc_ops = &proc_net_seq_ops;
112112
p->seq_ops = ops;
113113
p->state_size = state_size;
114114
return proc_register(parent, p);
@@ -152,7 +152,7 @@ struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode
152152
if (!p)
153153
return NULL;
154154
pde_force_lookup(p);
155-
p->proc_fops = &proc_net_seq_fops;
155+
p->proc_ops = &proc_net_seq_ops;
156156
p->seq_ops = ops;
157157
p->state_size = state_size;
158158
p->write = write;
@@ -183,12 +183,12 @@ static int single_release_net(struct inode *ino, struct file *f)
183183
return single_release(ino, f);
184184
}
185185

186-
static const struct file_operations proc_net_single_fops = {
187-
.open = single_open_net,
188-
.read = seq_read,
189-
.write = proc_simple_write,
190-
.llseek = seq_lseek,
191-
.release = single_release_net,
186+
static const struct proc_ops proc_net_single_ops = {
187+
.proc_open = single_open_net,
188+
.proc_read = seq_read,
189+
.proc_write = proc_simple_write,
190+
.proc_lseek = seq_lseek,
191+
.proc_release = single_release_net,
192192
};
193193

194194
struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
@@ -201,7 +201,7 @@ struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
201201
if (!p)
202202
return NULL;
203203
pde_force_lookup(p);
204-
p->proc_fops = &proc_net_single_fops;
204+
p->proc_ops = &proc_net_single_ops;
205205
p->single_show = show;
206206
return proc_register(parent, p);
207207
}
@@ -244,7 +244,7 @@ struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mo
244244
if (!p)
245245
return NULL;
246246
pde_force_lookup(p);
247-
p->proc_fops = &proc_net_single_fops;
247+
p->proc_ops = &proc_net_single_ops;
248248
p->single_show = show;
249249
p->write = write;
250250
return proc_register(parent, p);

fs/proc/proc_sysctl.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1720,7 +1720,7 @@ int __init proc_sys_init(void)
17201720

17211721
proc_sys_root = proc_mkdir("sys", NULL);
17221722
proc_sys_root->proc_iops = &proc_sys_dir_operations;
1723-
proc_sys_root->proc_fops = &proc_sys_dir_file_operations;
1723+
proc_sys_root->proc_dir_ops = &proc_sys_dir_file_operations;
17241724
proc_sys_root->nlink = 0;
17251725

17261726
return sysctl_init();

fs/proc/root.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ struct proc_dir_entry proc_root = {
292292
.nlink = 2,
293293
.refcnt = REFCOUNT_INIT(1),
294294
.proc_iops = &proc_root_inode_operations,
295-
.proc_fops = &proc_root_operations,
295+
.proc_dir_ops = &proc_root_operations,
296296
.parent = &proc_root,
297297
.subdir = RB_ROOT,
298298
.name = "/proc",

0 commit comments

Comments
 (0)