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
Kirill Smelkov
linux
Commits
eeab5fdc
Commit
eeab5fdc
authored
Nov 14, 2002
by
Davide Libenzi
Committed by
Jens Axboe
Nov 14, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] epoll bit 0.47
- Improved file cleanup code
parent
424980a8
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
52 additions
and
43 deletions
+52
-43
fs/eventpoll.c
fs/eventpoll.c
+39
-43
fs/file_table.c
fs/file_table.c
+6
-0
include/linux/eventpoll.h
include/linux/eventpoll.h
+3
-0
include/linux/fs.h
include/linux/fs.h
+4
-0
No files found.
fs/eventpoll.c
View file @
eeab5fdc
...
@@ -124,9 +124,6 @@
...
@@ -124,9 +124,6 @@
* interface.
* interface.
*/
*/
struct
eventpoll
{
struct
eventpoll
{
/* Used to link to the "struct eventpoll" list ( eplist ) */
struct
list_head
llink
;
/* Protect the this structure access */
/* Protect the this structure access */
rwlock_t
lock
;
rwlock_t
lock
;
...
@@ -192,6 +189,9 @@ struct epitem {
...
@@ -192,6 +189,9 @@ struct epitem {
* that the structure will desappear from underneath our processing.
* that the structure will desappear from underneath our processing.
*/
*/
atomic_t
usecnt
;
atomic_t
usecnt
;
/* List header used to link this item to the "struct file" items list */
struct
list_head
fllink
;
};
};
/* Wrapper struct used by poll queueing */
/* Wrapper struct used by poll queueing */
...
@@ -235,20 +235,13 @@ static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
...
@@ -235,20 +235,13 @@ static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
int
flags
,
char
*
dev_name
,
void
*
data
);
int
flags
,
char
*
dev_name
,
void
*
data
);
/*
* Use to link togheter all the "struct eventpoll". We need to link
* all the available eventpoll structures to be able to perform proper
* cleanup in case a file that is stored inside epoll is closed without
* previously being removed.
*/
static
struct
list_head
eplist
;
/*
/*
* Serialize the access to "eplist" and also to ep_notify_file_close().
* This semaphore is used to ensure that files are not removed
* It is read-held when we want to be sure that a given file will not
* while epoll is using them. Namely the f_op->poll(), since
* vanish while we're doing f_op->poll(). When "ep->lock" is taken,
* it has to be called from outside the lock, must be protected.
* it will nest inside this semaphore.
* This is read-held during the event transfer loop to userspace
* and it is write-held during the file cleanup path and the epoll
* exit code.
*/
*/
struct
rw_semaphore
epsem
;
struct
rw_semaphore
epsem
;
...
@@ -294,6 +287,15 @@ static unsigned int ep_get_hash_bits(unsigned int hintsize)
...
@@ -294,6 +287,15 @@ static unsigned int ep_get_hash_bits(unsigned int hintsize)
}
}
/* Used to initialize the epoll bits inside the "struct file" */
void
ep_init_file_struct
(
struct
file
*
file
)
{
INIT_LIST_HEAD
(
&
file
->
f_ep_links
);
spin_lock_init
(
&
file
->
f_ep_lock
);
}
/*
/*
* This is called from inside fs/file_table.c:__fput() to unlink files
* This is called from inside fs/file_table.c:__fput() to unlink files
* from the eventpoll interface. We need to have this facility to cleanup
* from the eventpoll interface. We need to have this facility to cleanup
...
@@ -302,22 +304,16 @@ static unsigned int ep_get_hash_bits(unsigned int hintsize)
...
@@ -302,22 +304,16 @@ static unsigned int ep_get_hash_bits(unsigned int hintsize)
*/
*/
void
ep_notify_file_close
(
struct
file
*
file
)
void
ep_notify_file_close
(
struct
file
*
file
)
{
{
struct
list_head
*
lnk
;
struct
list_head
*
lsthead
=
&
file
->
f_ep_links
;
struct
eventpoll
*
ep
;
struct
epitem
*
dpi
;
struct
epitem
*
dpi
;
down_write
(
&
epsem
);
down_write
(
&
epsem
);
list_for_each
(
lnk
,
&
eplist
)
{
while
(
!
list_empty
(
lsthead
)
)
{
ep
=
list_entry
(
lnk
,
struct
eventpoll
,
llink
);
dpi
=
list_entry
(
lsthead
->
next
,
struct
epitem
,
f
llink
);
/*
EP_LIST_DEL
(
&
dpi
->
fllink
);
* The ep_find() function increases the "struct epitem" usage count
* so we have to do an ep_remove() + ep_release_epitem().
ep_remove
(
dpi
->
ep
,
dpi
);
*/
while
((
dpi
=
ep_find
(
ep
,
file
)))
{
ep_remove
(
ep
,
dpi
);
ep_release_epitem
(
dpi
);
}
}
}
up_write
(
&
epsem
);
up_write
(
&
epsem
);
}
}
...
@@ -653,11 +649,6 @@ static int ep_file_init(struct file *file, unsigned int hashbits)
...
@@ -653,11 +649,6 @@ static int ep_file_init(struct file *file, unsigned int hashbits)
file
->
private_data
=
ep
;
file
->
private_data
=
ep
;
/* Add the structure to the linked list that links "struct eventpoll" */
down_write
(
&
epsem
);
list_add
(
&
ep
->
llink
,
&
eplist
);
up_write
(
&
epsem
);
DNPRINTK
(
3
,
(
KERN_INFO
"[%p] eventpoll: ep_file_init() ep=%p
\n
"
,
DNPRINTK
(
3
,
(
KERN_INFO
"[%p] eventpoll: ep_file_init() ep=%p
\n
"
,
current
,
ep
));
current
,
ep
));
return
0
;
return
0
;
...
@@ -690,7 +681,6 @@ static int ep_init(struct eventpoll *ep, unsigned int hashbits)
...
@@ -690,7 +681,6 @@ static int ep_init(struct eventpoll *ep, unsigned int hashbits)
int
error
;
int
error
;
unsigned
int
i
,
hsize
;
unsigned
int
i
,
hsize
;
INIT_LIST_HEAD
(
&
ep
->
llink
);
rwlock_init
(
&
ep
->
lock
);
rwlock_init
(
&
ep
->
lock
);
init_waitqueue_head
(
&
ep
->
wq
);
init_waitqueue_head
(
&
ep
->
wq
);
init_waitqueue_head
(
&
ep
->
poll_wait
);
init_waitqueue_head
(
&
ep
->
poll_wait
);
...
@@ -739,8 +729,9 @@ static void ep_free(struct eventpoll *ep)
...
@@ -739,8 +729,9 @@ static void ep_free(struct eventpoll *ep)
/*
/*
* Walks through the whole hash by freeing each "struct epitem". At this
* Walks through the whole hash by freeing each "struct epitem". At this
* point we are sure no poll callbacks will be lingering around, so we can
* point we are sure no poll callbacks will be lingering around, and also by
* avoid the lock on "ep->lock".
* write-holding "epsem" we can be sure that no file cleanup code will hit
* us during this operation. So we can avoid the lock on "ep->lock".
*/
*/
for
(
i
=
0
,
hsize
=
1
<<
ep
->
hashbits
;
i
<
hsize
;
i
++
)
{
for
(
i
=
0
,
hsize
=
1
<<
ep
->
hashbits
;
i
<
hsize
;
i
++
)
{
lsthead
=
ep_hash_entry
(
ep
,
i
);
lsthead
=
ep_hash_entry
(
ep
,
i
);
...
@@ -752,9 +743,6 @@ static void ep_free(struct eventpoll *ep)
...
@@ -752,9 +743,6 @@ static void ep_free(struct eventpoll *ep)
}
}
}
}
/* Remove the structure to the linked list that links "struct eventpoll" */
EP_LIST_DEL
(
&
ep
->
llink
);
up_write
(
&
epsem
);
up_write
(
&
epsem
);
/* Free hash pages */
/* Free hash pages */
...
@@ -850,6 +838,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
...
@@ -850,6 +838,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
/* Item initialization follow here ... */
/* Item initialization follow here ... */
INIT_LIST_HEAD
(
&
dpi
->
llink
);
INIT_LIST_HEAD
(
&
dpi
->
llink
);
INIT_LIST_HEAD
(
&
dpi
->
rdllink
);
INIT_LIST_HEAD
(
&
dpi
->
rdllink
);
INIT_LIST_HEAD
(
&
dpi
->
fllink
);
dpi
->
ep
=
ep
;
dpi
->
ep
=
ep
;
dpi
->
file
=
tfile
;
dpi
->
file
=
tfile
;
dpi
->
pfd
=
*
pfd
;
dpi
->
pfd
=
*
pfd
;
...
@@ -893,6 +882,11 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
...
@@ -893,6 +882,11 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
write_unlock_irqrestore
(
&
ep
->
lock
,
flags
);
write_unlock_irqrestore
(
&
ep
->
lock
,
flags
);
/* Add the current item to the list of active epoll hook for this file */
spin_lock
(
&
tfile
->
f_ep_lock
);
list_add_tail
(
&
dpi
->
fllink
,
&
tfile
->
f_ep_links
);
spin_unlock
(
&
tfile
->
f_ep_lock
);
DNPRINTK
(
3
,
(
KERN_INFO
"[%p] eventpoll: ep_insert(%p, %d)
\n
"
,
DNPRINTK
(
3
,
(
KERN_INFO
"[%p] eventpoll: ep_insert(%p, %d)
\n
"
,
current
,
ep
,
pfd
->
fd
));
current
,
ep
,
pfd
->
fd
));
...
@@ -1023,6 +1017,12 @@ static int ep_remove(struct eventpoll *ep, struct epitem *dpi)
...
@@ -1023,6 +1017,12 @@ static int ep_remove(struct eventpoll *ep, struct epitem *dpi)
*/
*/
ep_unregister_pollwait
(
ep
,
dpi
);
ep_unregister_pollwait
(
ep
,
dpi
);
/* Remove the current item from the list of epoll hooks */
spin_lock
(
&
dpi
->
file
->
f_ep_lock
);
if
(
EP_IS_LINKED
(
&
dpi
->
fllink
))
EP_LIST_DEL
(
&
dpi
->
fllink
);
spin_unlock
(
&
dpi
->
file
->
f_ep_lock
);
/* We need to acquire the write IRQ lock before calling ep_unlink() */
/* We need to acquire the write IRQ lock before calling ep_unlink() */
write_lock_irqsave
(
&
ep
->
lock
,
flags
);
write_lock_irqsave
(
&
ep
->
lock
,
flags
);
...
@@ -1369,10 +1369,6 @@ static int __init eventpoll_init(void)
...
@@ -1369,10 +1369,6 @@ static int __init eventpoll_init(void)
{
{
int
error
;
int
error
;
/* Initialize the list that will link "struct eventpoll" */
INIT_LIST_HEAD
(
&
eplist
);
/* Initialize the rwsem used to access "eplist" */
init_rwsem
(
&
epsem
);
init_rwsem
(
&
epsem
);
/* Allocates slab cache used to allocate "struct epitem" items */
/* Allocates slab cache used to allocate "struct epitem" items */
...
...
fs/file_table.c
View file @
eeab5fdc
...
@@ -50,6 +50,7 @@ struct file * get_empty_filp(void)
...
@@ -50,6 +50,7 @@ struct file * get_empty_filp(void)
file_list_unlock
();
file_list_unlock
();
return
NULL
;
return
NULL
;
}
}
ep_init_file_struct
(
f
);
atomic_set
(
&
f
->
f_count
,
1
);
atomic_set
(
&
f
->
f_count
,
1
);
f
->
f_version
=
0
;
f
->
f_version
=
0
;
f
->
f_uid
=
current
->
fsuid
;
f
->
f_uid
=
current
->
fsuid
;
...
@@ -94,6 +95,7 @@ struct file * get_empty_filp(void)
...
@@ -94,6 +95,7 @@ struct file * get_empty_filp(void)
int
init_private_file
(
struct
file
*
filp
,
struct
dentry
*
dentry
,
int
mode
)
int
init_private_file
(
struct
file
*
filp
,
struct
dentry
*
dentry
,
int
mode
)
{
{
memset
(
filp
,
0
,
sizeof
(
*
filp
));
memset
(
filp
,
0
,
sizeof
(
*
filp
));
ep_init_file_struct
(
filp
);
filp
->
f_mode
=
mode
;
filp
->
f_mode
=
mode
;
atomic_set
(
&
filp
->
f_count
,
1
);
atomic_set
(
&
filp
->
f_count
,
1
);
filp
->
f_dentry
=
dentry
;
filp
->
f_dentry
=
dentry
;
...
@@ -121,6 +123,10 @@ void __fput(struct file * file)
...
@@ -121,6 +123,10 @@ void __fput(struct file * file)
struct
vfsmount
*
mnt
=
file
->
f_vfsmnt
;
struct
vfsmount
*
mnt
=
file
->
f_vfsmnt
;
struct
inode
*
inode
=
dentry
->
d_inode
;
struct
inode
*
inode
=
dentry
->
d_inode
;
/*
* The function ep_notify_file_close() should be the first called
* in the file cleanup chain.
*/
ep_notify_file_close
(
file
);
ep_notify_file_close
(
file
);
locks_remove_flock
(
file
);
locks_remove_flock
(
file
);
...
...
include/linux/eventpoll.h
View file @
eeab5fdc
...
@@ -34,6 +34,9 @@ asmlinkage int sys_epoll_ctl(int epfd, int op, int fd, unsigned int events);
...
@@ -34,6 +34,9 @@ asmlinkage int sys_epoll_ctl(int epfd, int op, int fd, unsigned int events);
asmlinkage
int
sys_epoll_wait
(
int
epfd
,
struct
pollfd
*
events
,
int
maxevents
,
asmlinkage
int
sys_epoll_wait
(
int
epfd
,
struct
pollfd
*
events
,
int
maxevents
,
int
timeout
);
int
timeout
);
/* Used to initialize the epoll bits inside the "struct file" */
void
ep_init_file_struct
(
struct
file
*
file
);
/* Used in fs/file_table.c:__fput() to unlink files from the eventpoll interface */
/* Used in fs/file_table.c:__fput() to unlink files from the eventpoll interface */
void
ep_notify_file_close
(
struct
file
*
file
);
void
ep_notify_file_close
(
struct
file
*
file
);
...
...
include/linux/fs.h
View file @
eeab5fdc
...
@@ -506,6 +506,10 @@ struct file {
...
@@ -506,6 +506,10 @@ struct file {
/* needed for tty driver, and maybe others */
/* needed for tty driver, and maybe others */
void
*
private_data
;
void
*
private_data
;
/* Used by fs/eventpoll.c to link all the hooks to this file */
struct
list_head
f_ep_links
;
spinlock_t
f_ep_lock
;
};
};
extern
spinlock_t
files_lock
;
extern
spinlock_t
files_lock
;
#define file_list_lock() spin_lock(&files_lock);
#define file_list_lock() spin_lock(&files_lock);
...
...
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