349 lines
10 KiB
Plaintext
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;
|