@@ -243,31 +243,25 @@ static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
243
243
return entry ;
244
244
}
245
245
246
- static struct ctl_table_header * __sysctl_head_next (struct nsproxy * namespaces ,
247
- struct ctl_table_header * prev )
246
+ static struct ctl_table_header * next_usable_entry (struct ctl_table * dir ,
247
+ struct ctl_table_root * root , struct list_head * tmp )
248
248
{
249
- struct ctl_table_root * root ;
249
+ struct nsproxy * namespaces = current -> nsproxy ;
250
250
struct list_head * header_list ;
251
251
struct ctl_table_header * head ;
252
- struct list_head * tmp ;
253
252
254
- spin_lock (& sysctl_lock );
255
- if (prev ) {
256
- head = prev ;
257
- tmp = & prev -> ctl_entry ;
258
- unuse_table (prev );
259
- goto next ;
260
- }
261
- tmp = & root_table_header .ctl_entry ;
253
+ goto next ;
262
254
for (;;) {
263
255
head = list_entry (tmp , struct ctl_table_header , ctl_entry );
256
+ root = head -> root ;
264
257
265
- if (!use_table (head ))
258
+ if (head -> attached_to != dir ||
259
+ !head -> attached_by -> procname ||
260
+ !use_table (head ))
266
261
goto next ;
267
- spin_unlock ( & sysctl_lock );
262
+
268
263
return head ;
269
264
next :
270
- root = head -> root ;
271
265
tmp = tmp -> next ;
272
266
header_list = lookup_header_list (root , namespaces );
273
267
if (tmp != header_list )
@@ -283,13 +277,53 @@ static struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces,
283
277
tmp = header_list -> next ;
284
278
}
285
279
out :
286
- spin_unlock (& sysctl_lock );
287
280
return NULL ;
288
281
}
289
282
290
- static struct ctl_table_header * sysctl_head_next (struct ctl_table_header * prev )
283
+ static void first_entry (
284
+ struct ctl_table_header * dir_head , struct ctl_table * dir ,
285
+ struct ctl_table_header * * phead , struct ctl_table * * pentry )
291
286
{
292
- return __sysctl_head_next (current -> nsproxy , prev );
287
+ struct ctl_table_header * head = dir_head ;
288
+ struct ctl_table * entry = dir ;
289
+
290
+ spin_lock (& sysctl_lock );
291
+ if (entry -> procname ) {
292
+ use_table (head );
293
+ } else {
294
+ head = next_usable_entry (dir , & sysctl_table_root ,
295
+ & sysctl_table_root .default_set .list );
296
+ if (head )
297
+ entry = head -> attached_by ;
298
+ }
299
+ spin_unlock (& sysctl_lock );
300
+ * phead = head ;
301
+ * pentry = entry ;
302
+ }
303
+
304
+ static void next_entry (struct ctl_table * dir ,
305
+ struct ctl_table_header * * phead , struct ctl_table * * pentry )
306
+ {
307
+ struct ctl_table_header * head = * phead ;
308
+ struct ctl_table * entry = * pentry ;
309
+
310
+ entry ++ ;
311
+ if (!entry -> procname ) {
312
+ struct ctl_table_root * root = head -> root ;
313
+ struct list_head * tmp = & head -> ctl_entry ;
314
+ if (head -> attached_to != dir ) {
315
+ root = & sysctl_table_root ;
316
+ tmp = & sysctl_table_root .default_set .list ;
317
+ }
318
+ spin_lock (& sysctl_lock );
319
+ unuse_table (head );
320
+ head = next_usable_entry (dir , root , tmp );
321
+ spin_unlock (& sysctl_lock );
322
+ if (head )
323
+ entry = head -> attached_by ;
324
+ }
325
+ * phead = head ;
326
+ * pentry = entry ;
293
327
}
294
328
295
329
void register_sysctl_root (struct ctl_table_root * root )
@@ -533,20 +567,17 @@ static int scan(struct ctl_table_header *head, ctl_table *table,
533
567
unsigned long * pos , struct file * file ,
534
568
void * dirent , filldir_t filldir )
535
569
{
570
+ int res ;
536
571
537
- for (; table -> procname ; table ++ , (* pos )++ ) {
538
- int res ;
572
+ if ( (* pos )++ < file -> f_pos )
573
+ return 0 ;
539
574
540
- if (* pos < file -> f_pos )
541
- continue ;
575
+ res = proc_sys_fill_cache (file , dirent , filldir , head , table );
542
576
543
- res = proc_sys_fill_cache (file , dirent , filldir , head , table );
544
- if (res )
545
- return res ;
577
+ if (res == 0 )
578
+ file -> f_pos = * pos ;
546
579
547
- file -> f_pos = * pos + 1 ;
548
- }
549
- return 0 ;
580
+ return res ;
550
581
}
551
582
552
583
static int proc_sys_readdir (struct file * filp , void * dirent , filldir_t filldir )
@@ -556,6 +587,7 @@ static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir)
556
587
struct ctl_table_header * head = grab_header (inode );
557
588
struct ctl_table * table = PROC_I (inode )-> sysctl_entry ;
558
589
struct ctl_table_header * h = NULL ;
590
+ struct ctl_table * entry ;
559
591
unsigned long pos ;
560
592
int ret = - EINVAL ;
561
593
@@ -585,14 +617,8 @@ static int proc_sys_readdir(struct file *filp, void *dirent, filldir_t filldir)
585
617
}
586
618
pos = 2 ;
587
619
588
- ret = scan (head , table , & pos , filp , dirent , filldir );
589
- if (ret )
590
- goto out ;
591
-
592
- for (h = sysctl_head_next (NULL ); h ; h = sysctl_head_next (h )) {
593
- if (h -> attached_to != table )
594
- continue ;
595
- ret = scan (h , h -> attached_by , & pos , filp , dirent , filldir );
620
+ for (first_entry (head , table , & h , & entry ); h ; next_entry (table , & h , & entry )) {
621
+ ret = scan (h , entry , & pos , filp , dirent , filldir );
596
622
if (ret ) {
597
623
sysctl_head_finish (h );
598
624
break ;
0 commit comments