[PATCH 02/23] vfs: Implement unpoll_file.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Eric W. Biederman <ebiederm@xxxxxxxxxxxxxxxxxxxxxxxxxx>

During a revoke operation it is necessary to stop using all state that is managed
by the underlying file operations implementation.  The poll wait queue is one part
of that state.

unpoll_file achieves that by walking through a specified waitqueue.  Finding
any entries that were added by select or poll of that file descriptor and
awakening them.  If action was taken unpoll sleeps and repeats until
the waitqueue has no entries for the spcified file.

Signed-off-by: Eric W. Biederman <ebiederm@xxxxxxxxxxxxxxxxxx>
---
 fs/select.c          |   31 +++++++++++++++++++++++++++++++
 include/linux/poll.h |    2 ++
 2 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/fs/select.c b/fs/select.c
index 0fe0e14..bd30fe8 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -941,3 +941,34 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
 	return ret;
 }
 #endif /* HAVE_SET_RESTORE_SIGMASK */
+
+#ifdef CONFIG_FILE_HOTPLUG
+static int unpoll_file_once(wait_queue_head_t *q, struct file *file)
+{
+	unsigned long flags;
+	wait_queue_t *curr, *next;
+	int found = 0;
+
+	spin_lock_irqsave(&q->lock, flags);
+	list_for_each_entry_safe(curr, next, &q->task_list, task_list) {
+		struct poll_table_entry *entry;
+		if (curr->func != pollwake)
+			continue;
+		entry = container_of(curr, struct poll_table_entry, wait);
+		if (entry->filp != file)
+			continue;
+		curr->func(curr, TASK_NORMAL, 0, NULL);
+		found = 1;
+	}
+	spin_unlock_irqrestore(&q->lock, flags);
+
+	return found;
+}
+
+void unpoll_file(wait_queue_head_t *q, struct file *file)
+{
+	while (unpoll_file_once(q, file))
+		schedule_timeout_uninterruptible(1);
+}
+EXPORT_SYMBOL(unpoll_file);
+#endif
diff --git a/include/linux/poll.h b/include/linux/poll.h
index 8c24ef8..d388620 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -131,6 +131,8 @@ extern int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
 
 extern int poll_select_set_timeout(struct timespec *to, long sec, long nsec);
 
+extern void unpoll_file(wait_queue_head_t *q, struct file *file);
+
 #endif /* KERNEL */
 
 #endif /* _LINUX_POLL_H */
-- 
1.6.3.1.54.g99dd.dirty

--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux