Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Guillaume Tucker
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
Hide 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
,
.
dentry
=
file
->
f_path
.
dentry
});
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,91 +1956,73 @@ 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
)
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
)
goto
out_put_task
;
down_read
(
&
mm
->
mmap_sem
);
if
(
!
dir_emit_dots
(
file
,
ctx
))
goto
out_put_task
;
nr_files
=
0
;
mm
=
get_task_mm
(
task
);
if
(
!
mm
)
goto
out_put_task
;
down_read
(
&
mm
->
mmap_sem
);
/*
* We need two passes here:
*
* 1) Collect vmas of mapped files with mmap_sem taken
* 2) Release mmap_sem and instantiate entries
*
* otherwise we get lockdep complained, since filldir()
* routine might require mmap_sem taken in might_fault().
*/
nr_files
=
0
;
for
(
vma
=
mm
->
mmap
,
pos
=
2
;
vma
;
vma
=
vma
->
vm_next
)
{
if
(
vma
->
vm_file
&&
++
pos
>
filp
->
f_pos
)
nr_files
++
;
}
/*
* We need two passes here:
*
* 1) Collect vmas of mapped files with mmap_sem taken
* 2) Release mmap_sem and instantiate entries
*
* otherwise we get lockdep complained, since filldir()
* routine might require mmap_sem taken in might_fault().
*/
if
(
nr_files
)
{
fa
=
flex_array_alloc
(
sizeof
(
info
),
nr_files
,
GFP_KERNEL
);
if
(
!
fa
||
flex_array_prealloc
(
fa
,
0
,
nr_files
,
GFP_KERNEL
))
{
ret
=
-
ENOMEM
;
if
(
fa
)
flex_array_free
(
fa
);
up_read
(
&
mm
->
mmap_sem
);
mmput
(
mm
);
goto
out_put_task
;
}
for
(
i
=
0
,
vma
=
mm
->
mmap
,
pos
=
2
;
vma
;
vma
=
vma
->
vm_next
)
{
if
(
!
vma
->
vm_file
)
continue
;
if
(
++
pos
<=
filp
->
f_pos
)
continue
;
info
.
mode
=
vma
->
vm_file
->
f_mode
;
info
.
len
=
snprintf
(
info
.
name
,
sizeof
(
info
.
name
),
"%lx-%lx"
,
vma
->
vm_start
,
vma
->
vm_end
);
if
(
flex_array_put
(
fa
,
i
++
,
&
info
,
GFP_KERNEL
))
BUG
();
}
for
(
vma
=
mm
->
mmap
,
pos
=
2
;
vma
;
vma
=
vma
->
vm_next
)
{
if
(
vma
->
vm_file
&&
++
pos
>
ctx
->
pos
)
nr_files
++
;
}
if
(
nr_files
)
{
fa
=
flex_array_alloc
(
sizeof
(
info
),
nr_files
,
GFP_KERNEL
);
if
(
!
fa
||
flex_array_prealloc
(
fa
,
0
,
nr_files
,
GFP_KERNEL
))
{
ret
=
-
ENOMEM
;
if
(
fa
)
flex_array_free
(
fa
);
up_read
(
&
mm
->
mmap_sem
);
mmput
(
mm
);
goto
out_put_task
;
}
up_read
(
&
mm
->
mmap_sem
);
for
(
i
=
0
;
i
<
nr_files
;
i
++
)
{
p
=
flex_array_get
(
fa
,
i
);
ret
=
proc_fill_cache
(
filp
,
dirent
,
filldir
,
p
->
name
,
p
->
len
,
proc_map_files_instantiate
,
task
,
(
void
*
)(
unsigned
long
)
p
->
mode
);
if
(
ret
)
break
;
filp
->
f_pos
++
;
for
(
i
=
0
,
vma
=
mm
->
mmap
,
pos
=
2
;
vma
;
vma
=
vma
->
vm_next
)
{
if
(
!
vma
->
vm_file
)
continue
;
if
(
++
pos
<=
ctx
->
pos
)
continue
;
info
.
mode
=
vma
->
vm_file
->
f_mode
;
info
.
len
=
snprintf
(
info
.
name
,
sizeof
(
info
.
name
),
"%lx-%lx"
,
vma
->
vm_start
,
vma
->
vm_end
);
if
(
flex_array_put
(
fa
,
i
++
,
&
info
,
GFP_KERNEL
))
BUG
();
}
if
(
fa
)
flex_array_free
(
fa
);
mmput
(
mm
);
}
up_read
(
&
mm
->
mmap_sem
);
for
(
i
=
0
;
i
<
nr_files
;
i
++
)
{
p
=
flex_array_get
(
fa
,
i
);
if
(
!
proc_fill_cache
(
file
,
ctx
,
p
->
name
,
p
->
len
,
proc_map_files_instantiate
,
task
,
(
void
*
)(
unsigned
long
)
p
->
mode
))
break
;
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
)
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
)
goto
out
;
filp
->
f_pos
++
;
p
++
;
}
}
if
(
!
dir_emit_dots
(
file
,
ctx
))
goto
out
;
if
(
ctx
->
pos
>=
nents
+
2
)
goto
out
;
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
)
goto
out
;
filp
->
f_pos
++
;
/* fall through */
}
if
(
!
dir_emit_dots
(
file
,
ctx
))
goto
out
;
/* 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
;