All of lore.kernel.org
 help / color / mirror / Atom feed
* Linux mainstream balloon driver fails to grow memory= -> maxmem=
@ 2010-08-23 23:49 Dan Magenheimer
  2010-08-24  0:50 ` Jeremy Fitzhardinge
  0 siblings, 1 reply; 7+ messages in thread
From: Dan Magenheimer @ 2010-08-23 23:49 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: xen-devel, Vasiliy G Tolstov

Hi Jeremy --

Vasiliy discovered (and I confirmed) that the mainstream
Linux balloon driver won't balloon above the initial
memory with which the Linux guest was launched.  E.g.
a 2.6.34 guest launched with these in vm.cfg:

memory=1024
maxmem=1536

displays properly in xentop, but changing target_kb
in /sys/devices/system/xen_memory/xen_memory0
doesn't "take" for any value greater than 1024*1024.

We tested with 2.6.34 but it even fails in RHEL6 Beta2.

Is this a known problem/bug (or maybe a feature)?

Thanks,
Dan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Linux mainstream balloon driver fails to grow memory= -> maxmem=
  2010-08-23 23:49 Linux mainstream balloon driver fails to grow memory= -> maxmem= Dan Magenheimer
@ 2010-08-24  0:50 ` Jeremy Fitzhardinge
  2010-08-24  2:11   ` Dan Magenheimer
  0 siblings, 1 reply; 7+ messages in thread
From: Jeremy Fitzhardinge @ 2010-08-24  0:50 UTC (permalink / raw)
  To: Dan Magenheimer; +Cc: xen-devel, Daniel Kiper, Vasiliy G Tolstov

 On 08/23/2010 04:49 PM, Dan Magenheimer wrote:
> Hi Jeremy --
>
> Vasiliy discovered (and I confirmed) that the mainstream
> Linux balloon driver won't balloon above the initial
> memory with which the Linux guest was launched.  E.g.
> a 2.6.34 guest launched with these in vm.cfg:
>
> memory=1024
> maxmem=1536
>
> displays properly in xentop, but changing target_kb
> in /sys/devices/system/xen_memory/xen_memory0
> doesn't "take" for any value greater than 1024*1024.
>
> We tested with 2.6.34 but it even fails in RHEL6 Beta2.
>
> Is this a known problem/bug (or maybe a feature)?

Known bug.  There's no machinery in there to allocate enough struct
pages for maxmem, only for "memory".

The immediately workaround is to start the domain with fully populated
"memory" and then have it balloon out the unwanted stuff asap, but it
does mean you need to have enough memory to start with.

There's a couple of experiments floating around in the tree to try to
honour maxmem, but they're somewhat rotted.  Its probably worth trying
to resurrect them though.

And of course there's Daniel's work which is a more flexible
andcomprehensive approach, but it does rely on hotplug memory (which has
its own overheads).

    J

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: Linux mainstream balloon driver fails to grow memory= -> maxmem=
  2010-08-24  0:50 ` Jeremy Fitzhardinge
@ 2010-08-24  2:11   ` Dan Magenheimer
  2010-08-24 11:29     ` Vasiliy G Tolstov
  2010-08-25 22:44     ` Dan Magenheimer
  0 siblings, 2 replies; 7+ messages in thread
From: Dan Magenheimer @ 2010-08-24  2:11 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: xen-devel, Daniel Kiper, Vasiliy G Tolstov

> From: Jeremy Fitzhardinge [mailto:jeremy@goop.org]
> Subject: Re: [Xen-devel] Linux mainstream balloon driver fails to grow
> memory= -> maxmem=
> 
>  On 08/23/2010 04:49 PM, Dan Magenheimer wrote:
> > Hi Jeremy --
> >
> > Vasiliy discovered (and I confirmed) that the mainstream
> > Linux balloon driver won't balloon above the initial
> > memory with which the Linux guest was launched.  E.g.
> > a 2.6.34 guest launched with these in vm.cfg:
> >
> > memory=1024
> > maxmem=1536
> >
> > displays properly in xentop, but changing target_kb
> > in /sys/devices/system/xen_memory/xen_memory0
> > doesn't "take" for any value greater than 1024*1024.
> >
> > We tested with 2.6.34 but it even fails in RHEL6 Beta2.
> >
> > Is this a known problem/bug (or maybe a feature)?
> 
> Known bug.  There's no machinery in there to allocate enough struct
> pages for maxmem, only for "memory".

OK, good to know.

> The immediately workaround is to start the domain with fully populated
> "memory" and then have it balloon out the unwanted stuff asap, but it
> does mean you need to have enough memory to start with.
> 
> There's a couple of experiments floating around in the tree to try to
> honour maxmem, but they're somewhat rotted.  Its probably worth trying
> to resurrect them though.

Not sure, except for backwards compatibility.

> And of course there's Daniel's work which is a more flexible
> andcomprehensive approach, but it does rely on hotplug memory (which
> has
> its own overheads).

Tmem (the "frontswap" part) also takes advantage of the difference
between memory= and maxmem=, allowing pages that are swapped to
"hypervisor RAM" to use RAM between the two numbers.  This requires
that the guest have a swap disk configured that is at least as
large as the difference between memory= and maxmem= though.

So if Daniel's stuff works along with tmem, I'm not too bothered about
fixing this known difference between 2.6.18-xen and mainstream.
And IIRC the maxmem= parameter is required for PoD to work for Windows
also.  IOW, this should probably be documented (any ideas where?)
but the "old way" may best be left to obsolesce with 2.6.18-xen.

Dan

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: Linux mainstream balloon driver fails to grow memory= -> maxmem=
  2010-08-24  2:11   ` Dan Magenheimer
