diff options
author | Davide Libenzi <davidel@xmailserver.org> | 2007-05-11 01:23:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-05-11 11:29:37 -0400 |
commit | da66f7cb0f69ab27dbf5b9d0b85c4b97716c44d1 (patch) | |
tree | 3d2dc033eb92d18f8b2debe2fd472d6f3a7b6b9f /fs | |
parent | 9c3060bedd84144653a2ad7bea32389f65598d40 (diff) |
epoll: use anonymous inodes
Cut out lots of code from epoll, by reusing the anonymous inode source
patch (fs/anon_inodes.c).
Signed-off-by: Davide Libenzi <davidel@xmailserver.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/eventpoll.c | 172 |
1 files changed, 3 insertions, 169 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index b5c7ca584939..2831c8f9f3e3 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/mount.h> | 34 | #include <linux/mount.h> |
35 | #include <linux/bitops.h> | 35 | #include <linux/bitops.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/anon_inodes.h> | ||
37 | #include <asm/uaccess.h> | 38 | #include <asm/uaccess.h> |
38 | #include <asm/system.h> | 39 | #include <asm/system.h> |
39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
@@ -75,8 +76,6 @@ | |||
75 | */ | 76 | */ |
76 | 77 | ||
77 | 78 | ||
78 | #define EVENTPOLLFS_MAGIC 0x03111965 /* My birthday should work for this :) */ | ||
79 | |||
80 | #define DEBUG_EPOLL 0 | 79 | #define DEBUG_EPOLL 0 |
81 | 80 | ||
82 | #if DEBUG_EPOLL > 0 | 81 | #if DEBUG_EPOLL > 0 |
@@ -228,8 +227,6 @@ struct ep_pqueue { | |||
228 | 227 | ||
229 | static void ep_poll_safewake_init(struct poll_safewake *psw); | 228 | static void ep_poll_safewake_init(struct poll_safewake *psw); |
230 | static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq); | 229 | static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq); |
231 | static int ep_getfd(int *efd, struct inode **einode, struct file **efile, | ||
232 | struct eventpoll *ep); | ||
233 | static int ep_alloc(struct eventpoll **pep); | 230 | static int ep_alloc(struct eventpoll **pep); |
234 | static void ep_free(struct eventpoll *ep); | 231 | static void ep_free(struct eventpoll *ep); |
235 | static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd); | 232 | static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd); |
@@ -255,11 +252,6 @@ static int ep_events_transfer(struct eventpoll *ep, | |||
255 | int maxevents); | 252 | int maxevents); |
256 | static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, | 253 | static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, |
257 | int maxevents, long timeout); | 254 | int maxevents, long timeout); |
258 | static int eventpollfs_delete_dentry(struct dentry *dentry); | ||
259 | static struct inode *ep_eventpoll_inode(void); | ||
260 | static int eventpollfs_get_sb(struct file_system_type *fs_type, | ||
261 | int flags, const char *dev_name, | ||
262 | void *data, struct vfsmount *mnt); | ||
263 | 255 | ||
264 | /* | 256 | /* |
265 | * This semaphore is used to serialize ep_free() and eventpoll_release_file(). | 257 | * This semaphore is used to serialize ep_free() and eventpoll_release_file(). |
@@ -275,30 +267,12 @@ static struct kmem_cache *epi_cache __read_mostly; | |||
275 | /* Slab cache used to allocate "struct eppoll_entry" */ | 267 | /* Slab cache used to allocate "struct eppoll_entry" */ |
276 | static struct kmem_cache *pwq_cache __read_mostly; | 268 | static struct kmem_cache *pwq_cache __read_mostly; |
277 | 269 | ||
278 | /* Virtual fs used to allocate inodes for eventpoll files */ | ||
279 | static struct vfsmount *eventpoll_mnt __read_mostly; | ||
280 | |||
281 | /* File callbacks that implement the eventpoll file behaviour */ | 270 | /* File callbacks that implement the eventpoll file behaviour */ |
282 | static const struct file_operations eventpoll_fops = { | 271 | static const struct file_operations eventpoll_fops = { |
283 | .release = ep_eventpoll_close, | 272 | .release = ep_eventpoll_close, |
284 | .poll = ep_eventpoll_poll | 273 | .poll = ep_eventpoll_poll |
285 | }; | 274 | }; |
286 | 275 | ||
287 | /* | ||
288 | * This is used to register the virtual file system from where | ||
289 | * eventpoll inodes are allocated. | ||
290 | */ | ||
291 | static struct file_system_type eventpoll_fs_type = { | ||
292 | .name = "eventpollfs", | ||
293 | .get_sb = eventpollfs_get_sb, | ||
294 | .kill_sb = kill_anon_super, | ||
295 | }; | ||
296 | |||
297 | /* Very basic directory entry operations for the eventpoll virtual file system */ | ||
298 | static struct dentry_operations eventpollfs_dentry_operations = { | ||
299 | .d_delete = eventpollfs_delete_dentry, | ||
300 | }; | ||
301 | |||
302 | 276 | ||
303 | 277 | ||
304 | /* Fast test to see if the file is an evenpoll file */ | 278 | /* Fast test to see if the file is an evenpoll file */ |
@@ -495,7 +469,8 @@ asmlinkage long sys_epoll_create(int size) | |||
495 | * Creates all the items needed to setup an eventpoll file. That is, | 469 | * Creates all the items needed to setup an eventpoll file. That is, |
496 | * a file structure, and inode and a free file descriptor. | 470 | * a file structure, and inode and a free file descriptor. |
497 | */ | 471 | */ |
498 | error = ep_getfd(&fd, &inode, &file, ep); | 472 | error = anon_inode_getfd(&fd, &inode, &file, "[eventpoll]", |
473 | &eventpoll_fops, ep); | ||
499 | if (error) | 474 | if (error) |
500 | goto eexit_2; | 475 | goto eexit_2; |
501 | 476 | ||
@@ -725,82 +700,6 @@ asmlinkage long sys_epoll_pwait(int epfd, struct epoll_event __user *events, | |||
725 | #endif /* #ifdef TIF_RESTORE_SIGMASK */ | 700 | #endif /* #ifdef TIF_RESTORE_SIGMASK */ |
726 | 701 | ||
727 | 702 | ||
728 | /* | ||
729 | * Creates the file descriptor to be used by the epoll interface. | ||
730 | */ | ||
731 | static int ep_getfd(int *efd, struct inode **einode, struct file **efile, | ||
732 | struct eventpoll *ep) | ||
733 | { | ||
734 | struct qstr this; | ||
735 | char name[32]; | ||
736 | struct dentry *dentry; | ||
737 | struct inode *inode; | ||
738 | struct file *file; | ||
739 | int error, fd; | ||
740 | |||
741 | /* Get an ready to use file */ | ||
742 | error = -ENFILE; | ||
743 | file = get_empty_filp(); | ||
744 | if (!file) | ||
745 | goto eexit_1; | ||
746 | |||
747 | /* Allocates an inode from the eventpoll file system */ | ||
748 | inode = ep_eventpoll_inode(); | ||
749 | if (IS_ERR(inode)) { | ||
750 | error = PTR_ERR(inode); | ||
751 | goto eexit_2; | ||
752 | } | ||
753 | |||
754 | /* Allocates a free descriptor to plug the file onto */ | ||
755 | error = get_unused_fd(); | ||
756 | if (error < 0) | ||
757 | goto eexit_3; | ||
758 | fd = error; | ||
759 | |||
760 | /* | ||
761 | * Link the inode to a directory entry by creating a unique name | ||
762 | * using the inode number. | ||
763 | */ | ||
764 | error = -ENOMEM; | ||
765 | sprintf(name, "[%lu]", inode->i_ino); | ||
766 | this.name = name; | ||
767 | this.len = strlen(name); | ||
768 | this.hash = inode->i_ino; | ||
769 | dentry = d_alloc(eventpoll_mnt->mnt_sb->s_root, &this); | ||
770 | if (!dentry) | ||
771 | goto eexit_4; | ||
772 | dentry->d_op = &eventpollfs_dentry_operations; | ||
773 | d_add(dentry, inode); | ||
774 | file->f_path.mnt = mntget(eventpoll_mnt); | ||
775 | file->f_path.dentry = dentry; | ||
776 | file->f_mapping = inode->i_mapping; | ||
777 | |||
778 | file->f_pos = 0; | ||
779 | file->f_flags = O_RDONLY; | ||
780 | file->f_op = &eventpoll_fops; | ||
781 | file->f_mode = FMODE_READ; | ||
782 | file->f_version = 0; | ||
783 | file->private_data = ep; | ||
784 | |||
785 | /* Install the new setup file into the allocated fd. */ | ||
786 | fd_install(fd, file); | ||
787 | |||
788 | *efd = fd; | ||
789 | *einode = inode; | ||
790 | *efile = file; | ||
791 | return 0; | ||
792 | |||
793 | eexit_4: | ||
794 | put_unused_fd(fd); | ||
795 | eexit_3: | ||
796 | iput(inode); | ||
797 | eexit_2: | ||
798 | put_filp(file); | ||
799 | eexit_1: | ||
800 | return error; | ||
801 | } | ||
802 | |||
803 | |||
804 | static int ep_alloc(struct eventpoll **pep) | 703 | static int ep_alloc(struct eventpoll **pep) |
805 | { | 704 | { |
806 | struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL); | 705 | struct eventpoll *ep = kzalloc(sizeof(*ep), GFP_KERNEL); |
@@ -1553,52 +1452,8 @@ retry: | |||
1553 | return res; | 1452 | return res; |
1554 | } | 1453 | } |
1555 | 1454 | ||
1556 | static int eventpollfs_delete_dentry(struct dentry *dentry) | ||
1557 | { | ||
1558 | |||
1559 | return 1; | ||
1560 | } | ||
1561 | |||
1562 | static struct inode *ep_eventpoll_inode(void) | ||
1563 | { | ||
1564 | int error = -ENOMEM; | ||
1565 | struct inode *inode = new_inode(eventpoll_mnt->mnt_sb); | ||
1566 | |||
1567 | if (!inode) | ||
1568 | goto eexit_1; | ||
1569 | |||
1570 | inode->i_fop = &eventpoll_fops; | ||
1571 | |||
1572 | /* | ||
1573 | * Mark the inode dirty from the very beginning, | ||
1574 | * that way it will never be moved to the dirty | ||
1575 | * list because mark_inode_dirty() will think | ||
1576 | * that it already _is_ on the dirty list. | ||
1577 | */ | ||
1578 | inode->i_state = I_DIRTY; | ||
1579 | inode->i_mode = S_IRUSR | S_IWUSR; | ||
1580 | inode->i_uid = current->fsuid; | ||
1581 | inode->i_gid = current->fsgid; | ||
1582 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
1583 | return inode; | ||
1584 | |||
1585 | eexit_1: | ||
1586 | return ERR_PTR(error); | ||
1587 | } | ||
1588 | |||
1589 | static int | ||
1590 | eventpollfs_get_sb(struct file_system_type *fs_type, int flags, | ||
1591 | const char *dev_name, void *data, struct vfsmount *mnt) | ||
1592 | { | ||
1593 | return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC, | ||
1594 | mnt); | ||
1595 | } | ||
1596 | |||
1597 | |||
1598 | static int __init eventpoll_init(void) | 1455 | static int __init eventpoll_init(void) |
1599 | { | 1456 | { |
1600 | int error; | ||
1601 | |||
1602 | mutex_init(&epmutex); | 1457 | mutex_init(&epmutex); |
1603 | 1458 | ||
1604 | /* Initialize the structure used to perform safe poll wait head wake ups */ | 1459 | /* Initialize the structure used to perform safe poll wait head wake ups */ |
@@ -1614,34 +1469,13 @@ static int __init eventpoll_init(void) | |||
1614 | sizeof(struct eppoll_entry), 0, | 1469 | sizeof(struct eppoll_entry), 0, |
1615 | EPI_SLAB_DEBUG|SLAB_PANIC, NULL, NULL); | 1470 | EPI_SLAB_DEBUG|SLAB_PANIC, NULL, NULL); |
1616 | 1471 | ||
1617 | /* | ||
1618 | * Register the virtual file system that will be the source of inodes | ||
1619 | * for the eventpoll files | ||
1620 | */ | ||
1621 | error = register_filesystem(&eventpoll_fs_type); | ||
1622 | if (error) | ||
1623 | goto epanic; | ||
1624 | |||
1625 | /* Mount the above commented virtual file system */ | ||
1626 | eventpoll_mnt = kern_mount(&eventpoll_fs_type); | ||
1627 | error = PTR_ERR(eventpoll_mnt); | ||
1628 | if (IS_ERR(eventpoll_mnt)) | ||
1629 | goto epanic; | ||
1630 | |||
1631 | DNPRINTK(3, (KERN_INFO "[%p] eventpoll: successfully initialized.\n", | ||
1632 | current)); | ||
1633 | return 0; | 1472 | return 0; |
1634 | |||
1635 | epanic: | ||
1636 | panic("eventpoll_init() failed\n"); | ||
1637 | } | 1473 | } |
1638 | 1474 | ||
1639 | 1475 | ||
1640 | static void __exit eventpoll_exit(void) | 1476 | static void __exit eventpoll_exit(void) |
1641 | { | 1477 | { |
1642 | /* Undo all operations done inside eventpoll_init() */ | 1478 | /* Undo all operations done inside eventpoll_init() */ |
1643 | unregister_filesystem(&eventpoll_fs_type); | ||
1644 | mntput(eventpoll_mnt); | ||
1645 | kmem_cache_destroy(pwq_cache); | 1479 | kmem_cache_destroy(pwq_cache); |
1646 | kmem_cache_destroy(epi_cache); | 1480 | kmem_cache_destroy(epi_cache); |
1647 | } | 1481 | } |