|
Lines 169-175
Link Here
|
| 169 |
|
169 |
|
| 170 |
extern struct proc_dir_entry *proc_sys_root; |
170 |
extern struct proc_dir_entry *proc_sys_root; |
| 171 |
|
171 |
|
| 172 |
static void register_proc_table(ctl_table *, struct proc_dir_entry *); |
172 |
static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *); |
| 173 |
static void unregister_proc_table(ctl_table *, struct proc_dir_entry *); |
173 |
static void unregister_proc_table(ctl_table *, struct proc_dir_entry *); |
| 174 |
#endif |
174 |
#endif |
| 175 |
|
175 |
|
|
Lines 992-1001
Link Here
|
| 992 |
|
992 |
|
| 993 |
extern void init_irq_proc (void); |
993 |
extern void init_irq_proc (void); |
| 994 |
|
994 |
|
|
|
995 |
static DEFINE_SPINLOCK(sysctl_lock); |
| 996 |
|
| 997 |
/* called under sysctl_lock */ |
| 998 |
static int use_table(struct ctl_table_header *p) |
| 999 |
{ |
| 1000 |
if (unlikely(p->unregistering)) |
| 1001 |
return 0; |
| 1002 |
p->used++; |
| 1003 |
return 1; |
| 1004 |
} |
| 1005 |
|
| 1006 |
/* called under sysctl_lock */ |
| 1007 |
static void unuse_table(struct ctl_table_header *p) |
| 1008 |
{ |
| 1009 |
if (!--p->used) |
| 1010 |
if (unlikely(p->unregistering)) |
| 1011 |
complete(p->unregistering); |
| 1012 |
} |
| 1013 |
|
| 1014 |
/* called under sysctl_lock, will reacquire if has to wait */ |
| 1015 |
static void start_unregistering(struct ctl_table_header *p) |
| 1016 |
{ |
| 1017 |
/* |
| 1018 |
* if p->used is 0, nobody will ever touch that entry again; |
| 1019 |
* we'll eliminate all paths to it before dropping sysctl_lock |
| 1020 |
*/ |
| 1021 |
if (unlikely(p->used)) { |
| 1022 |
struct completion wait; |
| 1023 |
init_completion(&wait); |
| 1024 |
p->unregistering = &wait; |
| 1025 |
spin_unlock(&sysctl_lock); |
| 1026 |
wait_for_completion(&wait); |
| 1027 |
spin_lock(&sysctl_lock); |
| 1028 |
} |
| 1029 |
/* |
| 1030 |
* do not remove from the list until nobody holds it; walking the |
| 1031 |
* list in do_sysctl() relies on that. |
| 1032 |
*/ |
| 1033 |
list_del_init(&p->ctl_entry); |
| 1034 |
} |
| 1035 |
|
| 995 |
void __init sysctl_init(void) |
1036 |
void __init sysctl_init(void) |
| 996 |
{ |
1037 |
{ |
| 997 |
#ifdef CONFIG_PROC_FS |
1038 |
#ifdef CONFIG_PROC_FS |
| 998 |
register_proc_table(root_table, proc_sys_root); |
1039 |
register_proc_table(root_table, proc_sys_root, &root_table_header); |
| 999 |
init_irq_proc(); |
1040 |
init_irq_proc(); |
| 1000 |
#endif |
1041 |
#endif |
| 1001 |
} |
1042 |
} |
|
Lines 1004-1009
Link Here
|
| 1004 |
void __user *newval, size_t newlen) |
1045 |
void __user *newval, size_t newlen) |
| 1005 |
{ |
1046 |
{ |
| 1006 |
struct list_head *tmp; |
1047 |
struct list_head *tmp; |
|
|
1048 |
int error = -ENOTDIR; |
| 1007 |
|
1049 |
|
| 1008 |
if (nlen <= 0 || nlen >= CTL_MAXNAME) |
1050 |
if (nlen <= 0 || nlen >= CTL_MAXNAME) |
| 1009 |
return -ENOTDIR; |
1051 |
return -ENOTDIR; |
|
Lines 1012-1031
Link Here
|
| 1012 |
if (!oldlenp || get_user(old_len, oldlenp)) |
1054 |
if (!oldlenp || get_user(old_len, oldlenp)) |
| 1013 |
return -EFAULT; |
1055 |
return -EFAULT; |
| 1014 |
} |
1056 |
} |
|
|
1057 |
spin_lock(&sysctl_lock); |
| 1015 |
tmp = &root_table_header.ctl_entry; |
1058 |
tmp = &root_table_header.ctl_entry; |
| 1016 |
do { |
1059 |
do { |
| 1017 |
struct ctl_table_header *head = |
1060 |
struct ctl_table_header *head = |
| 1018 |
list_entry(tmp, struct ctl_table_header, ctl_entry); |
1061 |
list_entry(tmp, struct ctl_table_header, ctl_entry); |
| 1019 |
void *context = NULL; |
1062 |
void *context = NULL; |
| 1020 |
int error = parse_table(name, nlen, oldval, oldlenp, |
1063 |
|
|
|
1064 |
if (!use_table(head)) |
| 1065 |
continue; |
| 1066 |
|
| 1067 |
spin_unlock(&sysctl_lock); |
| 1068 |
|
| 1069 |
error = parse_table(name, nlen, oldval, oldlenp, |
| 1021 |
newval, newlen, head->ctl_table, |
1070 |
newval, newlen, head->ctl_table, |
| 1022 |
&context); |
1071 |
&context); |
| 1023 |
kfree(context); |
1072 |
kfree(context); |
|
|
1073 |
|
| 1074 |
spin_lock(&sysctl_lock); |
| 1075 |
unuse_table(head); |
| 1024 |
if (error != -ENOTDIR) |
1076 |
if (error != -ENOTDIR) |
| 1025 |
return error; |
1077 |
break; |
| 1026 |
tmp = tmp->next; |
1078 |
} while ((tmp = tmp->next) != &root_table_header.ctl_entry); |
| 1027 |
} while (tmp != &root_table_header.ctl_entry); |
1079 |
spin_unlock(&sysctl_lock); |
| 1028 |
return -ENOTDIR; |
1080 |
return error; |
| 1029 |
} |
1081 |
} |
| 1030 |
|
1082 |
|
| 1031 |
asmlinkage long sys_sysctl(struct __sysctl_args __user *args) |
1083 |
asmlinkage long sys_sysctl(struct __sysctl_args __user *args) |
|
Lines 1236-1247
Link Here
|
| 1236 |
return NULL; |
1288 |
return NULL; |
| 1237 |
tmp->ctl_table = table; |
1289 |
tmp->ctl_table = table; |
| 1238 |
INIT_LIST_HEAD(&tmp->ctl_entry); |
1290 |
INIT_LIST_HEAD(&tmp->ctl_entry); |
|
|
1291 |
tmp->used = 0; |
| 1292 |
tmp->unregistering = NULL; |
| 1293 |
spin_lock(&sysctl_lock); |
| 1239 |
if (insert_at_head) |
1294 |
if (insert_at_head) |
| 1240 |
list_add(&tmp->ctl_entry, &root_table_header.ctl_entry); |
1295 |
list_add(&tmp->ctl_entry, &root_table_header.ctl_entry); |
| 1241 |
else |
1296 |
else |
| 1242 |
list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); |
1297 |
list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); |
|
|
1298 |
spin_unlock(&sysctl_lock); |
| 1243 |
#ifdef CONFIG_PROC_FS |
1299 |
#ifdef CONFIG_PROC_FS |
| 1244 |
register_proc_table(table, proc_sys_root); |
1300 |
register_proc_table(table, proc_sys_root, tmp); |
| 1245 |
#endif |
1301 |
#endif |
| 1246 |
return tmp; |
1302 |
return tmp; |
| 1247 |
} |
1303 |
} |
|
Lines 1255-1264
Link Here
|
| 1255 |
*/ |
1311 |
*/ |
| 1256 |
void unregister_sysctl_table(struct ctl_table_header * header) |
1312 |
void unregister_sysctl_table(struct ctl_table_header * header) |
| 1257 |
{ |
1313 |
{ |
| 1258 |
list_del(&header->ctl_entry); |
1314 |
might_sleep(); |
|
|
1315 |
spin_lock(&sysctl_lock); |
| 1316 |
start_unregistering(header); |
| 1259 |
#ifdef CONFIG_PROC_FS |
1317 |
#ifdef CONFIG_PROC_FS |
| 1260 |
unregister_proc_table(header->ctl_table, proc_sys_root); |
1318 |
unregister_proc_table(header->ctl_table, proc_sys_root); |
| 1261 |
#endif |
1319 |
#endif |
|
|
1320 |
spin_unlock(&sysctl_lock); |
| 1262 |
kfree(header); |
1321 |
kfree(header); |
| 1263 |
} |
1322 |
} |
| 1264 |
|
1323 |
|
|
Lines 1269-1275
Link Here
|
| 1269 |
#ifdef CONFIG_PROC_FS |
1328 |
#ifdef CONFIG_PROC_FS |
| 1270 |
|
1329 |
|
| 1271 |
/* Scan the sysctl entries in table and add them all into /proc */ |
1330 |
/* Scan the sysctl entries in table and add them all into /proc */ |
| 1272 |
static void register_proc_table(ctl_table * table, struct proc_dir_entry *root) |
1331 |
static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set) |
| 1273 |
{ |
1332 |
{ |
| 1274 |
struct proc_dir_entry *de; |
1333 |
struct proc_dir_entry *de; |
| 1275 |
int len; |
1334 |
int len; |
|
Lines 1305-1317
Link Here
|
| 1305 |
de = create_proc_entry(table->procname, mode, root); |
1364 |
de = create_proc_entry(table->procname, mode, root); |
| 1306 |
if (!de) |
1365 |
if (!de) |
| 1307 |
continue; |
1366 |
continue; |
|
|
1367 |
de->set = set; |
| 1308 |
de->data = (void *) table; |
1368 |
de->data = (void *) table; |
| 1309 |
if (table->proc_handler) |
1369 |
if (table->proc_handler) |
| 1310 |
de->proc_fops = &proc_sys_file_operations; |
1370 |
de->proc_fops = &proc_sys_file_operations; |
| 1311 |
} |
1371 |
} |
| 1312 |
table->de = de; |
1372 |
table->de = de; |
| 1313 |
if (de->mode & S_IFDIR) |
1373 |
if (de->mode & S_IFDIR) |
| 1314 |
register_proc_table(table->child, de); |
1374 |
register_proc_table(table->child, de, set); |
| 1315 |
} |
1375 |
} |
| 1316 |
} |
1376 |
} |
| 1317 |
|
1377 |
|
|
Lines 1336-1341
Link Here
|
| 1336 |
continue; |
1396 |
continue; |
| 1337 |
} |
1397 |
} |
| 1338 |
|
1398 |
|
|
|
1399 |
/* |
| 1400 |
* In any case, mark the entry as goner; we'll keep it |
| 1401 |
* around if it's busy, but we'll know to do nothing with |
| 1402 |
* its fields. We are under sysctl_lock here. |
| 1403 |
*/ |
| 1404 |
de->data = NULL; |
| 1405 |
|
| 1339 |
/* Don't unregister proc entries that are still being used.. */ |
1406 |
/* Don't unregister proc entries that are still being used.. */ |
| 1340 |
if (atomic_read(&de->count)) |
1407 |
if (atomic_read(&de->count)) |
| 1341 |
continue; |
1408 |
continue; |
|
Lines 1349-1375
Link Here
|
| 1349 |
size_t count, loff_t *ppos) |
1416 |
size_t count, loff_t *ppos) |
| 1350 |
{ |
1417 |
{ |
| 1351 |
int op; |
1418 |
int op; |
| 1352 |
struct proc_dir_entry *de; |
1419 |
struct proc_dir_entry *de = PDE(file->f_dentry->d_inode); |
| 1353 |
struct ctl_table *table; |
1420 |
struct ctl_table *table; |
| 1354 |
size_t res; |
1421 |
size_t res; |
| 1355 |
ssize_t error; |
1422 |
ssize_t error = -ENOTDIR; |
| 1356 |
|
|
|
| 1357 |
de = PDE(file->f_dentry->d_inode); |
| 1358 |
if (!de || !de->data) |
| 1359 |
return -ENOTDIR; |
| 1360 |
table = (struct ctl_table *) de->data; |
| 1361 |
if (!table || !table->proc_handler) |
| 1362 |
return -ENOTDIR; |
| 1363 |
op = (write ? 002 : 004); |
| 1364 |
if (ctl_perm(table, op)) |
| 1365 |
return -EPERM; |
| 1366 |
|
1423 |
|
| 1367 |
res = count; |
1424 |
spin_lock(&sysctl_lock); |
| 1368 |
|
1425 |
if (de && de->data && use_table(de->set)) { |
| 1369 |
error = (*table->proc_handler) (table, write, file, buf, &res, ppos); |
1426 |
/* |
| 1370 |
if (error) |
1427 |
* at that point we know that sysctl was not unregistered |
| 1371 |
return error; |
1428 |
* and won't be until we finish |
| 1372 |
return res; |
1429 |
*/ |
|
|
1430 |
spin_unlock(&sysctl_lock); |
| 1431 |
table = (struct ctl_table *) de->data; |
| 1432 |
if (!table || !table->proc_handler) |
| 1433 |
goto out; |
| 1434 |
error = -EPERM; |
| 1435 |
op = (write ? 002 : 004); |
| 1436 |
if (ctl_perm(table, op)) |
| 1437 |
goto out; |
| 1438 |
|
| 1439 |
/* careful: calling conventions are nasty here */ |
| 1440 |
res = count; |
| 1441 |
error = (*table->proc_handler)(table, write, file, |
| 1442 |
buf, &res, ppos); |
| 1443 |
if (!error) |
| 1444 |
error = res; |
| 1445 |
out: |
| 1446 |
spin_lock(&sysctl_lock); |
| 1447 |
unuse_table(de->set); |
| 1448 |
} |
| 1449 |
spin_unlock(&sysctl_lock); |
| 1450 |
return error; |
| 1373 |
} |
1451 |
} |
| 1374 |
|
1452 |
|
| 1375 |
static int proc_opensys(struct inode *inode, struct file *file) |
1453 |
static int proc_opensys(struct inode *inode, struct file *file) |