@ 2010-08-24 11:29     ` Vasiliy G Tolstov
  2010-08-24 19:56       ` Daniel Kiper
  2010-08-25 22:44     ` Dan Magenheimer
  1 sibling, 1 reply; 7+ messages in thread
From: Vasiliy G Tolstov @ 2010-08-24 11:29 UTC (permalink / raw)
  To: Dan Magenheimer; +Cc: Jeremy Fitzhardinge, xen-devel, Daniel Kiper

[-- Attachment #1: Type: text/plain, Size: 5726 bytes --]

В Пнд, 23/08/2010 в 19:11 -0700, Dan Magenheimer пишет:
> > From: Jeremy Fitzhardinge [mailto:jeremy@goop.org]
> > Subject: Re: [Xen-devel] Linux mainstream balloon driver fails to grow
> > memory= -> maxmem=
> > 
> >  On 08/23/2010 04:49 PM, Dan Magenheimer wrote:
> > > Hi Jeremy --
> > >
> > > Vasiliy discovered (and I confirmed) that the mainstream
> > > Linux balloon driver won't balloon above the initial
> > > memory with which the Linux guest was launched.  E.g.
> > > a 2.6.34 guest launched with these in vm.cfg:
> > >
> > > memory=1024
> > > maxmem=1536
> > >
> > > displays properly in xentop, but changing target_kb
> > > in /sys/devices/system/xen_memory/xen_memory0
> > > doesn't "take" for any value greater than 1024*1024.
> > >
> > > We tested with 2.6.34 but it even fails in RHEL6 Beta2.
> > >
> > > Is this a known problem/bug (or maybe a feature)?
> > 
> > Known bug.  There's no machinery in there to allocate enough struct
> > pages for maxmem, only for "memory".
> 
> OK, good to know.
> 
> > The immediately workaround is to start the domain with fully populated
> > "memory" and then have it balloon out the unwanted stuff asap, but it
> > does mean you need to have enough memory to start with.
> > 
> > There's a couple of experiments floating around in the tree to try to
> > honour maxmem, but they're somewhat rotted.  Its probably worth trying
> > to resurrect them though.
> 
> Not sure, except for backwards compatibility.
> 
> > And of course there's Daniel's work which is a more flexible
> > andcomprehensive approach, but it does rely on hotplug memory (which
> > has
> > its own overheads).
> 
> Tmem (the "frontswap" part) also takes advantage of the difference
> between memory= and maxmem=, allowing pages that are swapped to
> "hypervisor RAM" to use RAM between the two numbers.  This requires
> that the guest have a swap disk configured that is at least as
> large as the difference between memory= and maxmem= though.
> 
> So if Daniel's stuff works along with tmem, I'm not too bothered about
> fixing this known difference between 2.6.18-xen and mainstream.
> And IIRC the maxmem= parameter is required for PoD to work for Windows
> also.  IOW, this should probably be documented (any ideas where?)
> but the "old way" may best be left to obsolesce with 2.6.18-xen.
> 
> Dan

Stupidly apply patch from Daniel and Dan to linux-2.6.34.5 does not
work. 
Dan, can You check what need to modify with Daniel patch to work
together with tmem?

P.S. Best, if the domU can selfballooning to memory, after that it can
emulate memory-hotplug and add needed memory slot, after that
selfballoon to next target.... If that possible.

With selfballooning = 0 xm mem-set xxx xxx not work's domU kernel panic:

Failed services in runlevel 3:
named
[  491.162333] ------------[ cut here ]------------
[  491.162333] kernel BUG at drivers/xen/balloon.c:449!
[  491.162333] invalid opcode: 0000 [#1] SMP 
[  491.162333] last sysfs
file: /sys/devices/system/xen_memory/xen_memory0/selfballooning
[  491.162333] CPU 0 
[  491.162333] Modules linked in:
[  491.162333] 
[  491.162333] Pid: 31, comm: events/0 Not tainted
2.6.34.5-cleancache_frontswap_tmem_hotplug #2 /
[  491.162333] RIP: e030:[<ffffffff81172165>]  [<ffffffff81172165>]
balloon_process+0xc6/0x80d
[  491.162333] RSP: e02b:ffff880176d23db0  EFLAGS: 00010046
[  491.162333] RAX: 0000000000000000 RBX: 0000000000000000 RCX:
0000000000000080
[  491.162333] RDX: ffffffff813d1790 RSI: 6db6db6db6db6db7 RDI:
ffffffff815117b0
[  491.162333] RBP: ffff880176d23e40 R08: dead000000100100 R09:
0000000000000002
[  492.825231] R10: dead000000100100 R11: 0000000000000000 R12:
0000000000000200
[  492.825231] R13: 0000000000000200 R14: 00000000000fa080 R15:
ffffea00050795a0
[  492.825231] FS:  00007fadd42eb720(0000) GS:ffff88000251d000(0000)
knlGS:0000000000000000
[  492.825231] CS:  e033 DS: 0000 ES: 0000 CR0: 000000008005003b
[  492.825231] CR2: 00000000019e00e0 CR3: 00000000d3557000 CR4:
0000000000002660
[  492.825231] DR0: 0000000000000000 DR1: 0000000000000000 DR2:
0000000000000000
[  492.825231] DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7:
0000000000000400
[  492.825231] Process events/0 (pid: 31, threadinfo ffff880176d22000,
task ffff880176d02fb0)
[  492.825231] Stack:
[  492.825231]  ffff880176d02fb0 00000000000131c0 00000000000131c0
ffff880176d23df0
[  492.825231] <0> 0000000000000000 ffff880176d23fd8 ffff880176d23fd8
0000000000000200
[  492.825231] <0> 0000000000000000 0000000000000000 0000000000000000
0000000000007ff0
[  492.825231] Call Trace:
[  492.825231]  [<ffffffff810429ad>] worker_thread+0x15b/0x1e4
[  492.825231]  [<ffffffff8117209f>] ? balloon_process+0x0/0x80d
[  492.825231]  [<ffffffff81046179>] ? autoremove_wake_function+0x0/0x34
[  492.825231]  [<ffffffff81042852>] ? worker_thread+0x0/0x1e4
[  492.825231]  [<ffffffff81045d9b>] kthread+0x7a/0x82
[  492.825231]  [<ffffffff81008a04>] kernel_thread_helper+0x4/0x10
[  492.825231]  [<ffffffff81007e21>] ? int_ret_from_sys_call+0x7/0x1b
[  492.825231]  [<ffffffff8125579d>] ? retint_restore_args+0x5/0x6
[  492.825231]  [<ffffffff81008a00>] ? kernel_thread_helper+0x0/0x10
[  492.825231] Code: 0e 00 48 8b 15 4d f6 25 00 48 8b 4d 90 48 81 fa 90
17 3d 81 48 89 45 a8 48 8d 42 d8 48 0f 44 c1 31 c9 31 db eb 45 48 85 c0
75 02 <0f> 0b 48 ba 00 00 00 00 00 16 00 00 48 be b7 6d db b6 6d db b6 
[  492.825231] RIP  [<ffffffff81172165>] balloon_process+0xc6/0x80d
[  492.825231]  RSP <ffff880176d23db0>
[  492.825231] ---[ end trace cc4f9bc7a1d45b2e ]---
 

-- 
Vasiliy G Tolstov <v.tolstov@selfip.ru>
Selfip.Ru

[-- Attachment #2: 2.6.34.5.config --]
[-- Type: text/x-mpsub, Size: 31124 bytes --]

#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.34.5
# Tue Aug 24 13:09:02 2010
#
CONFIG_64BIT=y
# CONFIG_X86_32 is not set
CONFIG_X86_64=y
CONFIG_X86=y
CONFIG_OUTPUT_FORMAT="elf64-x86-64"
CONFIG_ARCH_DEFCONFIG="arch/x86/configs/x86_64_defconfig"
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CMOS_UPDATE=y
CONFIG_CLOCKSOURCE_WATCHDOG=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_LOCKDEP_SUPPORT=y
CONFIG_STACKTRACE_SUPPORT=y
CONFIG_HAVE_LATENCYTOP_SUPPORT=y
CONFIG_MMU=y
CONFIG_ZONE_DMA=y
CONFIG_NEED_DMA_MAP_STATE=y
CONFIG_GENERIC_ISA_DMA=y
CONFIG_GENERIC_IOMAP=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
CONFIG_GENERIC_HWEIGHT=y
CONFIG_ARCH_MAY_HAVE_PC_FDC=y
# CONFIG_RWSEM_GENERIC_SPINLOCK is not set
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_GENERIC_TIME_VSYSCALL=y
CONFIG_ARCH_HAS_CPU_RELAX=y
CONFIG_ARCH_HAS_DEFAULT_IDLE=y
CONFIG_ARCH_HAS_CACHE_LINE_SIZE=y
CONFIG_HAVE_SETUP_PER_CPU_AREA=y
CONFIG_NEED_PER_CPU_EMBED_FIRST_CHUNK=y
CONFIG_NEED_PER_CPU_PAGE_FIRST_CHUNK=y
CONFIG_HAVE_CPUMASK_OF_CPU_MAP=y
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ZONE_DMA32=y
CONFIG_ARCH_POPULATES_NODE_MAP=y
CONFIG_AUDIT_ARCH=y
CONFIG_ARCH_SUPPORTS_OPTIMIZED_INLINING=y
CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y
CONFIG_HAVE_EARLY_RES=y
CONFIG_GENERIC_HARDIRQS=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_GENERIC_PENDING_IRQ=y
CONFIG_USE_GENERIC_SMP_HELPERS=y
CONFIG_X86_64_SMP=y
CONFIG_X86_HT=y
CONFIG_X86_TRAMPOLINE=y
# CONFIG_KTIME_SCALAR is not set
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
CONFIG_CONSTRUCTORS=y

#
# General setup
#
CONFIG_EXPERIMENTAL=y
CONFIG_LOCK_KERNEL=y
CONFIG_INIT_ENV_ARG_LIMIT=32
CONFIG_LOCALVERSION="-cleancache_frontswap_tmem_hotplug"
CONFIG_LOCALVERSION_AUTO=y
CONFIG_HAVE_KERNEL_GZIP=y
CONFIG_HAVE_KERNEL_BZIP2=y
CONFIG_HAVE_KERNEL_LZMA=y
CONFIG_HAVE_KERNEL_LZO=y
CONFIG_KERNEL_GZIP=y
# CONFIG_KERNEL_BZIP2 is not set
# CONFIG_KERNEL_LZMA is not set
# CONFIG_KERNEL_LZO is not set
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_SYSVIPC_SYSCTL=y
CONFIG_POSIX_MQUEUE=y
CONFIG_POSIX_MQUEUE_SYSCTL=y
CONFIG_BSD_PROCESS_ACCT=y
CONFIG_BSD_PROCESS_ACCT_V3=y
CONFIG_TASKSTATS=y
CONFIG_TASK_DELAY_ACCT=y
CONFIG_TASK_XACCT=y
CONFIG_TASK_IO_ACCOUNTING=y
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
CONFIG_AUDIT_TREE=y

#
# RCU Subsystem
#
CONFIG_TREE_RCU=y
# CONFIG_TREE_PREEMPT_RCU is not set
# CONFIG_TINY_RCU is not set
# CONFIG_RCU_TRACE is not set
CONFIG_RCU_FANOUT=64
# CONFIG_RCU_FANOUT_EXACT is not set
# CONFIG_RCU_FAST_NO_HZ is not set
# CONFIG_TREE_RCU_TRACE is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_LOG_BUF_SHIFT=18
CONFIG_HAVE_UNSTABLE_SCHED_CLOCK=y
CONFIG_CGROUPS=y
# CONFIG_CGROUP_DEBUG is not set
CONFIG_CGROUP_NS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CPUSETS=y
# CONFIG_PROC_PID_CPUSET is not set
CONFIG_CGROUP_CPUACCT=y
CONFIG_RESOURCE_COUNTERS=y
CONFIG_CGROUP_MEM_RES_CTLR=y
CONFIG_CGROUP_MEM_RES_CTLR_SWAP=y
CONFIG_CGROUP_SCHED=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_RT_GROUP_SCHED=y
CONFIG_MM_OWNER=y
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_RELAY=y
CONFIG_NAMESPACES=y
CONFIG_UTS_NS=y
CONFIG_IPC_NS=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_NET_NS=y
CONFIG_BLK_DEV_INITRD=y
CONFIG_INITRAMFS_SOURCE=""
CONFIG_RD_GZIP=y
CONFIG_RD_BZIP2=y
CONFIG_RD_LZMA=y
CONFIG_RD_LZO=y
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_EXTRA_PASS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
CONFIG_PCSPKR_PLATFORM=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
CONFIG_AIO=y
CONFIG_HAVE_PERF_EVENTS=y

#
# Kernel Performance Events And Counters
#
CONFIG_PERF_EVENTS=y
# CONFIG_PERF_COUNTERS is not set
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_SLUB_DEBUG=y
# CONFIG_COMPAT_BRK is not set
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
# CONFIG_PROFILING is not set
CONFIG_HAVE_OPROFILE=y
# CONFIG_KPROBES is not set
CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y
CONFIG_HAVE_IOREMAP_PROT=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
CONFIG_HAVE_OPTPROBES=y
CONFIG_HAVE_ARCH_TRACEHOOK=y
CONFIG_HAVE_DMA_ATTRS=y
CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
CONFIG_HAVE_DMA_API_DEBUG=y
CONFIG_HAVE_HW_BREAKPOINT=y
CONFIG_HAVE_USER_RETURN_NOTIFIER=y

#
# GCOV-based kernel profiling
#
# CONFIG_GCOV_KERNEL is not set
# CONFIG_SLOW_WORK is not set
# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
CONFIG_MODULE_FORCE_LOAD=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODVERSIONS=y
CONFIG_MODULE_SRCVERSION_ALL=y
CONFIG_STOP_MACHINE=y
CONFIG_BLOCK=y
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
CONFIG_BLK_CGROUP=y
# CONFIG_DEBUG_BLK_CGROUP is not set
CONFIG_BLOCK_COMPAT=y

#
# IO Schedulers
#
CONFIG_IOSCHED_NOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=y
CONFIG_CFQ_GROUP_IOSCHED=y
# CONFIG_DEBUG_CFQ_IOSCHED is not set
# CONFIG_DEFAULT_DEADLINE is not set
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
# CONFIG_INLINE_SPIN_TRYLOCK is not set
# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
# CONFIG_INLINE_SPIN_LOCK is not set
# CONFIG_INLINE_SPIN_LOCK_BH is not set
# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
CONFIG_INLINE_SPIN_UNLOCK=y
# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
# CONFIG_INLINE_READ_TRYLOCK is not set
# CONFIG_INLINE_READ_LOCK is not set
# CONFIG_INLINE_READ_LOCK_BH is not set
# CONFIG_INLINE_READ_LOCK_IRQ is not set
# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
CONFIG_INLINE_READ_UNLOCK=y
# CONFIG_INLINE_READ_UNLOCK_BH is not set
CONFIG_INLINE_READ_UNLOCK_IRQ=y
# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
# CONFIG_INLINE_WRITE_TRYLOCK is not set
# CONFIG_INLINE_WRITE_LOCK is not set
# CONFIG_INLINE_WRITE_LOCK_BH is not set
# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
CONFIG_INLINE_WRITE_UNLOCK=y
# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
CONFIG_MUTEX_SPIN_ON_OWNER=y
CONFIG_FREEZER=y

#
# Processor type and features
#
CONFIG_TICK_ONESHOT=y
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
CONFIG_SMP=y
CONFIG_X86_MPPARSE=y
# CONFIG_X86_EXTENDED_PLATFORM is not set
CONFIG_SCHED_OMIT_FRAME_POINTER=y
CONFIG_PARAVIRT_GUEST=y
CONFIG_XEN=y
CONFIG_XEN_MAX_DOMAIN_MEMORY=64
CONFIG_XEN_DEBUG_FS=y
# CONFIG_KVM_CLOCK is not set
# CONFIG_KVM_GUEST is not set
CONFIG_PARAVIRT=y
# CONFIG_PARAVIRT_SPINLOCKS is not set
CONFIG_PARAVIRT_CLOCK=y
# CONFIG_NO_BOOTMEM is not set
# CONFIG_MEMTEST is not set
# CONFIG_M386 is not set
# CONFIG_M486 is not set
# CONFIG_M586 is not set
# CONFIG_M586TSC is not set
# CONFIG_M586MMX is not set
# CONFIG_M686 is not set
# CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set
# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
# CONFIG_MCRUSOE is not set
# CONFIG_MEFFICEON is not set
# CONFIG_MWINCHIPC6 is not set
# CONFIG_MWINCHIP3D is not set
# CONFIG_MGEODEGX1 is not set
# CONFIG_MGEODE_LX is not set
# CONFIG_MCYRIXIII is not set
# CONFIG_MVIAC3_2 is not set
# CONFIG_MVIAC7 is not set
# CONFIG_MPSC is not set
CONFIG_MCORE2=y
# CONFIG_MATOM is not set
# CONFIG_GENERIC_CPU is not set
CONFIG_X86_CPU=y
CONFIG_X86_INTERNODE_CACHE_SHIFT=6
CONFIG_X86_CMPXCHG=y
CONFIG_X86_L1_CACHE_SHIFT=6
CONFIG_X86_XADD=y
CONFIG_X86_WP_WORKS_OK=y
CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
CONFIG_X86_P6_NOP=y
CONFIG_X86_TSC=y
CONFIG_X86_CMPXCHG64=y
CONFIG_X86_CMOV=y
CONFIG_X86_MINIMUM_CPU_FAMILY=64
CONFIG_X86_DEBUGCTLMSR=y
CONFIG_CPU_SUP_INTEL=y
CONFIG_CPU_SUP_AMD=y
CONFIG_CPU_SUP_CENTAUR=y
# CONFIG_X86_DS is not set
CONFIG_HPET_TIMER=y
CONFIG_DMI=y
CONFIG_SWIOTLB=y
CONFIG_IOMMU_HELPER=y
# CONFIG_IOMMU_API is not set
CONFIG_NR_CPUS=24
CONFIG_SCHED_SMT=y
CONFIG_SCHED_MC=y
CONFIG_PREEMPT_NONE=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_PREEMPT is not set
CONFIG_X86_LOCAL_APIC=y
CONFIG_X86_IO_APIC=y
# CONFIG_X86_REROUTE_FOR_BROKEN_BOOT_IRQS is not set
# CONFIG_X86_MCE is not set
# CONFIG_I8K is not set
# CONFIG_MICROCODE is not set
CONFIG_X86_MSR=y
CONFIG_X86_CPUID=y
CONFIG_ARCH_PHYS_ADDR_T_64BIT=y
CONFIG_DIRECT_GBPAGES=y
# CONFIG_NUMA is not set
CONFIG_ARCH_PROC_KCORE_TEXT=y
CONFIG_ARCH_SPARSEMEM_DEFAULT=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
CONFIG_ARCH_MEMORY_PROBE=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_SELECT_MEMORY_MODEL=y
# CONFIG_FLATMEM_MANUAL is not set
# CONFIG_DISCONTIGMEM_MANUAL is not set
CONFIG_SPARSEMEM_MANUAL=y
CONFIG_SPARSEMEM=y
CONFIG_HAVE_MEMORY_PRESENT=y
CONFIG_SPARSEMEM_EXTREME=y
CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER=y
CONFIG_SPARSEMEM_VMEMMAP=y
CONFIG_MEMORY_HOTPLUG=y
CONFIG_MEMORY_HOTPLUG_SPARSE=y
CONFIG_MEMORY_HOTREMOVE=y
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4
CONFIG_MIGRATION=y
CONFIG_PHYS_ADDR_T_64BIT=y
CONFIG_ZONE_DMA_FLAG=1
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
# CONFIG_KSM is not set
CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
CONFIG_CLEANCACHE=y
CONFIG_FRONTSWAP=y
# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
# CONFIG_X86_RESERVE_LOW_64K is not set
CONFIG_MTRR=y
# CONFIG_MTRR_SANITIZER is not set
CONFIG_X86_PAT=y
CONFIG_ARCH_USES_PG_UNCACHED=y
CONFIG_SECCOMP=y
# CONFIG_CC_STACKPROTECTOR is not set
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_SCHED_HRTICK=y
# CONFIG_KEXEC is not set
# CONFIG_CRASH_DUMP is not set
CONFIG_PHYSICAL_START=0x1000000
# CONFIG_RELOCATABLE is not set
CONFIG_PHYSICAL_ALIGN=0x1000000
CONFIG_HOTPLUG_CPU=y
# CONFIG_COMPAT_VDSO is not set
# CONFIG_CMDLINE_BOOL is not set
CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y
CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE=y

#
# Power management and ACPI options
#
# CONFIG_PM is not set
# CONFIG_SFI is not set

#
# CPU Frequency scaling
#
# CONFIG_CPU_FREQ is not set
# CONFIG_CPU_IDLE is not set

#
# Memory power savings
#
# CONFIG_I7300_IDLE is not set

#
# Bus options (PCI etc.)
#
# CONFIG_PCI is not set
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_ISA_DMA_API=y
# CONFIG_PCCARD is not set

#
# Executable file formats / Emulations
#
CONFIG_BINFMT_ELF=y
CONFIG_COMPAT_BINFMT_ELF=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
# CONFIG_HAVE_AOUT is not set
# CONFIG_BINFMT_MISC is not set
CONFIG_IA32_EMULATION=y
# CONFIG_IA32_AOUT is not set
CONFIG_COMPAT=y
CONFIG_COMPAT_FOR_U64_ALIGNMENT=y
CONFIG_SYSVIPC_COMPAT=y
CONFIG_NET=y

#
# Networking options
#
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM=y
CONFIG_XFRM_USER=y
# CONFIG_XFRM_SUB_POLICY is not set
# CONFIG_XFRM_MIGRATE is not set
# CONFIG_XFRM_STATISTICS is not set
# CONFIG_NET_KEY is not set
CONFIG_INET=y
CONFIG_IP_MULTICAST=y
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_ASK_IP_FIB_HASH=y
# CONFIG_IP_FIB_TRIE is not set
CONFIG_IP_FIB_HASH=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_ROUTE_MULTIPATH=y
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_IP_PNP_BOOTP=y
CONFIG_IP_PNP_RARP=y
# CONFIG_NET_IPIP is not set
# CONFIG_NET_IPGRE is not set
CONFIG_IP_MROUTE=y
CONFIG_IP_PIMSM_V1=y
CONFIG_IP_PIMSM_V2=y
# CONFIG_ARPD is not set
CONFIG_SYN_COOKIES=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
# CONFIG_INET_XFRM_TUNNEL is not set
CONFIG_INET_TUNNEL=y
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
# CONFIG_INET_XFRM_MODE_BEET is not set
CONFIG_INET_LRO=y
# CONFIG_INET_DIAG is not set
CONFIG_TCP_CONG_ADVANCED=y
# CONFIG_TCP_CONG_BIC is not set
CONFIG_TCP_CONG_CUBIC=y
# CONFIG_TCP_CONG_WESTWOOD is not set
# CONFIG_TCP_CONG_HTCP is not set
# CONFIG_TCP_CONG_HSTCP is not set
# CONFIG_TCP_CONG_HYBLA is not set
# CONFIG_TCP_CONG_VEGAS is not set
# CONFIG_TCP_CONG_SCALABLE is not set
# CONFIG_TCP_CONG_LP is not set
# CONFIG_TCP_CONG_VENO is not set
# CONFIG_TCP_CONG_YEAH is not set
# CONFIG_TCP_CONG_ILLINOIS is not set
# CONFIG_DEFAULT_BIC is not set
CONFIG_DEFAULT_CUBIC=y
# CONFIG_DEFAULT_HTCP is not set
# CONFIG_DEFAULT_VEGAS is not set
# CONFIG_DEFAULT_WESTWOOD is not set
# CONFIG_DEFAULT_RENO is not set
CONFIG_DEFAULT_TCP_CONG="cubic"
CONFIG_TCP_MD5SIG=y
CONFIG_IPV6=y
# CONFIG_IPV6_PRIVACY is not set
# CONFIG_IPV6_ROUTER_PREF is not set
# CONFIG_IPV6_OPTIMISTIC_DAD is not set
CONFIG_INET6_AH=y
CONFIG_INET6_ESP=y
# CONFIG_INET6_IPCOMP is not set
# CONFIG_IPV6_MIP6 is not set
# CONFIG_INET6_XFRM_TUNNEL is not set
# CONFIG_INET6_TUNNEL is not set
CONFIG_INET6_XFRM_MODE_TRANSPORT=y
CONFIG_INET6_XFRM_MODE_TUNNEL=y
CONFIG_INET6_XFRM_MODE_BEET=y
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
CONFIG_IPV6_SIT=y
# CONFIG_IPV6_SIT_6RD is not set
CONFIG_IPV6_NDISC_NODETYPE=y
# CONFIG_IPV6_TUNNEL is not set
# CONFIG_IPV6_MULTIPLE_TABLES is not set
# CONFIG_IPV6_MROUTE is not set
CONFIG_NETWORK_SECMARK=y
# CONFIG_NETFILTER is not set
# CONFIG_IP_DCCP is not set
# CONFIG_IP_SCTP is not set
# CONFIG_RDS is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_IPX is not set
# CONFIG_ATALK is not set
# CONFIG_X25 is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
# CONFIG_PHONET is not set
# CONFIG_IEEE802154 is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set

#
# Network testing
#
# CONFIG_NET_PKTGEN is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
CONFIG_FIB_RULES=y
# CONFIG_WIRELESS is not set
# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set

#
# Device Drivers
#

#
# Generic Driver Options
#
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
CONFIG_FIRMWARE_IN_KERNEL=y
CONFIG_EXTRA_FIRMWARE=""
CONFIG_SYS_HYPERVISOR=y
CONFIG_CONNECTOR=y
CONFIG_PROC_EVENTS=y
# CONFIG_MTD is not set
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_FD is not set
# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_DRBD is not set
# CONFIG_BLK_DEV_NBD is not set
# CONFIG_BLK_DEV_RAM is not set
# CONFIG_CDROM_PKTCDVD is not set
# CONFIG_ATA_OVER_ETH is not set
CONFIG_XEN_BLKDEV_FRONTEND=y
# CONFIG_BLK_DEV_HD is not set
# CONFIG_MISC_DEVICES is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set

#
# SCSI device support
#
CONFIG_SCSI_MOD=y
# CONFIG_RAID_ATTRS is not set
# CONFIG_SCSI is not set
# CONFIG_SCSI_DMA is not set
# CONFIG_SCSI_NETLINK is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
# CONFIG_MACINTOSH_DRIVERS is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_NET_ETHERNET is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_WLAN is not set

#
# Enable WiMAX (Networking options) to see the WiMAX drivers
#
# CONFIG_WAN is not set
CONFIG_XEN_NETDEV_FRONTEND=y
# CONFIG_PPP is not set
# CONFIG_SLIP is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_ISDN is not set
# CONFIG_PHONE is not set

#
# Input device support
#
CONFIG_INPUT=y
CONFIG_INPUT_FF_MEMLESS=y
CONFIG_INPUT_POLLDEV=y
CONFIG_INPUT_SPARSEKMAP=y

#
# Userland interfaces
#
CONFIG_INPUT_MOUSEDEV=y
# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
# CONFIG_INPUT_JOYDEV is not set
CONFIG_INPUT_EVDEV=y
# CONFIG_INPUT_EVBUG is not set
CONFIG_XEN_KBDDEV_FRONTEND=y

#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
# CONFIG_KEYBOARD_LKKBD is not set
# CONFIG_KEYBOARD_NEWTON is not set
# CONFIG_KEYBOARD_OPENCORES is not set
# CONFIG_KEYBOARD_STOWAWAY is not set
# CONFIG_KEYBOARD_SUNKBD is not set
# CONFIG_KEYBOARD_XTKBD is not set
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
CONFIG_MOUSE_PS2_ALPS=y
CONFIG_MOUSE_PS2_LOGIPS2PP=y
CONFIG_MOUSE_PS2_SYNAPTICS=y
CONFIG_MOUSE_PS2_LIFEBOOK=y
CONFIG_MOUSE_PS2_TRACKPOINT=y
# CONFIG_MOUSE_PS2_ELANTECH is not set
# CONFIG_MOUSE_PS2_SENTELIC is not set
# CONFIG_MOUSE_PS2_TOUCHKIT is not set
# CONFIG_MOUSE_SERIAL is not set
# CONFIG_MOUSE_VSXXXAA is not set
CONFIG_INPUT_JOYSTICK=y
# CONFIG_JOYSTICK_ANALOG is not set
# CONFIG_JOYSTICK_A3D is not set
# CONFIG_JOYSTICK_ADI is not set
# CONFIG_JOYSTICK_COBRA is not set
# CONFIG_JOYSTICK_GF2K is not set
# CONFIG_JOYSTICK_GRIP is not set
# CONFIG_JOYSTICK_GRIP_MP is not set
# CONFIG_JOYSTICK_GUILLEMOT is not set
# CONFIG_JOYSTICK_INTERACT is not set
# CONFIG_JOYSTICK_SIDEWINDER is not set
# CONFIG_JOYSTICK_TMDC is not set
# CONFIG_JOYSTICK_IFORCE is not set
# CONFIG_JOYSTICK_WARRIOR is not set
# CONFIG_JOYSTICK_MAGELLAN is not set
# CONFIG_JOYSTICK_SPACEORB is not set
# CONFIG_JOYSTICK_SPACEBALL is not set
# CONFIG_JOYSTICK_STINGER is not set
# CONFIG_JOYSTICK_TWIDJOY is not set
# CONFIG_JOYSTICK_ZHENHUA is not set
# CONFIG_JOYSTICK_JOYDUMP is not set
CONFIG_INPUT_TABLET=y
CONFIG_INPUT_TOUCHSCREEN=y
# CONFIG_TOUCHSCREEN_AD7879 is not set
# CONFIG_TOUCHSCREEN_DYNAPRO is not set
# CONFIG_TOUCHSCREEN_FUJITSU is not set
# CONFIG_TOUCHSCREEN_GUNZE is not set
# CONFIG_TOUCHSCREEN_ELO is not set
# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
# CONFIG_TOUCHSCREEN_MTOUCH is not set
# CONFIG_TOUCHSCREEN_INEXIO is not set
# CONFIG_TOUCHSCREEN_MK712 is not set
# CONFIG_TOUCHSCREEN_PENMOUNT is not set
# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
CONFIG_INPUT_MISC=y
# CONFIG_INPUT_PCSPKR is not set
# CONFIG_INPUT_UINPUT is not set

#
# Hardware I/O ports
#
CONFIG_SERIO=y
CONFIG_SERIO_I8042=y
CONFIG_SERIO_SERPORT=y
# CONFIG_SERIO_CT82C710 is not set
CONFIG_SERIO_LIBPS2=y
# CONFIG_SERIO_RAW is not set
# CONFIG_SERIO_ALTERA_PS2 is not set
# CONFIG_GAMEPORT is not set

#
# Character devices
#
CONFIG_VT=y
CONFIG_CONSOLE_TRANSLATIONS=y
CONFIG_VT_CONSOLE=y
CONFIG_HW_CONSOLE=y
CONFIG_VT_HW_CONSOLE_BINDING=y
CONFIG_DEVKMEM=y
# CONFIG_SERIAL_NONSTANDARD is not set

#
# Serial drivers
#
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_SERIAL_8250_NR_UARTS=32
CONFIG_SERIAL_8250_RUNTIME_UARTS=4
CONFIG_SERIAL_8250_EXTENDED=y
CONFIG_SERIAL_8250_MANY_PORTS=y
CONFIG_SERIAL_8250_SHARE_IRQ=y
CONFIG_SERIAL_8250_DETECT_IRQ=y
CONFIG_SERIAL_8250_RSA=y

#
# Non-8250 serial port support
#
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_TIMBERDALE is not set
CONFIG_UNIX98_PTYS=y
# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
# CONFIG_LEGACY_PTYS is not set
CONFIG_HVC_DRIVER=y
CONFIG_HVC_IRQ=y
CONFIG_HVC_XEN=y
# CONFIG_IPMI_HANDLER is not set
CONFIG_HW_RANDOM=y
# CONFIG_HW_RANDOM_TIMERIOMEM is not set
CONFIG_HW_RANDOM_VIA=y
CONFIG_NVRAM=y
# CONFIG_RTC is not set
# CONFIG_GEN_RTC is not set
# CONFIG_R3964 is not set
# CONFIG_MWAVE is not set
# CONFIG_PC8736x_GPIO is not set
# CONFIG_RAW_DRIVER is not set
# CONFIG_HANGCHECK_TIMER is not set
# CONFIG_TCG_TPM is not set
# CONFIG_TELCLOCK is not set
# CONFIG_I2C is not set
# CONFIG_SPI is not set

#
# PPS support
#
# CONFIG_PPS is not set
CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
# CONFIG_GPIOLIB is not set
# CONFIG_W1 is not set
# CONFIG_POWER_SUPPLY is not set
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_WATCHDOG is not set
CONFIG_SSB_POSSIBLE=y

#
# Sonics Silicon Backplane
#
# CONFIG_SSB is not set

#
# Multifunction device drivers
#
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_REGULATOR is not set
# CONFIG_MEDIA_SUPPORT is not set

#
# Graphics support
#
# CONFIG_VGASTATE is not set
# CONFIG_VIDEO_OUTPUT_CONTROL is not set
CONFIG_FB=y
# CONFIG_FIRMWARE_EDID is not set
# CONFIG_FB_DDC is not set
CONFIG_FB_BOOT_VESA_SUPPORT=y
CONFIG_FB_CFB_FILLRECT=y
CONFIG_FB_CFB_COPYAREA=y
CONFIG_FB_CFB_IMAGEBLIT=y
# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
CONFIG_FB_SYS_FILLRECT=y
CONFIG_FB_SYS_COPYAREA=y
CONFIG_FB_SYS_IMAGEBLIT=y
# CONFIG_FB_FOREIGN_ENDIAN is not set
CONFIG_FB_SYS_FOPS=y
CONFIG_FB_DEFERRED_IO=y
# CONFIG_FB_SVGALIB is not set
# CONFIG_FB_MACMODES is not set
# CONFIG_FB_BACKLIGHT is not set
CONFIG_FB_MODE_HELPERS=y
CONFIG_FB_TILEBLITTING=y

#
# Frame buffer hardware drivers
#
# CONFIG_FB_ARC is not set
# CONFIG_FB_VGA16 is not set
# CONFIG_FB_UVESA is not set
CONFIG_FB_VESA=y
# CONFIG_FB_N411 is not set
# CONFIG_FB_HGA is not set
# CONFIG_FB_S1D13XXX is not set
# CONFIG_FB_VIRTUAL is not set
CONFIG_XEN_FBDEV_FRONTEND=y
# CONFIG_FB_METRONOME is not set
# CONFIG_FB_MB862XX is not set
# CONFIG_FB_BROADSHEET is not set
# CONFIG_BACKLIGHT_LCD_SUPPORT is not set

#
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set

#
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
CONFIG_VGACON_SOFT_SCROLLBACK=y
CONFIG_VGACON_SOFT_SCROLLBACK_SIZE=64
CONFIG_DUMMY_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
# CONFIG_FONTS is not set
CONFIG_FONT_8x8=y
CONFIG_FONT_8x16=y
# CONFIG_LOGO is not set
# CONFIG_SOUND is not set
# CONFIG_HID_SUPPORT is not set
# CONFIG_USB_SUPPORT is not set
# CONFIG_MMC is not set
# CONFIG_MEMSTICK is not set
# CONFIG_NEW_LEDS is not set
# CONFIG_ACCESSIBILITY is not set
# CONFIG_EDAC is not set
# CONFIG_RTC_CLASS is not set
# CONFIG_DMADEVICES is not set
# CONFIG_AUXDISPLAY is not set
# CONFIG_UIO is not set

#
# TI VLYNQ
#

#
# Xen driver support
#
CONFIG_XEN_BALLOON=y
CONFIG_XEN_BALLOON_MEMORY_HOTPLUG=y
CONFIG_XEN_SELFBALLOONING=y
CONFIG_XEN_SCRUB_PAGES=y
CONFIG_XEN_DEV_EVTCHN=y
CONFIG_XENFS=y
CONFIG_XEN_COMPAT_XENFS=y
CONFIG_XEN_SYS_HYPERVISOR=y
# CONFIG_STAGING is not set
# CONFIG_X86_PLATFORM_DEVICES is not set

#
# Firmware Drivers
#
# CONFIG_EDD is not set
CONFIG_FIRMWARE_MEMMAP=y
# CONFIG_DELL_RBU is not set
# CONFIG_DCDBAS is not set
# CONFIG_DMIID is not set
# CONFIG_ISCSI_IBFT_FIND is not set

#
# File systems
#
# CONFIG_EXT2_FS is not set
CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
CONFIG_FS_POSIX_ACL=y
# CONFIG_XFS_FS is not set
# CONFIG_GFS2_FS is not set
# CONFIG_OCFS2_FS is not set
# CONFIG_BTRFS_FS is not set
# CONFIG_NILFS2_FS is not set
CONFIG_FILE_LOCKING=y
CONFIG_FSNOTIFY=y
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
CONFIG_QUOTA=y
CONFIG_QUOTA_NETLINK_INTERFACE=y
# CONFIG_PRINT_QUOTA_WARNING is not set
# CONFIG_QUOTA_DEBUG is not set
CONFIG_QUOTA_TREE=y
# CONFIG_QFMT_V1 is not set
CONFIG_QFMT_V2=y
CONFIG_QUOTACTL=y
CONFIG_QUOTACTL_COMPAT=y
# CONFIG_AUTOFS_FS is not set
# CONFIG_AUTOFS4_FS is not set
CONFIG_FUSE_FS=y
CONFIG_CUSE=y
CONFIG_GENERIC_ACL=y

#
# Caches
#
# CONFIG_FSCACHE is not set

#
# CD-ROM/DVD Filesystems
#
CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
CONFIG_ZISOFS=y
# CONFIG_UDF_FS is not set

#
# DOS/FAT/NT Filesystems
#
# CONFIG_MSDOS_FS is not set
# CONFIG_VFAT_FS is not set
# CONFIG_NTFS_FS is not set

#
# Pseudo filesystems
#
CONFIG_PROC_FS=y
CONFIG_PROC_KCORE=y
CONFIG_PROC_SYSCTL=y
CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
CONFIG_TMPFS_POSIX_ACL=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y
# CONFIG_CONFIGFS_FS is not set
# CONFIG_MISC_FILESYSTEMS is not set
# CONFIG_NETWORK_FILESYSTEMS is not set

#
# Partition Types
#
CONFIG_PARTITION_ADVANCED=y
# CONFIG_ACORN_PARTITION is not set
# CONFIG_OSF_PARTITION is not set
CONFIG_AMIGA_PARTITION=y
# CONFIG_ATARI_PARTITION is not set
# CONFIG_MAC_PARTITION is not set
CONFIG_MSDOS_PARTITION=y
# CONFIG_BSD_DISKLABEL is not set
# CONFIG_MINIX_SUBPARTITION is not set
# CONFIG_SOLARIS_X86_PARTITION is not set
# CONFIG_UNIXWARE_DISKLABEL is not set
# CONFIG_LDM_PARTITION is not set
# CONFIG_SGI_PARTITION is not set
# CONFIG_ULTRIX_PARTITION is not set
# CONFIG_SUN_PARTITION is not set
# CONFIG_KARMA_PARTITION is not set
# CONFIG_EFI_PARTITION is not set
# CONFIG_SYSV68_PARTITION is not set
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
# CONFIG_NLS_CODEPAGE_737 is not set
# CONFIG_NLS_CODEPAGE_775 is not set
# CONFIG_NLS_CODEPAGE_850 is not set
# CONFIG_NLS_CODEPAGE_852 is not set
# CONFIG_NLS_CODEPAGE_855 is not set
# CONFIG_NLS_CODEPAGE_857 is not set
# CONFIG_NLS_CODEPAGE_860 is not set
# CONFIG_NLS_CODEPAGE_861 is not set
# CONFIG_NLS_CODEPAGE_862 is not set
# CONFIG_NLS_CODEPAGE_863 is not set
# CONFIG_NLS_CODEPAGE_864 is not set
# CONFIG_NLS_CODEPAGE_865 is not set
# CONFIG_NLS_CODEPAGE_866 is not set
# CONFIG_NLS_CODEPAGE_869 is not set
# CONFIG_NLS_CODEPAGE_936 is not set
# CONFIG_NLS_CODEPAGE_950 is not set
# CONFIG_NLS_CODEPAGE_932 is not set
# CONFIG_NLS_CODEPAGE_949 is not set
# CONFIG_NLS_CODEPAGE_874 is not set
# CONFIG_NLS_ISO8859_8 is not set
# CONFIG_NLS_CODEPAGE_1250 is not set
# CONFIG_NLS_CODEPAGE_1251 is not set
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
# CONFIG_NLS_ISO8859_2 is not set
# CONFIG_NLS_ISO8859_3 is not set
# CONFIG_NLS_ISO8859_4 is not set
# CONFIG_NLS_ISO8859_5 is not set
# CONFIG_NLS_ISO8859_6 is not set
# CONFIG_NLS_ISO8859_7 is not set
# CONFIG_NLS_ISO8859_9 is not set
# CONFIG_NLS_ISO8859_13 is not set
# CONFIG_NLS_ISO8859_14 is not set
# CONFIG_NLS_ISO8859_15 is not set
# CONFIG_NLS_KOI8_R is not set
# CONFIG_NLS_KOI8_U is not set
CONFIG_NLS_UTF8=y
# CONFIG_DLM is not set

#
# Kernel hacking
#
CONFIG_TRACE_IRQFLAGS_SUPPORT=y
CONFIG_PRINTK_TIME=y
# CONFIG_ENABLE_WARN_DEPRECATED is not set
CONFIG_ENABLE_MUST_CHECK=y
CONFIG_FRAME_WARN=2048
CONFIG_MAGIC_SYSRQ=y
# CONFIG_STRIP_ASM_SYMS is not set
# CONFIG_UNUSED_SYMBOLS is not set
CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_SLUB_DEBUG_ON is not set
# CONFIG_SLUB_STATS is not set
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_ARCH_WANT_FRAME_POINTERS=y
CONFIG_FRAME_POINTER=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_LKDTM is not set
# CONFIG_LATENCYTOP is not set
# CONFIG_SYSCTL_SYSCALL_CHECK is not set
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
CONFIG_HAVE_FUNCTION_GRAPH_FP_TEST=y
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
CONFIG_HAVE_DYNAMIC_FTRACE=y
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
CONFIG_HAVE_SYSCALL_TRACEPOINTS=y
CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
CONFIG_HAVE_ARCH_KMEMCHECK=y
CONFIG_STRICT_DEVMEM=y
CONFIG_X86_VERBOSE_BOOTUP=y
CONFIG_EARLY_PRINTK=y
# CONFIG_IOMMU_STRESS is not set
CONFIG_HAVE_MMIOTRACE_SUPPORT=y
CONFIG_IO_DELAY_TYPE_0X80=0
CONFIG_IO_DELAY_TYPE_0XED=1
CONFIG_IO_DELAY_TYPE_UDELAY=2
CONFIG_IO_DELAY_TYPE_NONE=3
CONFIG_IO_DELAY_0X80=y
# CONFIG_IO_DELAY_0XED is not set
# CONFIG_IO_DELAY_UDELAY is not set
# CONFIG_IO_DELAY_NONE is not set
CONFIG_DEFAULT_IO_DELAY_TYPE=0
CONFIG_OPTIMIZE_INLINING=y

#
# Security options
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
# CONFIG_SECURITYFS is not set
# CONFIG_DEFAULT_SECURITY_SELINUX is not set
# CONFIG_DEFAULT_SECURITY_SMACK is not set
# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
CONFIG_DEFAULT_SECURITY_DAC=y
CONFIG_DEFAULT_SECURITY=""
CONFIG_CRYPTO=y

#
# Crypto core or helper
#
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=y
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
# CONFIG_CRYPTO_PCRYPT is not set
CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
CONFIG_CRYPTO_AUTHENC=y
# CONFIG_CRYPTO_TEST is not set

#
# Authenticated Encryption with Associated Data
#
# CONFIG_CRYPTO_CCM is not set
# CONFIG_CRYPTO_GCM is not set
# CONFIG_CRYPTO_SEQIV is not set

#
# Block modes
#
CONFIG_CRYPTO_CBC=y
# CONFIG_CRYPTO_CTR is not set
# CONFIG_CRYPTO_CTS is not set
CONFIG_CRYPTO_ECB=y
# CONFIG_CRYPTO_LRW is not set
# CONFIG_CRYPTO_PCBC is not set
# CONFIG_CRYPTO_XTS is not set

#
# Hash modes
#
CONFIG_CRYPTO_HMAC=y
# CONFIG_CRYPTO_XCBC is not set
# CONFIG_CRYPTO_VMAC is not set

#
# Digest
#
# CONFIG_CRYPTO_CRC32C is not set
# CONFIG_CRYPTO_CRC32C_INTEL is not set
# CONFIG_CRYPTO_GHASH is not set
# CONFIG_CRYPTO_MD4 is not set
CONFIG_CRYPTO_MD5=y
# CONFIG_CRYPTO_MICHAEL_MIC is not set
# CONFIG_CRYPTO_RMD128 is not set
# CONFIG_CRYPTO_RMD160 is not set
# CONFIG_CRYPTO_RMD256 is not set
# CONFIG_CRYPTO_RMD320 is not set
CONFIG_CRYPTO_SHA1=y
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
# CONFIG_CRYPTO_TGR192 is not set
# CONFIG_CRYPTO_WP512 is not set
# CONFIG_CRYPTO_GHASH_CLMUL_NI_INTEL is not set

#
# Ciphers
#
CONFIG_CRYPTO_AES=y
CONFIG_CRYPTO_AES_X86_64=y
# CONFIG_CRYPTO_AES_NI_INTEL is not set
# CONFIG_CRYPTO_ANUBIS is not set
CONFIG_CRYPTO_ARC4=y
# CONFIG_CRYPTO_BLOWFISH is not set
# CONFIG_CRYPTO_CAMELLIA is not set
# CONFIG_CRYPTO_CAST5 is not set
# CONFIG_CRYPTO_CAST6 is not set
CONFIG_CRYPTO_DES=y
# CONFIG_CRYPTO_FCRYPT is not set
# CONFIG_CRYPTO_KHAZAD is not set
# CONFIG_CRYPTO_SALSA20 is not set
# CONFIG_CRYPTO_SALSA20_X86_64 is not set
# CONFIG_CRYPTO_SEED is not set
# CONFIG_CRYPTO_SERPENT is not set
# CONFIG_CRYPTO_TEA is not set
# CONFIG_CRYPTO_TWOFISH is not set
# CONFIG_CRYPTO_TWOFISH_X86_64 is not set

#
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set

#
# Random Number Generation
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_PADLOCK is not set
CONFIG_HAVE_KVM=y
# CONFIG_VIRTUALIZATION is not set
# CONFIG_BINARY_PRINTF is not set

#
# Library routines
#
CONFIG_BITREVERSE=y
CONFIG_GENERIC_FIND_FIRST_BIT=y
CONFIG_GENERIC_FIND_NEXT_BIT=y
CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
# CONFIG_CRC16 is not set
CONFIG_CRC_T10DIF=y
# CONFIG_CRC_ITU_T is not set
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_DECOMPRESS_GZIP=y
CONFIG_DECOMPRESS_BZIP2=y
CONFIG_DECOMPRESS_LZMA=y
CONFIG_DECOMPRESS_LZO=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_NLATTR=y

[-- Attachment #3: tmem_hotplug.patch --]
[-- Type: text/x-patch, Size: 91654 bytes --]

diff -NruabBEp linux-2.6.34.5/arch/x86/include/asm/xen/hypercall.h l-t/arch/x86/include/asm/xen/hypercall.h
--- linux-2.6.34.5/arch/x86/include/asm/xen/hypercall.h	2010-08-20 22:52:05.000000000 +0400
+++ l-t/arch/x86/include/asm/xen/hypercall.h	2010-08-24 12:36:08.000000000 +0400
@@ -45,6 +45,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/sched.h>
 #include <xen/interface/physdev.h>
+#include <xen/interface/tmem.h>
 
 /*
  * The hypercall asms have to meet several constraints:
@@ -417,6 +418,12 @@ HYPERVISOR_nmi_op(unsigned long op, unsi
 	return _hypercall2(int, nmi_op, op, arg);
 }
 
+static inline int
+HYPERVISOR_tmem_op(struct tmem_op *op)
+{
+	return _hypercall1(int, tmem_op, op);
+}
+
 static inline void
 MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set)
 {
diff -NruabBEp linux-2.6.34.5/Documentation/ABI/testing/sysfs-kernel-mm-cleancache l-t/Documentation/ABI/testing/sysfs-kernel-mm-cleancache
--- linux-2.6.34.5/Documentation/ABI/testing/sysfs-kernel-mm-cleancache	1970-01-01 03:00:00.000000000 +0300
+++ l-t/Documentation/ABI/testing/sysfs-kernel-mm-cleancache	2010-08-24 12:35:44.000000000 +0400
@@ -0,0 +1,11 @@
+What:		/sys/kernel/mm/cleancache/
+Date:		June 2010
+Contact:	Dan Magenheimer <dan.magenheimer@oracle.com>
+Description:
+		/sys/kernel/mm/cleancache/ contains a number of files which
+		record a count of various cleancache operations
+		(sum across all filesystems):
+			succ_gets
+			failed_gets
+			puts
+			flushes
diff -NruabBEp linux-2.6.34.5/Documentation/ABI/testing/sysfs-kernel-mm-frontswap l-t/Documentation/ABI/testing/sysfs-kernel-mm-frontswap
--- linux-2.6.34.5/Documentation/ABI/testing/sysfs-kernel-mm-frontswap	1970-01-01 03:00:00.000000000 +0300
+++ l-t/Documentation/ABI/testing/sysfs-kernel-mm-frontswap	2010-08-24 12:35:47.000000000 +0400
@@ -0,0 +1,16 @@
+What:		/sys/kernel/mm/frontswap/
+Date:		June 2010
+Contact:	Dan Magenheimer <dan.magenheimer@oracle.com>
+Description:
+		/sys/kernel/mm/frontswap/ contains a number of files which
+		record a count of various frontswap operations (sum across
+		all swap devices):
+			succ_puts
+			failed_puts
+			gets
+			flushes
+		In addition, reading the curr_pages file shows how many
+		pages are currently contained in frontswap and writing this
+		file with an integer performs a "partial swapoff", reducing
+		the number of frontswap pages to that integer if memory
+		constraints permit.
diff -NruabBEp linux-2.6.34.5/Documentation/vm/cleancache.txt l-t/Documentation/vm/cleancache.txt
--- linux-2.6.34.5/Documentation/vm/cleancache.txt	1970-01-01 03:00:00.000000000 +0300
+++ l-t/Documentation/vm/cleancache.txt	2010-08-24 12:35:53.000000000 +0400
@@ -0,0 +1,74 @@
+Cleancache can be thought of as a page-granularity victim cache for clean
+pages that the kernel's pageframe replacement algorithm (PFRA) would like
+to keep around, but can't since there isn't enough memory.  So when the
+PFRA "evicts" a page, it first attempts to put it into a synchronous
+concurrency-safe page-oriented "pseudo-RAM" device (such as Xen's Transcendent
+Memory, aka "tmem", or in-kernel compressed memory, aka "zmem", or other
+RAM-like devices) which is not directly accessible or addressable by the
+kernel and is of unknown and possibly time-varying size.  And when a
+cleancache-enabled filesystem wishes to access a page in a file on disk,
+it first checks cleancache to see if it already contains it; if it does,
+the page is copied into the kernel and a disk access is avoided.
+A cleancache "backend" that interfaces to this pseudo-RAM links itself
+to the kernel's cleancache "frontend" by setting the cleancache_ops funcs
+appropriately and the functions it provides must conform to certain
+semantics as follows:
+
+Most important, cleancache is "ephemeral".  Pages which are copied into
+cleancache have an indefinite lifetime which is completely unknowable
+by the kernel and so may or may not still be in cleancache at any later time.
+Thus, as its name implies, cleancache is not suitable for dirty pages.
+Cleancache has complete discretion over what pages to preserve and what
+pages to discard and when.
+
+Mounting a cleancache-enabled filesystem should call "init_fs" to obtain a
+pool id which, if positive, must be saved in the filesystem's superblock;
+a negative return value indicates failure.  A "put_page" will copy a
+(presumably about-to-be-evicted) page into cleancache and associate it with
+the pool id, the file inode, and a page index into the file.  (The combination
+of a pool id, an inode, and an index is sometimes called a "handle".)
+A "get_page" will copy the page, if found, from cleancache into kernel memory.
+A "flush_page" will ensure the page no longer is present in cleancache;
+a "flush_inode" will flush all pages associated with the specified inode;
+and, when a filesystem is unmounted, a "flush_fs" will flush all pages in
+all inodes specified by the given pool id and also surrender the pool id.
+
+A "init_shared_fs", like init, obtains a pool id but tells cleancache
+to treat the pool as shared using a 128-bit UUID as a key.  On systems
+that may run multiple kernels (such as hard partitioned or virtualized
+systems) that may share a clustered filesystem, and where cleancache
+may be shared among those kernels, calls to init_shared_fs that specify the
+same UUID will receive the same pool id, thus allowing the pages to
+be shared.  Note that any security requirements must be imposed outside
+of the kernel (e.g. by "tools" that control cleancache).  Or a
+cleancache implementation can simply disable shared_init by always
+returning a negative value.
+
+If a get_page is successful on a non-shared pool, the page is flushed (thus
+making cleancache an "exclusive" cache).  On a shared pool, the page
+is NOT flushed on a successful get_page so that it remains accessible to
+other sharers.  The kernel is responsible for ensuring coherency between
+cleancache (shared or not), the page cache, and the filesystem, using
+cleancache flush operations as required.
+
+Note that cleancache must enforce put-put-get coherency and get-get
+coherency.  For the former, if two puts are made to the same handle but
+with different data, say AAA by the first put and BBB by the second, a
+subsequent get can never return the stale data (AAA).  For get-get coherency,
+if a get for a given handle fails, subsequent gets for that handle will
+never succeed unless preceded by a successful put with that handle.
+
+Last, cleancache provides no SMP serialization guarantees; if two
+different Linux threads are simultaneously putting and flushing a page
+with the same handle, the results are indeterminate.
+
+Cleancache monitoring is done by sysfs files in the
+/sys/kernel/mm/cleancache directory.  The effectiveness of cleancache
+can be measured (across all filesystems) with:
+
+succ_gets	- number of gets that were successful
+failed_gets	- number of gets that failed
+puts		- number of puts attempted (all "succeed")
+flushes		- number of flushes attempted
+
+Dan Magenheimer, June 04 2010
diff -NruabBEp linux-2.6.34.5/Documentation/vm/frontswap.txt l-t/Documentation/vm/frontswap.txt
--- linux-2.6.34.5/Documentation/vm/frontswap.txt	1970-01-01 03:00:00.000000000 +0300
+++ l-t/Documentation/vm/frontswap.txt	2010-08-24 12:35:56.000000000 +0400
@@ -0,0 +1,48 @@
+Frontswap is so named because it can be thought of as the opposite of
+a "backing" store for a swap device.  The storage is assumed to be
+a synchronous concurrency-safe page-oriented pseudo-RAM device (such as
+Xen's Transcendent Memory, aka "tmem", or in-kernel compressed memory,
+aka "zmem", or other RAM-like devices) which is not directly accessible
+or addressable by the kernel and is of unknown and possibly time-varying
+size.  This pseudo-RAM device links itself to frontswap by setting the
+frontswap_ops funcs appropriately and the functions it provides must
+conform to certain policies as follows:
+
+An "init" prepares the pseudo-RAM to receive frontswap pages and returns
+a non-negative pool id, used for all swap device numbers (aka "type").
+A "put_page" will copy the page to pseudo-RAM and associate it with
+the type and offset associated with the page. A "get_page" will copy the
+page, if found, from pseudo-RAM into kernel memory, but will NOT remove
+the page from pseudo-RAM.  A "flush_page" will remove the page from
+pseudo-RAM and a "flush_area" will remove ALL pages associated with the
+swap type (e.g., like swapoff) and notify the pseudo-RAM device to refuse
+further puts with that swap type.
+
+Once a page is successfully put, a matching get on the page will always
+succeed.  So when the kernel finds itself in a situation where it needs
+to swap out a page, it first attempts to use frontswap.  If the put returns
+non-zero, the data has been successfully saved to pseudo-RAM and
+a disk write and, if the data is later read back, a disk read are avoided.
+If a put returns zero, pseudo-RAM has rejected the data, and the page can
+be written to swap as usual.
+
+Note that if a page is put and the page already exists in pseudo-RAM
+(a "duplicate" put), either the put succeeds and the data is overwritten,
+or the put fails AND the page is flushed.  This ensures stale data may
+never be obtained from psuedo-RAM.
+
+Monitoring and control of frontswap is done by sysfs files in the
+/sys/kernel/mm/frontswap directory.  The effectiveness of frontswap can
+be measured (across all swap devices) with:
+
+curr_pages	- number of pages currently contained in frontswap
+failed_puts	- how many put attempts have failed
+gets		- how many gets were attempted (all should succeed)
+succ_puts	- how many put attempts have succeeded
+flushes		- how many flushes were attempted
+
+The number can be reduced by root by writing an integer target to curr_pages,
+which results in a "partial swapoff", thus reducing the number of frontswap
+pages to that target if memory constraints permit.
+
+Dan Magenheimer, June 04 2010
diff -NruabBEp linux-2.6.34.5/drivers/xen/balloon.c l-t/drivers/xen/balloon.c
--- linux-2.6.34.5/drivers/xen/balloon.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/drivers/xen/balloon.c	2010-08-24 15:02:27.000000000 +0400
@@ -6,6 +6,7 @@
  * Copyright (c) 2003, B Dragovic
  * Copyright (c) 2003-2004, M Williamson, K Fraser
  * Copyright (c) 2005 Dan M. Smith, IBM Corporation
+ * Copyright (c) 2010 Daniel Kiper
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License version 2
@@ -43,7 +44,11 @@
 #include <linux/mutex.h>
 #include <linux/list.h>
 #include <linux/sysdev.h>
+#include <linux/memory.h>
 #include <linux/gfp.h>
+#include <linux/swap.h>
+#include <linux/cleancache.h> /* for cleancache_enabled */
+#include <linux/frontswap.h> /* for frontswap_enabled */
 
 #include <asm/page.h>
 #include <asm/pgalloc.h>
@@ -69,6 +74,9 @@ struct balloon_stats {
 	/* We aim for 'current allocation' == 'target allocation'. */
 	unsigned long current_pages;
 	unsigned long target_pages;
+        unsigned long min_target_pages;
+        /* We may hit the hard limit in Xen. If we do then we remember it. */
+        unsigned long hard_limit;
 	/*
 	 * Drivers may alter the memory reservation independently, but they
 	 * must inform the balloon driver so we avoid hitting the hard limit.
@@ -77,8 +85,35 @@ struct balloon_stats {
 	/* Number of pages in high- and low-memory balloons. */
 	unsigned long balloon_low;
 	unsigned long balloon_high;
+#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+        unsigned long boot_max_pfn;
+        u64 hotplug_start_paddr;
+        u64 hotplug_size;
+#endif
+#ifdef CONFIG_XEN_SELFBALLOONING
+        int selfballooning_enabled;
+        unsigned int selfballoon_interval;
+        unsigned int selfballoon_downhysteresis;
+        unsigned int selfballoon_uphysteresis;
+#ifdef CONFIG_FRONTSWAP
+        unsigned int frontswap_selfshrinking;
+        unsigned int frontswap_hysteresis;
+        unsigned int frontswap_inertia;
+#endif
+#endif
 };
 
+#ifdef CONFIG_XEN_SELFBALLOONING
+/* for disabling from boot parameter even when cleancache is enabled */
+static int use_selfballooning __read_mostly = 1;
+/* for enabling from sysfs even when cleancache is disabled */
+static int force_enable_selfballooning __read_mostly = 0;
+#ifdef CONFIG_FRONTSWAP
+/* for disabling from boot parameter even when frontswap is enabled */
+static int use_frontswap_selfshrink __read_mostly = 1;
+#endif
+#endif
+
 static DEFINE_MUTEX(balloon_mutex);
 
 static struct sys_device balloon_sysdev;
@@ -112,6 +147,11 @@ static LIST_HEAD(ballooned_pages);
 static void balloon_process(struct work_struct *work);
 static DECLARE_WORK(balloon_worker, balloon_process);
 static struct timer_list balloon_timer;
+#ifdef CONFIG_XEN_SELFBALLOONING
+static void selfballoon_process(struct work_struct *work);
+static DECLARE_WORK(selfballoon_worker, selfballoon_process);
+static struct timer_list selfballoon_timer;
+#endif
 
 /* When ballooning out (allocating memory to return to Xen) we don't really
    want the kernel to try too hard since that can trigger the oom killer. */
@@ -125,6 +165,35 @@ static void scrub_page(struct page *page
 #endif
 }
 
+/* Heuristics to ensure over-ballooning doesn't occur.  Can be overridden */
+static unsigned long init_totalram_pages;
+
+static unsigned long min_target_pages(void)
+{
+#define MB2PAGES(mb) ((mb) << (20 - PAGE_SHIFT))
+       /* Simple continuous piecewiese linear function:
+        *  max MiB -> min MiB  gradient
+        *       0         0
+        *      16        16
+        *      32        24
+        *     128        72    (1/2)
+        *     512       168    (1/4)
+        *    2048       360    (1/8)
+        *    8192       552    (1/32)
+        *   32768      1320
+        *  131072      4392
+        */
+       if (init_totalram_pages < MB2PAGES(128))
+               return MB2PAGES(8) + (init_totalram_pages >> 1);
+       else if (init_totalram_pages < MB2PAGES(512))
+               return MB2PAGES(40) + (init_totalram_pages >> 2);
+       else if (init_totalram_pages < MB2PAGES(2048))
+               return MB2PAGES(104) + (init_totalram_pages >> 3);
+       else
+               return MB2PAGES(296) + (init_totalram_pages >> 5);
+#undef max_pfn
+}
+
 /* balloon_append: add the given page to the balloon. */
 static void balloon_append(struct page *page)
 {
@@ -184,18 +253,181 @@ static void balloon_alarm(unsigned long
 	schedule_work(&balloon_worker);
 }
 
-static unsigned long current_target(void)
+#ifdef CONFIG_XEN_SELFBALLOONING
+static void selfballoon_alarm(unsigned long unused)
 {
-	unsigned long target = balloon_stats.target_pages;
+       schedule_work(&selfballoon_worker);
+}
+#endif
+
+#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+static inline u64 is_memory_resource_reserved(void)
+{
+       return balloon_stats.hotplug_start_paddr;
+}
+
+static int allocate_additional_memory(unsigned long nr_pages)
+{
+       long rc;
+       resource_size_t r_min, r_size;
+       struct resource *r;
+       struct xen_memory_reservation reservation = {
+               .address_bits = 0,
+               .extent_order = 0,
+               .domid        = DOMID_SELF
+       };
+       unsigned long flags, i, pfn;
+
+       if (nr_pages > ARRAY_SIZE(frame_list))
+               nr_pages = ARRAY_SIZE(frame_list);
+
+       if (!is_memory_resource_reserved()) {
+
+               /*
+                * Look for first unused memory region starting at page
+                * boundary. Skip last memory section created at boot time
+                * becuase it may contains unused memory pages with PG_reserved
+                * bit not set (online_pages require PG_reserved bit set).
+                */
+
+               r = kzalloc(sizeof(struct resource), GFP_KERNEL);
+
+               if (!r) {
+                       rc = -ENOMEM;
+                       goto out_0;
+               }
+
+               r->name = "System RAM";
+               r->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+               r_min = PFN_PHYS(section_nr_to_pfn(pfn_to_section_nr(balloon_stats.boot_max_pfn) + 1));
+               r_size = (balloon_stats.target_pages - balloon_stats.current_pages) << PAGE_SHIFT;
+
+               rc = allocate_resource(&iomem_resource, r, r_size, r_min,
+                                       ULONG_MAX, PAGE_SIZE, NULL, NULL);
+
+               if (rc < 0) {
+                       kfree(r);
+                       goto out_0;
+               }
+
+               balloon_stats.hotplug_start_paddr = r->start;
+       }
+
+       spin_lock_irqsave(&balloon_lock, flags);
+
+       pfn = PFN_DOWN(balloon_stats.hotplug_start_paddr + balloon_stats.hotplug_size);
+
+       for (i = 0; i < nr_pages; ++i, ++pfn)
+               frame_list[i] = pfn;
 
-	target = min(target,
-		     balloon_stats.current_pages +
-		     balloon_stats.balloon_low +
-		     balloon_stats.balloon_high);
+       set_xen_guest_handle(reservation.extent_start, frame_list);
+       reservation.nr_extents = nr_pages;
 
-	return target;
+       rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
+
+       if (rc < 0)
+               goto out_1;
+
+       pfn = PFN_DOWN(balloon_stats.hotplug_start_paddr + balloon_stats.hotplug_size);
+
+       for (i = 0; i < rc; ++i, ++pfn) {
+               BUG_ON(!xen_feature(XENFEAT_auto_translated_physmap) &&
+                      phys_to_machine_mapping_valid(pfn));
+               set_phys_to_machine(pfn, frame_list[i]);
+       }
+
+       balloon_stats.hotplug_size += rc << PAGE_SHIFT;
+       balloon_stats.current_pages += rc;
+
+out_1:
+       spin_unlock_irqrestore(&balloon_lock, flags);
+
+out_0:
+       return rc < 0 ? rc : rc != nr_pages;
 }
 
+static void hotplug_allocated_memory(void)
+{
+       int nid, ret;
+       struct memory_block *mem;
+       unsigned long pfn, pfn_limit;
+
+       nid = memory_add_physaddr_to_nid(balloon_stats.hotplug_start_paddr);
+
+       ret = add_registered_memory(nid, balloon_stats.hotplug_start_paddr,
+                                               balloon_stats.hotplug_size);
+
+       if (ret) {
+               pr_err("%s: add_registered_memory: Memory hotplug failed: %i\n",
+                       __func__, ret);
+               goto error;
+       }
+
+       if (xen_pv_domain()) {
+               pfn = PFN_DOWN(balloon_stats.hotplug_start_paddr);
+               pfn_limit = pfn + (balloon_stats.hotplug_size >> PAGE_SHIFT);
+
+               for (; pfn < pfn_limit; ++pfn)
+                       if (!PageHighMem(pfn_to_page(pfn)))
+                               BUG_ON(HYPERVISOR_update_va_mapping(
+                                       (unsigned long)__va(pfn << PAGE_SHIFT),
+                                       mfn_pte(pfn_to_mfn(pfn), PAGE_KERNEL), 0));
+       }
+
+       ret = online_pages(PFN_DOWN(balloon_stats.hotplug_start_paddr),
+                               balloon_stats.hotplug_size >> PAGE_SHIFT);
+
+       if (ret) {
+               pr_err("%s: online_pages: Failed: %i\n", __func__, ret);
+               goto error;
+       }
+
+       pfn = PFN_DOWN(balloon_stats.hotplug_start_paddr);
+       pfn_limit = pfn + (balloon_stats.hotplug_size >> PAGE_SHIFT);
+
+       for (; pfn < pfn_limit; pfn += PAGES_PER_SECTION) {
+               mem = find_memory_block(__pfn_to_section(pfn));
+               BUG_ON(!mem);
+               BUG_ON(!present_section_nr(mem->phys_index));
+               mutex_lock(&mem->state_mutex);
+               mem->state = MEM_ONLINE;
+               mutex_unlock(&mem->state_mutex);
+       }
+
+       goto out;
+
+error:
+       balloon_stats.current_pages -= balloon_stats.hotplug_size >> PAGE_SHIFT;
+       balloon_stats.target_pages -= balloon_stats.hotplug_size >> PAGE_SHIFT;
+
+out:
+       balloon_stats.hotplug_start_paddr = 0;
+       balloon_stats.hotplug_size = 0;
+}
+#else
+static inline u64 is_memory_resource_reserved(void)
+{
+       return 0;
+}
+
+static inline int allocate_additional_memory(unsigned long nr_pages)
+{
+       /*
+        * CONFIG_XEN_BALLOON_MEMORY_HOTPLUG is not set.
+        * balloon_stats.target_pages could not be bigger
+        * than balloon_stats.current_pages because additional
+        * memory allocation is not possible.
+        */
+       balloon_stats.target_pages = balloon_stats.current_pages;
+
+       return 0;
+}
+
+static inline void hotplug_allocated_memory(void)
+{
+}
+#endif /* CONFIG_XEN_BALLOON_MEMORY_HOTPLUG */
+
 static int increase_reservation(unsigned long nr_pages)
 {
 	unsigned long  pfn, i, flags;
@@ -222,10 +454,23 @@ static int increase_reservation(unsigned
 	set_xen_guest_handle(reservation.extent_start, frame_list);
 	reservation.nr_extents = nr_pages;
 	rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
-	if (rc < 0)
+        if (rc < nr_pages) {
+                if (rc > 0) {
+                        int ret;
+ 
+                        /* We hit the Xen hard limit: reprobe. */
+                        reservation.nr_extents = rc;
+                        ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
+                                                   &reservation);
+                        BUG_ON(ret != rc);
+                }
+                if (rc >= 0)
+                        balloon_stats.hard_limit = (balloon_stats.current_pages + rc -
+                                                    balloon_stats.driver_pages);
 		goto out;
+	}
 
-	for (i = 0; i < rc; i++) {
+	for (i = 0; i < nr_pages; i++) {
 		page = balloon_retrieve();
 		BUG_ON(page == NULL);
 
@@ -236,7 +481,7 @@ static int increase_reservation(unsigned
 		set_phys_to_machine(pfn, frame_list[i]);
 
 		/* Link back into the page tables if not highmem. */
-		if (pfn < max_low_pfn) {
+		if (xen_pv_domain() && !PageHighMem(page)) {
 			int ret;
 			ret = HYPERVISOR_update_va_mapping(
 				(unsigned long)__va(pfn << PAGE_SHIFT),
@@ -251,12 +496,13 @@ static int increase_reservation(unsigned
 		__free_page(page);
 	}
 
-	balloon_stats.current_pages += rc;
+         balloon_stats.current_pages += nr_pages;
+         totalram_pages = balloon_stats.current_pages;
 
  out:
 	spin_unlock_irqrestore(&balloon_lock, flags);
 
-	return rc < 0 ? rc : rc != nr_pages;
+	return 0;
 }
 
 static int decrease_reservation(unsigned long nr_pages)
@@ -314,6 +560,7 @@ static int decrease_reservation(unsigned
 	BUG_ON(ret != nr_pages);
 
 	balloon_stats.current_pages -= nr_pages;
+	totalram_pages = balloon_stats.current_pages;
 
 	spin_unlock_irqrestore(&balloon_lock, flags);
 
@@ -334,9 +581,15 @@ static void balloon_process(struct work_
 	mutex_lock(&balloon_mutex);
 
 	do {
-		credit = current_target() - balloon_stats.current_pages;
-		if (credit > 0)
+                credit = balloon_stats.target_pages - balloon_stats.current_pages;
+
+                if (credit > 0) {
+                        if (balloon_stats.balloon_low || balloon_stats.balloon_high)
 			need_sleep = (increase_reservation(credit) != 0);
+                        else
+                                need_sleep = (allocate_additional_memory(credit) != 0);
+                }
+
 		if (credit < 0)
 			need_sleep = (decrease_reservation(-credit) != 0);
 
@@ -347,8 +600,10 @@ static void balloon_process(struct work_
 	} while ((credit != 0) && !need_sleep);
 
 	/* Schedule more work if there is some still to be done. */
-	if (current_target() != balloon_stats.current_pages)
+	if (balloon_stats.target_pages != balloon_stats.current_pages)
 		mod_timer(&balloon_timer, jiffies + HZ);
+        else if (is_memory_resource_reserved())
+                hotplug_allocated_memory();
 
 	mutex_unlock(&balloon_mutex);
 }
@@ -357,7 +612,8 @@ static void balloon_process(struct work_
 static void balloon_set_new_target(unsigned long target)
 {
 	/* No need for lock. Not read-modify-write updates. */
-	balloon_stats.target_pages = target;
+        balloon_stats.hard_limit   = ~0UL;
+	balloon_stats.target_pages = max(target, balloon_stats.min_target_pages);
 	schedule_work(&balloon_worker);
 }
 
@@ -405,24 +661,52 @@ static int __init balloon_init(void)
 	unsigned long pfn;
 	struct page *page;
 
-	if (!xen_pv_domain())
+	if (!xen_domain())
 		return -ENODEV;
 
 	pr_info("xen_balloon: Initialising balloon driver.\n");
 
+        if (xen_pv_domain())
 	balloon_stats.current_pages = min(xen_start_info->nr_pages, max_pfn);
+        else
+                balloon_stats.current_pages = max_pfn;
+        init_totalram_pages = totalram_pages   = balloon_stats.current_pages;
+        balloon_stats.min_target_pages  = min_target_pages();
 	balloon_stats.target_pages  = balloon_stats.current_pages;
 	balloon_stats.balloon_low   = 0;
 	balloon_stats.balloon_high  = 0;
 	balloon_stats.driver_pages  = 0UL;
+	balloon_stats.hard_limit    = ~0UL;
+#ifdef CONFIG_XEN_BALLOON_MEMORY_HOTPLUG
+        balloon_stats.boot_max_pfn = max_pfn;
+        balloon_stats.hotplug_start_paddr = 0;
+        balloon_stats.hotplug_size = 0;
+#endif
 
 	init_timer(&balloon_timer);
 	balloon_timer.data = 0;
 	balloon_timer.function = balloon_alarm;
 
+#ifdef CONFIG_XEN_SELFBALLOONING
+        balloon_stats.selfballooning_enabled = use_selfballooning;
+        balloon_stats.selfballoon_interval = 1;
+        balloon_stats.selfballoon_downhysteresis = 8;
+        balloon_stats.selfballoon_uphysteresis = 1;
+#ifdef CONFIG_FRONTSWAP
+        balloon_stats.frontswap_selfshrinking = use_frontswap_selfshrink;
+        balloon_stats.frontswap_hysteresis = 20;
+        balloon_stats.frontswap_inertia = 1;
+#endif
+        init_timer(&selfballoon_timer);
+        selfballoon_timer.data = 0;
+        selfballoon_timer.function = selfballoon_alarm;
+        mod_timer(&selfballoon_timer, jiffies + balloon_stats.selfballoon_interval * HZ);
+#endif
+
 	register_balloon(&balloon_sysdev);
 
 	/* Initialise the balloon with excess memory space. */
+        if (xen_pv_domain())
 	for (pfn = xen_start_info->nr_pages; pfn < max_pfn; pfn++) {
 		page = pfn_to_page(pfn);
 		if (!PageReserved(page))
@@ -460,6 +745,9 @@ BALLOON_SHOW(current_kb, "%lu\n", PAGES2
 BALLOON_SHOW(low_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_low));
 BALLOON_SHOW(high_kb, "%lu\n", PAGES2KB(balloon_stats.balloon_high));
 BALLOON_SHOW(driver_kb, "%lu\n", PAGES2KB(balloon_stats.driver_pages));
+BALLOON_SHOW(hard_limit_kb,
+            (balloon_stats.hard_limit!=~0UL) ? "%lu\n" : "???\n",
+            (balloon_stats.hard_limit!=~0UL) ? PAGES2KB(balloon_stats.hard_limit) : 0);
 
 static ssize_t show_target_kb(struct sys_device *dev, struct sysdev_attribute *attr,
 			      char *buf)
@@ -488,6 +776,30 @@ static ssize_t store_target_kb(struct sy
 static SYSDEV_ATTR(target_kb, S_IRUGO | S_IWUSR,
 		   show_target_kb, store_target_kb);
 
+static ssize_t show_min_target_kb(struct sys_device *dev, struct sysdev_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%lu\n", PAGES2KB(balloon_stats.min_target_pages));
+}
+
+static ssize_t store_min_target_kb(struct sys_device *dev,
+                              struct sysdev_attribute *attr,
+                              const char *buf,
+                              size_t count)
+{
+       char *endchar;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       balloon_stats.min_target_pages =
+               (simple_strtoull(buf, &endchar, 0) * 1024) >> PAGE_SHIFT;
+
+       return count;
+}
+
+static SYSDEV_ATTR(min_target_kb, S_IRUGO | S_IWUSR,
+                  show_min_target_kb, store_min_target_kb);
 
 static ssize_t show_target(struct sys_device *dev, struct sysdev_attribute *attr,
 			      char *buf)
@@ -518,12 +830,206 @@ static ssize_t store_target(struct sys_d
 static SYSDEV_ATTR(target, S_IRUGO | S_IWUSR,
 		   show_target, store_target);
 
+#ifdef CONFIG_XEN_SELFBALLOONING
+static ssize_t show_selfballooning(struct sys_device *dev, struct sysdev_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%d\n", balloon_stats.selfballooning_enabled);
+}
+
+static ssize_t store_selfballooning(struct sys_device *dev,
+                           struct sysdev_attribute *attr,
+                           const char *buf,
+                           size_t count)
+{
+       char *endchar;
+       int was_enabled = balloon_stats.selfballooning_enabled;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       balloon_stats.selfballooning_enabled = !!memparse(buf, &endchar);
+
+       if (!was_enabled && balloon_stats.selfballooning_enabled) {
+               mod_timer(&selfballoon_timer,
+                       jiffies + balloon_stats.selfballoon_interval * HZ);
+               force_enable_selfballooning = 1;
+       } else
+               force_enable_selfballooning = 0;
+
+       return count;
+}
+
+static SYSDEV_ATTR(selfballooning, S_IRUGO | S_IWUSR,
+                  show_selfballooning, store_selfballooning);
+
+static ssize_t show_selfballoon_interval(struct sys_device *dev, struct sysdev_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%d\n", balloon_stats.selfballoon_interval);
+}
+
+static ssize_t store_selfballoon_interval(struct sys_device *dev,
+                           struct sysdev_attribute *attr,
+                           const char *buf,
+                           size_t count)
+{
+       char *endchar;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       balloon_stats.selfballoon_interval = memparse(buf, &endchar);
+       return count;
+}
+
+static SYSDEV_ATTR(selfballoon_interval, S_IRUGO | S_IWUSR,
+                  show_selfballoon_interval, store_selfballoon_interval);
+
+static ssize_t show_selfballoon_downhys(struct sys_device *dev, struct sysdev_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%d\n", balloon_stats.selfballoon_downhysteresis);
+}
+
+static ssize_t store_selfballoon_downhys(struct sys_device *dev,
+                           struct sysdev_attribute *attr,
+                           const char *buf,
+                           size_t count)
+{
+       char *endchar;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       balloon_stats.selfballoon_downhysteresis = memparse(buf, &endchar);
+       return count;
+}
+
+static SYSDEV_ATTR(selfballoon_downhysteresis, S_IRUGO | S_IWUSR,
+                  show_selfballoon_downhys, store_selfballoon_downhys);
+
+
+static ssize_t show_selfballoon_uphys(struct sys_device *dev, struct sysdev_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%d\n", balloon_stats.selfballoon_uphysteresis);
+}
+
+static ssize_t store_selfballoon_uphys(struct sys_device *dev,
+                           struct sysdev_attribute *attr,
+                           const char *buf,
+                           size_t count)
+{
+       char *endchar;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       balloon_stats.selfballoon_uphysteresis = memparse(buf, &endchar);
+       return count;
+}
+
+static SYSDEV_ATTR(selfballoon_uphysteresis, S_IRUGO | S_IWUSR,
+                  show_selfballoon_uphys, store_selfballoon_uphys);
+
+#ifdef CONFIG_FRONTSWAP
+static ssize_t show_frontswap_selfshrinking(struct sys_device *dev, struct sysdev_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%d\n", balloon_stats.frontswap_selfshrinking);
+}
+
+
+static ssize_t store_frontswap_selfshrinking(struct sys_device *dev,
+                           struct sysdev_attribute *attr,
+                           const char *buf,
+                           size_t count)
+{
+       char *endchar;
+       int was_enabled = balloon_stats.frontswap_selfshrinking;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       balloon_stats.frontswap_selfshrinking = !!memparse(buf, &endchar);
+
+       if (!was_enabled && !balloon_stats.selfballooning_enabled &&
+                                       balloon_stats.frontswap_selfshrinking)
+               mod_timer(&selfballoon_timer,
+                       jiffies + balloon_stats.selfballoon_interval * HZ);
+
+       return count;
+}
+
+static SYSDEV_ATTR(frontswap_selfshrinking, S_IRUGO | S_IWUSR,
+                  show_frontswap_selfshrinking, store_frontswap_selfshrinking);
+
+static unsigned long frontswap_inertia_counter = 0;
+
+
+static ssize_t show_frontswap_inertia(struct sys_device *dev, struct sysdev_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%d\n", balloon_stats.frontswap_inertia);
+}
+static ssize_t store_frontswap_inertia(struct sys_device *dev,
+                           struct sysdev_attribute *attr,
+                           const char *buf,
+                           size_t count)
+{
+       char *endchar;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       balloon_stats.frontswap_inertia = memparse(buf, &endchar);
+       frontswap_inertia_counter = balloon_stats.frontswap_inertia;
+       return count;
+}
+
+static SYSDEV_ATTR(frontswap_inertia, S_IRUGO | S_IWUSR,
+                  show_frontswap_inertia, store_frontswap_inertia);
+
+static ssize_t show_frontswap_hysteresis(struct sys_device *dev, struct sysdev_attribute *attr,
+                             char *buf)
+{
+       return sprintf(buf, "%d\n", balloon_stats.frontswap_hysteresis);
+}
+
+static ssize_t store_frontswap_hysteresis(struct sys_device *dev,
+                           struct sysdev_attribute *attr,
+                           const char *buf,
+                           size_t count)
+{
+       char *endchar;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       balloon_stats.frontswap_hysteresis = memparse(buf, &endchar);
+       return count;
+}
+
+static SYSDEV_ATTR(frontswap_hysteresis, S_IRUGO | S_IWUSR,
+                  show_frontswap_hysteresis, store_frontswap_hysteresis);
+
+#endif /* CONFIG_FRONTSWAP */
+#endif /* CONFIG_XEN_SELFBALLOONING */
 
 static struct sysdev_attribute *balloon_attrs[] = {
 	&attr_target_kb,
+	&attr_min_target_kb,
 	&attr_target,
+#ifdef CONFIG_XEN_SELFBALLOONING
+        &attr_selfballooning,
+        &attr_selfballoon_interval,
+        &attr_selfballoon_downhysteresis,
+        &attr_selfballoon_uphysteresis,
+#ifdef CONFIG_FRONTSWAP
+        &attr_frontswap_selfshrinking,
+        &attr_frontswap_hysteresis,
+        &attr_frontswap_inertia,
+#endif
+#endif
 };
 
+
 static struct attribute *balloon_info_attrs[] = {
 	&attr_current_kb.attr,
 	&attr_low_kb.attr,
@@ -529,6 +1035,7 @@ static struct attribute *balloon_info_at
 	&attr_low_kb.attr,
 	&attr_high_kb.attr,
 	&attr_driver_kb.attr,
+	&attr_hard_limit_kb.attr,
 	NULL
 };
 
@@ -578,4 +1085,76 @@ static int register_balloon(struct sys_d
 	return error;
 }
 
+#ifdef CONFIG_XEN_SELFBALLOONING
+#ifdef CONFIG_FRONTSWAP
+static void frontswap_selfshrink(void)
+{
+       static unsigned long cur_frontswap_pages = 0;
+       static unsigned long last_frontswap_pages = 0;
+       static unsigned long tgt_frontswap_pages = 0;
+
+       if (!balloon_stats.frontswap_hysteresis)
+               return;
+       last_frontswap_pages = cur_frontswap_pages;
+       cur_frontswap_pages = frontswap_curr_pages();
+       if (!cur_frontswap_pages || (cur_frontswap_pages > last_frontswap_pages)) {
+               frontswap_inertia_counter = balloon_stats.frontswap_inertia;
+               return;
+       }
+       if (frontswap_inertia_counter && --frontswap_inertia_counter)
+               return;
+       if ( cur_frontswap_pages <= balloon_stats.frontswap_hysteresis)
+               tgt_frontswap_pages = 0;
+       else tgt_frontswap_pages = cur_frontswap_pages -
+               (cur_frontswap_pages / balloon_stats.frontswap_hysteresis);
+       frontswap_shrink(tgt_frontswap_pages);
+}
+
+static int __init no_frontswap_selfshrink_setup(char *s)
+{
+       use_frontswap_selfshrink = 0;
+       return 1;
+}
+
+__setup("noselfshrink", no_frontswap_selfshrink_setup);
+#endif
+
+static void selfballoon_process(struct work_struct *work)
+{
+       extern unsigned long vm_get_committed_as(void);
+       unsigned long cur_pages, goal_pages, tgt_pages;
+       int reset_timer = 0;
+
+       if (balloon_stats.selfballooning_enabled &&
+            (force_enable_selfballooning || cleancache_enabled)) {
+               tgt_pages = cur_pages = totalram_pages;
+               goal_pages = vm_get_committed_as();
+               if (cur_pages > goal_pages)
+                       tgt_pages = cur_pages -
+                               (cur_pages - goal_pages) / balloon_stats.selfballoon_downhysteresis;
+               else if (cur_pages < goal_pages)
+                       tgt_pages = cur_pages +
+                               (goal_pages - cur_pages) / balloon_stats.selfballoon_uphysteresis;
+               balloon_set_new_target(tgt_pages);
+               reset_timer = 1;
+       }
+#ifdef CONFIG_FRONTSWAP
+       if (balloon_stats.frontswap_selfshrinking && frontswap_enabled) {
+               frontswap_selfshrink();
+               reset_timer = 1;
+       }
+#endif
+       if (reset_timer)
+               mod_timer(&selfballoon_timer, jiffies + balloon_stats.selfballoon_interval * HZ);
+}
+
+static int __init noselfballooning_setup(char *s)
+{
+       use_selfballooning = 0;
+       return 1;
+}
+
+__setup("noselfballooning", noselfballooning_setup);
+#endif
+
 MODULE_LICENSE("GPL");
diff -NruabBEp linux-2.6.34.5/drivers/xen/Kconfig l-t/drivers/xen/Kconfig
--- linux-2.6.34.5/drivers/xen/Kconfig	2010-08-20 22:52:05.000000000 +0400
+++ l-t/drivers/xen/Kconfig	2010-08-24 12:38:12.000000000 +0400
@@ -9,6 +9,26 @@ config XEN_BALLOON
 	  the system to expand the domain's memory allocation, or alternatively
 	  return unneeded memory to the system.
 
+config XEN_BALLOON_MEMORY_HOTPLUG
+       bool "Xen memory balloon driver with memory hotplug support"
+       default y
+       depends on XEN_BALLOON && MEMORY_HOTPLUG
+       help
+         Xen memory balloon driver with memory hotplug support allows expanding
+         memory available for the system above limit declared at system startup.
+         It is very useful on critical systems which require long run without
+         rebooting.
+
+config XEN_SELFBALLOONING
+	bool "dynamically self-balloon kernel memory to target"
+	depends on XEN && XEN_BALLOON_MEMORY_HOTPLUG
+	default y
+	help
+	  Self-ballooning dynamically balloons available kernel memory driven
+	  by the current usage of anonymous memory ("committed AS") and
+	  controlled by various sysfs-settable parameters.  May be overridden
+	  by the noselfballooning kernel boot parameter
+
 config XEN_SCRUB_PAGES
 	bool "Scrub pages before returning them to system"
 	depends on XEN_BALLOON
diff -NruabBEp linux-2.6.34.5/drivers/xen/Makefile l-t/drivers/xen/Makefile
--- linux-2.6.34.5/drivers/xen/Makefile	2010-08-20 22:52:05.000000000 +0400
+++ l-t/drivers/xen/Makefile	2010-08-24 12:38:34.000000000 +0400
@@ -1,5 +1,6 @@
 obj-y	+= grant-table.o features.o events.o manage.o
 obj-y	+= xenbus/
+obj-y	+= tmem.o
 
 nostackp := $(call cc-option, -fno-stack-protector)
 CFLAGS_features.o			:= $(nostackp)
diff -NruabBEp linux-2.6.34.5/drivers/xen/tmem.c l-t/drivers/xen/tmem.c
--- linux-2.6.34.5/drivers/xen/tmem.c	1970-01-01 03:00:00.000000000 +0300
+++ l-t/drivers/xen/tmem.c	2010-08-24 12:36:51.000000000 +0400
@@ -0,0 +1,320 @@
+/*
+ * Xen implementation for transcendent memory (tmem)
+ *
+ * Copyright (C) 2009-2010 Oracle Corp.  All rights reserved.
+ * Author: Dan Magenheimer
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pagemap.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
+#include <linux/cleancache.h>
+#include <linux/frontswap.h>
+
+#include <xen/xen.h>
+#include <xen/tmem.h>
+#include <xen/interface/xen.h>
+#include <xen/interface/tmem.h>
+#include <asm/xen/hypercall.h>
+#include <asm/xen/page.h>
+#include <asm/xen/hypervisor.h>
+
+/* xen tmem foundation ops/hypercalls */
+
+static inline int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, u64 object,
+	u32 index, unsigned long gmfn, u32 tmem_offset, u32 pfn_offset, u32 len)
+{
+	struct tmem_op op;
+	int rc = 0;
+
+	op.cmd = tmem_cmd;
+	op.pool_id = tmem_pool;
+	op.u.gen.object = object;
+	op.u.gen.index = index;
+	op.u.gen.tmem_offset = tmem_offset;
+	op.u.gen.pfn_offset = pfn_offset;
+	op.u.gen.len = len;
+	set_xen_guest_handle(op.u.gen.gmfn, (void *)gmfn);
+	rc = HYPERVISOR_tmem_op(&op);
+	return rc;
+}
+
+static int xen_tmem_new_pool(struct tmem_pool_uuid uuid,
+				u32 flags, unsigned long pagesize)
+{
+	struct tmem_op op;
+	int rc = 0, pageshift;
+
+	for (pageshift = 0; pagesize != 1; pageshift++)
+		pagesize >>= 1;
+	flags |= (pageshift - 12) << TMEM_POOL_PAGESIZE_SHIFT;
+	op.cmd = TMEM_NEW_POOL;
+	op.u.new.uuid[0] = uuid.uuid_lo;
+	op.u.new.uuid[1] = uuid.uuid_hi;
+	op.u.new.flags = flags;
+	rc = HYPERVISOR_tmem_op(&op);
+	return rc;
+}
+
+/* xen generic tmem ops */
+
+static int xen_tmem_put_page(u32 pool_id, u64 object, u32 index,
+	unsigned long pfn)
+{
+	unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn;
+
+	return xen_tmem_op(TMEM_PUT_PAGE, pool_id, object, index,
+		gmfn, 0, 0, 0);
+}
+
+static int xen_tmem_get_page(u32 pool_id, u64 object, u32 index,
+	unsigned long pfn)
+{
+	unsigned long gmfn = xen_pv_domain() ? pfn_to_mfn(pfn) : pfn;
+
+	return xen_tmem_op(TMEM_GET_PAGE, pool_id, object, index,
+		gmfn, 0, 0, 0);
+}
+
+static int xen_tmem_flush_page(u32 pool_id, u64 object, u32 index)
+{
+	return xen_tmem_op(TMEM_FLUSH_PAGE, pool_id, object, index,
+		0, 0, 0, 0);
+}
+
+static int xen_tmem_flush_object(u32 pool_id, u64 object)
+{
+	return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, object, 0, 0, 0, 0, 0);
+}
+
+static int xen_tmem_destroy_pool(u32 pool_id)
+{
+	return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, 0, 0, 0, 0, 0, 0);
+}
+
+int tmem_enabled = 0;
+
+static int __init enable_tmem(char *s)
+{
+	tmem_enabled = 1;
+	return 1;
+}
+
+__setup("tmem", enable_tmem);
+
+/* cleancache ops */
+
+static void tmem_cleancache_put_page(int pool, ino_t inode, pgoff_t index,
+				     struct page *page)
+{
+	u32 ind = (u32) index;
+	unsigned long pfn = page_to_pfn(page);
+
+	if (pool < 0)
+		return;
+	if (ind != index)
+		return;
+	mb(); /* ensure page is quiescent; tmem may address it with an alias */
+	(void)xen_tmem_put_page((u32)pool, (u64)inode, ind, pfn);
+}
+
+static int tmem_cleancache_get_page(int pool, ino_t inode, pgoff_t index,
+				    struct page *page)
+{
+	u32 ind = (u32) index;
+	unsigned long pfn = page_to_pfn(page);
+	int ret;
+
+	/* translate return values to linux semantics */
+	if (pool < 0)
+		return -1;
+	if (ind != index)
+		return -1;
+	ret = xen_tmem_get_page((u32)pool, (u64)inode, ind, pfn);
+	if (ret == 1)
+		return 0;
+	else
+		return -1;
+}
+
+static void tmem_cleancache_flush_page(int pool, ino_t inode, pgoff_t index)
+{
+	u32 ind = (u32) index;
+
+	if (pool < 0)
+		return;
+	if (ind != index)
+		return;
+	(void)xen_tmem_flush_page((u32)pool, (u64)inode, ind);
+}
+
+static void tmem_cleancache_flush_inode(int pool, ino_t inode)
+{
+	if (pool < 0)
+		return;
+	(void)xen_tmem_flush_object((u32)pool, (u64)inode);
+}
+
+static void tmem_cleancache_flush_fs(int pool)
+{
+	if (pool < 0)
+		return;
+	(void)xen_tmem_destroy_pool((u32)pool);
+}
+
+static int tmem_cleancache_init_fs(size_t pagesize)
+{
+	struct tmem_pool_uuid uuid_private = TMEM_POOL_PRIVATE_UUID;
+
+	return xen_tmem_new_pool(uuid_private, 0, pagesize);
+}
+
+static int tmem_cleancache_init_shared_fs(char *uuid, size_t pagesize)
+{
+	struct tmem_pool_uuid shared_uuid;
+
+	shared_uuid.uuid_lo = *(u64 *)uuid;
+	shared_uuid.uuid_hi = *(u64 *)(&uuid[8]);
+	return xen_tmem_new_pool(shared_uuid, TMEM_POOL_SHARED, pagesize);
+}
+
+static int use_cleancache = 1;
+
+static int __init no_cleancache(char *s)
+{
+	use_cleancache = 0;
+	return 1;
+}
+
+__setup("nocleancache", no_cleancache);
+
+/* frontswap tmem operations */
+
+/*
+ * Swizzling increases objects per swaptype, increasing tmem concurrency
+ * for heavy swaploads.  Later, larger nr_cpus -> larger SWIZ_BITS
+ */
+#define SWIZ_BITS		4
+#define SWIZ_MASK		((1 << SWIZ_BITS) - 1)
+#define oswiz(_type, _ind)	((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
+#define iswiz(_ind)		(_ind >> SWIZ_BITS)
+
+/* returns 0 if the page was successfully put into frontswap, -1 if not */
+static int tmem_frontswap_put_page(int pool, unsigned type, pgoff_t offset,
+				   struct page *page)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	unsigned long pfn = page_to_pfn(page);
+	int ret;
+
+	if (ind64 != ind)
+		return -1;
+	mb(); /* ensure page is quiescent; tmem may address it with an alias */
+	ret = xen_tmem_put_page(pool, oswiz(type, ind), iswiz(ind), pfn);
+	/* translate Xen tmem return values to linux semantics */
+	if (ret == 1)
+		return 0;
+	else
+		return -1;
+}
+
+/* returns 0 if the page was successfully gotten from frontswap, -1 if
+ * was not present (should never happen!) */
+static int tmem_frontswap_get_page(int pool, unsigned type, pgoff_t offset,
+				   struct page *page)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+	unsigned long pfn = page_to_pfn(page);
+	int ret;
+
+	if (ind64 != ind)
+		return -1;
+	ret = xen_tmem_get_page(pool, oswiz(type, ind), iswiz(ind), pfn);
+	/* translate Xen tmem return values to linux semantics */
+	if (ret == 1)
+		return 0;
+	else
+		return -1;
+}
+
+/* flush a single page from frontswap */
+static void tmem_frontswap_flush_page(int pool, unsigned type, pgoff_t offset)
+{
+	u64 ind64 = (u64)offset;
+	u32 ind = (u32)offset;
+
+	if (ind64 != ind)
+		return;
+	(void) xen_tmem_flush_page(pool, oswiz(type, ind), iswiz(ind));
+}
+
+/* flush all pages from the passed swaptype */
+static void tmem_frontswap_flush_area(int pool, unsigned type)
+{
+	int ind;
+
+	for (ind = SWIZ_MASK; ind >= 0; ind--)
+		(void)xen_tmem_flush_object(pool, oswiz(type, ind));
+}
+
+static int tmem_frontswap_init(unsigned ignored)
+{
+	struct tmem_pool_uuid private = TMEM_POOL_PRIVATE_UUID;
+	static int tmem_frontswap_poolid = -1;
+	int ret;
+
+	if (tmem_frontswap_poolid < 0)
+		ret =  (int)xen_tmem_new_pool(private, TMEM_POOL_PERSIST,
+					      PAGE_SIZE);
+	else
+		ret = tmem_frontswap_poolid;
+	return ret;
+}
+
+static int use_frontswap = 1;
+
+static int __init no_frontswap(char *s)
+{
+	use_frontswap = 0;
+	return 1;
+}
+
+__setup("nofrontswap", no_frontswap);
+
+static int __init xen_tmem_init(void)
+{
+	if (!xen_domain())
+		return 0;
+#ifdef CONFIG_FRONTSWAP
+	if (tmem_enabled && use_frontswap) {
+		frontswap_ops.put_page = tmem_frontswap_put_page;
+		frontswap_ops.get_page = tmem_frontswap_get_page;
+		frontswap_ops.flush_page = tmem_frontswap_flush_page;
+		frontswap_ops.flush_area = tmem_frontswap_flush_area;
+		frontswap_ops.init = tmem_frontswap_init;
+		printk(KERN_INFO "frontswap enabled, RAM provided by "
+				 "Xen Transcendent Memory\n");
+	}
+#endif
+#ifdef CONFIG_CLEANCACHE
+	if (tmem_enabled && use_cleancache) {
+		cleancache_ops.put_page = tmem_cleancache_put_page;
+		cleancache_ops.get_page = tmem_cleancache_get_page;
+		cleancache_ops.flush_page = tmem_cleancache_flush_page;
+		cleancache_ops.flush_inode = tmem_cleancache_flush_inode;
+		cleancache_ops.flush_fs = tmem_cleancache_flush_fs;
+		cleancache_ops.init_shared_fs = tmem_cleancache_init_shared_fs;
+		cleancache_ops.init_fs = tmem_cleancache_init_fs;
+		printk(KERN_INFO "cleancache enabled, RAM provided by "
+				 "Xen Transcendent Memory\n");
+	}
+#endif
+	return 0;
+}
+
+module_init(xen_tmem_init)
diff -NruabBEp linux-2.6.34.5/fs/buffer.c l-t/fs/buffer.c
--- linux-2.6.34.5/fs/buffer.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/fs/buffer.c	2010-08-24 12:36:23.000000000 +0400
@@ -41,6 +41,7 @@
 #include <linux/bitops.h>
 #include <linux/mpage.h>
 #include <linux/bit_spinlock.h>
+#include <linux/cleancache.h>
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 
@@ -276,6 +277,11 @@ void invalidate_bdev(struct block_device
 
 	invalidate_bh_lrus();
 	invalidate_mapping_pages(mapping, 0, -1);
+
+	/* 99% of the time, we don't need to flush the cleancache on the bdev.
+	 * But, for the strange corners, lets be cautious
+	 */
+	cleancache_flush_inode(mapping);
 }
 EXPORT_SYMBOL(invalidate_bdev);
 
diff -NruabBEp linux-2.6.34.5/fs/ext3/super.c l-t/fs/ext3/super.c
--- linux-2.6.34.5/fs/ext3/super.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/fs/ext3/super.c	2010-08-24 12:36:27.000000000 +0400
@@ -37,6 +37,7 @@
 #include <linux/quotaops.h>
 #include <linux/seq_file.h>
 #include <linux/log2.h>
+#include <linux/cleancache.h>
 
 #include <asm/uaccess.h>
 
@@ -1344,6 +1345,7 @@ static int ext3_setup_super(struct super
 	} else {
 		ext3_msg(sb, KERN_INFO, "using internal journal");
 	}
+	sb->cleancache_poolid = cleancache_init_fs(PAGE_SIZE);
 	return res;
 }
 
diff -NruabBEp linux-2.6.34.5/fs/mpage.c l-t/fs/mpage.c
--- linux-2.6.34.5/fs/mpage.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/fs/mpage.c	2010-08-24 12:36:34.000000000 +0400
@@ -27,6 +27,7 @@
 #include <linux/writeback.h>
 #include <linux/backing-dev.h>
 #include <linux/pagevec.h>
+#include <linux/cleancache.h>
 
 /*
  * I/O completion handler for multipage BIOs.
@@ -286,6 +287,12 @@ do_mpage_readpage(struct bio *bio, struc
 		SetPageMappedToDisk(page);
 	}
 
+	if (fully_mapped && blocks_per_page == 1 && !PageUptodate(page) &&
+	    cleancache_get_page(page) == 0) {
+		SetPageUptodate(page);
+		goto confused;
+	}
+
 	/*
 	 * This page will go to BIO.  Do we need to send this BIO off first?
 	 */
diff -NruabBEp linux-2.6.34.5/fs/super.c l-t/fs/super.c
--- linux-2.6.34.5/fs/super.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/fs/super.c	2010-08-24 12:36:37.000000000 +0400
@@ -37,6 +37,7 @@
 #include <linux/kobject.h>
 #include <linux/mutex.h>
 #include <linux/file.h>
+#include <linux/cleancache.h>
 #include <linux/backing-dev.h>
 #include <asm/uaccess.h>
 #include "internal.h"
@@ -105,6 +106,7 @@ static struct super_block *alloc_super(s
 		s->s_qcop = sb_quotactl_ops;
 		s->s_op = &default_op;
 		s->s_time_gran = 1000000000;
+		s->cleancache_poolid = -1;
 	}
 out:
 	return s;
@@ -195,6 +197,11 @@ void deactivate_super(struct super_block
 		vfs_dq_off(s, 0);
 		down_write(&s->s_umount);
 		fs->kill_sb(s);
+		if (s->cleancache_poolid >= 0) {
+			int cleancache_poolid = s->cleancache_poolid;
+			s->cleancache_poolid = -1; /* avoid races */
+			cleancache_flush_fs(cleancache_poolid);
+		}
 		put_filesystem(fs);
 		put_super(s);
 	}
@@ -221,6 +228,7 @@ void deactivate_locked_super(struct supe
 		spin_unlock(&sb_lock);
 		vfs_dq_off(s, 0);
 		fs->kill_sb(s);
+		cleancache_flush_fs(s->cleancache_poolid);
 		put_filesystem(fs);
 		put_super(s);
 	} else {
diff -NruabBEp linux-2.6.34.5/include/linux/cleancache.h l-t/include/linux/cleancache.h
--- linux-2.6.34.5/include/linux/cleancache.h	1970-01-01 03:00:00.000000000 +0300
+++ l-t/include/linux/cleancache.h	2010-08-24 12:33:21.000000000 +0400
@@ -0,0 +1,88 @@
+#ifndef _LINUX_CLEANCACHE_H
+#define _LINUX_CLEANCACHE_H
+
+#include <linux/fs.h>
+#include <linux/mm.h>
+
+struct cleancache_ops {
+	int (*init_fs)(size_t);
+	int (*init_shared_fs)(char *uuid, size_t);
+	int (*get_page)(int, ino_t, pgoff_t, struct page *);
+	void (*put_page)(int, ino_t, pgoff_t, struct page *);
+	void (*flush_page)(int, ino_t, pgoff_t);
+	void (*flush_inode)(int, ino_t);
+	void (*flush_fs)(int);
+};
+
+extern struct cleancache_ops cleancache_ops;
+extern int __cleancache_get_page(struct page *);
+extern void __cleancache_put_page(struct page *);
+extern void __cleancache_flush_page(struct address_space *, struct page *);
+extern void __cleancache_flush_inode(struct address_space *);
+
+#ifdef CONFIG_CLEANCACHE
+#define cleancache_enabled (cleancache_ops.init_fs)
+#else
+#define cleancache_enabled (0)
+#endif
+
+/* called by a cleancache-enabled filesystem at time of mount */
+static inline int cleancache_init_fs(size_t pagesize)
+{
+	int ret = -1;
+
+	if (cleancache_enabled)
+		ret = (*cleancache_ops.init_fs)(pagesize);
+	return ret;
+}
+
+/* called by a cleancache-enabled clustered filesystem at time of mount */
+static inline int cleancache_init_shared_fs(char *uuid, size_t pagesize)
+{
+	int ret = -1;
+
+	if (cleancache_enabled)
+		ret = (*cleancache_ops.init_shared_fs)(uuid, pagesize);
+	return ret;
+}
+
+static inline int cleancache_get_page(struct page *page)
+{
+	int ret = -1;
+
+	if (cleancache_enabled)
+		ret = __cleancache_get_page(page);
+	return ret;
+}
+
+static inline void cleancache_put_page(struct page *page)
+{
+	if (cleancache_enabled)
+		__cleancache_put_page(page);
+}
+
+static inline void cleancache_flush_page(struct address_space *mapping,
+					struct page *page)
+{
+	if (cleancache_enabled)
+		__cleancache_flush_page(mapping, page);
+}
+
+static inline void cleancache_flush_inode(struct address_space *mapping)
+{
+	if (cleancache_enabled)
+		__cleancache_flush_inode(mapping);
+}
+
+/*
+ * called by any cleancache-enabled filesystem at time of unmount;
+ * note that pool_id is surrendered and may be returned by a subsequent
+ * cleancache_init_fs or cleancache_init_shared_fs
+ */
+static inline void cleancache_flush_fs(int pool_id)
+{
+	if (cleancache_enabled && pool_id >= 0)
+		(*cleancache_ops.flush_fs)(pool_id);
+}
+
+#endif /* _LINUX_CLEANCACHE_H */
diff -NruabBEp linux-2.6.34.5/include/linux/frontswap.h l-t/include/linux/frontswap.h
--- linux-2.6.34.5/include/linux/frontswap.h	1970-01-01 03:00:00.000000000 +0300
+++ l-t/include/linux/frontswap.h	2010-08-24 12:33:25.000000000 +0400
@@ -0,0 +1,97 @@
+#ifndef _LINUX_FRONTSWAP_H
+#define _LINUX_FRONTSWAP_H
+
+#include <linux/swap.h>
+#include <linux/mm.h>
+
+struct frontswap_ops {
+	int (*init)(unsigned);  /* frontswap enabled if non-NULL */
+	int (*put_page)(int, unsigned, pgoff_t, struct page *);
+	int (*get_page)(int, unsigned, pgoff_t, struct page *);
+	void (*flush_page)(int, unsigned, pgoff_t);
+	void (*flush_area)(int, unsigned);
+};
+
+extern int frontswap_poolid;
+
+extern struct frontswap_ops frontswap_ops;
+extern void frontswap_shrink(unsigned long);
+extern unsigned long frontswap_curr_pages(void);
+
+extern int __frontswap_put_page(struct page *page);
+extern int __frontswap_get_page(struct page *page);
+extern void __frontswap_flush_page(unsigned, pgoff_t);
+extern void __frontswap_flush_area(unsigned);
+
+#ifdef CONFIG_FRONTSWAP
+#define frontswap_enabled (frontswap_ops.init)
+#else
+/* all inline routines become no-ops and all externs are ignored */
+#define frontswap_enabled ((struct frontswap_ops *)NULL)
+#endif
+
+static inline int frontswap_test(struct swap_info_struct *sis, pgoff_t offset)
+{
+	int ret = 0;
+
+	if (frontswap_enabled && sis->frontswap_map)
+		ret = test_bit(offset % BITS_PER_LONG,
+			&sis->frontswap_map[offset/BITS_PER_LONG]);
+	return ret;
+}
+
+static inline void frontswap_set(struct swap_info_struct *sis, pgoff_t offset)
+{
+	if (frontswap_enabled && sis->frontswap_map)
+		set_bit(offset % BITS_PER_LONG,
+			&sis->frontswap_map[offset/BITS_PER_LONG]);
+}
+
+static inline void frontswap_clear(struct swap_info_struct *sis, pgoff_t offset)
+{
+	if (frontswap_enabled && sis->frontswap_map)
+		clear_bit(offset % BITS_PER_LONG,
+			&sis->frontswap_map[offset/BITS_PER_LONG]);
+}
+
+
+static inline void frontswap_init(unsigned type)
+{
+	if (frontswap_enabled) {
+		/* only need one poolid regardless of number of swap types */
+		if (frontswap_poolid < 0)
+			frontswap_poolid = (*frontswap_ops.init)(type);
+	}
+}
+
+static inline int frontswap_put_page(struct page *page)
+{
+	int ret = 0;
+
+	if (frontswap_enabled && frontswap_poolid >= 0)
+		ret = __frontswap_put_page(page);
+	return ret;
+}
+
+static inline int frontswap_get_page(struct page *page)
+{
+	int ret = 0;
+
+	if (frontswap_enabled && frontswap_poolid >= 0)
+		ret = __frontswap_get_page(page);
+	return ret;
+}
+
+static inline void frontswap_flush_page(unsigned type, pgoff_t offset)
+{
+	if (frontswap_enabled && frontswap_poolid >= 0)
+		__frontswap_flush_page(type, offset);
+}
+
+static inline void frontswap_flush_area(unsigned type)
+{
+	if (frontswap_enabled && frontswap_poolid >= 0)
+		__frontswap_flush_area(type);
+}
+
+#endif /* _LINUX_FRONTSWAP_H */
diff -NruabBEp linux-2.6.34.5/include/linux/fs.h l-t/include/linux/fs.h
--- linux-2.6.34.5/include/linux/fs.h	2010-08-20 22:52:05.000000000 +0400
+++ l-t/include/linux/fs.h	2010-08-24 12:33:29.000000000 +0400
@@ -1383,6 +1383,13 @@ struct super_block {
 	 * generic_show_options()
 	 */
 	char *s_options;
+
+#ifndef __GENKSYMS__
+	/*
+	 * Saved pool identifier for cleancache (-1 means none)
+	 */
+	int cleancache_poolid;
+#endif
 };
 
 extern struct timespec current_fs_time(struct super_block *sb);
diff -NruabBEp linux-2.6.34.5/include/linux/memory_hotplug.h l-t/include/linux/memory_hotplug.h
--- linux-2.6.34.5/include/linux/memory_hotplug.h	2010-08-20 22:52:05.000000000 +0400
+++ l-t/include/linux/memory_hotplug.h	2010-08-24 12:12:05.000000000 +0400
@@ -202,6 +202,7 @@ static inline int is_mem_section_removab
 }
 #endif /* CONFIG_MEMORY_HOTREMOVE */
 
+extern int add_registered_memory(int nid, u64 start, u64 size);
 extern int add_memory(int nid, u64 start, u64 size);
 extern int arch_add_memory(int nid, u64 start, u64 size);
 extern int remove_memory(u64 start, u64 size);
diff -NruabBEp linux-2.6.34.5/include/linux/swapfile.h l-t/include/linux/swapfile.h
--- linux-2.6.34.5/include/linux/swapfile.h	1970-01-01 03:00:00.000000000 +0300
+++ l-t/include/linux/swapfile.h	2010-08-24 12:33:33.000000000 +0400
@@ -0,0 +1,13 @@
+#ifndef _LINUX_SWAPFILE_H
+#define _LINUX_SWAPFILE_H
+
+/*
+ * these were static in swapfile.c but frontswap.c needs them and we don't
+ * want to expose them to the dozens of source files that include swap.h
+ */
+extern spinlock_t swap_lock;
+extern struct swap_list_t swap_list;
+extern struct swap_info_struct *swap_info[];
+extern int try_to_unuse(unsigned int, bool, unsigned long);
+
+#endif /* _LINUX_SWAPFILE_H */
diff -NruabBEp linux-2.6.34.5/include/linux/swap.h l-t/include/linux/swap.h
--- linux-2.6.34.5/include/linux/swap.h	2010-08-20 22:52:05.000000000 +0400
+++ l-t/include/linux/swap.h	2010-08-24 12:33:37.000000000 +0400
@@ -182,6 +182,10 @@ struct swap_info_struct {
 	struct block_device *bdev;	/* swap device or bdev of swap file */
 	struct file *swap_file;		/* seldom referenced */
 	unsigned int old_block_size;	/* seldom referenced */
+#ifndef __GENKSYMS__
+	unsigned long *frontswap_map;	/* frontswap in-use, one bit per page */
+	unsigned int frontswap_pages;	/* frontswap pages in-use counter */
+#endif
 };
 
 struct swap_list_t {
diff -NruabBEp linux-2.6.34.5/include/xen/interface/tmem.h l-t/include/xen/interface/tmem.h
--- linux-2.6.34.5/include/xen/interface/tmem.h	1970-01-01 03:00:00.000000000 +0300
+++ l-t/include/xen/interface/tmem.h	2010-08-24 13:15:49.000000000 +0400
@@ -0,0 +1,43 @@
+/*
+ * include/xen/interface/tmem.h
+ *
+ * Interface to Xen implementation of transcendent memory
+ *
+ * Copyright (C) 2009 Dan Magenheimer, Oracle Corp.
+ */
+
+#include <xen/interface/xen.h>
+
+#define TMEM_CONTROL               0
+#define TMEM_NEW_POOL              1
+#define TMEM_DESTROY_POOL          2
+#define TMEM_NEW_PAGE              3
+#define TMEM_PUT_PAGE              4
+#define TMEM_GET_PAGE              5
+#define TMEM_FLUSH_PAGE            6
+#define TMEM_FLUSH_OBJECT          7
+#define TMEM_READ                  8
+#define TMEM_WRITE                 9
+#define TMEM_XCHG                 10
+
+/* Subops for HYPERVISOR_tmem_op(TMEM_CONTROL) */
+#define TMEMC_THAW                 0
+#define TMEMC_FREEZE               1
+#define TMEMC_FLUSH                2
+#define TMEMC_DESTROY              3
+#define TMEMC_LIST                 4
+#define TMEMC_SET_WEIGHT           5
+#define TMEMC_SET_CAP              6
+#define TMEMC_SET_COMPRESS         7
+
+/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
+#define TMEM_POOL_PERSIST          1
+#define TMEM_POOL_SHARED           2
+#define TMEM_POOL_PAGESIZE_SHIFT   4
+#define TMEM_POOL_PAGESIZE_MASK  0xf
+#define TMEM_POOL_VERSION_SHIFT   24
+#define TMEM_POOL_VERSION_MASK  0xff
+
+/* Special errno values */
+#define EFROZEN                 1000
+#define EEMPTY                  1001
diff -NruabBEp linux-2.6.34.5/include/xen/interface/xen.h l-t/include/xen/interface/xen.h
--- linux-2.6.34.5/include/xen/interface/xen.h	2010-08-20 22:52:05.000000000 +0400
+++ l-t/include/xen/interface/xen.h	2010-08-24 12:34:45.000000000 +0400
@@ -58,6 +58,7 @@
 #define __HYPERVISOR_event_channel_op     32
 #define __HYPERVISOR_physdev_op           33
 #define __HYPERVISOR_hvm_op               34
+#define __HYPERVISOR_tmem_op              38
 
 /* Architecture-specific hypercall definitions. */
 #define __HYPERVISOR_arch_0               48
@@ -461,6 +462,27 @@ typedef uint8_t xen_domain_handle_t[16];
 #define __mk_unsigned_long(x) x ## UL
 #define mk_unsigned_long(x) __mk_unsigned_long(x)
 
+struct tmem_op {
+	uint32_t cmd;
+	int32_t pool_id;
+	union {
+		struct {  /* for cmd == TMEM_NEW_POOL */
+			uint64_t uuid[2];
+			uint32_t flags;
+		} new;
+		struct {
+			uint64_t object;
+			uint32_t index;
+			uint32_t tmem_offset;
+			uint32_t pfn_offset;
+			uint32_t len;
+			GUEST_HANDLE(void) gmfn; /* guest machine page frame */
+		} gen;
+	} u;
+};
+typedef struct tmem_op tmem_op_t;
+DEFINE_GUEST_HANDLE_STRUCT(tmem_op_t);
+
 #else /* __ASSEMBLY__ */
 
 /* In assembly code we cannot use C numeric constant suffixes. */
diff -NruabBEp linux-2.6.34.5/include/xen/tmem.h l-t/include/xen/tmem.h
--- linux-2.6.34.5/include/xen/tmem.h	1970-01-01 03:00:00.000000000 +0300
+++ l-t/include/xen/tmem.h	2010-08-24 13:15:44.000000000 +0400
@@ -0,0 +1,22 @@
+/*
+ * include/xen/tmem.h
+ *
+ * Interface to transcendent memory
+ *
+ * Copyright (C) 2008,2009 Dan Magenheimer, Oracle Corp.
+ */
+
+#include <linux/errno.h>
+
+struct tmem_pool_uuid {
+	u64 uuid_lo;
+	u64 uuid_hi;
+};
+
+#define TMEM_POOL_PRIVATE_UUID	{ 0, 0 }
+
+/* flags for tmem_ops.new_pool */
+#define TMEM_POOL_PERSIST          1
+#define TMEM_POOL_SHARED           2
+
+extern int tmem_enabled;
diff -NruabBEp linux-2.6.34.5/mm/cleancache.c l-t/mm/cleancache.c
--- linux-2.6.34.5/mm/cleancache.c	1970-01-01 03:00:00.000000000 +0300
+++ l-t/mm/cleancache.c	2010-08-24 12:32:15.000000000 +0400
@@ -0,0 +1,169 @@
+/*
+ * Cleancache frontend
+ *
+ * This code provides the generic "frontend" layer to call a matching
+ * "backend" driver implementation of cleancache.  See
+ * Documentation/vm/cleancache.txt for more information.
+ *
+ * Copyright (C) 2009-2010 Oracle Corp. All rights reserved.
+ * Author: Dan Magenheimer
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/cleancache.h>
+
+/*
+ * cleancache_ops contains the pointers to the cleancache "backend"
+ * implementation functions
+ */
+struct cleancache_ops cleancache_ops;
+EXPORT_SYMBOL(cleancache_ops);
+
+/* useful stats available in /sys/kernel/mm/cleancache */
+static unsigned long succ_gets;
+static unsigned long failed_gets;
+static unsigned long puts;
+static unsigned long flushes;
+
+/*
+ * "Get" data from cleancache associated with the poolid/inode/index
+ * that were specified when the data was put to cleanache and, if
+ * successful, use it to fill the specified page with data and return 0.
+ * The pageframe is unchanged and returns -1 if the get fails.
+ * Page must be locked by caller.
+ */
+int __cleancache_get_page(struct page *page)
+{
+	int ret = -1;
+	int pool_id;
+
+	VM_BUG_ON(!PageLocked(page));
+	pool_id = page->mapping->host->i_sb->cleancache_poolid;
+	if (pool_id >= 0) {
+		ret = (*cleancache_ops.get_page)(pool_id,
+						 page->mapping->host->i_ino,
+						 page->index,
+						 page);
+		if (ret == 0)
+			succ_gets++;
+		else
+			failed_gets++;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(__cleancache_get_page);
+
+/*
+ * "Put" data from a page to cleancache and associate it with the
+ * (previously-obtained per-filesystem) poolid and the page's,
+ * inode and page index.  Page must be locked.  Note that a put_page
+ * always "succeeds", though a subsequent get_page may succeed or fail.
+ */
+void __cleancache_put_page(struct page *page)
+{
+	int pool_id;
+
+	VM_BUG_ON(!PageLocked(page));
+	pool_id = page->mapping->host->i_sb->cleancache_poolid;
+	if (pool_id >= 0) {
+		(*cleancache_ops.put_page)(pool_id, page->mapping->host->i_ino,
+					   page->index, page);
+		puts++;
+	}
+}
+
+/*
+ * Flush any data from cleancache associated with the poolid and the
+ * page's inode and page index so that a subsequent "get" will fail.
+ */
+void __cleancache_flush_page(struct address_space *mapping, struct page *page)
+{
+	int pool_id = mapping->host->i_sb->cleancache_poolid;
+
+	if (pool_id >= 0) {
+		VM_BUG_ON(!PageLocked(page));
+		(*cleancache_ops.flush_page)(pool_id, mapping->host->i_ino,
+					     page->index);
+		flushes++;
+	}
+}
+EXPORT_SYMBOL(__cleancache_flush_page);
+
+/*
+ * Flush all data from cleancache associated with the poolid and the
+ * mappings's inode so that all subsequent gets to this poolid/inode
+ * will fail.
+ */
+void __cleancache_flush_inode(struct address_space *mapping)
+{
+	int pool_id = mapping->host->i_sb->cleancache_poolid;
+
+	if (pool_id >= 0)
+		(*cleancache_ops.flush_inode)(pool_id, mapping->host->i_ino);
+}
+EXPORT_SYMBOL(__cleancache_flush_inode);
+
+#ifdef CONFIG_SYSFS
+
+/* see Documentation/ABI/xxx/sysfs-kernel-mm-cleancache */
+
+#define CLEANCACHE_ATTR_RO(_name) \
+	static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
+
+static ssize_t succ_gets_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", succ_gets);
+}
+CLEANCACHE_ATTR_RO(succ_gets);
+
+static ssize_t failed_gets_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", failed_gets);
+}
+CLEANCACHE_ATTR_RO(failed_gets);
+
+static ssize_t puts_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", puts);
+}
+CLEANCACHE_ATTR_RO(puts);
+
+static ssize_t flushes_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", flushes);
+}
+CLEANCACHE_ATTR_RO(flushes);
+
+static struct attribute *cleancache_attrs[] = {
+	&succ_gets_attr.attr,
+	&failed_gets_attr.attr,
+	&puts_attr.attr,
+	&flushes_attr.attr,
+	NULL,
+};
+
+static struct attribute_group cleancache_attr_group = {
+	.attrs = cleancache_attrs,
+	.name = "cleancache",
+};
+
+#endif /* CONFIG_SYSFS */
+
+static int __init init_cleancache(void)
+{
+#ifdef CONFIG_SYSFS
+	int err;
+
+	err = sysfs_create_group(mm_kobj, &cleancache_attr_group);
+#endif /* CONFIG_SYSFS */
+	return 0;
+}
+module_init(init_cleancache)
diff -NruabBEp linux-2.6.34.5/mm/filemap.c l-t/mm/filemap.c
--- linux-2.6.34.5/mm/filemap.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/mm/filemap.c	2010-08-24 12:32:18.000000000 +0400
@@ -34,6 +34,7 @@
 #include <linux/hardirq.h> /* for BUG_ON(!in_atomic()) only */
 #include <linux/memcontrol.h>
 #include <linux/mm_inline.h> /* for page_is_file_cache() */
+#include <linux/cleancache.h>
 #include "internal.h"
 
 /*
@@ -119,6 +120,16 @@ void __remove_from_page_cache(struct pag
 {
 	struct address_space *mapping = page->mapping;
 
+	/*
+	 * if we're uptodate, flush out into the cleancache, otherwise
+	 * invalidate any existing cleancache entries.  We can't leave
+	 * stale data around in the cleancache once our page is gone
+	 */
+	if (PageUptodate(page))
+		cleancache_put_page(page);
+	else
+		cleancache_flush_page(mapping, page);
+
 	radix_tree_delete(&mapping->page_tree, page->index);
 	page->mapping = NULL;
 	mapping->nrpages--;
diff -NruabBEp linux-2.6.34.5/mm/frontswap.c l-t/mm/frontswap.c
--- linux-2.6.34.5/mm/frontswap.c	1970-01-01 03:00:00.000000000 +0300
+++ l-t/mm/frontswap.c	2010-08-24 12:32:23.000000000 +0400
@@ -0,0 +1,307 @@
+/*
+ * Frontswap frontend
+ *
+ * This code provides the generic "frontend" layer to call a matching
+ * "backend" driver implementation of frontswap.  See
+ * Documentation/vm/frontswap.txt for more information.
+ *
+ * Copyright (C) 2009-2010 Oracle Corp.  All rights reserved.
+ * Author: Dan Magenheimer
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.
+ */
+
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/sysctl.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
+#include <linux/proc_fs.h>
+#include <linux/security.h>
+#include <linux/capability.h>
+#include <linux/frontswap.h>
+#include <linux/swapfile.h>
+
+/*
+ * frontswap_ops contains the pointers to the frontswap "backend"
+ * implementation functions
+ */
+struct frontswap_ops frontswap_ops;
+EXPORT_SYMBOL(frontswap_ops);
+
+/* one poolid is shared by frontswap across all "fronted" swap devices */
+int frontswap_poolid = -1;
+EXPORT_SYMBOL(frontswap_poolid);
+
+/* useful stats available in /sys/kernel/mm/frontswap */
+static unsigned long gets;
+static unsigned long succ_puts;
+static unsigned long failed_puts;
+static unsigned long flushes;
+
+/*
+ * "Put" data from a page to frontswap and associate it with the page's
+ * swaptype and offset.  Page must be locked and in the swap cache.
+ * If frontswap already contains a page with matching swaptype and
+ * offset, the frontswap implmentation may either overwrite the data
+ * and return success or flush the page from frontswap and return failure
+ */
+int __frontswap_put_page(struct page *page)
+{
+	int ret = 0, dup = 0;
+	swp_entry_t entry = { .val = page_private(page), };
+	int type = swp_type(entry);
+	struct swap_info_struct *sis = swap_info[type];
+	unsigned long offset = (unsigned long)swp_offset(entry);
+
+	VM_BUG_ON(!PageLocked(page));
+	if (frontswap_test(sis, offset))
+		dup = 1;
+	ret = (*frontswap_ops.put_page)(frontswap_poolid, type, offset, page);
+	if (ret == 0) {
+		frontswap_set(sis, offset);
+		succ_puts++;
+		if (!dup)
+			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--;
+		failed_puts++;
+	} else
+		failed_puts++;
+	return ret;
+}
+
+/*
+ * "Get" data from frontswap associated with swaptype and offset that were
+ * specified when the data was put to frontswap and use it to fill the
+ * specified page with data. Page must be locked and in the swap cache
+ */
+int __frontswap_get_page(struct page *page)
+{
+	int ret = 0;
+	swp_entry_t entry = { .val = page_private(page), };
+	int type = swp_type(entry);
+	struct swap_info_struct *sis = swap_info[type];
+	unsigned long offset = (unsigned long)swp_offset(entry);
+
+	VM_BUG_ON(!PageLocked(page));
+	if (frontswap_test(sis, offset))
+		ret = (*frontswap_ops.get_page)(frontswap_poolid,
+						 type, offset, page);
+	if (ret == 0)
+		gets++;
+	return ret;
+}
+
+/*
+ * Flush any data from frontswap associated with the specified swaptype
+ * and offset so that a subsequent "get" will fail.
+ */
+void __frontswap_flush_page(unsigned type, pgoff_t offset)
+{
+	struct swap_info_struct *sis = swap_info[type];
+
+	if (frontswap_test(sis, offset)) {
+		(*frontswap_ops.flush_page)(frontswap_poolid, type, offset);
+		sis->frontswap_pages--;
+		frontswap_clear(sis, offset);
+		flushes++;
+	}
+}
+
+/*
+ * Flush all data from frontswap associated with all offsets for the
+ * specified swaptype.
+ */
+void __frontswap_flush_area(unsigned type)
+{
+	struct swap_info_struct *sis = swap_info[type];
+
+	(*frontswap_ops.flush_area)(frontswap_poolid, type);
+	sis->frontswap_pages = 0;
+	memset(sis->frontswap_map, 0, sis->max / sizeof(long));
+}
+
+/*
+ * Frontswap, like a true swap device, may unnecessarily retain pages
+ * under certain circumstances; "shrink" frontswap is essentially a
+ * "partial swapoff" and works by calling try_to_unuse to attempt to
+ * unuse enough frontswap pages to attempt to -- subject to memory
+ * constraints -- reduce the number of pages in frontswap
+ */
+void frontswap_shrink(unsigned long target_pages)
+{
+	int wrapped = 0;
+	bool locked = false;
+
+	for (wrapped = 0; wrapped <= 3; wrapped++) {
+
+		struct swap_info_struct *si = NULL;
+		unsigned long total_pages = 0, total_pages_to_unuse;
+		unsigned long pages = 0, unuse_pages = 0;
+		int type;
+
+		/*
+		 * we don't want to hold swap_lock while doing a very
+		 * lengthy try_to_unuse, but swap_list may change
+		 * so restart scan from swap_list.head each time
+		 */
+		spin_lock(&swap_lock);
+		locked = true;
+		total_pages = 0;
+		for (type = swap_list.head; type >= 0; type = si->next) {
+			si = swap_info[type];
+			total_pages += 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)
+				pages = unuse_pages = total_pages_to_unuse;
+			else {
+				pages = si->frontswap_pages;
+				unuse_pages = 0; /* unuse all */
+			}
+			if (security_vm_enough_memory_kern(pages))
+				continue;
+			vm_unacct_memory(pages);
+			break;
+		}
+		if (type < 0)
+			goto out;
+		locked = false;
+		spin_unlock(&swap_lock);
+		current->flags |= PF_OOM_ORIGIN;
+		try_to_unuse(type, true, unuse_pages);
+		current->flags &= ~PF_OOM_ORIGIN;
+	}
+
+out:
+	if (locked)
+		spin_unlock(&swap_lock);
+	return;
+}
+EXPORT_SYMBOL(frontswap_shrink);
+
+/*
+ * 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.
+ */
+unsigned long frontswap_curr_pages(void)
+{
+	int type;
+	unsigned long totalpages = 0;
+	struct swap_info_struct *si = NULL;
+
+	spin_lock(&swap_lock);
+	for (type = swap_list.head; type >= 0; type = si->next) {
+		si = swap_info[type];
+		totalpages += si->frontswap_pages;
+	}
+	spin_unlock(&swap_lock);
+	return totalpages;
+}
+EXPORT_SYMBOL(frontswap_curr_pages);
+
+#ifdef CONFIG_SYSFS
+
+/* see Documentation/ABI/xxx/sysfs-kernel-mm-frontswap */
+
+#define FRONTSWAP_ATTR_RO(_name) \
+	static struct kobj_attribute _name##_attr = __ATTR_RO(_name)
+#define FRONTSWAP_ATTR(_name) \
+	static struct kobj_attribute _name##_attr = \
+		__ATTR(_name, 0644, _name##_show, _name##_store)
+
+static ssize_t curr_pages_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", frontswap_curr_pages());
+}
+
+static ssize_t curr_pages_store(struct kobject *kobj,
+			       struct kobj_attribute *attr,
+			       const char *buf, size_t count)
+{
+	unsigned long target_pages;
+	int err;
+
+	err = strict_strtoul(buf, 10, &target_pages);
+	if (err)
+		return -EINVAL;
+
+	frontswap_shrink(target_pages);
+
+	return count;
+}
+FRONTSWAP_ATTR(curr_pages);
+
+static ssize_t succ_puts_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", succ_puts);
+}
+FRONTSWAP_ATTR_RO(succ_puts);
+
+static ssize_t failed_puts_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", failed_puts);
+}
+FRONTSWAP_ATTR_RO(failed_puts);
+
+static ssize_t gets_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", gets);
+}
+FRONTSWAP_ATTR_RO(gets);
+
+static ssize_t flushes_show(struct kobject *kobj,
+			       struct kobj_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%lu\n", flushes);
+}
+FRONTSWAP_ATTR_RO(flushes);
+
+static struct attribute *frontswap_attrs[] = {
+	&curr_pages_attr.attr,
+	&succ_puts_attr.attr,
+	&failed_puts_attr.attr,
+	&gets_attr.attr,
+	&flushes_attr.attr,
+	NULL,
+};
+
+static struct attribute_group frontswap_attr_group = {
+	.attrs = frontswap_attrs,
+	.name = "frontswap",
+};
+
+#endif /* CONFIG_SYSFS */
+
+static int __init init_frontswap(void)
+{
+#ifdef CONFIG_SYSFS
+	int err;
+
+	err = sysfs_create_group(mm_kobj, &frontswap_attr_group);
+#endif /* CONFIG_SYSFS */
+	return 0;
+}
+
+static void __exit exit_frontswap(void)
+{
+	frontswap_shrink(0UL);
+}
+
+module_init(init_frontswap);
+module_exit(exit_frontswap);
diff -NruabBEp linux-2.6.34.5/mm/Kconfig l-t/mm/Kconfig
--- linux-2.6.34.5/mm/Kconfig	2010-08-20 22:52:05.000000000 +0400
+++ l-t/mm/Kconfig	2010-08-24 12:32:56.000000000 +0400
@@ -287,3 +287,42 @@ config NOMMU_INITIAL_TRIM_EXCESS
 	  of 1 says that all excess pages should be trimmed.
 
 	  See Documentation/nommu-mmap.txt for more information.
+
+config CLEANCACHE
+	bool "Enable cleancache pseudo-RAM driver to cache clean pages"
+	default y
+	help
+ 	  Cleancache can be thought of as a page-granularity victim cache
+	  for clean pages that the kernel's pageframe replacement algorithm
+	  (PFRA) would like to keep around, but can't since there isn't enough
+	  memory.  So when the PFRA "evicts" a page, it first attempts to put
+	  it into a synchronous concurrency-safe page-oriented pseudo-RAM
+	  device (such as Xen's Transcendent Memory, aka "tmem") which is not
+	  directly accessible or addressable by the kernel and is of unknown
+	  (and possibly time-varying) size.  And when a cleancache-enabled
+	  filesystem wishes to access a page in a file on disk, it first
+	  checks cleancache to see if it already contains it; if it does,
+ 	  the page is copied into the kernel and a disk access is avoided.
+	  When a pseudo-RAM device is available, a significant I/O reduction
+	  may be achieved.  When none is available, all cleancache calls
+	  are reduced to a single pointer-compare-against-NULL resulting
+	  in a negligible performance hit.
+
+	  If unsure, say Y to enable cleancache
+
+config FRONTSWAP
+	bool "Enable frontswap pseudo-RAM driver to cache swap pages"
+	default y
+	help
+ 	  Frontswap is so named because it can be thought of as the opposite of
+ 	  a "backing" store for a swap device.  The storage is assumed to be
+ 	  a synchronous concurrency-safe page-oriented pseudo-RAM device (such
+	  as Xen's Transcendent Memory, aka "tmem") which is not directly
+	  accessible or addressable by the kernel and is of unknown (and
+	  possibly time-varying) size.  When a pseudo-RAM device is available,
+	  a signficant swap I/O reduction may be achieved.  When none is
+	  available, all frontswap calls are reduced to a single pointer-
+	  compare-against-NULL resulting in a negligible performance hit.
+
+	  If unsure, say Y to enable frontswap.
+
diff -NruabBEp linux-2.6.34.5/mm/Makefile l-t/mm/Makefile
--- linux-2.6.34.5/mm/Makefile	2010-08-20 22:52:05.000000000 +0400
+++ l-t/mm/Makefile	2010-08-24 12:32:59.000000000 +0400
@@ -17,6 +17,7 @@ obj-y += init-mm.o
 
 obj-$(CONFIG_BOUNCE)	+= bounce.o
 obj-$(CONFIG_SWAP)	+= page_io.o swap_state.o swapfile.o thrash.o
+obj-$(CONFIG_FRONTSWAP)	+= frontswap.o
 obj-$(CONFIG_HAS_DMA)	+= dmapool.o
 obj-$(CONFIG_HUGETLBFS)	+= hugetlb.o
 obj-$(CONFIG_NUMA) 	+= mempolicy.o
@@ -44,3 +45,4 @@ obj-$(CONFIG_MEMORY_FAILURE) += memory-f
 obj-$(CONFIG_HWPOISON_INJECT) += hwpoison-inject.o
 obj-$(CONFIG_DEBUG_KMEMLEAK) += kmemleak.o
 obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak-test.o
+obj-$(CONFIG_CLEANCACHE) += cleancache.o
diff -NruabBEp linux-2.6.34.5/mm/memory_hotplug.c l-t/mm/memory_hotplug.c
--- linux-2.6.34.5/mm/memory_hotplug.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/mm/memory_hotplug.c	2010-08-24 12:27:42.000000000 +0400
@@ -481,22 +481,13 @@ static void rollback_node_hotadd(int nid
 	return;
 }
 
-
 /* we are OK calling __meminit stuff here - we have CONFIG_MEMORY_HOTPLUG */
-int __ref add_memory(int nid, u64 start, u64 size)
+static int __ref __add_memory(int nid, u64 start, u64 size)
 {
 	pg_data_t *pgdat = NULL;
 	int new_pgdat = 0;
-	struct resource *res;
 	int ret;
 
-	lock_system_sleep();
-
-	res = register_memory_resource(start, size);
-	ret = -EEXIST;
-	if (!res)
-		goto out;
-
 	if (!node_online(nid)) {
 		pgdat = hotadd_new_pgdat(nid, start);
 		ret = -ENOMEM;
@@ -530,10 +521,44 @@ int __ref add_memory(int nid, u64 start,
 	goto out;
 
 error:
-	/* rollback pgdat allocation and others */
+	/* rollback pgdat allocation */
 	if (new_pgdat)
 		rollback_node_hotadd(nid, pgdat);
-	if (res)
+
+out:
+	return ret;
+}
+
+int add_registered_memory(int nid, u64 start, u64 size)
+{
+        int ret;
+
+        lock_system_sleep();
+        ret = __add_memory(nid, start, size);
+
+	unlock_system_sleep();
+
+        return ret;
+}
+EXPORT_SYMBOL_GPL(add_registered_memory);
+
+int add_memory(int nid, u64 start, u64 size)
+{
+        int ret = -EEXIST;
+        struct resource *res;
+
+        lock_system_sleep();
+
+        res = register_memory_resource(start, size);
+
+        if (!res)
+                goto out;
+
+        ret = __add_memory(nid, start, size);
+
+        if (!ret)
+                goto out;
+
 		release_memory_resource(res);
 
 out:
diff -NruabBEp linux-2.6.34.5/mm/mmap.c l-t/mm/mmap.c
--- linux-2.6.34.5/mm/mmap.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/mm/mmap.c	2010-08-24 12:31:52.000000000 +0400
@@ -87,6 +87,12 @@ int sysctl_overcommit_ratio = 50;	/* def
 int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
 struct percpu_counter vm_committed_as;
 
+unsigned long vm_get_committed_as(void)
+{
+	return percpu_counter_read_positive(&vm_committed_as);
+}
+EXPORT_SYMBOL(vm_get_committed_as);
+
 /*
  * Check that a process has enough memory to allocate a new virtual
  * mapping. 0 means there is enough memory for the allocation to
diff -NruabBEp linux-2.6.34.5/mm/page_io.c l-t/mm/page_io.c
--- linux-2.6.34.5/mm/page_io.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/mm/page_io.c	2010-08-24 12:31:30.000000000 +0400
@@ -18,6 +18,7 @@
 #include <linux/bio.h>
 #include <linux/swapops.h>
 #include <linux/writeback.h>
+#include <linux/frontswap.h>
 #include <asm/pgtable.h>
 
 static struct bio *get_swap_bio(gfp_t gfp_flags,
@@ -98,6 +99,12 @@ int swap_writepage(struct page *page, st
 		unlock_page(page);
 		goto out;
 	}
+	if (frontswap_put_page(page) == 0) {
+		set_page_writeback(page);
+		unlock_page(page);
+		end_page_writeback(page);
+		goto out;
+	}
 	bio = get_swap_bio(GFP_NOIO, page, end_swap_bio_write);
 	if (bio == NULL) {
 		set_page_dirty(page);
@@ -122,6 +129,11 @@ 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);
+		goto out;
+	}
 	bio = get_swap_bio(GFP_KERNEL, page, end_swap_bio_read);
 	if (bio == NULL) {
 		unlock_page(page);
diff -NruabBEp linux-2.6.34.5/mm/swapfile.c l-t/mm/swapfile.c
--- linux-2.6.34.5/mm/swapfile.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/mm/swapfile.c	2010-08-24 12:31:56.000000000 +0400
@@ -30,6 +30,8 @@
 #include <linux/capability.h>
 #include <linux/syscalls.h>
 #include <linux/memcontrol.h>
+#include <linux/frontswap.h>
+#include <linux/swapfile.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -41,7 +43,7 @@ static bool swap_count_continued(struct
 static void free_swap_count_continuations(struct swap_info_struct *);
 static sector_t map_swap_entry(swp_entry_t, struct block_device**);
 
-static DEFINE_SPINLOCK(swap_lock);
+DEFINE_SPINLOCK(swap_lock);
 static unsigned int nr_swapfiles;
 long nr_swap_pages;
 long total_swap_pages;
@@ -52,9 +54,9 @@ static const char Unused_file[] = "Unuse
 static const char Bad_offset[] = "Bad swap offset entry ";
 static const char Unused_offset[] = "Unused swap offset entry ";
 
-static struct swap_list_t swap_list = {-1, -1};
+struct swap_list_t swap_list = {-1, -1};
 
-static struct swap_info_struct *swap_info[MAX_SWAPFILES];
+struct swap_info_struct *swap_info[MAX_SWAPFILES];
 
 static DEFINE_MUTEX(swapon_mutex);
 
@@ -585,6 +587,7 @@ static unsigned char swap_entry_free(str
 			swap_list.next = p->type;
 		nr_swap_pages++;
 		p->inuse_pages--;
+		frontswap_flush_page(p->type, offset);
 	}
 
 	return usage;
@@ -1027,7 +1030,7 @@ static int unuse_mm(struct mm_struct *mm
  * Recycle to start on reaching the end, returning 0 when empty.
  */
 static unsigned int find_next_to_unuse(struct swap_info_struct *si,
-					unsigned int prev)
+					unsigned int prev, bool frontswap)
 {
 	unsigned int max = si->max;
 	unsigned int i = prev;
@@ -1053,6 +1056,12 @@ static unsigned int find_next_to_unuse(s
 			prev = 0;
 			i = 1;
 		}
+                if (frontswap) {
+                        if (frontswap_test(si, i))
+                                break;
+                        else
+                                continue;
+                }
 		count = si->swap_map[i];
 		if (count && swap_count(count) != SWAP_MAP_BAD)
 			break;
@@ -1064,8 +1073,12 @@ static unsigned int find_next_to_unuse(s
  * We completely avoid races by reading each swap page in advance,
  * and then search for the process using it.  All the necessary
  * page table adjustments can then be made atomically.
+ *
+ * if the boolean frontswap is true, only unuse pages_to_unuse pages;
+ * pages_to_unuse==0 means all pages
  */
-static int try_to_unuse(unsigned int type)
+int try_to_unuse(unsigned int type, bool frontswap,
+               unsigned long pages_to_unuse)
 {
 	struct swap_info_struct *si = swap_info[type];
 	struct mm_struct *start_mm;
@@ -1098,7 +1111,7 @@ static int try_to_unuse(unsigned int typ
 	 * one pass through swap_map is enough, but not necessarily:
 	 * there are races when an instance of an entry might be missed.
 	 */
-	while ((i = find_next_to_unuse(si, i)) != 0) {
+	while ((i = find_next_to_unuse(si, i, frontswap)) != 0) {
 		if (signal_pending(current)) {
 			retval = -EINTR;
 			break;
@@ -1265,6 +1278,11 @@ static int try_to_unuse(unsigned int typ
 		 * interactive performance.
 		 */
 		cond_resched();
+                if (frontswap && pages_to_unuse > 0) {
+                        if (!--pages_to_unuse)
+                                break;
+                }
+
 	}
 
 	mmput(start_mm);
@@ -1590,7 +1608,7 @@ SYSCALL_DEFINE1(swapoff, const char __us
 	spin_unlock(&swap_lock);
 
 	current->flags |= PF_OOM_ORIGIN;
-	err = try_to_unuse(type);
+	err = try_to_unuse(type, false, 0);
 	current->flags &= ~PF_OOM_ORIGIN;
 
 	if (err) {
@@ -1642,9 +1660,12 @@ SYSCALL_DEFINE1(swapoff, const char __us
 	swap_map = p->swap_map;
 	p->swap_map = NULL;
 	p->flags = 0;
+	frontswap_flush_area(type);
 	spin_unlock(&swap_lock);
 	mutex_unlock(&swapon_mutex);
 	vfree(swap_map);
+        if (p->frontswap_map)
+                vfree(p->frontswap_map);
 	/* Destroy swap account informatin */
 	swap_cgroup_swapoff(type);
 
@@ -1800,6 +1821,7 @@ SYSCALL_DEFINE2(swapon, const char __use
 	unsigned long maxpages;
 	unsigned long swapfilepages;
 	unsigned char *swap_map = NULL;
+	unsigned long *frontswap_map = NULL;
 	struct page *page = NULL;
 	struct inode *inode = NULL;
 	int did_down = 0;
@@ -2020,6 +2042,12 @@ SYSCALL_DEFINE2(swapon, const char __use
 		error = -EINVAL;
 		goto bad_swap;
 	}
+        /* frontswap enabled? set up bit-per-page map for frontswap */
+        if (frontswap_enabled) {
+                frontswap_map = vmalloc(maxpages / sizeof(long));
+                if (frontswap_map)
+                        memset(frontswap_map, 0, maxpages / sizeof(long));
+        }
 
 	if (p->bdev) {
 		if (blk_queue_nonrot(bdev_get_queue(p->bdev))) {
@@ -2038,16 +2066,18 @@ SYSCALL_DEFINE2(swapon, const char __use
 	else
 		p->prio = --least_priority;
 	p->swap_map = swap_map;
+	p->frontswap_map = frontswap_map;
 	p->flags |= SWP_WRITEOK;
 	nr_swap_pages += nr_good_pages;
 	total_swap_pages += nr_good_pages;
 
 	printk(KERN_INFO "Adding %uk swap on %s.  "
-			"Priority:%d extents:%d across:%lluk %s%s\n",
+	                 "Priority:%d extents:%d across:%lluk %s%s%s\n",
 		nr_good_pages<<(PAGE_SHIFT-10), name, p->prio,
 		nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
 		(p->flags & SWP_SOLIDSTATE) ? "SS" : "",
-		(p->flags & SWP_DISCARDABLE) ? "D" : "");
+		(p->flags & SWP_DISCARDABLE) ? "D" : "",
+		(p->frontswap_map) ? "FS" : "");
 
 	/* insert swap space into swap_list: */
 	prev = -1;
@@ -2061,6 +2091,7 @@ SYSCALL_DEFINE2(swapon, const char __use
 		swap_list.head = swap_list.next = type;
 	else
 		swap_info[prev]->next = type;
+	frontswap_init(type);
 	spin_unlock(&swap_lock);
 	mutex_unlock(&swapon_mutex);
 	error = 0;
@@ -2245,6 +2276,10 @@ int valid_swaphandles(swp_entry_t entry,
 		base++;
 
 	spin_lock(&swap_lock);
+        if (frontswap_test(si, target)) {
+                spin_unlock(&swap_lock);
+                return 0;
+        }
 	if (end > si->max)	/* don't go beyond end of map */
 		end = si->max;
 
@@ -2255,6 +2290,9 @@ int valid_swaphandles(swp_entry_t entry,
 			break;
 		if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD)
 			break;
+		/* Don't read in frontswap pages */
+                if (frontswap_test(si, toff))
+                        break;
 	}
 	/* Count contiguous allocated slots below our target */
 	for (toff = target; --toff >= base; nr_pages++) {
@@ -2263,6 +2301,9 @@ int valid_swaphandles(swp_entry_t entry,
 			break;
 		if (swap_count(si->swap_map[toff]) == SWAP_MAP_BAD)
 			break;
+                /* Don't read in frontswap pages */
+                if (frontswap_test(si, toff))
+                        break;
 	}
 	spin_unlock(&swap_lock);
 
diff -NruabBEp linux-2.6.34.5/mm/truncate.c l-t/mm/truncate.c
--- linux-2.6.34.5/mm/truncate.c	2010-08-20 22:52:05.000000000 +0400
+++ l-t/mm/truncate.c	2010-08-24 12:31:43.000000000 +0400
@@ -19,6 +19,7 @@
 #include <linux/task_io_accounting_ops.h>
 #include <linux/buffer_head.h>	/* grr. try_to_release_page,
 				   do_invalidatepage */
+#include <linux/cleancache.h>
 #include "internal.h"
 
 
@@ -51,6 +52,7 @@ void do_invalidatepage(struct page *page
 static inline void truncate_partial_page(struct page *page, unsigned partial)
 {
 	zero_user_segment(page, partial, PAGE_CACHE_SIZE);
+	cleancache_flush_page(page->mapping, page);
 	if (page_has_private(page))
 		do_invalidatepage(page, partial);
 }
@@ -108,6 +110,10 @@ truncate_complete_page(struct address_sp
 	clear_page_mlock(page);
 	remove_from_page_cache(page);
 	ClearPageMappedToDisk(page);
+	/* this must be after the remove_from_page_cache which
+	 * calls cleancache_put_page (and note page->mapping is now NULL)
+	 */
+	cleancache_flush_page(mapping, page);
 	page_cache_release(page);	/* pagecache ref */
 	return 0;
 }
@@ -215,6 +221,7 @@ void truncate_inode_pages_range(struct a
 	pgoff_t next;
 	int i;
 
+	cleancache_flush_inode(mapping);
 	if (mapping->nrpages == 0)
 		return;
 
@@ -290,6 +297,7 @@ void truncate_inode_pages_range(struct a
 		pagevec_release(&pvec);
 		mem_cgroup_uncharge_end();
 	}
+	cleancache_flush_inode(mapping);
 }
 EXPORT_SYMBOL(truncate_inode_pages_range);
 
@@ -428,6 +436,7 @@ int invalidate_inode_pages2_range(struct
 	int did_range_unmap = 0;
 	int wrapped = 0;
 
+	cleancache_flush_inode(mapping);
 	pagevec_init(&pvec, 0);
 	next = start;
 	while (next <= end && !wrapped &&
@@ -486,6 +495,7 @@ int invalidate_inode_pages2_range(struct
 		mem_cgroup_uncharge_end();
 		cond_resched();
 	}
+	cleancache_flush_inode(mapping);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(invalidate_inode_pages2_range);

[-- Attachment #4: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Linux mainstream balloon driver fails to grow memory= -> maxmem=
  2010-08-24 11:29     ` Vasiliy G Tolstov
@ 2010-08-24 19:56       ` Daniel Kiper
  2010-08-24 20:22         ` Vasiliy G Tolstov
  0 siblings, 1 reply; 7+ messages in thread
From: Daniel Kiper @ 2010-08-24 19:56 UTC (permalink / raw)
  To: Vasiliy G Tolstov
  Cc: Dan Magenheimer, xen-devel, Jeremy Fitzhardinge, Daniel Kiper

Hello,

On Tue, Aug 24, 2010 at 03:29:46PM +0400, Vasiliy G Tolstov wrote:
> Stupidly apply patch from Daniel and Dan to linux-2.6.34.5 does not
> work.
> Dan, can You check what need to modify with Daniel patch to work
> together with tmem?
>
> P.S. Best, if the domU can selfballooning to memory, after that it can
> emulate memory-hotplug and add needed memory slot, after that
> selfballoon to next target.... If that possible.
>
> With selfballooning = 0 xm mem-set xxx xxx not work's domU kernel panic:

[...]

Thx for report. I will check that also.

Daniel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: Linux mainstream balloon driver fails to grow memory= -> maxmem=
  2010-08-24 19:56       ` Daniel Kiper
@ 2010-08-24 20:22         ` Vasiliy G Tolstov
  0 siblings, 0 replies; 7+ messages in thread
