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
05c0ae21
Commit
05c0ae21
authored
Apr 04, 2013
by
Al Viro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
try a saner locking for pde_opener...
Signed-off-by:
Al Viro
<
viro@zeniv.linux.org.uk
>
parent
ca469f35
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
24 additions
and
44 deletions
+24
-44
fs/proc/inode.c
fs/proc/inode.c
+21
-41
fs/proc/internal.h
fs/proc/internal.h
+2
-2
include/linux/proc_fs.h
include/linux/proc_fs.h
+1
-1
No files found.
fs/proc/inode.c
View file @
05c0ae21
...
...
@@ -133,67 +133,48 @@ enum {BIAS = -1U<<31};
static
inline
int
use_pde
(
struct
proc_dir_entry
*
pde
)
{
int
res
=
1
;
spin_lock
(
&
pde
->
pde_unload_lock
);
if
(
unlikely
(
pde
->
pde_users
<
0
))
res
=
0
;
else
pde
->
pde_users
++
;
spin_unlock
(
&
pde
->
pde_unload_lock
);
return
res
;
}
static
void
__pde_users_dec
(
struct
proc_dir_entry
*
pde
)
{
if
(
--
pde
->
pde_users
==
BIAS
)
complete
(
pde
->
pde_unload_completion
);
return
atomic_inc_unless_negative
(
&
pde
->
in_use
);
}
static
void
unuse_pde
(
struct
proc_dir_entry
*
pde
)
{
spin_lock
(
&
pde
->
pde_unload_lock
);
__pde_users_dec
(
pde
);
spin_unlock
(
&
pde
->
pde_unload_lock
);
if
(
atomic_dec_return
(
&
pde
->
in_use
)
==
BIAS
)
complete
(
pde
->
pde_unload_completion
);
}
/* pde is locked */
static
void
close_pdeo
(
struct
proc_dir_entry
*
pde
,
struct
pde_opener
*
pdeo
)
{
pdeo
->
count
++
;
if
(
!
mutex_trylock
(
&
pdeo
->
mutex
))
{
if
(
pdeo
->
closing
)
{
/* somebody else is doing that, just wait */
DECLARE_COMPLETION_ONSTACK
(
c
);
pdeo
->
c
=
&
c
;
spin_unlock
(
&
pde
->
pde_unload_lock
);
mutex_lock
(
&
pdeo
->
mutex
);
wait_for_completion
(
&
c
);
spin_lock
(
&
pde
->
pde_unload_lock
);
WARN_ON
(
!
list_empty
(
&
pdeo
->
lh
));
}
else
{
struct
file
*
file
;
pdeo
->
closing
=
1
;
spin_unlock
(
&
pde
->
pde_unload_lock
);
file
=
pdeo
->
file
;
pde
->
proc_fops
->
release
(
file_inode
(
file
),
file
);
spin_lock
(
&
pde
->
pde_unload_lock
);
list_del_init
(
&
pdeo
->
lh
);
}
mutex_unlock
(
&
pdeo
->
mutex
);
if
(
!--
pdeo
->
count
)
if
(
pdeo
->
c
)
complete
(
pdeo
->
c
);
kfree
(
pdeo
);
}
}
void
proc_entry_rundown
(
struct
proc_dir_entry
*
de
)
{
spin_lock
(
&
de
->
pde_unload_lock
);
de
->
pde_users
+=
BIAS
;
/* Wait until all existing callers into module are done. */
if
(
de
->
pde_users
!=
BIAS
)
{
DECLARE_COMPLETION_ONSTACK
(
c
);
/* Wait until all existing callers into module are done. */
de
->
pde_unload_completion
=
&
c
;
spin_unlock
(
&
de
->
pde_unload_lock
);
wait_for_completion
(
de
->
pde_unload_completion
);
if
(
atomic_add_return
(
BIAS
,
&
de
->
in_use
)
!=
BIAS
)
wait_for_completion
(
&
c
);
spin_lock
(
&
de
->
pde_unload_lock
);
}
while
(
!
list_empty
(
&
de
->
pde_openers
))
{
struct
pde_opener
*
pdeo
;
pdeo
=
list_first_entry
(
&
de
->
pde_openers
,
struct
pde_opener
,
lh
);
...
...
@@ -356,7 +337,7 @@ static int proc_reg_open(struct inode *inode, struct file *file)
* by hand in remove_proc_entry(). For this, save opener's credentials
* for later.
*/
pdeo
=
k
m
alloc
(
sizeof
(
struct
pde_opener
),
GFP_KERNEL
);
pdeo
=
k
z
alloc
(
sizeof
(
struct
pde_opener
),
GFP_KERNEL
);
if
(
!
pdeo
)
return
-
ENOMEM
;
...
...
@@ -370,18 +351,17 @@ static int proc_reg_open(struct inode *inode, struct file *file)
if
(
open
)
rv
=
open
(
inode
,
file
);
spin_lock
(
&
pde
->
pde_unload_lock
);
if
(
rv
==
0
&&
release
)
{
/* To know what to release. */
mutex_init
(
&
pdeo
->
mutex
);
pdeo
->
count
=
0
;
pdeo
->
file
=
file
;
/* Strictly for "too late" ->release in proc_reg_release(). */
spin_lock
(
&
pde
->
pde_unload_lock
);
list_add
(
&
pdeo
->
lh
,
&
pde
->
pde_openers
);
spin_unlock
(
&
pde
->
pde_unload_lock
);
}
else
kfree
(
pdeo
);
__pde_users_dec
(
pde
);
spin_unlock
(
&
pde
->
pde_unload_lock
);
unuse_pde
(
pde
);
return
rv
;
}
...
...
fs/proc/internal.h
View file @
05c0ae21
...
...
@@ -153,8 +153,8 @@ int proc_readdir_de(struct proc_dir_entry *de, struct file *filp, void *dirent,
struct
pde_opener
{
struct
file
*
file
;
struct
list_head
lh
;
int
c
ount
;
/* number of threads in close_pdeo() */
struct
mutex
mutex
;
int
c
losing
;
struct
completion
*
c
;
};
ssize_t
__proc_file_read
(
struct
file
*
,
char
__user
*
,
size_t
,
loff_t
*
);
...
...
include/linux/proc_fs.h
View file @
05c0ae21
...
...
@@ -65,7 +65,7 @@ struct proc_dir_entry {
void
*
data
;
read_proc_t
*
read_proc
;
atomic_t
count
;
/* use count */
int
pde_users
;
/* number of callers into module in progress; */
atomic_t
in_use
;
/* number of callers into module in progress; */
/* negative -> it's going away RSN */
struct
completion
*
pde_unload_completion
;
struct
list_head
pde_openers
;
/* who did ->open, but not ->release */
...
...
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