aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-02-14 03:34:12 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-14 11:10:00 -0500
commit77b14db502cb85a031fe8fde6c85d52f3e0acb63 (patch)
tree4201f6a4dfe1062d1dc00659c403d630401b87cc /kernel/sysctl.c
parent1ff007eb8e8c7c44e9a384a67d0fdd0fd06ba811 (diff)
[PATCH] sysctl: reimplement the sysctl proc support
With this change the sysctl inodes can be cached and nothing needs to be done when removing a sysctl table. For a cost of 2K code we will save about 4K of static tables (when we remove de from ctl_table) and 70K in proc_dir_entries that we will not allocate, or about half that on a 32bit arch. The speed feels about the same, even though we can now cache the sysctl dentries :( We get the core advantage that we don't need to have a 1 to 1 mapping between ctl table entries and proc files. Making it possible to have /proc/sys vary depending on the namespace you are in. The currently merged namespaces don't have an issue here but the network namespace under /proc/sys/net needs to have different directories depending on which network adapters are visible. By simply being a cache different directories being visible depending on who you are is trivial to implement. [akpm@osdl.org: fix uninitialised var] [akpm@osdl.org: fix ARM build] [bunk@stusta.de: make things static] Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Cc: Russell King <rmk@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c182
1 files changed, 0 insertions, 182 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 6bbac5ce75ed..b3ee791ad663 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -159,26 +159,6 @@ int sysctl_legacy_va_layout;
159#endif 159#endif
160 160
161 161
162/* /proc declarations: */
163
164#ifdef CONFIG_PROC_SYSCTL
165
166static ssize_t proc_readsys(struct file *, char __user *, size_t, loff_t *);
167static ssize_t proc_writesys(struct file *, const char __user *, size_t, loff_t *);
168static int proc_opensys(struct inode *, struct file *);
169
170const struct file_operations proc_sys_file_operations = {
171 .open = proc_opensys,
172 .read = proc_readsys,
173 .write = proc_writesys,
174};
175
176extern struct proc_dir_entry *proc_sys_root;
177
178static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *);
179static void unregister_proc_table(ctl_table *, struct proc_dir_entry *);
180#endif
181
182/* The default sysctl tables: */ 162/* The default sysctl tables: */
183 163
184static ctl_table root_table[] = { 164static ctl_table root_table[] = {
@@ -1106,13 +1086,6 @@ struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev)
1106 return NULL; 1086 return NULL;
1107} 1087}
1108 1088
1109void __init sysctl_init(void)
1110{
1111#ifdef CONFIG_PROC_SYSCTL
1112 register_proc_table(root_table, proc_sys_root, &root_table_header);
1113#endif
1114}
1115
1116#ifdef CONFIG_SYSCTL_SYSCALL 1089#ifdef CONFIG_SYSCTL_SYSCALL
1117int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, 1090int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
1118 void __user *newval, size_t newlen) 1091 void __user *newval, size_t newlen)
@@ -1348,9 +1321,6 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table)
1348 spin_lock(&sysctl_lock); 1321 spin_lock(&sysctl_lock);
1349 list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); 1322 list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry);
1350 spin_unlock(&sysctl_lock); 1323 spin_unlock(&sysctl_lock);
1351#ifdef CONFIG_PROC_SYSCTL
1352 register_proc_table(table, proc_sys_root, tmp);
1353#endif
1354 return tmp; 1324 return tmp;
1355} 1325}
1356 1326
@@ -1366,9 +1336,6 @@ void unregister_sysctl_table(struct ctl_table_header * header)
1366 might_sleep(); 1336 might_sleep();
1367 spin_lock(&sysctl_lock); 1337 spin_lock(&sysctl_lock);
1368 start_unregistering(header); 1338 start_unregistering(header);
1369#ifdef CONFIG_PROC_SYSCTL
1370 unregister_proc_table(header->ctl_table, proc_sys_root);
1371#endif
1372 spin_unlock(&sysctl_lock); 1339 spin_unlock(&sysctl_lock);
1373 kfree(header); 1340 kfree(header);
1374} 1341}
@@ -1392,155 +1359,6 @@ void unregister_sysctl_table(struct ctl_table_header * table)
1392 1359
1393#ifdef CONFIG_PROC_SYSCTL 1360#ifdef CONFIG_PROC_SYSCTL
1394 1361
1395/* Scan the sysctl entries in table and add them all into /proc */
1396static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set)
1397{
1398 struct proc_dir_entry *de;
1399 int len;
1400 mode_t mode;
1401
1402 for (; table->ctl_name || table->procname; table++) {
1403 /* Can't do anything without a proc name. */
1404 if (!table->procname)
1405 continue;
1406 /* Maybe we can't do anything with it... */
1407 if (!table->proc_handler && !table->child) {
1408 printk(KERN_WARNING "SYSCTL: Can't register %s\n",
1409 table->procname);
1410 continue;
1411 }
1412
1413 len = strlen(table->procname);
1414 mode = table->mode;
1415
1416 de = NULL;
1417 if (table->proc_handler)
1418 mode |= S_IFREG;
1419 else {
1420 mode |= S_IFDIR;
1421 for (de = root->subdir; de; de = de->next) {
1422 if (proc_match(len, table->procname, de))
1423 break;
1424 }
1425 /* If the subdir exists already, de is non-NULL */
1426 }
1427
1428 if (!de) {
1429 de = create_proc_entry(table->procname, mode, root);
1430 if (!de)
1431 continue;
1432 de->set = set;
1433 de->data = (void *) table;
1434 if (table->proc_handler)
1435 de->proc_fops = &proc_sys_file_operations;
1436 }
1437 table->de = de;
1438 if (de->mode & S_IFDIR)
1439 register_proc_table(table->child, de, set);
1440 }
1441}
1442
1443/*
1444 * Unregister a /proc sysctl table and any subdirectories.
1445 */
1446static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root)
1447{
1448 struct proc_dir_entry *de;
1449 for (; table->ctl_name || table->procname; table++) {
1450 if (!(de = table->de))
1451 continue;
1452 if (de->mode & S_IFDIR) {
1453 if (!table->child) {
1454 printk (KERN_ALERT "Help - malformed sysctl tree on free\n");
1455 continue;
1456 }
1457 unregister_proc_table(table->child, de);
1458
1459 /* Don't unregister directories which still have entries.. */
1460 if (de->subdir)
1461 continue;
1462 }
1463
1464 /*
1465 * In any case, mark the entry as goner; we'll keep it
1466 * around if it's busy, but we'll know to do nothing with
1467 * its fields. We are under sysctl_lock here.
1468 */
1469 de->data = NULL;
1470
1471 /* Don't unregister proc entries that are still being used.. */
1472 if (atomic_read(&de->count))
1473 continue;
1474
1475 table->de = NULL;
1476 remove_proc_entry(table->procname, root);
1477 }
1478}
1479
1480static ssize_t do_rw_proc(int write, struct file * file, char __user * buf,
1481 size_t count, loff_t *ppos)
1482{
1483 int op;
1484 struct proc_dir_entry *de = PDE(file->f_path.dentry->d_inode);
1485 struct ctl_table *table;
1486 size_t res;
1487 ssize_t error = -ENOTDIR;
1488
1489 spin_lock(&sysctl_lock);
1490 if (de && de->data && use_table(de->set)) {
1491 /*
1492 * at that point we know that sysctl was not unregistered
1493 * and won't be until we finish
1494 */
1495 spin_unlock(&sysctl_lock);
1496 table = (struct ctl_table *) de->data;
1497 if (!table || !table->proc_handler)
1498 goto out;
1499 error = -EPERM;
1500 op = (write ? 002 : 004);
1501 if (sysctl_perm(table, op))
1502 goto out;
1503
1504 /* careful: calling conventions are nasty here */
1505 res = count;
1506 error = (*table->proc_handler)(table, write, file,
1507 buf, &res, ppos);
1508 if (!error)
1509 error = res;
1510 out:
1511 spin_lock(&sysctl_lock);
1512 unuse_table(de->set);
1513 }
1514 spin_unlock(&sysctl_lock);
1515 return error;
1516}
1517
1518static int proc_opensys(struct inode *inode, struct file *file)
1519{
1520 if (file->f_mode & FMODE_WRITE) {
1521 /*
1522 * sysctl entries that are not writable,
1523 * are _NOT_ writable, capabilities or not.
1524 */
1525 if (!(inode->i_mode & S_IWUSR))
1526 return -EPERM;
1527 }
1528
1529 return 0;
1530}
1531
1532static ssize_t proc_readsys(struct file * file, char __user * buf,
1533 size_t count, loff_t *ppos)
1534{
1535 return do_rw_proc(0, file, buf, count, ppos);
1536}
1537
1538static ssize_t proc_writesys(struct file * file, const char __user * buf,
1539 size_t count, loff_t *ppos)
1540{
1541 return do_rw_proc(1, file, (char __user *) buf, count, ppos);
1542}
1543
1544static int _proc_do_string(void* data, int maxlen, int write, 1362static int _proc_do_string(void* data, int maxlen, int write,
1545 struct file *filp, void __user *buffer, 1363 struct file *filp, void __user *buffer,
1546 size_t *lenp, loff_t *ppos) 1364 size_t *lenp, loff_t *ppos)