Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
L
Linux
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package Registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
E-EXK4 - Operating System Group
projects
Linux
Commits
05c0ae21
Commit
05c0ae21
authored
12 years ago
by
Al Viro
Browse files
Options
Downloads
Patches
Plain Diff
try a saner locking for pde_opener...
Signed-off-by:
Al Viro
<
viro@zeniv.linux.org.uk
>
parent
ca469f35
Loading
Loading
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
fs/proc/inode.c
+21
-41
21 additions, 41 deletions
fs/proc/inode.c
fs/proc/internal.h
+2
-2
2 additions, 2 deletions
fs/proc/internal.h
include/linux/proc_fs.h
+1
-1
1 addition, 1 deletion
include/linux/proc_fs.h
with
24 additions
and
44 deletions
fs/proc/inode.c
+
21
−
41
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
;
DECLARE_COMPLETION_ONSTACK
(
c
);
/* Wait until all existing callers into module are done. */
if
(
de
->
pde_users
!=
BIAS
)
{
DECLARE_COMPLETION_ONSTACK
(
c
);
de
->
pde_unload_completion
=
&
c
;
spin_unlock
(
&
de
->
pde_unload_lock
);
wait_for_completion
(
de
->
pde_unload_completion
);
spin_lock
(
&
de
->
pde_unload_lock
);
}
de
->
pde_unload_completion
=
&
c
;
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
;
}
...
...
This diff is collapsed.
Click to expand it.
fs/proc/internal.h
+
2
−
2
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
*
);
...
...
This diff is collapsed.
Click to expand it.
include/linux/proc_fs.h
+
1
−
1
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
_use
rs
;
/* 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 */
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment