Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2011-09-08 11:30:21 +0200
committerJan Beulich <jbeulich@novell.com>2011-09-08 11:30:21 +0200
commitd405db72caed795e7c16daa383340baf6295fa0f (patch)
tree2e6505c6311cfcef76656d8f20f32528a65ff705
parent902b471ea940b97a06bf0668e577519ef3e62fbf (diff)
- Update Xen patches to 3.0.4 and c/s 1104.rpm-3.0.4-0.13
- patches.xen/frontswap-*: Update to v8 of upstream submission. - patches.xen/xen3-acpi_processor_delay_cpuidle_init_on_hotplug.patch: Delete. suse-commit: 249816db9250da316484577e887320f94615cd6c
-rw-r--r--arch/x86/include/asm/acpi.h14
-rw-r--r--arch/x86/include/mach-xen/asm/hypercall.h7
-rw-r--r--arch/x86/include/mach-xen/asm/hypervisor.h2
-rw-r--r--arch/x86/kernel/acpi/processor_extcntl_xen.c12
-rw-r--r--arch/x86/kernel/time-xen.c4
-rw-r--r--drivers/acpi/processor_core.c14
-rw-r--r--drivers/acpi/processor_idle.c2
-rw-r--r--drivers/staging/vt6655/ttype.h3
-rw-r--r--drivers/staging/vt6656/ttype.h4
-rw-r--r--drivers/xen/blkback/blkback.c32
-rw-r--r--drivers/xen/blkback/common.h4
-rw-r--r--drivers/xen/blkback/vbd.c5
-rw-r--r--drivers/xen/blkback/xenbus.c20
-rw-r--r--drivers/xen/blkfront/blkfront.c6
-rw-r--r--include/linux/frontswap.h57
-rw-r--r--include/linux/swap.h2
-rw-r--r--include/xen/interface/platform.h2
-rw-r--r--mm/frontswap.c27
-rw-r--r--mm/page_io.c24
-rw-r--r--mm/swapfile.c20
20 files changed, 160 insertions, 101 deletions
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 0e2021f9da2b..d39db8a5991b 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -31,7 +31,7 @@
#include <asm/mpspec.h>
#include <asm/trampoline.h>
-#ifdef CONFIG_XEN
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
#include <xen/interface/platform.h>
#endif
@@ -99,10 +99,6 @@ extern u8 acpi_sci_flags;
extern int acpi_sci_override_gsi;
void acpi_pic_sci_set_trigger(unsigned int, u16);
-#ifdef CONFIG_PROCESSOR_EXTERNAL_CONTROL
-bool processor_extcntl_has_mwait(void);
-#endif
-
extern int (*__acpi_register_gsi)(struct device *dev, u32 gsi,
int trigger, int polarity);
@@ -135,7 +131,7 @@ extern const unsigned char acpi_wakeup_code[];
/* early initialization routine */
extern void acpi_reserve_wakeup_memory(void);
-#ifdef CONFIG_XEN
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
static inline int acpi_notify_hypervisor_state(u8 sleep_state,
u32 pm1a_cnt_val,
u32 pm1b_cnt_val)
@@ -154,7 +150,7 @@ static inline int acpi_notify_hypervisor_state(u8 sleep_state,
return HYPERVISOR_platform_op(&op);
}
-#endif /* CONFIG_XEN */
+#endif
/*
* Check if the CPU can handle C2 and deeper
@@ -202,11 +198,7 @@ static inline void arch_acpi_set_pdc_bits(u32 *buf)
/*
* If mwait/monitor is unsupported, C2/C3_FFH will be disabled
*/
-#ifndef CONFIG_PROCESSOR_EXTERNAL_CONTROL
if (!cpu_has(c, X86_FEATURE_MWAIT))
-#else
- if (!processor_extcntl_has_mwait())
-#endif
buf[2] &= ~(ACPI_PDC_C_C2C3_FFH);
}
diff --git a/arch/x86/include/mach-xen/asm/hypercall.h b/arch/x86/include/mach-xen/asm/hypercall.h
index 6ae9d31ba030..573ce8d1b7f1 100644
--- a/arch/x86/include/mach-xen/asm/hypercall.h
+++ b/arch/x86/include/mach-xen/asm/hypercall.h
@@ -41,6 +41,10 @@
# error "please don't include this file directly"
#endif
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
+# include <xen/interface/platform.h>
+# include <xen/interface/arch-x86/xen-mca.h>
+#endif
#if CONFIG_XEN_COMPAT <= 0x030002
# include <linux/string.h> /* memcpy() */
# include <xen/interface/event_channel.h>
@@ -231,6 +235,7 @@ HYPERVISOR_sched_op(
return _hypercall2(int, sched_op, cmd, arg);
}
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
static inline int __must_check
HYPERVISOR_platform_op(
struct xen_platform_op *platform_op)
@@ -239,7 +244,6 @@ HYPERVISOR_platform_op(
return _hypercall1(int, platform_op, platform_op);
}
-struct xen_mc;
static inline int __must_check
HYPERVISOR_mca(
struct xen_mc *mc_op)
@@ -247,6 +251,7 @@ HYPERVISOR_mca(
mc_op->interface_version = XEN_MCA_INTERFACE_VERSION;
return _hypercall1(int, mca, mc_op);
}
+#endif
static inline int __must_check
HYPERVISOR_set_debugreg(
diff --git a/arch/x86/include/mach-xen/asm/hypervisor.h b/arch/x86/include/mach-xen/asm/hypervisor.h
index 74f3de680d50..b15ccedb7358 100644
--- a/arch/x86/include/mach-xen/asm/hypervisor.h
+++ b/arch/x86/include/mach-xen/asm/hypervisor.h
@@ -37,10 +37,8 @@
#include <linux/kernel.h>
#include <linux/errno.h>
#include <xen/interface/xen.h>
-#include <xen/interface/platform.h>
#include <xen/interface/sched.h>
#include <xen/interface/vcpu.h>
-#include <xen/interface/arch-x86/xen-mca.h>
#include <asm/percpu.h>
#include <asm/ptrace.h>
#include <asm/pgtable_types.h>
diff --git a/arch/x86/kernel/acpi/processor_extcntl_xen.c b/arch/x86/kernel/acpi/processor_extcntl_xen.c
index 204f5c713e52..e80885f07c18 100644
--- a/arch/x86/kernel/acpi/processor_extcntl_xen.c
+++ b/arch/x86/kernel/acpi/processor_extcntl_xen.c
@@ -267,18 +267,6 @@ static int __init init_extcntl(void)
}
arch_initcall(init_extcntl);
-bool processor_extcntl_has_mwait(void)
-{
- u32 eax, ecx;
-
- if (!(xen_start_info->flags & (XEN_PROCESSOR_PM_CX << 8)))
- return false;
-
- asm("cpuid" : "=a" (eax), "=c" (ecx) : "0" (1) : "edx", "ebx");
-
- return ecx & (1 << (X86_FEATURE_MWAIT % 32));
-}
-
unsigned int cpufreq_quick_get(unsigned int cpu)
{
xen_platform_op_t op;
diff --git a/arch/x86/kernel/time-xen.c b/arch/x86/kernel/time-xen.c
index 156c915325ff..e1c9beea307e 100644
--- a/arch/x86/kernel/time-xen.c
+++ b/arch/x86/kernel/time-xen.c
@@ -284,7 +284,6 @@ int xen_update_wallclock(const struct timespec *tv)
return 0;
}
-#endif
static void sync_xen_wallclock(unsigned long dummy);
static DEFINE_TIMER(sync_xen_wallclock_timer, sync_xen_wallclock, 0, 0);
@@ -311,6 +310,7 @@ static void sync_xen_wallclock(unsigned long dummy)
/* Once per minute. */
mod_timer(&sync_xen_wallclock_timer, jiffies + 60*HZ);
}
+#endif /* CONFIG_XEN_PRIVILEGED_GUEST */
unsigned long long xen_local_clock(void)
{
@@ -358,7 +358,9 @@ int xen_write_wallclock(unsigned long now)
if (!is_initial_xendomain() || independent_wallclock)
return 0;
+#ifdef CONFIG_XEN_PRIVILEGED_GUEST
mod_timer(&sync_xen_wallclock_timer, jiffies + 1);
+#endif
return mach_set_rtc_mmss(now);
}
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c
index 7e63b8a1d0eb..f8705041f2eb 100644
--- a/drivers/acpi/processor_core.c
+++ b/drivers/acpi/processor_core.c
@@ -314,19 +314,31 @@ acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
{
acpi_status status = AE_OK;
+#ifndef CONFIG_XEN
if (boot_option_idle_override == IDLE_NOMWAIT) {
/*
* If mwait is disabled for CPU C-states, the C2C3_FFH access
* mode will be disabled in the parameter of _PDC object.
* Of course C1_FFH access mode will also be disabled.
*/
+#else
+ {
+ struct xen_platform_op op;
+#endif
union acpi_object *obj;
u32 *buffer = NULL;
obj = pdc_in->pointer;
buffer = (u32 *)(obj->buffer.pointer);
+#ifndef CONFIG_XEN
buffer[2] &= ~(ACPI_PDC_C_C2C3_FFH | ACPI_PDC_C_C1_FFH);
-
+#else
+ op.cmd = XENPF_set_processor_pminfo;
+ op.u.set_pminfo.id = -1;
+ op.u.set_pminfo.type = XEN_PM_PDC;
+ set_xen_guest_handle(op.u.set_pminfo.u.pdc, buffer);
+ VOID(HYPERVISOR_platform_op(&op));
+#endif
}
status = acpi_evaluate_object(handle, "_PDC", pdc_in, NULL);
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 1814d254d990..ca01152b807d 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -527,7 +527,7 @@ static int acpi_processor_get_power_info_cst(struct acpi_processor *pr)
current_count));
/* Validate number of power states discovered */
- if (current_count < 2)
+ if (current_count < (processor_pm_external() ? 1 : 2))
status = -EFAULT;
end:
diff --git a/drivers/staging/vt6655/ttype.h b/drivers/staging/vt6655/ttype.h
index cf620dce0b65..be223bd25d2c 100644
--- a/drivers/staging/vt6655/ttype.h
+++ b/drivers/staging/vt6655/ttype.h
@@ -30,9 +30,6 @@
#ifndef __TTYPE_H__
#define __TTYPE_H__
-#ifdef CONFIG_XEN
-#include <asm/hypervisor.h>
-#endif
/******* Common definitions and typedefs ***********************************/
diff --git a/drivers/staging/vt6656/ttype.h b/drivers/staging/vt6656/ttype.h
index 07e023bbeaa6..8e9450ef3997 100644
--- a/drivers/staging/vt6656/ttype.h
+++ b/drivers/staging/vt6656/ttype.h
@@ -29,10 +29,6 @@
#ifndef __TTYPE_H__
#define __TTYPE_H__
-#ifdef CONFIG_XEN
-#include <asm/hypervisor.h>
-#endif
-
/******* Common definitions and typedefs ***********************************/
typedef int BOOL;
diff --git a/drivers/xen/blkback/blkback.c b/drivers/xen/blkback/blkback.c
index 25b35be3f273..9fca744c4647 100644
--- a/drivers/xen/blkback/blkback.c
+++ b/drivers/xen/blkback/blkback.c
@@ -194,14 +194,17 @@ static void fast_flush_area(pending_req_t *req)
static void print_stats(blkif_t *blkif)
{
- printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | br %4d | pk %4d\n",
+ printk(KERN_DEBUG "%s: oo %3d | rd %4d | wr %4d | br %4d"
+ " | fl %4d | pk %4d\n",
current->comm, blkif->st_oo_req,
- blkif->st_rd_req, blkif->st_wr_req, blkif->st_br_req,
- blkif->st_pk_req);
+ blkif->st_rd_req, blkif->st_wr_req,
+ blkif->st_br_req, blkif->st_fl_req, blkif->st_pk_req);
blkif->st_print = jiffies + msecs_to_jiffies(10 * 1000);
blkif->st_rd_req = 0;
blkif->st_wr_req = 0;
blkif->st_oo_req = 0;
+ blkif->st_br_req = 0;
+ blkif->st_fl_req = 0;
blkif->st_pk_req = 0;
}
@@ -264,6 +267,11 @@ static void __end_block_io_op(pending_req_t *pending_req, int error)
DPRINTK("blkback: write barrier op failed, not supported\n");
blkback_barrier(XBT_NIL, pending_req->blkif->be, 0);
status = BLKIF_RSP_EOPNOTSUPP;
+ } else if ((pending_req->operation == BLKIF_OP_FLUSH_DISKCACHE) &&
+ (error == -EOPNOTSUPP)) {
+ DPRINTK("blkback: flush diskcache op failed, not supported\n");
+ blkback_flush_diskcache(XBT_NIL, pending_req->blkif->be, 0);
+ status = BLKIF_RSP_EOPNOTSUPP;
} else if (error) {
DPRINTK("Buffer not up-to-date at end of operation, "
"error=%d\n", error);
@@ -357,14 +365,9 @@ static int do_block_io_op(blkif_t *blkif)
switch (req.operation) {
case BLKIF_OP_READ:
- blkif->st_rd_req++;
- dispatch_rw_block_io(blkif, &req, pending_req);
- break;
- case BLKIF_OP_WRITE_BARRIER:
- blkif->st_br_req++;
- /* fall through */
case BLKIF_OP_WRITE:
- blkif->st_wr_req++;
+ case BLKIF_OP_WRITE_BARRIER:
+ case BLKIF_OP_FLUSH_DISKCACHE:
dispatch_rw_block_io(blkif, &req, pending_req);
break;
case BLKIF_OP_PACKET:
@@ -410,14 +413,21 @@ static void dispatch_rw_block_io(blkif_t *blkif,
switch (req->operation) {
case BLKIF_OP_READ:
+ blkif->st_rd_req++;
operation = READ;
break;
case BLKIF_OP_WRITE:
+ blkif->st_wr_req++;
operation = WRITE;
break;
case BLKIF_OP_WRITE_BARRIER:
+ blkif->st_br_req++;
operation = WRITE_FLUSH_FUA;
break;
+ case BLKIF_OP_FLUSH_DISKCACHE:
+ blkif->st_fl_req++;
+ operation = WRITE_FLUSH;
+ break;
default:
operation = 0; /* make gcc happy */
BUG();
@@ -425,7 +435,7 @@ static void dispatch_rw_block_io(blkif_t *blkif,
/* Check that number of segments is sane. */
nseg = req->nr_segments;
- if (unlikely(nseg == 0 && req->operation != BLKIF_OP_WRITE_BARRIER) ||
+ if (unlikely(nseg == 0 && !(operation & REQ_FLUSH)) ||
unlikely(nseg > BLKIF_MAX_SEGMENTS_PER_REQUEST)) {
DPRINTK("Bad number of segments in request (%d)\n", nseg);
goto fail_response;
diff --git a/drivers/xen/blkback/common.h b/drivers/xen/blkback/common.h
index 7ac10dfed1c2..5771a05d99d0 100644
--- a/drivers/xen/blkback/common.h
+++ b/drivers/xen/blkback/common.h
@@ -48,6 +48,7 @@ struct vbd {
blkif_vdev_t handle; /* what the domain refers to this vbd as */
unsigned char readonly; /* Non-zero -> read-only */
unsigned char type; /* VDISK_xxx */
+ bool flush_support;
u32 pdevice; /* phys device that this vbd maps to */
struct block_device *bdev;
sector_t size; /* Cached size parameter */
@@ -84,6 +85,7 @@ typedef struct blkif_st {
int st_wr_req;
int st_oo_req;
int st_br_req;
+ int st_fl_req;
int st_pk_req;
int st_rd_sect;
int st_wr_sect;
@@ -142,6 +144,8 @@ int blkif_schedule(void *arg);
int blkback_barrier(struct xenbus_transaction xbt,
struct backend_info *be, int state);
+int blkback_flush_diskcache(struct xenbus_transaction,
+ struct backend_info *, int state);
/* cdrom media change */
void cdrom_add_media_watch(struct backend_info *be);
diff --git a/drivers/xen/blkback/vbd.c b/drivers/xen/blkback/vbd.c
index 23a430f5e5b1..31553a9433e7 100644
--- a/drivers/xen/blkback/vbd.c
+++ b/drivers/xen/blkback/vbd.c
@@ -55,6 +55,7 @@ int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major,
{
struct vbd *vbd;
struct block_device *bdev;
+ struct request_queue *q;
vbd = &blkif->vbd;
vbd->handle = handle;
@@ -90,6 +91,10 @@ int vbd_create(blkif_t *blkif, blkif_vdev_t handle, unsigned major,
if (vbd->bdev->bd_disk->flags & GENHD_FL_REMOVABLE)
vbd->type |= VDISK_REMOVABLE;
+ q = bdev_get_queue(bdev);
+ if (q && q->flush_flags)
+ vbd->flush_support = true;
+
DPRINTK("Successful creation of handle=%04x (dom=%u)\n",
handle, blkif->domid);
return 0;
diff --git a/drivers/xen/blkback/xenbus.c b/drivers/xen/blkback/xenbus.c
index 639146c3fba8..903828178297 100644
--- a/drivers/xen/blkback/xenbus.c
+++ b/drivers/xen/blkback/xenbus.c
@@ -120,6 +120,7 @@ VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req);
VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req);
VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req);
VBD_SHOW(br_req, "%d\n", be->blkif->st_br_req);
+VBD_SHOW(fl_req, "%d\n", be->blkif->st_fl_req);
VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
@@ -128,6 +129,7 @@ static struct attribute *vbdstat_attrs[] = {
&dev_attr_rd_req.attr,
&dev_attr_wr_req.attr,
&dev_attr_br_req.attr,
+ &dev_attr_fl_req.attr,
&dev_attr_rd_sect.attr,
&dev_attr_wr_sect.attr,
NULL
@@ -219,6 +221,20 @@ int blkback_barrier(struct xenbus_transaction xbt,
return err;
}
+int blkback_flush_diskcache(struct xenbus_transaction xbt,
+ struct backend_info *be, int state)
+{
+ struct xenbus_device *dev = be->dev;
+ int err;
+
+ err = xenbus_printf(xbt, dev->nodename, "feature-flush-cache",
+ "%d", state);
+ if (err)
+ xenbus_dev_fatal(dev, err, "writing feature-flush-cache");
+
+ return err;
+}
+
/**
* Entry point to this code when a new device is created. Allocate the basic
* structures, and watch the store waiting for the hotplug scripts to tell us
@@ -440,6 +456,10 @@ again:
return;
}
+ err = blkback_flush_diskcache(xbt, be, be->blkif->vbd.flush_support);
+ if (err)
+ goto abort;
+
err = blkback_barrier(xbt, be, 1);
if (err)
goto abort;
diff --git a/drivers/xen/blkfront/blkfront.c b/drivers/xen/blkfront/blkfront.c
index 76565a9d07cb..0d8044551f17 100644
--- a/drivers/xen/blkfront/blkfront.c
+++ b/drivers/xen/blkfront/blkfront.c
@@ -867,15 +867,15 @@ static irqreturn_t blkif_int(int irq, void *dev_id)
case BLKIF_OP_FLUSH_DISKCACHE:
case BLKIF_OP_WRITE_BARRIER:
what = bret->operation == BLKIF_OP_WRITE_BARRIER ?
- "barrier" : "flush disk cache";
+ "write barrier" : "flush disk cache";
if (unlikely(bret->status == BLKIF_RSP_EOPNOTSUPP)) {
- pr_warn("blkfront: %s: write %s op failed\n",
+ pr_warn("blkfront: %s: %s op failed\n",
what, info->gd->disk_name);
ret = -EOPNOTSUPP;
}
if (unlikely(bret->status == BLKIF_RSP_ERROR &&
info->shadow[id].req.nr_segments == 0)) {
- pr_warn("blkfront: %s: empty write %s op failed\n",
+ pr_warn("blkfront: %s: empty %s op failed\n",
what, info->gd->disk_name);
ret = -EOPNOTSUPP;
}
diff --git a/include/linux/frontswap.h b/include/linux/frontswap.h
index f87231714655..b25bceae1052 100644
--- a/include/linux/frontswap.h
+++ b/include/linux/frontswap.h
@@ -24,39 +24,68 @@ extern int __frontswap_get_page(struct page *page);
extern void __frontswap_flush_page(unsigned, pgoff_t);
extern void __frontswap_flush_area(unsigned);
-#ifndef CONFIG_FRONTSWAP
-/* all inline routines become no-ops and all externs are ignored */
-#define frontswap_enabled (0)
-#endif
+#ifdef CONFIG_FRONTSWAP
static inline int frontswap_test(struct swap_info_struct *sis, pgoff_t offset)
{
int ret = 0;
-#ifdef CONFIG_FRONTSWAP
- if (sis->frontswap_map)
+ if (frontswap_enabled && sis->frontswap_map)
ret = test_bit(offset, sis->frontswap_map);
-#endif
-
return ret;
}
static inline void frontswap_set(struct swap_info_struct *sis, pgoff_t offset)
{
-#ifdef CONFIG_FRONTSWAP
- if (sis->frontswap_map)
+ if (frontswap_enabled && sis->frontswap_map)
set_bit(offset, sis->frontswap_map);
-#endif
}
static inline void frontswap_clear(struct swap_info_struct *sis, pgoff_t offset)
{
-#ifdef CONFIG_FRONTSWAP
- if (sis->frontswap_map)
+ if (frontswap_enabled && sis->frontswap_map)
clear_bit(offset, sis->frontswap_map);
-#endif
}
+static inline void frontswap_map_set(struct swap_info_struct *p,
+ unsigned long *map)
+{
+ p->frontswap_map = map;
+}
+
+static inline unsigned long *frontswap_map_get(struct swap_info_struct *p)
+{
+ return p->frontswap_map;
+}
+#else
+/* all inline routines become no-ops and all externs are ignored */
+
+#define frontswap_enabled (0)
+
+static inline int frontswap_test(struct swap_info_struct *sis, pgoff_t offset)
+{
+ return 0;
+}
+
+static inline void frontswap_set(struct swap_info_struct *sis, pgoff_t offset)
+{
+}
+
+static inline void frontswap_clear(struct swap_info_struct *sis, pgoff_t offset)
+{
+}
+
+static inline void frontswap_map_set(struct swap_info_struct *p,
+ unsigned long *map)
+{
+}
+
+static inline unsigned long *frontswap_map_get(struct swap_info_struct *p)
+{
+ return NULL;
+}
+#endif
+
static inline int frontswap_put_page(struct page *page)
{
int ret = -1;
diff --git a/include/linux/swap.h b/include/linux/swap.h
index 367bf11dc9c1..cdde63bedadb 100644
--- a/include/linux/swap.h
+++ b/include/linux/swap.h
@@ -196,7 +196,7 @@ struct swap_info_struct {
unsigned int old_block_size; /* seldom referenced */
#ifdef CONFIG_FRONTSWAP
unsigned long *frontswap_map; /* frontswap in-use, one bit per page */
- unsigned int frontswap_pages; /* frontswap pages in-use counter */
+ atomic_t frontswap_pages; /* frontswap pages in-use counter */
#endif
};
diff --git a/include/xen/interface/platform.h b/include/xen/interface/platform.h
index c180d40f8b8e..e0d2a1cfc4db 100644
--- a/include/xen/interface/platform.h
+++ b/include/xen/interface/platform.h
@@ -304,6 +304,7 @@ DEFINE_XEN_GUEST_HANDLE(xenpf_getidletime_t);
#define XEN_PM_CX 0
#define XEN_PM_PX 1
#define XEN_PM_TX 2
+#define XEN_PM_PDC 3
/* Px sub info type */
#define XEN_PX_PCT 1
@@ -401,6 +402,7 @@ struct xenpf_set_processor_pminfo {
union {
struct xen_processor_power power;/* Cx: _CST/_CSD */
struct xen_processor_performance perf; /* Px: _PPC/_PCT/_PSS/_PSD */
+ XEN_GUEST_HANDLE(uint32) pdc; /* _PDC */
} u;
};
typedef struct xenpf_set_processor_pminfo xenpf_set_processor_pminfo_t;
diff --git a/mm/frontswap.c b/mm/frontswap.c
index afa52479d7a8..b8aebcadb528 100644
--- a/mm/frontswap.c
+++ b/mm/frontswap.c
@@ -38,14 +38,17 @@ static struct frontswap_ops frontswap_ops;
int frontswap_enabled;
EXPORT_SYMBOL(frontswap_enabled);
-/* useful stats available in /sys/kernel/mm/frontswap */
+/*
+ * Useful stats available in /sys/kernel/mm/frontswap. These are for
+ * information only so are not protected against increment/decrement races.
+ */
static unsigned long frontswap_gets;
static unsigned long frontswap_succ_puts;
static unsigned long frontswap_failed_puts;
static unsigned long frontswap_flushes;
/*
- * register operations for frontswap, returning previous thus allowing
+ * Register operations for frontswap, returning previous thus allowing
* detection of multiple backends and possible nesting
*/
struct frontswap_ops frontswap_register_ops(struct frontswap_ops *ops)
@@ -95,14 +98,14 @@ int __frontswap_put_page(struct page *page)
frontswap_set(sis, offset);
frontswap_succ_puts++;
if (!dup)
- sis->frontswap_pages++;
+ atomic_inc(&sis->frontswap_pages);
} else if (dup) {
/*
failed dup always results in automatic flush of
the (older) page from frontswap
*/
frontswap_clear(sis, offset);
- sis->frontswap_pages--;
+ atomic_dec(&sis->frontswap_pages);
frontswap_failed_puts++;
} else
frontswap_failed_puts++;
@@ -144,7 +147,7 @@ void __frontswap_flush_page(unsigned type, pgoff_t offset)
BUG_ON(sis == NULL);
if (frontswap_test(sis, offset)) {
(*frontswap_ops.flush_page)(type, offset);
- sis->frontswap_pages--;
+ atomic_dec(&sis->frontswap_pages);
frontswap_clear(sis, offset);
frontswap_flushes++;
}
@@ -163,7 +166,7 @@ void __frontswap_flush_area(unsigned type)
if (sis->frontswap_map == NULL)
return;
(*frontswap_ops.flush_area)(type);
- sis->frontswap_pages = 0;
+ atomic_set(&sis->frontswap_pages, 0);
memset(sis->frontswap_map, 0, sis->max / sizeof(long));
}
EXPORT_SYMBOL(__frontswap_flush_area);
@@ -184,6 +187,7 @@ void frontswap_shrink(unsigned long target_pages)
for (wrapped = 0; wrapped < 3; wrapped++) {
struct swap_info_struct *si = NULL;
+ int si_frontswap_pages;
unsigned long total_pages = 0, total_pages_to_unuse;
unsigned long pages = 0, pages_to_unuse = 0;
int type;
@@ -198,17 +202,18 @@ void frontswap_shrink(unsigned long target_pages)
total_pages = 0;
for (type = swap_list.head; type >= 0; type = si->next) {
si = swap_info[type];
- total_pages += si->frontswap_pages;
+ total_pages += atomic_read(&si->frontswap_pages);
}
if (total_pages <= target_pages)
goto out;
total_pages_to_unuse = total_pages - target_pages;
for (type = swap_list.head; type >= 0; type = si->next) {
si = swap_info[type];
- if (total_pages_to_unuse < si->frontswap_pages)
+ si_frontswap_pages = atomic_read(&si->frontswap_pages);
+ if (total_pages_to_unuse < si_frontswap_pages)
pages = pages_to_unuse = total_pages_to_unuse;
else {
- pages = si->frontswap_pages;
+ pages = si_frontswap_pages;
pages_to_unuse = 0; /* unuse all */
}
if (security_vm_enough_memory_kern(pages))
@@ -231,7 +236,7 @@ out:
EXPORT_SYMBOL(frontswap_shrink);
/*
- * count and return the number of pages frontswap pages across all
+ * Count and return the number of pages frontswap pages across all
* swap devices. This is exported so that a kernel module can
* determine current usage without reading sysfs.
*/
@@ -245,7 +250,7 @@ unsigned long frontswap_curr_pages(void)
for (type = swap_list.head; type >= 0; type = si->next) {
si = swap_info[type];
if (si != NULL)
- totalpages += si->frontswap_pages;
+ totalpages += atomic_read(&si->frontswap_pages);
}
spin_unlock(&swap_lock);
return totalpages;
diff --git a/mm/page_io.c b/mm/page_io.c
index bc3122cc82b6..d51dc61986f2 100644
--- a/mm/page_io.c
+++ b/mm/page_io.c
@@ -92,12 +92,6 @@ int generic_swap_writepage(struct page *page, struct writeback_control *wbc)
struct bio *bio;
int rw = WRITE;
- if (frontswap_put_page(page) == 0) {
- set_page_writeback(page);
- unlock_page(page);
- end_page_writeback(page);
- return 0;
- }
bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write);
if (bio == NULL) {
set_page_dirty(page);
@@ -117,11 +111,6 @@ int generic_swap_writepage(struct page *page, struct writeback_control *wbc)
int generic_swap_readpage(struct page *page)
{
struct bio *bio;
- if (frontswap_get_page(page) == 0) {
- SetPageUptodate(page);
- unlock_page(page);
- return 0;
- }
bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read);
if (bio == NULL) {
unlock_page(page);
@@ -240,6 +229,13 @@ int swap_writepage(struct page *page, struct writeback_control *wbc)
return ret;
}
+ if (frontswap_put_page(page) == 0) {
+ set_page_writeback(page);
+ unlock_page(page);
+ end_page_writeback(page);
+ return 0;
+ }
+
swap_file = sis->swap_file;
mapping = swap_file->f_mapping;
if (mapping->a_ops->swap_writepage) {
@@ -262,6 +258,12 @@ int swap_readpage(struct page *page)
VM_BUG_ON(!PageLocked(page));
VM_BUG_ON(PageUptodate(page));
+ if (frontswap_get_page(page) == 0) {
+ SetPageUptodate(page);
+ unlock_page(page);
+ return 0;
+ }
+
swap_file = sis->swap_file;
mapping = swap_file->f_mapping;
if (mapping->a_ops->swap_readpage) {
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 3a1d8be12585..1b570d9e7f49 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1022,7 +1022,8 @@ static int unuse_mm(struct mm_struct *mm,
}
/*
- * Scan swap_map from current position to next entry still in use.
+ * Scan swap_map (or frontswap_map if frontswap parameter is true)
+ * from current position to next entry still in use.
* Recycle to start on reaching the end, returning 0 when empty.
*/
static unsigned int find_next_to_unuse(struct swap_info_struct *si,
@@ -1471,10 +1472,6 @@ static int setup_swap_extents(struct swap_info_struct *sis, sector_t *span)
return generic_swapfile_activate(sis, swap_file, span);
}
-#ifndef CONFIG_FRONTSWAP
-#define enable_swap_info(si, prio, swap_map, frontswap_map) \
- enable_swap_info(si, prio, swap_map)
-#endif
static void enable_swap_info(struct swap_info_struct *p, int prio,
unsigned char *swap_map,
unsigned long *frontswap_map)
@@ -1487,9 +1484,7 @@ static void enable_swap_info(struct swap_info_struct *p, int prio,
else
p->prio = --least_priority;
p->swap_map = swap_map;
-#ifdef CONFIG_FRONTSWAP
- p->frontswap_map = frontswap_map;
-#endif
+ frontswap_map_set(p, frontswap_map);
p->flags |= SWP_WRITEOK;
nr_swap_pages += p->pages;
total_swap_pages += p->pages;
@@ -1589,7 +1584,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
* sys_swapoff for this swap_info_struct at this point.
*/
/* re-insert swap space back into swap_list */
- enable_swap_info(p, p->prio, p->swap_map, p->frontswap_map);
+ enable_swap_info(p, p->prio, p->swap_map, frontswap_map_get(p));
goto out_dput;
}
@@ -1619,10 +1614,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
spin_unlock(&swap_lock);
mutex_unlock(&swapon_mutex);
vfree(swap_map);
-#ifdef CONFIG_FRONTSWAP
- if (p->frontswap_map)
- vfree(p->frontswap_map);
-#endif
+ vfree(frontswap_map_get(p));
/* Destroy swap account informatin */
swap_cgroup_swapoff(type);
@@ -2102,7 +2094,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
(p->flags & SWP_SOLIDSTATE) ? "SS" : "",
(p->flags & SWP_DISCARDABLE) ? "D" : "",
- frontswap_map ? "FS" : "");
+ (frontswap_map) ? "FS" : "");
mutex_unlock(&swapon_mutex);
atomic_inc(&proc_poll_event);