From: Vasiliy G Tolstov @ 2010-08-24 20:22 UTC (permalink / raw)
  To: Daniel Kiper; +Cc: Dan Magenheimer, xen-devel, Jeremy Fitzhardinge

On Tue, 2010-08-24 at 21:56 +0200, Daniel Kiper wrote:
> Hello,
> 
> On Tue, Aug 24, 2010 at 03:29:46PM +0400, Vasiliy G Tolstov wrote:
> > Stupidly apply patch from Daniel and Dan to linux-2.6.34.5 does not
> > work.
> > Dan, can You check what need to modify with Daniel patch to work
> > together with tmem?
> >
> > P.S. Best, if the domU can selfballooning to memory, after that it can
> > emulate memory-hotplug and add needed memory slot, after that
> > selfballoon to next target.... If that possible.
> >
> > With selfballooning = 0 xm mem-set xxx xxx not work's domU kernel panic:
> 
> [...]
> 
> Thx for report. I will check that also.
> 
> Danielrget memory and others.

I'm investigate, that memory hotplug work's fine. Problem with
selfballoonin - i think it needs to recalculate some variables, like
minimal target memory and others.

-- 
Vasiliy G Tolstov <v.tolstov@selfip.ru>
Selfip.Ru

^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: Linux mainstream balloon driver fails to grow memory= -> maxmem=
  2010-08-24  2:11   ` Dan Magenheimer
  2010-08-24 11:29     ` Vasiliy G Tolstov
