mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-11-18 07:35:12 +08:00
/proc/swaps: support polling
System management wants to subscribe to changes in swap configuration. Make /proc/swaps pollable like /proc/mounts. [akpm@linux-foundation.org: document proc_poll_event] Signed-off-by: Kay Sievers <kay.sievers@vrfy.org> Acked-by: Greg KH <greg@kroah.com> Cc: Jonathan Corbet <corbet@lwn.net> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
e1ca7788de
commit
66d7dd518a
@ -30,6 +30,7 @@
|
||||
#include <linux/capability.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/memcontrol.h>
|
||||
#include <linux/poll.h>
|
||||
|
||||
#include <asm/pgtable.h>
|
||||
#include <asm/tlbflush.h>
|
||||
@ -58,6 +59,10 @@ static struct swap_info_struct *swap_info[MAX_SWAPFILES];
|
||||
|
||||
static DEFINE_MUTEX(swapon_mutex);
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(proc_poll_wait);
|
||||
/* Activity counter to indicate that a swapon or swapoff has occurred */
|
||||
static atomic_t proc_poll_event = ATOMIC_INIT(0);
|
||||
|
||||
static inline unsigned char swap_count(unsigned char ent)
|
||||
{
|
||||
return ent & ~SWAP_HAS_CACHE; /* may include SWAP_HAS_CONT flag */
|
||||
@ -1680,6 +1685,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
|
||||
}
|
||||
filp_close(swap_file, NULL);
|
||||
err = 0;
|
||||
atomic_inc(&proc_poll_event);
|
||||
wake_up_interruptible(&proc_poll_wait);
|
||||
|
||||
out_dput:
|
||||
filp_close(victim, NULL);
|
||||
@ -1688,6 +1695,25 @@ out:
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_swaps {
|
||||
struct seq_file seq;
|
||||
int event;
|
||||
};
|
||||
|
||||
static unsigned swaps_poll(struct file *file, poll_table *wait)
|
||||
{
|
||||
struct proc_swaps *s = file->private_data;
|
||||
|
||||
poll_wait(file, &proc_poll_wait, wait);
|
||||
|
||||
if (s->event != atomic_read(&proc_poll_event)) {
|
||||
s->event = atomic_read(&proc_poll_event);
|
||||
return POLLIN | POLLRDNORM | POLLERR | POLLPRI;
|
||||
}
|
||||
|
||||
return POLLIN | POLLRDNORM;
|
||||
}
|
||||
|
||||
/* iterator */
|
||||
static void *swap_start(struct seq_file *swap, loff_t *pos)
|
||||
{
|
||||
@ -1771,7 +1797,24 @@ static const struct seq_operations swaps_op = {
|
||||
|
||||
static int swaps_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return seq_open(file, &swaps_op);
|
||||
struct proc_swaps *s;
|
||||
int ret;
|
||||
|
||||
s = kmalloc(sizeof(struct proc_swaps), GFP_KERNEL);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
file->private_data = s;
|
||||
|
||||
ret = seq_open(file, &swaps_op);
|
||||
if (ret) {
|
||||
kfree(s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s->seq.private = s;
|
||||
s->event = atomic_read(&proc_poll_event);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations proc_swaps_operations = {
|
||||
@ -1779,6 +1822,7 @@ static const struct file_operations proc_swaps_operations = {
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = seq_release,
|
||||
.poll = swaps_poll,
|
||||
};
|
||||
|
||||
static int __init procswaps_init(void)
|
||||
@ -2084,6 +2128,9 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
||||
swap_info[prev]->next = type;
|
||||
spin_unlock(&swap_lock);
|
||||
mutex_unlock(&swapon_mutex);
|
||||
atomic_inc(&proc_poll_event);
|
||||
wake_up_interruptible(&proc_poll_wait);
|
||||
|
||||
error = 0;
|
||||
goto out;
|
||||
bad_swap:
|
||||
|
Loading…
Reference in New Issue
Block a user