Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
f0c3b509
Commit
f0c3b509
authored
May 16, 2013
by
Al Viro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[readdir] convert procfs
Signed-off-by:
Al Viro
<
viro@zeniv.linux.org.uk
>
parent
68c61471
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
284 additions
and
489 deletions
+284
-489
fs/hppfs/hppfs.c
fs/hppfs/hppfs.c
+14
-19
fs/proc/base.c
fs/proc/base.c
+133
-230
fs/proc/fd.c
fs/proc/fd.c
+40
-56
fs/proc/generic.c
fs/proc/generic.c
+38
-62
fs/proc/internal.h
fs/proc/internal.h
+4
-4
fs/proc/namespaces.c
fs/proc/namespaces.c
+18
-56
fs/proc/proc_net.c
fs/proc/proc_net.c
+4
-5
fs/proc/proc_sysctl.c
fs/proc/proc_sysctl.c
+27
-44
fs/proc/root.c
fs/proc/root.c
+6
-13
No files found.
fs/hppfs/hppfs.c
View file @
f0c3b509
...
...
@@ -542,8 +542,8 @@ static const struct file_operations hppfs_file_fops = {
};
struct
hppfs_dirent
{
void
*
vfs_dirent
;
filldir_t
filldi
r
;
struct
dir_context
ctx
;
struct
dir_context
*
calle
r
;
struct
dentry
*
dentry
;
};
...
...
@@ -555,34 +555,29 @@ static int hppfs_filldir(void *d, const char *name, int size,
if
(
file_removed
(
dirent
->
dentry
,
name
))
return
0
;
return
(
*
dirent
->
filldir
)(
dirent
->
vfs_dirent
,
name
,
size
,
offset
,
inode
,
type
);
dirent
->
caller
->
pos
=
dirent
->
ctx
.
pos
;
return
!
dir_emit
(
dirent
->
caller
,
name
,
size
,
inode
,
type
);
}
static
int
hppfs_readdir
(
struct
file
*
file
,
void
*
ent
,
filldir_t
filldir
)
static
int
hppfs_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
struct
hppfs_private
*
data
=
file
->
private_data
;
struct
file
*
proc_file
=
data
->
proc_file
;
int
(
*
readdir
)(
struct
file
*
,
void
*
,
filldir_t
);
struct
hppfs_dirent
dirent
=
((
struct
hppfs_dirent
)
{
.
vfs_dirent
=
ent
,
.
filldir
=
filldir
,
struct
hppfs_dirent
d
=
{
.
ctx
.
actor
=
hppfs_filldir
,
.
caller
=
ctx
,
.
dentry
=
file
->
f_path
.
dentry
})
;
}
;
int
err
;
readdir
=
file_inode
(
proc_file
)
->
i_fop
->
readdir
;
proc_file
->
f_pos
=
file
->
f_pos
;
err
=
(
*
readdir
)(
proc_file
,
&
dirent
,
hppfs_filldir
);
file
->
f_pos
=
proc_file
->
f_pos
;
proc_file
->
f_pos
=
ctx
->
pos
;
err
=
iterate_dir
(
proc_file
,
&
d
.
ctx
);
ctx
->
pos
=
d
.
ctx
.
pos
;
return
err
;
}
static
const
struct
file_operations
hppfs_dir_fops
=
{
.
owner
=
NULL
,
.
readdir
=
hppfs_readdir
,
.
iterate
=
hppfs_readdir
,
.
open
=
hppfs_dir_open
,
.
llseek
=
default_llseek
,
.
release
=
hppfs_release
,
...
...
fs/proc/base.c
View file @
f0c3b509
...
...
@@ -1681,11 +1681,11 @@ const struct dentry_operations pid_dentry_operations =
* reported by readdir in sync with the inode numbers reported
* by stat.
*/
int
proc_fill_cache
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
,
bool
proc_fill_cache
(
struct
file
*
file
,
struct
dir_context
*
ctx
,
const
char
*
name
,
int
len
,
instantiate_t
instantiate
,
struct
task_struct
*
task
,
const
void
*
ptr
)
{
struct
dentry
*
child
,
*
dir
=
fil
p
->
f_path
.
dentry
;
struct
dentry
*
child
,
*
dir
=
fil
e
->
f_path
.
dentry
;
struct
inode
*
inode
;
struct
qstr
qname
;
ino_t
ino
=
0
;
...
...
@@ -1720,7 +1720,7 @@ int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
ino
=
find_inode_number
(
dir
,
&
qname
);
if
(
!
ino
)
ino
=
1
;
return
filldir
(
dirent
,
name
,
len
,
filp
->
f_pos
,
ino
,
type
);
return
dir_emit
(
ctx
,
name
,
len
,
ino
,
type
);
}
#ifdef CONFIG_CHECKPOINT_RESTORE
...
...
@@ -1931,14 +1931,15 @@ static const struct inode_operations proc_map_files_inode_operations = {
};
static
int
proc_map_files_readdir
(
struct
file
*
fil
p
,
void
*
dirent
,
filldir_t
filldir
)
proc_map_files_readdir
(
struct
file
*
fil
e
,
struct
dir_context
*
ctx
)
{
struct
dentry
*
dentry
=
filp
->
f_path
.
dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
vm_area_struct
*
vma
;
struct
task_struct
*
task
;
struct
mm_struct
*
mm
;
ino_t
ino
;
unsigned
long
nr_files
,
pos
,
i
;
struct
flex_array
*
fa
=
NULL
;
struct
map_files_info
info
;
struct
map_files_info
*
p
;
int
ret
;
ret
=
-
EPERM
;
...
...
@@ -1946,7 +1947,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto
out
;
ret
=
-
ENOENT
;
task
=
get_proc_task
(
inode
);
task
=
get_proc_task
(
file_inode
(
file
)
);
if
(
!
task
)
goto
out
;
...
...
@@ -1955,23 +1956,8 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
goto
out_put_task
;
ret
=
0
;
switch
(
filp
->
f_pos
)
{
case
0
:
ino
=
inode
->
i_ino
;
if
(
filldir
(
dirent
,
"."
,
1
,
0
,
ino
,
DT_DIR
)
<
0
)
if
(
!
dir_emit_dots
(
file
,
ctx
))
goto
out_put_task
;
filp
->
f_pos
++
;
case
1
:
ino
=
parent_ino
(
dentry
);
if
(
filldir
(
dirent
,
".."
,
2
,
1
,
ino
,
DT_DIR
)
<
0
)
goto
out_put_task
;
filp
->
f_pos
++
;
default:
{
unsigned
long
nr_files
,
pos
,
i
;
struct
flex_array
*
fa
=
NULL
;
struct
map_files_info
info
;
struct
map_files_info
*
p
;
mm
=
get_task_mm
(
task
);
if
(
!
mm
)
...
...
@@ -1991,7 +1977,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
*/
for
(
vma
=
mm
->
mmap
,
pos
=
2
;
vma
;
vma
=
vma
->
vm_next
)
{
if
(
vma
->
vm_file
&&
++
pos
>
filp
->
f_
pos
)
if
(
vma
->
vm_file
&&
++
pos
>
ctx
->
pos
)
nr_files
++
;
}
...
...
@@ -2011,7 +1997,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
vma
=
vma
->
vm_next
)
{
if
(
!
vma
->
vm_file
)
continue
;
if
(
++
pos
<=
filp
->
f_
pos
)
if
(
++
pos
<=
ctx
->
pos
)
continue
;
info
.
mode
=
vma
->
vm_file
->
f_mode
;
...
...
@@ -2026,20 +2012,17 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
for
(
i
=
0
;
i
<
nr_files
;
i
++
)
{
p
=
flex_array_get
(
fa
,
i
);
ret
=
proc_fill_cache
(
filp
,
dirent
,
filldir
,
if
(
!
proc_fill_cache
(
file
,
ctx
,
p
->
name
,
p
->
len
,
proc_map_files_instantiate
,
task
,
(
void
*
)(
unsigned
long
)
p
->
mode
);
if
(
ret
)
(
void
*
)(
unsigned
long
)
p
->
mode
))
break
;
filp
->
f_
pos
++
;
ctx
->
pos
++
;
}
if
(
fa
)
flex_array_free
(
fa
);
mmput
(
mm
);
}
}
out_put_task:
put_task_struct
(
task
);
...
...
@@ -2049,7 +2032,7 @@ proc_map_files_readdir(struct file *filp, void *dirent, filldir_t filldir)
static
const
struct
file_operations
proc_map_files_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_map_files_readdir
,
.
iterate
=
proc_map_files_readdir
,
.
llseek
=
default_llseek
,
};
...
...
@@ -2217,67 +2200,30 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
return
error
;
}
static
int
proc_pident_fill_cache
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
,
struct
task_struct
*
task
,
const
struct
pid_entry
*
p
)
{
return
proc_fill_cache
(
filp
,
dirent
,
filldir
,
p
->
name
,
p
->
len
,
proc_pident_instantiate
,
task
,
p
);
}
static
int
proc_pident_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
,
static
int
proc_pident_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
,
const
struct
pid_entry
*
ents
,
unsigned
int
nents
)
{
int
i
;
struct
dentry
*
dentry
=
filp
->
f_path
.
dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
task_struct
*
task
=
get_proc_task
(
inode
);
const
struct
pid_entry
*
p
,
*
last
;
ino_t
ino
;
int
ret
;
struct
task_struct
*
task
=
get_proc_task
(
file_inode
(
file
));
const
struct
pid_entry
*
p
;
ret
=
-
ENOENT
;
if
(
!
task
)
goto
out_no_task
;
return
-
ENOENT
;
ret
=
0
;
i
=
filp
->
f_pos
;
switch
(
i
)
{
case
0
:
ino
=
inode
->
i_ino
;
if
(
filldir
(
dirent
,
"."
,
1
,
i
,
ino
,
DT_DIR
)
<
0
)
goto
out
;
i
++
;
filp
->
f_pos
++
;
/* fall through */
case
1
:
ino
=
parent_ino
(
dentry
);
if
(
filldir
(
dirent
,
".."
,
2
,
i
,
ino
,
DT_DIR
)
<
0
)
if
(
!
dir_emit_dots
(
file
,
ctx
))
goto
out
;
i
++
;
filp
->
f_pos
++
;
/* fall through */
default:
i
-=
2
;
if
(
i
>=
nents
)
{
ret
=
1
;
goto
out
;
}
p
=
ents
+
i
;
last
=
&
ents
[
nents
-
1
];
while
(
p
<=
last
)
{
if
(
proc_pident_fill_cache
(
filp
,
dirent
,
filldir
,
task
,
p
)
<
0
)
if
(
ctx
->
pos
>=
nents
+
2
)
goto
out
;
filp
->
f_pos
++
;
p
++
;
}
}
ret
=
1
;
for
(
p
=
ents
+
(
ctx
->
pos
-
2
);
p
<=
ents
+
nents
-
1
;
p
++
)
{
if
(
!
proc_fill_cache
(
file
,
ctx
,
p
->
name
,
p
->
len
,
proc_pident_instantiate
,
task
,
p
))
break
;
ctx
->
pos
++
;
}
out:
put_task_struct
(
task
);
out_no_task:
return
ret
;
return
0
;
}
#ifdef CONFIG_SECURITY
...
...
@@ -2362,16 +2308,15 @@ static const struct pid_entry attr_dir_stuff[] = {
REG
(
"sockcreate"
,
S_IRUGO
|
S_IWUGO
,
proc_pid_attr_operations
),
};
static
int
proc_attr_dir_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
static
int
proc_attr_dir_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
return
proc_pident_readdir
(
fil
p
,
dirent
,
filldir
,
attr_dir_stuff
,
ARRAY_SIZE
(
attr_dir_stuff
));
return
proc_pident_readdir
(
fil
e
,
ctx
,
attr_dir_stuff
,
ARRAY_SIZE
(
attr_dir_stuff
));
}
static
const
struct
file_operations
proc_attr_dir_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_attr_dir_readdir
,
.
iterate
=
proc_attr_dir_readdir
,
.
llseek
=
default_llseek
,
};
...
...
@@ -2725,16 +2670,15 @@ static const struct pid_entry tgid_base_stuff[] = {
#endif
};
static
int
proc_tgid_base_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
static
int
proc_tgid_base_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
return
proc_pident_readdir
(
fil
p
,
dirent
,
filldir
,
tgid_base_stuff
,
ARRAY_SIZE
(
tgid_base_stuff
));
return
proc_pident_readdir
(
fil
e
,
ctx
,
tgid_base_stuff
,
ARRAY_SIZE
(
tgid_base_stuff
));
}
static
const
struct
file_operations
proc_tgid_base_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_tgid_base_readdir
,
.
iterate
=
proc_tgid_base_readdir
,
.
llseek
=
default_llseek
,
};
...
...
@@ -2936,58 +2880,42 @@ static struct tgid_iter next_tgid(struct pid_namespace *ns, struct tgid_iter ite
#define TGID_OFFSET (FIRST_PROCESS_ENTRY + 1)
static
int
proc_pid_fill_cache
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
,
struct
tgid_iter
iter
)
{
char
name
[
PROC_NUMBUF
];
int
len
=
snprintf
(
name
,
sizeof
(
name
),
"%d"
,
iter
.
tgid
);
return
proc_fill_cache
(
filp
,
dirent
,
filldir
,
name
,
len
,
proc_pid_instantiate
,
iter
.
task
,
NULL
);
}
static
int
fake_filldir
(
void
*
buf
,
const
char
*
name
,
int
namelen
,
loff_t
offset
,
u64
ino
,
unsigned
d_type
)
{
return
0
;
}
/* for the /proc/ directory itself, after non-process stuff has been done */
int
proc_pid_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
int
proc_pid_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
struct
tgid_iter
iter
;
struct
pid_namespace
*
ns
;
filldir_t
__filldir
;
loff_t
pos
=
filp
->
f_pos
;
loff_t
pos
=
ctx
->
pos
;
if
(
pos
>=
PID_MAX_LIMIT
+
TGID_OFFSET
)
goto
out
;
return
0
;
if
(
pos
==
TGID_OFFSET
-
1
)
{
if
(
proc_fill_cache
(
filp
,
dirent
,
filldir
,
"self"
,
4
,
NULL
,
NULL
,
NULL
)
<
0
)
goto
out
;
if
(
!
proc_fill_cache
(
file
,
ctx
,
"self"
,
4
,
NULL
,
NULL
,
NULL
))
return
0
;
iter
.
tgid
=
0
;
}
else
{
iter
.
tgid
=
pos
-
TGID_OFFSET
;
}
iter
.
task
=
NULL
;
ns
=
fil
p
->
f_dentry
->
d_sb
->
s_fs_info
;
ns
=
fil
e
->
f_dentry
->
d_sb
->
s_fs_info
;
for
(
iter
=
next_tgid
(
ns
,
iter
);
iter
.
task
;
iter
.
tgid
+=
1
,
iter
=
next_tgid
(
ns
,
iter
))
{
if
(
has_pid_permissions
(
ns
,
iter
.
task
,
2
))
__filldir
=
filldir
;
else
__filldir
=
fake_filldir
;
char
name
[
PROC_NUMBUF
];
int
len
;
if
(
!
has_pid_permissions
(
ns
,
iter
.
task
,
2
))
continue
;
filp
->
f_pos
=
iter
.
tgid
+
TGID_OFFSET
;
if
(
proc_pid_fill_cache
(
filp
,
dirent
,
__filldir
,
iter
)
<
0
)
{
len
=
snprintf
(
name
,
sizeof
(
name
),
"%d"
,
iter
.
tgid
);
ctx
->
pos
=
iter
.
tgid
+
TGID_OFFSET
;
if
(
!
proc_fill_cache
(
file
,
ctx
,
name
,
len
,
proc_pid_instantiate
,
iter
.
task
,
NULL
))
{
put_task_struct
(
iter
.
task
);
goto
out
;
return
0
;
}
}
filp
->
f_pos
=
PID_MAX_LIMIT
+
TGID_OFFSET
;
out:
ctx
->
pos
=
PID_MAX_LIMIT
+
TGID_OFFSET
;
return
0
;
}
...
...
@@ -3075,11 +3003,10 @@ static const struct pid_entry tid_base_stuff[] = {
#endif
};
static
int
proc_tid_base_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
static
int
proc_tid_base_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
return
proc_pident_readdir
(
fil
p
,
dirent
,
filldir
,
tid_base_stuff
,
ARRAY_SIZE
(
tid_base_stuff
));
return
proc_pident_readdir
(
fil
e
,
ctx
,
tid_base_stuff
,
ARRAY_SIZE
(
tid_base_stuff
));
}
static
struct
dentry
*
proc_tid_base_lookup
(
struct
inode
*
dir
,
struct
dentry
*
dentry
,
unsigned
int
flags
)
...
...
@@ -3090,7 +3017,7 @@ static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *den
static
const
struct
file_operations
proc_tid_base_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_tid_base_readdir
,
.
iterate
=
proc_tid_base_readdir
,
.
llseek
=
default_llseek
,
};
...
...
@@ -3231,30 +3158,16 @@ static struct task_struct *next_tid(struct task_struct *start)
return
pos
;
}
static
int
proc_task_fill_cache
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
,
struct
task_struct
*
task
,
int
tid
)
{
char
name
[
PROC_NUMBUF
];
int
len
=
snprintf
(
name
,
sizeof
(
name
),
"%d"
,
tid
);
return
proc_fill_cache
(
filp
,
dirent
,
filldir
,
name
,
len
,
proc_task_instantiate
,
task
,
NULL
);
}
/* for the /proc/TGID/task/ directories */
static
int
proc_task_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
static
int
proc_task_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
struct
dentry
*
dentry
=
filp
->
f_path
.
dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
task_struct
*
leader
=
NULL
;
struct
task_struct
*
task
;
int
retval
=
-
ENOENT
;
ino_t
ino
;
int
tid
;
struct
task_struct
*
task
=
get_proc_task
(
file_inode
(
file
));
struct
pid_namespace
*
ns
;
int
tid
;
task
=
get_proc_task
(
inode
);
if
(
!
task
)
goto
out_no_task
;
return
-
ENOENT
;
rcu_read_lock
();
if
(
pid_alive
(
task
))
{
leader
=
task
->
group_leader
;
...
...
@@ -3263,46 +3176,36 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
rcu_read_unlock
();
put_task_struct
(
task
);
if
(
!
leader
)
goto
out_no_task
;
retval
=
0
;
return
-
ENOENT
;
switch
((
unsigned
long
)
filp
->
f_pos
)
{
case
0
:
ino
=
inode
->
i_ino
;
if
(
filldir
(
dirent
,
"."
,
1
,
filp
->
f_pos
,
ino
,
DT_DIR
)
<
0
)
goto
out
;
filp
->
f_pos
++
;
/* fall through */
case
1
:
ino
=
parent_ino
(
dentry
);
if
(
filldir
(
dirent
,
".."
,
2
,
filp
->
f_pos
,
ino
,
DT_DIR
)
<
0
)
if
(
!
dir_emit_dots
(
file
,
ctx
))
goto
out
;
filp
->
f_pos
++
;
/* fall through */
}
/* f_version caches the tgid value that the last readdir call couldn't
* return. lseek aka telldir automagically resets f_version to 0.
*/
ns
=
fil
p
->
f_dentry
->
d_sb
->
s_fs_info
;
tid
=
(
int
)
fil
p
->
f_version
;
fil
p
->
f_version
=
0
;
for
(
task
=
first_tid
(
leader
,
tid
,
filp
->
f_
pos
-
2
,
ns
);
ns
=
fil
e
->
f_dentry
->
d_sb
->
s_fs_info
;
tid
=
(
int
)
fil
e
->
f_version
;
fil
e
->
f_version
=
0
;
for
(
task
=
first_tid
(
leader
,
tid
,
ctx
->
pos
-
2
,
ns
);
task
;
task
=
next_tid
(
task
),
filp
->
f_pos
++
)
{
task
=
next_tid
(
task
),
ctx
->
pos
++
)
{
char
name
[
PROC_NUMBUF
];
int
len
;
tid
=
task_pid_nr_ns
(
task
,
ns
);
if
(
proc_task_fill_cache
(
filp
,
dirent
,
filldir
,
task
,
tid
)
<
0
)
{
len
=
snprintf
(
name
,
sizeof
(
name
),
"%d"
,
tid
);
if
(
!
proc_fill_cache
(
file
,
ctx
,
name
,
len
,
proc_task_instantiate
,
task
,
NULL
))
{
/* returning this tgid failed, save it as the first
* pid for the next readir call */
fil
p
->
f_version
=
(
u64
)
tid
;
fil
e
->
f_version
=
(
u64
)
tid
;
put_task_struct
(
task
);
break
;
}
}
out:
put_task_struct
(
leader
);
out_no_task:
return
retval
;
return
0
;
}
static
int
proc_task_getattr
(
struct
vfsmount
*
mnt
,
struct
dentry
*
dentry
,
struct
kstat
*
stat
)
...
...
@@ -3328,6 +3231,6 @@ static const struct inode_operations proc_task_inode_operations = {
static
const
struct
file_operations
proc_task_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_task_readdir
,
.
iterate
=
proc_task_readdir
,
.
llseek
=
default_llseek
,
};
fs/proc/fd.c
View file @
f0c3b509
...
...
@@ -219,74 +219,58 @@ static struct dentry *proc_lookupfd_common(struct inode *dir,
return
result
;
}
static
int
proc_readfd_common
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
,
instantiate_t
instantiate
)
static
int
proc_readfd_common
(
struct
file
*
file
,
struct
dir_context
*
ctx
,
instantiate_t
instantiate
)
{
struct
dentry
*
dentry
=
filp
->
f_path
.
dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
task_struct
*
p
=
get_proc_task
(
inode
);
struct
task_struct
*
p
=
get_proc_task
(
file_inode
(
file
));
struct
files_struct
*
files
;
unsigned
int
fd
,
ino
;
int
retval
;
unsigned
int
fd
;
retval
=
-
ENOENT
;
if
(
!
p
)
goto
out_no_task
;
retval
=
0
;
return
-
ENOENT
;
fd
=
filp
->
f_pos
;
switch
(
fd
)
{
case
0
:
if
(
filldir
(
dirent
,
"."
,
1
,
0
,
inode
->
i_ino
,
DT_DIR
)
<
0
)
if
(
!
dir_emit_dots
(
file
,
ctx
))
goto
out
;
filp
->
f_pos
++
;
case
1
:
ino
=
parent_ino
(
dentry
);
if
(
filldir
(
dirent
,
".."
,
2
,
1
,
ino
,
DT_DIR
)
<
0
)
if
(
!
dir_emit_dots
(
file
,
ctx
))
goto
out
;
filp
->
f_pos
++
;
default:
files
=
get_files_struct
(
p
);
if
(
!
files
)
goto
out
;
rcu_read_lock
();
for
(
fd
=
filp
->
f_
pos
-
2
;
for
(
fd
=
ctx
->
pos
-
2
;
fd
<
files_fdtable
(
files
)
->
max_fds
;
fd
++
,
filp
->
f_
pos
++
)
{
fd
++
,
ctx
->
pos
++
)
{
char
name
[
PROC_NUMBUF
];
int
len
;
int
rv
;
if
(
!
fcheck_files
(
files
,
fd
))
continue
;
rcu_read_unlock
();
len
=
snprintf
(
name
,
sizeof
(
name
),
"%d"
,
fd
);
rv
=
proc_fill_cache
(
filp
,
dirent
,
filldir
,
if
(
!
proc_fill_cache
(
file
,
ctx
,
name
,
len
,
instantiate
,
p
,
(
void
*
)(
unsigned
long
)
fd
);
if
(
rv
<
0
)
(
void
*
)(
unsigned
long
)
fd
))
goto
out_fd_loop
;
rcu_read_lock
();
}
rcu_read_unlock
();
out_fd_loop:
put_files_struct
(
files
);
}
out:
put_task_struct
(
p
);
out_no_task:
return
retval
;
return
0
;
}
static
int
proc_readfd
(
struct
file
*
fil
p
,
void
*
dirent
,
filldir_t
filldir
)
static
int
proc_readfd
(
struct
file
*
fil
e
,
struct
dir_context
*
ctx
)
{
return
proc_readfd_common
(
fil
p
,
dirent
,
filldir
,
proc_fd_instantiate
);
return
proc_readfd_common
(
fil
e
,
ctx
,
proc_fd_instantiate
);
}
const
struct
file_operations
proc_fd_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_readfd
,
.
iterate
=
proc_readfd
,
.
llseek
=
default_llseek
,
};
...
...
@@ -351,9 +335,9 @@ proc_lookupfdinfo(struct inode *dir, struct dentry *dentry, unsigned int flags)
return
proc_lookupfd_common
(
dir
,
dentry
,
proc_fdinfo_instantiate
);
}
static
int
proc_readfdinfo
(
struct
file
*
fil
p
,
void
*
dirent
,
filldir_t
filldir
)
static
int
proc_readfdinfo
(
struct
file
*
fil
e
,
struct
dir_context
*
ctx
)
{
return
proc_readfd_common
(
fil
p
,
dirent
,
filldir
,
return
proc_readfd_common
(
fil
e
,
ctx
,
proc_fdinfo_instantiate
);
}
...
...
@@ -364,6 +348,6 @@ const struct inode_operations proc_fdinfo_inode_operations = {
const
struct
file_operations
proc_fdinfo_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_readfdinfo
,
.
iterate
=
proc_readfdinfo
,
.
llseek
=
default_llseek
,
};
fs/proc/generic.c
View file @
f0c3b509
...
...
@@ -233,40 +233,21 @@ struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
* value of the readdir() call, as long as it's non-negative
* for success..
*/
int
proc_readdir_de
(
struct
proc_dir_entry
*
de
,
struct
file
*
fil
p
,
void
*
dirent
,
filldir_t
filldir
)
int
proc_readdir_de
(
struct
proc_dir_entry
*
de
,
struct
file
*
fil
e
,
struct
dir_context
*
ctx
)
{
unsigned
int
ino
;
int
i
;
struct
inode
*
inode
=
file_inode
(
filp
);
int
ret
=
0
;
ino
=
inode
->
i_ino
;
i
=
filp
->
f_pos
;
switch
(
i
)
{
case
0
:
if
(
filldir
(
dirent
,
"."
,
1
,
i
,
ino
,
DT_DIR
)
<
0
)
goto
out
;
i
++
;
filp
->
f_pos
++
;
/* fall through */
case
1
:
if
(
filldir
(
dirent
,
".."
,
2
,
i
,
parent_ino
(
filp
->
f_path
.
dentry
),
DT_DIR
)
<
0
)
goto
out
;
i
++
;
filp
->
f_pos
++
;
/* fall through */
default:
if
(
!
dir_emit_dots
(
file
,
ctx
))
return
0
;
spin_lock
(
&
proc_subdir_lock
);
de
=
de
->
subdir
;
i
-=
2
;
i
=
ctx
->
pos
-
2
;
for
(;;)
{
if
(
!
de
)
{
ret
=
1
;
spin_unlock
(
&
proc_subdir_lock
);
goto
out
;
return
0
;
}
if
(
!
i
)
break
;
...
...
@@ -276,33 +257,28 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
do
{
struct
proc_dir_entry
*
next
;
/* filldir passes info to user space */
pde_get
(
de
);
spin_unlock
(
&
proc_subdir_lock
);
if
(
filldir
(
dirent
,
de
->
name
,
de
->
namelen
,
filp
->
f_pos
,
de
->
low_ino
,
de
->
mode
>>
12
)
<
0
)
{
if
(
!
dir_emit
(
ctx
,
de
->
name
,
de
->
namelen
,
de
->
low_ino
,
de
->
mode
>>
12
)
)
{
pde_put
(
de
);
goto
out
;
return
0
;
}
spin_lock
(
&
proc_subdir_lock
);
filp
->
f_
pos
++
;
ctx
->
pos
++
;
next
=
de
->
next
;
pde_put
(
de
);
de
=
next
;
}
while
(
de
);
spin_unlock
(
&
proc_subdir_lock
);
}
ret
=
1
;
out:
return
ret
;
return
0
;
}
int
proc_readdir
(
struct
file
*
fil
p
,
void
*
dirent
,
filldir_t
filldir
)
int
proc_readdir
(
struct
file
*
fil
e
,
struct
dir_context
*
ctx
)
{
struct
inode
*
inode
=
file_inode
(
fil
p
);
struct
inode
*
inode
=
file_inode
(
fil
e
);
return
proc_readdir_de
(
PDE
(
inode
),
fil
p
,
dirent
,
filldir
);
return
proc_readdir_de
(
PDE
(
inode
),
fil
e
,
ctx
);
}
/*
...
...
@@ -313,7 +289,7 @@ int proc_readdir(struct file *filp, void *dirent, filldir_t filldir)
static
const
struct
file_operations
proc_dir_operations
=
{
.
llseek
=
generic_file_llseek
,
.
read
=
generic_read_dir
,
.
readdir
=
proc_readdir
,
.
iterate
=
proc_readdir
,
};
/*
...
...
fs/proc/internal.h
View file @
f0c3b509
...
...
@@ -165,14 +165,14 @@ extern int proc_setattr(struct dentry *, struct iattr *);
extern
struct
inode
*
proc_pid_make_inode
(
struct
super_block
*
,
struct
task_struct
*
);
extern
int
pid_revalidate
(
struct
dentry
*
,
unsigned
int
);
extern
int
pid_delete_dentry
(
const
struct
dentry
*
);
extern
int
proc_pid_readdir
(
struct
file
*
,
void
*
,
filldir_t
);
extern
int
proc_pid_readdir
(
struct
file
*
,
struct
dir_context
*
);
extern
struct
dentry
*
proc_pid_lookup
(
struct
inode
*
,
struct
dentry
*
,
unsigned
int
);
extern
loff_t
mem_lseek
(
struct
file
*
,
loff_t
,
int
);
/* Lookups */
typedef
struct
dentry
*
instantiate_t
(
struct
inode
*
,
struct
dentry
*
,
struct
task_struct
*
,
const
void
*
);
extern
int
proc_fill_cache
(
struct
file
*
,
void
*
,
filldir_t
,
const
char
*
,
int
,
extern
bool
proc_fill_cache
(
struct
file
*
,
struct
dir_context
*
,
const
char
*
,
int
,
instantiate_t
,
struct
task_struct
*
,
const
void
*
);
/*
...
...
@@ -183,8 +183,8 @@ extern spinlock_t proc_subdir_lock;
extern
struct
dentry
*
proc_lookup
(
struct
inode
*
,
struct
dentry
*
,
unsigned
int
);
extern
struct
dentry
*
proc_lookup_de
(
struct
proc_dir_entry
*
,
struct
inode
*
,
struct
dentry
*
);
extern
int
proc_readdir
(
struct
file
*
,
void
*
,
filldir_t
);
extern
int
proc_readdir_de
(
struct
proc_dir_entry
*
,
struct
file
*
,
void
*
,
filldir_t
);
extern
int
proc_readdir
(
struct
file
*
,
struct
dir_context
*
);
extern
int
proc_readdir_de
(
struct
proc_dir_entry
*
,
struct
file
*
,
struct
dir_context
*
);
static
inline
struct
proc_dir_entry
*
pde_get
(
struct
proc_dir_entry
*
pde
)
{
...
...
fs/proc/namespaces.c
View file @
f0c3b509
...
...
@@ -213,74 +213,36 @@ static struct dentry *proc_ns_instantiate(struct inode *dir,
return
error
;
}
static
int
proc_ns_fill_cache
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
,
struct
task_struct
*
task
,
const
struct
proc_ns_operations
*
ops
)
static
int
proc_ns_dir_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
return
proc_fill_cache
(
filp
,
dirent
,
filldir
,
ops
->
name
,
strlen
(
ops
->
name
),
proc_ns_instantiate
,
task
,
ops
);
}
static
int
proc_ns_dir_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
{
int
i
;
struct
dentry
*
dentry
=
filp
->
f_path
.
dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
task_struct
*
task
=
get_proc_task
(
inode
);
struct
task_struct
*
task
=
get_proc_task
(
file_inode
(
file
));
const
struct
proc_ns_operations
**
entry
,
**
last
;
ino_t
ino
;
int
ret
;
ret
=
-
ENOENT
;
if
(
!
task
)
goto
out_no_task
;
return
-
ENOENT
;
ret
=
0
;
i
=
filp
->
f_pos
;
switch
(
i
)
{
case
0
:
ino
=
inode
->
i_ino
;
if
(
filldir
(
dirent
,
"."
,
1
,
i
,
ino
,
DT_DIR
)
<
0
)
goto
out
;
i
++
;
filp
->
f_pos
++
;
/* fall through */
case
1
:
ino
=
parent_ino
(
dentry
);
if
(
filldir
(
dirent
,
".."
,
2
,
i
,
ino
,
DT_DIR
)
<
0
)
if
(
!
dir_emit_dots
(
file
,
ctx
))
goto
out
;
i
++
;
filp
->
f_pos
++
;
/* fall through */
default:
i
-=
2
;
if
(
i
>=
ARRAY_SIZE
(
ns_entries
))
{
ret
=
1
;
if
(
ctx
->
pos
>=
2
+
ARRAY_SIZE
(
ns_entries
))
goto
out
;
}
entry
=
ns_entries
+
i
;
entry
=
ns_entries
+
(
ctx
->
pos
-
2
);
last
=
&
ns_entries
[
ARRAY_SIZE
(
ns_entries
)
-
1
];
while
(
entry
<=
last
)
{
if
(
proc_ns_fill_cache
(
filp
,
dirent
,
filldir
,
task
,
*
entry
)
<
0
)
goto
out
;
filp
->
f_pos
++
;
const
struct
proc_ns_operations
*
ops
=
*
entry
;
if
(
!
proc_fill_cache
(
file
,
ctx
,
ops
->
name
,
strlen
(
ops
->
name
),
proc_ns_instantiate
,
task
,
ops
))
break
;
ctx
->
pos
++
;
entry
++
;
}
}
ret
=
1
;
out:
put_task_struct
(
task
);
out_no_task:
return
ret
;
return
0
;
}
const
struct
file_operations
proc_ns_dir_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_ns_dir_readdir
,
.
iterate
=
proc_ns_dir_readdir
,
};
static
struct
dentry
*
proc_ns_dir_lookup
(
struct
inode
*
dir
,
...
...
fs/proc/proc_net.c
View file @
f0c3b509
...
...
@@ -160,16 +160,15 @@ const struct inode_operations proc_net_inode_operations = {
.
getattr
=
proc_tgid_net_getattr
,
};
static
int
proc_tgid_net_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
static
int
proc_tgid_net_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
int
ret
;
struct
net
*
net
;
ret
=
-
EINVAL
;
net
=
get_proc_task_net
(
file_inode
(
fil
p
));
net
=
get_proc_task_net
(
file_inode
(
fil
e
));
if
(
net
!=
NULL
)
{
ret
=
proc_readdir_de
(
net
->
proc_net
,
fil
p
,
dirent
,
filldir
);
ret
=
proc_readdir_de
(
net
->
proc_net
,
fil
e
,
ctx
);
put_net
(
net
);
}
return
ret
;
...
...
@@ -178,7 +177,7 @@ static int proc_tgid_net_readdir(struct file *filp, void *dirent,
const
struct
file_operations
proc_net_operations
=
{
.
llseek
=
generic_file_llseek
,
.
read
=
generic_read_dir
,
.
readdir
=
proc_tgid_net_readdir
,
.
iterate
=
proc_tgid_net_readdir
,
};
static
__net_init
int
proc_net_ns_init
(
struct
net
*
net
)
...
...
fs/proc/proc_sysctl.c
View file @
f0c3b509
...
...
@@ -573,12 +573,12 @@ static unsigned int proc_sys_poll(struct file *filp, poll_table *wait)
return
ret
;
}
static
int
proc_sys_fill_cache
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
,
static
bool
proc_sys_fill_cache
(
struct
file
*
file
,
struct
dir_context
*
ctx
,
struct
ctl_table_header
*
head
,
struct
ctl_table
*
table
)
{
struct
dentry
*
child
,
*
dir
=
fil
p
->
f_path
.
dentry
;
struct
dentry
*
child
,
*
dir
=
fil
e
->
f_path
.
dentry
;
struct
inode
*
inode
;
struct
qstr
qname
;
ino_t
ino
=
0
;
...
...
@@ -595,38 +595,38 @@ static int proc_sys_fill_cache(struct file *filp, void *dirent,
inode
=
proc_sys_make_inode
(
dir
->
d_sb
,
head
,
table
);
if
(
!
inode
)
{
dput
(
child
);
return
-
ENOMEM
;
return
false
;
}
else
{
d_set_d_op
(
child
,
&
proc_sys_dentry_operations
);
d_add
(
child
,
inode
);
}
}
else
{
return
-
ENOMEM
;
return
false
;
}
}
inode
=
child
->
d_inode
;
ino
=
inode
->
i_ino
;
type
=
inode
->
i_mode
>>
12
;
dput
(
child
);
return
!!
filldir
(
dirent
,
qname
.
name
,
qname
.
len
,
filp
->
f_pos
,
ino
,
type
);
return
dir_emit
(
ctx
,
qname
.
name
,
qname
.
len
,
ino
,
type
);
}
static
int
proc_sys_link_fill_cache
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
,
static
bool
proc_sys_link_fill_cache
(
struct
file
*
file
,
struct
dir_context
*
ctx
,
struct
ctl_table_header
*
head
,
struct
ctl_table
*
table
)
{
int
err
,
ret
=
0
;
bool
ret
=
true
;
head
=
sysctl_head_grab
(
head
);
if
(
S_ISLNK
(
table
->
mode
))
{
/* It is not an error if we can not follow the link ignore it */
err
=
sysctl_follow_link
(
&
head
,
&
table
,
current
->
nsproxy
);
int
err
=
sysctl_follow_link
(
&
head
,
&
table
,
current
->
nsproxy
);
if
(
err
)
goto
out
;
}
ret
=
proc_sys_fill_cache
(
fil
p
,
dirent
,
filldir
,
head
,
table
);
ret
=
proc_sys_fill_cache
(
fil
e
,
ctx
,
head
,
table
);
out:
sysctl_head_finish
(
head
);
return
ret
;
...
...
@@ -634,67 +634,50 @@ static int proc_sys_link_fill_cache(struct file *filp, void *dirent,
static
int
scan
(
struct
ctl_table_header
*
head
,
ctl_table
*
table
,
unsigned
long
*
pos
,
struct
file
*
file
,
void
*
dirent
,
filldir_t
filldir
)
struct
dir_context
*
ctx
)
{
int
res
;
bool
res
;
if
((
*
pos
)
++
<
file
->
f_
pos
)
return
0
;
if
((
*
pos
)
++
<
ctx
->
pos
)
return
true
;
if
(
unlikely
(
S_ISLNK
(
table
->
mode
)))
res
=
proc_sys_link_fill_cache
(
file
,
dirent
,
filldir
,
head
,
table
);
res
=
proc_sys_link_fill_cache
(
file
,
ctx
,
head
,
table
);
else
res
=
proc_sys_fill_cache
(
file
,
dirent
,
filldir
,
head
,
table
);
res
=
proc_sys_fill_cache
(
file
,
ctx
,
head
,
table
);
if
(
res
==
0
)
file
->
f_
pos
=
*
pos
;
if
(
res
)
ctx
->
pos
=
*
pos
;
return
res
;
}
static
int
proc_sys_readdir
(
struct
file
*
fil
p
,
void
*
dirent
,
filldir_t
filldir
)
static
int
proc_sys_readdir
(
struct
file
*
fil
e
,
struct
dir_context
*
ctx
)
{
struct
dentry
*
dentry
=
filp
->
f_path
.
dentry
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
ctl_table_header
*
head
=
grab_header
(
inode
);
struct
ctl_table_header
*
head
=
grab_header
(
file_inode
(
file
));
struct
ctl_table_header
*
h
=
NULL
;
struct
ctl_table
*
entry
;
struct
ctl_dir
*
ctl_dir
;
unsigned
long
pos
;
int
ret
=
-
EINVAL
;
if
(
IS_ERR
(
head
))
return
PTR_ERR
(
head
);
ctl_dir
=
container_of
(
head
,
struct
ctl_dir
,
header
);
ret
=
0
;
/* Avoid a switch here: arm builds fail with missing __cmpdi2 */
if
(
filp
->
f_pos
==
0
)
{
if
(
filldir
(
dirent
,
"."
,
1
,
filp
->
f_pos
,
inode
->
i_ino
,
DT_DIR
)
<
0
)
goto
out
;
filp
->
f_pos
++
;
}
if
(
filp
->
f_pos
==
1
)
{
if
(
filldir
(
dirent
,
".."
,
2
,
filp
->
f_pos
,
parent_ino
(
dentry
),
DT_DIR
)
<
0
)
goto
out
;
filp
->
f_pos
++
;
}
if
(
!
dir_emit_dots
(
file
,
ctx
))
return
0
;
pos
=
2
;
for
(
first_entry
(
ctl_dir
,
&
h
,
&
entry
);
h
;
next_entry
(
&
h
,
&
entry
))
{
ret
=
scan
(
h
,
entry
,
&
pos
,
filp
,
dirent
,
filldir
);
if
(
ret
)
{
if
(
!
scan
(
h
,
entry
,
&
pos
,
file
,
ctx
))
{
sysctl_head_finish
(
h
);
break
;
}
}
ret
=
1
;
out:
sysctl_head_finish
(
head
);
return
ret
;
return
0
;
}
static
int
proc_sys_permission
(
struct
inode
*
inode
,
int
mask
)
...
...
@@ -769,7 +752,7 @@ static const struct file_operations proc_sys_file_operations = {
static
const
struct
file_operations
proc_sys_dir_file_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_sys_readdir
,
.
iterate
=
proc_sys_readdir
,
.
llseek
=
generic_file_llseek
,
};
...
...
fs/proc/root.c
View file @
f0c3b509
...
...
@@ -202,21 +202,14 @@ static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentr
return
proc_pid_lookup
(
dir
,
dentry
,
flags
);
}
static
int
proc_root_readdir
(
struct
file
*
filp
,
void
*
dirent
,
filldir_t
filldir
)
static
int
proc_root_readdir
(
struct
file
*
file
,
struct
dir_context
*
ctx
)
{
unsigned
int
nr
=
filp
->
f_pos
;
int
ret
;
if
(
nr
<
FIRST_PROCESS_ENTRY
)
{
int
error
=
proc_readdir
(
filp
,
dirent
,
filldir
);
if
(
error
<=
0
)
return
error
;
filp
->
f_pos
=
FIRST_PROCESS_ENTRY
;
if
(
ctx
->
pos
<
FIRST_PROCESS_ENTRY
)
{
proc_readdir
(
file
,
ctx
);
ctx
->
pos
=
FIRST_PROCESS_ENTRY
;
}
ret
=
proc_pid_readdir
(
filp
,
dirent
,
filldir
);
return
ret
;
return
proc_pid_readdir
(
file
,
ctx
);
}
/*
...
...
@@ -226,7 +219,7 @@ static int proc_root_readdir(struct file * filp,
*/
static
const
struct
file_operations
proc_root_operations
=
{
.
read
=
generic_read_dir
,
.
readdir
=
proc_root_readdir
,
.
iterate
=
proc_root_readdir
,
.
llseek
=
default_llseek
,
};
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment