qubes-linux-kernel/patches.xen/xen-tmem-v1
2011-04-19 22:09:59 +02:00

349 lines
10 KiB
Plaintext

From: jbeulich@novell.com
Subject: update tmem interface to v1
Patch-mainline: n/a
--- head-2010-10-05.orig/include/xen/interface/tmem.h 2010-01-04 11:56:34.000000000 +0100
+++ head-2010-10-05/include/xen/interface/tmem.h 2010-10-06 12:12:59.000000000 +0200
@@ -29,6 +29,9 @@
#include "xen.h"
+/* version of ABI */
+#define TMEM_SPEC_VERSION 1
+
/* Commands to HYPERVISOR_tmem_op() */
#define TMEM_CONTROL 0
#define TMEM_NEW_POOL 1
@@ -75,10 +78,12 @@
/* Bits for HYPERVISOR_tmem_op(TMEM_NEW_POOL) */
#define TMEM_POOL_PERSIST 1
#define TMEM_POOL_SHARED 2
+#define TMEM_POOL_PRECOMPRESSED 4
#define TMEM_POOL_PAGESIZE_SHIFT 4
#define TMEM_POOL_PAGESIZE_MASK 0xf
#define TMEM_POOL_VERSION_SHIFT 24
#define TMEM_POOL_VERSION_MASK 0xff
+#define TMEM_POOL_RESERVED_BITS 0x00ffff00
/* Bits for client flags (save/restore) */
#define TMEM_CLIENT_COMPRESS 1
@@ -106,12 +111,12 @@ struct tmem_op {
uint32_t cli_id;
uint32_t arg1;
uint32_t arg2;
- uint64_t arg3;
+ uint64_t oid[3];
tmem_cli_va_t buf;
} ctrl; /* for cmd == TMEM_CONTROL */
struct {
- uint64_t object;
+ uint64_t oid[3];
uint32_t index;
uint32_t tmem_offset;
uint32_t pfn_offset;
@@ -126,9 +131,8 @@ DEFINE_XEN_GUEST_HANDLE(tmem_op_t);
struct tmem_handle {
uint32_t pool_id;
uint32_t index;
- uint64_t oid;
+ uint64_t oid[3];
};
-
#endif
#endif /* __XEN_PUBLIC_TMEM_H__ */
--- head-2010-10-05.orig/mm/precache.c 2010-10-08 16:25:45.000000000 +0200
+++ head-2010-10-05/mm/precache.c 2010-10-11 10:58:42.000000000 +0200
@@ -31,16 +31,57 @@
*/
#include <linux/precache.h>
+#include <linux/exportfs.h>
#include <linux/module.h>
#include "tmem.h"
static int precache_auto_allocate; /* set to 1 to auto_allocate */
+union precache_filekey {
+ struct tmem_oid oid;
+ u32 fh[0];
+};
+
+/*
+ * If the filesystem uses exportable filehandles, use the filehandle as
+ * the key, else use the inode number.
+ */
+static int precache_get_key(struct inode *inode, union precache_filekey *key)
+{
+#define PRECACHE_KEY_MAX (sizeof(key->oid) / sizeof(*key->fh))
+ struct super_block *sb = inode->i_sb;
+
+ memset(key, 0, sizeof(key));
+ if (sb->s_export_op) {
+ int (*fhfn)(struct dentry *, __u32 *fh, int *, int);
+
+ fhfn = sb->s_export_op->encode_fh;
+ if (fhfn) {
+ struct dentry *d;
+ int ret, maxlen = PRECACHE_KEY_MAX;
+
+ d = list_first_entry(&inode->i_dentry,
+ struct dentry, d_alias);
+ ret = fhfn(d, key->fh, &maxlen, 0);
+ if (ret < 0)
+ return ret;
+ if (ret >= 255 || maxlen > PRECACHE_KEY_MAX)
+ return -EPERM;
+ if (maxlen > 0)
+ return 0;
+ }
+ }
+ key->oid.oid[0] = inode->i_ino;
+ key->oid.oid[1] = inode->i_generation;
+ return 0;
+#undef PRECACHE_KEY_MAX
+}
+
int precache_put(struct address_space *mapping, unsigned long index,
struct page *page)
{
u32 tmem_pool = mapping->host->i_sb->precache_poolid;
- u64 obj = (unsigned long) mapping->host->i_ino;
+ union precache_filekey key;
u32 ind = (u32) index;
unsigned long mfn = pfn_to_mfn(page_to_pfn(page));
int ret;
@@ -56,53 +97,53 @@ int precache_put(struct address_space *m
mapping->host->i_sb->s_id, tmem_pool);
mapping->host->i_sb->precache_poolid = tmem_pool;
}
- if (ind != index)
+ if (ind != index || precache_get_key(mapping->host, &key))
return 0;
mb(); /* ensure page is quiescent; tmem may address it with an alias */
- return tmem_put_page(tmem_pool, obj, ind, mfn);
+ return tmem_put_page(tmem_pool, key.oid, ind, mfn);
}
int precache_get(struct address_space *mapping, unsigned long index,
struct page *empty_page)
{
u32 tmem_pool = mapping->host->i_sb->precache_poolid;
- u64 obj = (unsigned long) mapping->host->i_ino;
+ union precache_filekey key;
u32 ind = (u32) index;
unsigned long mfn = pfn_to_mfn(page_to_pfn(empty_page));
if ((s32)tmem_pool < 0)
return 0;
- if (ind != index)
+ if (ind != index || precache_get_key(mapping->host, &key))
return 0;
- return tmem_get_page(tmem_pool, obj, ind, mfn);
+ return tmem_get_page(tmem_pool, key.oid, ind, mfn);
}
EXPORT_SYMBOL(precache_get);
int precache_flush(struct address_space *mapping, unsigned long index)
{
u32 tmem_pool = mapping->host->i_sb->precache_poolid;
- u64 obj = (unsigned long) mapping->host->i_ino;
+ union precache_filekey key;
u32 ind = (u32) index;
if ((s32)tmem_pool < 0)
return 0;
- if (ind != index)
+ if (ind != index || precache_get_key(mapping->host, &key))
return 0;
- return tmem_flush_page(tmem_pool, obj, ind);
+ return tmem_flush_page(tmem_pool, key.oid, ind);
}
EXPORT_SYMBOL(precache_flush);
int precache_flush_inode(struct address_space *mapping)
{
u32 tmem_pool = mapping->host->i_sb->precache_poolid;
- u64 obj = (unsigned long) mapping->host->i_ino;
+ union precache_filekey key;
- if ((s32)tmem_pool < 0)
+ if ((s32)tmem_pool < 0 || precache_get_key(mapping->host, &key))
return 0;
- return tmem_flush_object(tmem_pool, obj);
+ return tmem_flush_object(tmem_pool, key.oid);
}
EXPORT_SYMBOL(precache_flush_inode);
--- head-2010-10-05.orig/mm/preswap.c 2010-08-24 11:19:44.000000000 +0200
+++ head-2010-10-05/mm/preswap.c 2010-10-06 13:08:11.000000000 +0200
@@ -46,7 +46,8 @@ const unsigned long preswap_zero = 0, pr
*/
#define SWIZ_BITS 4
#define SWIZ_MASK ((1 << SWIZ_BITS) - 1)
-#define oswiz(_type, _ind) ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
+#define oswiz(_type, _ind) ((struct tmem_oid){ \
+ .oid[0] = (_type << SWIZ_BITS) | (_ind & SWIZ_MASK) })
#define iswiz(_ind) (_ind >> SWIZ_BITS)
/*
--- head-2010-10-05.orig/mm/tmem.h 2010-08-24 11:19:44.000000000 +0200
+++ head-2010-10-05/mm/tmem.h 2010-10-06 14:27:10.000000000 +0200
@@ -14,71 +14,58 @@
#define TMEM_POOL_MIN_PAGESHIFT 12
#define TMEM_POOL_PAGEORDER (PAGE_SHIFT - TMEM_POOL_MIN_PAGESHIFT)
-extern int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, u64 object, u32 index,
+struct tmem_pool_uuid {
+ u64 lo;
+ u64 hi;
+};
+
+struct tmem_oid {
+ u64 oid[3];
+};
+
+extern int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, struct tmem_oid, u32 index,
unsigned long gmfn, u32 tmem_offset, u32 pfn_offset, u32 len);
-extern int xen_tmem_new_pool(u32 tmem_cmd, u64 uuid_lo, u64 uuid_hi, u32 flags);
+extern int xen_tmem_new_pool(struct tmem_pool_uuid, u32 flags);
-static inline int tmem_put_page(u32 pool_id, u64 object, u32 index,
+static inline int tmem_put_page(u32 pool_id, struct tmem_oid oid, u32 index,
unsigned long gmfn)
{
- return xen_tmem_op(TMEM_PUT_PAGE, pool_id, object, index,
+ return xen_tmem_op(TMEM_PUT_PAGE, pool_id, oid, index,
gmfn, 0, 0, 0);
}
-static inline int tmem_get_page(u32 pool_id, u64 object, u32 index,
+static inline int tmem_get_page(u32 pool_id, struct tmem_oid oid, u32 index,
unsigned long gmfn)
{
- return xen_tmem_op(TMEM_GET_PAGE, pool_id, object, index,
+ return xen_tmem_op(TMEM_GET_PAGE, pool_id, oid, index,
gmfn, 0, 0, 0);
}
-static inline int tmem_flush_page(u32 pool_id, u64 object, u32 index)
+static inline int tmem_flush_page(u32 pool_id, struct tmem_oid oid, u32 index)
{
- return xen_tmem_op(TMEM_FLUSH_PAGE, pool_id, object, index,
+ return xen_tmem_op(TMEM_FLUSH_PAGE, pool_id, oid, index,
0, 0, 0, 0);
}
-static inline int tmem_flush_object(u32 pool_id, u64 object)
+static inline int tmem_flush_object(u32 pool_id, struct tmem_oid oid)
{
- return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, object, 0, 0, 0, 0, 0);
+ return xen_tmem_op(TMEM_FLUSH_OBJECT, pool_id, oid, 0, 0, 0, 0, 0);
}
static inline int tmem_new_pool(u64 uuid_lo, u64 uuid_hi, u32 flags)
{
+ struct tmem_pool_uuid uuid = { .lo = uuid_lo, .hi = uuid_hi };
+
BUILD_BUG_ON((TMEM_POOL_PAGEORDER < 0) ||
(TMEM_POOL_PAGEORDER >= TMEM_POOL_PAGESIZE_MASK));
flags |= TMEM_POOL_PAGEORDER << TMEM_POOL_PAGESIZE_SHIFT;
- return xen_tmem_new_pool(TMEM_NEW_POOL, uuid_lo, uuid_hi, flags);
+ return xen_tmem_new_pool(uuid, flags);
}
static inline int tmem_destroy_pool(u32 pool_id)
{
- return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, 0, 0, 0, 0, 0, 0);
+ static const struct tmem_oid oid = {};
+
+ return xen_tmem_op(TMEM_DESTROY_POOL, pool_id, oid, 0, 0, 0, 0, 0);
}
-#else
-struct tmem_op {
- u32 cmd;
- s32 pool_id; /* private > 0; shared < 0; 0 is invalid */
- union {
- struct { /* for cmd == TMEM_NEW_POOL */
- u64 uuid[2];
- u32 flags;
- } new;
- struct { /* for cmd == TMEM_CONTROL */
- u32 subop;
- u32 cli_id;
- u32 arg1;
- u32 arg2;
- void *buf;
- } ctrl;
- struct {
- u64 object;
- u32 index;
- u32 tmem_offset;
- u32 pfn_offset;
- u32 len;
- unsigned long pfn; /* page frame */
- } gen;
- } u;
-};
#endif
--- head-2010-10-05.orig/mm/tmem-xen.c 2009-06-23 09:28:21.000000000 +0200
+++ head-2010-10-05/mm/tmem-xen.c 2010-10-06 14:27:25.000000000 +0200
@@ -7,8 +7,9 @@
#include <linux/types.h>
#include <xen/interface/xen.h>
#include <asm/hypervisor.h>
+#include "tmem.h"
-int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, u64 object, u32 index,
+int xen_tmem_op(u32 tmem_cmd, u32 tmem_pool, struct tmem_oid oid, u32 index,
unsigned long gmfn, u32 tmem_offset, u32 pfn_offset, u32 len)
{
struct tmem_op op;
@@ -16,7 +17,8 @@ int xen_tmem_op(u32 tmem_cmd, u32 tmem_p
op.cmd = tmem_cmd;
op.pool_id = tmem_pool;
- op.u.gen.object = object;
+ BUILD_BUG_ON(sizeof(op.u.gen.oid) != sizeof(oid.oid));
+ memcpy(op.u.gen.oid, oid.oid, sizeof(op.u.gen.oid));
op.u.gen.index = index;
op.u.gen.tmem_offset = tmem_offset;
op.u.gen.pfn_offset = pfn_offset;
@@ -26,15 +28,27 @@ int xen_tmem_op(u32 tmem_cmd, u32 tmem_p
return rc;
}
-int xen_tmem_new_pool(uint32_t tmem_cmd, uint64_t uuid_lo,
- uint64_t uuid_hi, uint32_t flags)
+int xen_tmem_new_pool(struct tmem_pool_uuid uuid, uint32_t flags)
{
struct tmem_op op;
int rc = 0;
- op.cmd = tmem_cmd;
- op.u.new.uuid[0] = uuid_lo;
- op.u.new.uuid[1] = uuid_hi;
+ op.cmd = TMEM_NEW_POOL;
+ op.u.new.uuid[0] = uuid.lo;
+ op.u.new.uuid[1] = uuid.hi;
+#ifdef TMEM_SPEC_VERSION
+ switch (flags >> TMEM_POOL_VERSION_SHIFT) {
+ case 0:
+ flags |= TMEM_SPEC_VERSION << TMEM_POOL_VERSION_SHIFT;
+ break;
+ case TMEM_SPEC_VERSION:
+ break;
+ default:
+ WARN(1, "TMEM: Bogus version %u, expecting %u\n",
+ flags >> TMEM_POOL_VERSION_SHIFT, TMEM_SPEC_VERSION);
+ return -ENOSYS;
+ }
+#endif
op.u.new.flags = flags;
rc = HYPERVISOR_tmem_op(&op);
return rc;