summaryrefslogtreecommitdiffstats
path: root/fs/eventpoll.c
diff options
context:
space:
mode:
authorDavidlohr Bueso <dave@stgolabs.net>2017-09-08 19:15:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-09-08 21:26:49 -0400
commitb2ac2ea6296e7dd779168eb085b09d0fab9d1294 (patch)
tree8fefe90ed4da5ac94000fd160d42c5c39a225670 /fs/eventpoll.c
parent410bd5ecb276593e7ec1552014083215d4a43c3a (diff)
fs/epoll: use faster rb_first_cached()
... such that we can avoid the tree walks to get the node with the smallest key. Semantically the same, as the previously used rb_first(), but O(1). The main overhead is the extra footprint for the cached rb_node pointer, which should not matter for epoll. Link: http://lkml.kernel.org/r/20170719014603.19029-15-dave@stgolabs.net Signed-off-by: Davidlohr Bueso <dbueso@suse.de> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Jan Kara <jack@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/eventpoll.c')
-rw-r--r--fs/eventpoll.c30
1 files changed, 16 insertions, 14 deletions
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index adbe328b957c..2fabd19cdeea 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -205,7 +205,7 @@ struct eventpoll {
205 struct list_head rdllist; 205 struct list_head rdllist;
206 206
207 /* RB tree root used to store monitored fd structs */ 207 /* RB tree root used to store monitored fd structs */
208 struct rb_root rbr; 208 struct rb_root_cached rbr;
209 209
210 /* 210 /*
211 * This is a single linked list that chains all the "struct epitem" that 211 * This is a single linked list that chains all the "struct epitem" that
@@ -796,7 +796,7 @@ static int ep_remove(struct eventpoll *ep, struct epitem *epi)
796 list_del_rcu(&epi->fllink); 796 list_del_rcu(&epi->fllink);
797 spin_unlock(&file->f_lock); 797 spin_unlock(&file->f_lock);
798 798
799 rb_erase(&epi->rbn, &ep->rbr); 799 rb_erase_cached(&epi->rbn, &ep->rbr);
800 800
801 spin_lock_irqsave(&ep->lock, flags); 801 spin_lock_irqsave(&ep->lock, flags);
802 if (ep_is_linked(&epi->rdllink)) 802 if (ep_is_linked(&epi->rdllink))
@@ -840,7 +840,7 @@ static void ep_free(struct eventpoll *ep)
840 /* 840 /*
841 * Walks through the whole tree by unregistering poll callbacks. 841 * Walks through the whole tree by unregistering poll callbacks.
842 */ 842 */
843 for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { 843 for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = rb_next(rbp)) {
844 epi = rb_entry(rbp, struct epitem, rbn); 844 epi = rb_entry(rbp, struct epitem, rbn);
845 845
846 ep_unregister_pollwait(ep, epi); 846 ep_unregister_pollwait(ep, epi);
@@ -856,7 +856,7 @@ static void ep_free(struct eventpoll *ep)
856 * a lockdep warning. 856 * a lockdep warning.
857 */ 857 */
858 mutex_lock(&ep->mtx); 858 mutex_lock(&ep->mtx);
859 while ((rbp = rb_first(&ep->rbr)) != NULL) { 859 while ((rbp = rb_first_cached(&ep->rbr)) != NULL) {
860 epi = rb_entry(rbp, struct epitem, rbn); 860 epi = rb_entry(rbp, struct epitem, rbn);
861 ep_remove(ep, epi); 861 ep_remove(ep, epi);
862 cond_resched(); 862 cond_resched();
@@ -963,7 +963,7 @@ static void ep_show_fdinfo(struct seq_file *m, struct file *f)
963 struct rb_node *rbp; 963 struct rb_node *rbp;
964 964
965 mutex_lock(&ep->mtx); 965 mutex_lock(&ep->mtx);
966 for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { 966 for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = rb_next(rbp)) {
967 struct epitem *epi = rb_entry(rbp, struct epitem, rbn); 967 struct epitem *epi = rb_entry(rbp, struct epitem, rbn);
968 struct inode *inode = file_inode(epi->ffd.file); 968 struct inode *inode = file_inode(epi->ffd.file);
969 969
@@ -1040,7 +1040,7 @@ static int ep_alloc(struct eventpoll **pep)
1040 init_waitqueue_head(&ep->wq); 1040 init_waitqueue_head(&ep->wq);
1041 init_waitqueue_head(&ep->poll_wait); 1041 init_waitqueue_head(&ep->poll_wait);
1042 INIT_LIST_HEAD(&ep->rdllist); 1042 INIT_LIST_HEAD(&ep->rdllist);
1043 ep->rbr = RB_ROOT; 1043 ep->rbr = RB_ROOT_CACHED;
1044 ep->ovflist = EP_UNACTIVE_PTR; 1044 ep->ovflist = EP_UNACTIVE_PTR;
1045 ep->user = user; 1045 ep->user = user;
1046 1046
@@ -1066,7 +1066,7 @@ static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd)
1066 struct epoll_filefd ffd; 1066 struct epoll_filefd ffd;
1067 1067
1068 ep_set_ffd(&ffd, file, fd); 1068 ep_set_ffd(&ffd, file, fd);
1069 for (rbp = ep->rbr.rb_node; rbp; ) { 1069 for (rbp = ep->rbr.rb_root.rb_node; rbp; ) {
1070 epi = rb_entry(rbp, struct epitem, rbn); 1070 epi = rb_entry(rbp, struct epitem, rbn);
1071 kcmp = ep_cmp_ffd(&ffd, &epi->ffd); 1071 kcmp = ep_cmp_ffd(&ffd, &epi->ffd);
1072 if (kcmp > 0) 1072 if (kcmp > 0)
@@ -1088,7 +1088,7 @@ static struct epitem *ep_find_tfd(struct eventpoll *ep, int tfd, unsigned long t
1088 struct rb_node *rbp; 1088 struct rb_node *rbp;
1089 struct epitem *epi; 1089 struct epitem *epi;
1090 1090
1091 for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { 1091 for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = rb_next(rbp)) {
1092 epi = rb_entry(rbp, struct epitem, rbn); 1092 epi = rb_entry(rbp, struct epitem, rbn);
1093 if (epi->ffd.fd == tfd) { 1093 if (epi->ffd.fd == tfd) {
1094 if (toff == 0) 1094 if (toff == 0)
@@ -1273,20 +1273,22 @@ static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
1273static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi) 1273static void ep_rbtree_insert(struct eventpoll *ep, struct epitem *epi)
1274{ 1274{
1275 int kcmp; 1275 int kcmp;
1276 struct rb_node **p = &ep->rbr.rb_node, *parent = NULL; 1276 struct rb_node **p = &ep->rbr.rb_root.rb_node, *parent = NULL;
1277 struct epitem *epic; 1277 struct epitem *epic;
1278 bool leftmost = true;
1278 1279
1279 while (*p) { 1280 while (*p) {
1280 parent = *p; 1281 parent = *p;
1281 epic = rb_entry(parent, struct epitem, rbn); 1282 epic = rb_entry(parent, struct epitem, rbn);
1282 kcmp = ep_cmp_ffd(&epi->ffd, &epic->ffd); 1283 kcmp = ep_cmp_ffd(&epi->ffd, &epic->ffd);
1283 if (kcmp > 0) 1284 if (kcmp > 0) {
1284 p = &parent->rb_right; 1285 p = &parent->rb_right;
1285 else 1286 leftmost = false;
1287 } else
1286 p = &parent->rb_left; 1288 p = &parent->rb_left;
1287 } 1289 }
1288 rb_link_node(&epi->rbn, parent, p); 1290 rb_link_node(&epi->rbn, parent, p);
1289 rb_insert_color(&epi->rbn, &ep->rbr); 1291 rb_insert_color_cached(&epi->rbn, &ep->rbr, leftmost);
1290} 1292}
1291 1293
1292 1294
@@ -1530,7 +1532,7 @@ error_remove_epi:
1530 list_del_rcu(&epi->fllink); 1532 list_del_rcu(&epi->fllink);
1531 spin_unlock(&tfile->f_lock); 1533 spin_unlock(&tfile->f_lock);
1532 1534
1533 rb_erase(&epi->rbn, &ep->rbr); 1535 rb_erase_cached(&epi->rbn, &ep->rbr);
1534 1536
1535error_unregister: 1537error_unregister:
1536 ep_unregister_pollwait(ep, epi); 1538 ep_unregister_pollwait(ep, epi);
@@ -1878,7 +1880,7 @@ static int ep_loop_check_proc(void *priv, void *cookie, int call_nests)
1878 mutex_lock_nested(&ep->mtx, call_nests + 1); 1880 mutex_lock_nested(&ep->mtx, call_nests + 1);
1879 ep->visited = 1; 1881 ep->visited = 1;
1880 list_add(&ep->visited_list_link, &visited_list); 1882 list_add(&ep->visited_list_link, &visited_list);
1881 for (rbp = rb_first(&ep->rbr); rbp; rbp = rb_next(rbp)) { 1883 for (rbp = rb_first_cached(&ep->rbr); rbp; rbp = rb_next(rbp)) {
1882 epi = rb_entry(rbp, struct epitem, rbn); 1884 epi = rb_entry(rbp, struct epitem, rbn);
1883 if (unlikely(is_file_epoll(epi->ffd.file))) { 1885 if (unlikely(is_file_epoll(epi->ffd.file))) {
1884 ep_tovisit = epi->ffd.file->private_data; 1886 ep_tovisit = epi->ffd.file->private_data;