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 +#include #include #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 #include #include +#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;