@ 2010-08-25 22:44     ` Dan Magenheimer
  1 sibling, 0 replies; 7+ messages in thread
From: Dan Magenheimer @ 2010-08-25 22:44 UTC (permalink / raw)
  To: Jeremy Fitzhardinge; +Cc: xen-devel, Daniel Kiper, Vasiliy G Tolstov

> So if Daniel's stuff works along with tmem, I'm not too bothered about
> fixing this known difference between 2.6.18-xen and mainstream.
> And IIRC the maxmem= parameter is required for PoD to work for Windows
> also.  IOW, this should probably be documented (any ideas where?)
> but the "old way" may best be left to obsolesce with 2.6.18-xen.

Hmmm... I spoke too soon.  We apparently have a number of customers
that use maxmem and would be upset if the functionality goes away.

> > There's a couple of experiments floating around in the tree to try to
> > honour maxmem, but they're somewhat rotted.  Its probably worth
> > trying to resurrect them though.

If you can send more information about the "experiments",
I may be able to take a look fairly soon (unless Daniel Kiper
is already looking into it).  Since the support is currently
missing from RHEL6 beta, future customers using RHEL6 as a
Xen PV guest may get very confused by what might appear to
them as a tools or Xen bug.

Thanks,
Dan

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2010-08-25 22:44 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-23 23:49 Linux mainstream balloon driver fails to grow memory= -> maxmem= Dan Magenheimer
2010-08-24  0:50 ` Jeremy Fitzhardinge
2010-08-24  2:11   ` Dan Magenheimer
2010-08-24 11:29     ` Vasiliy G Tolstov
2010-08-24 19:56       ` Daniel Kiper
2010-08-24 20:22         ` Vasiliy G Tolstov
2010-08-25 22:44     ` Dan Magenheimer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.