PM: hibernate: encrypted snapshots under lockdown
Subsystems (5)
v2 cover PM: hibernate: encrypted snapshots under lockdown
v1 was sent as an RFC. This version keeps TPM policy and seed unsealing in early userspace, while the kernel encrypts and authenticates the uswsusp image from a locked seed.
The stack adds the snapshot_seed ABI, permits the snapshot device under lockdown only once encryption is enabled, documents the userspace flow, and restricts lockdown-time block writes to the active encrypted snapshot image/header path.
Changes in v2:
- Keep raw writes to active swap blocked under lockdown.
- Track encrypted snapshot bytes and header writes before allowing lockdown-time image writes.
- Only split the encrypted stream at the metadata boundary when a user key switch is used.
- Return -EFAULT for userspace copy failures.
- Document resume meta_size handling.
Tested on StarFighter MTL with a TPM-sealed seed: encrypted uswsusp suspend/resume completed and restored the image. Also tested with lockdown enabled through the encrypted snapshot device path.
Evan Green (1):
PM: hibernate: add seed-wrapped encrypted snapshots
Sean Rhodes (3):
PM: hibernate: permit encrypted snapshot device under lockdown
PM: hibernate: document encrypted snapshot seed ABI
PM: hibernate: harden encrypted snapshot write path
Documentation/ABI/testing/sysfs-power | 14 + Documentation/power/userland-swsusp.rst | 20 + block/fops.c | 55 +- include/linux/suspend.h | 22 + include/linux/swap.h | 16 + include/uapi/linux/suspend_ioctls.h | 31 +- kernel/power/Kconfig | 15 + kernel/power/Makefile | 1 + kernel/power/hibernate.c | 32 + kernel/power/power.h | 4 + kernel/power/snapenc.c | 940 ++++++++++++++++++++++++ kernel/power/snapshot.c | 5 + kernel/power/swap.c | 98 +++ kernel/power/user.c | 247 ++++++- kernel/power/user.h | 151 ++++ mm/swapfile.c | 32 + 16 files changed, 1651 insertions(+), 32 deletions(-) create mode 100644 kernel/power/snapenc.c create mode 100644 kernel/power/user.h
PATCH v2 1/4 PM: hibernate: add seed-wrapped encrypted snapshots
From: Evan Green <[email protected]>
Encrypt and authenticate uswsusp hibernation images in the kernel so userspace cannot tamper with the image that will be restored as kernel memory.
The image data is protected with gcm(aes) in 16-page chunks. SNAPSHOT_ENABLE_ENCRYPTION enables the encrypted read/write paths and returns an opaque wrapped image-key blob with the starting nonce on suspend. On resume, userspace provides the same blob and nonce after trusted early userspace has written the same 32-byte seed to /sys/power/snapshot_seed.
The plaintext image key is generated and unwrapped inside the kernel. The wrapping key is derived from the locked seed, leaving TPM PCR policy and seed unsealing to early userspace rather than adding TPM or trusted-key state to PM code.
SNAPSHOT_SET_USER_KEY lets userspace fold extra key material into the data encryption key after the metadata area has been read or written.
Tested on StarFighter MTL with a TPM-sealed seed: encrypted uswsusp suspend/resume completed and restored the image.
--- Documentation/power/userland-swsusp.rst | 16 + include/uapi/linux/suspend_ioctls.h | 31 +- kernel/power/Kconfig | 15 + kernel/power/Makefile | 1 + kernel/power/hibernate.c | 24 + kernel/power/power.h | 1 + kernel/power/snapenc.c | 878 ++++++++++++++++++++++++ kernel/power/snapshot.c | 5 + kernel/power/user.c | 58 +- kernel/power/user.h | 132 ++++ 10 files changed, 1143 insertions(+), 18 deletions(-) create mode 100644 kernel/power/snapenc.c create mode 100644 kernel/power/user.h
Documentation/power/userland-swsusp.rst +16 -0
@@ -115,6 +115,22 @@ SNAPSHOT_S2RAM to resume the system from RAM if there's enough battery power or restore its state on the basis of the saved suspend image otherwise) +SNAPSHOT_ENABLE_ENCRYPTION + Enables encryption of the hibernate image within the kernel. Upon suspend + (ie when the snapshot device was opened for reading), returns a blob + representing the random encryption key the kernel created to encrypt the + hibernate image with. Upon resume (ie when the snapshot device was opened + for writing), receives a blob from usermode containing the key material + previously returned during hibernate. + +SNAPSHOT_SET_USER_KEY + Mixes additional user key material into the data portion of an encrypted + hibernate image. The ioctl argument points to struct uswsusp_user_key. + key_len must be between 8 and USWSUSP_USER_KEY_SIZE bytes, and reserved + must be zero. The kernel writes meta_size with the encrypted metadata + size that userspace may transfer before providing the user key during + resume. + The device's read() operation can be used to transfer the snapshot image from the kernel. It has the following limitations:
include/uapi/linux/suspend_ioctls.h +30 -1
@@ -13,6 +13,31 @@ struct resume_swap_area {__u32 dev; } __attribute__((packed)); +#define USWSUSP_KEY_NONCE_SIZE 16 +#define USWSUSP_USER_KEY_SIZE 32 + +/* +* This structure is used to pass the opaque wrapped hibernate image +* encryption key and starting nonce in either direction. +*/ +struct uswsusp_key_blob { +__u32 blob_len; +__u8 blob[512 ]; + __u8 nonce[USWSUSP_KEY_NONCE_SIZE] __kernel_nonstring; +} __attribute__((packed)); + +/* +* Allow user mode to fold in key material for the data portion of the hibernate +* image. +*/ +struct uswsusp_user_key { +/* Kernel returns the metadata size. */ +__u64 meta_size; +__u32 key_len; +__u32 reserved; + __u8 key[USWSUSP_USER_KEY_SIZE] __kernel_nonstring; +} __attribute__((packed)); +#define SNAPSHOT_IOC_MAGIC '3'#define SNAPSHOT_FREEZE _IO(SNAPSHOT_IOC_MAGIC, 1)#define SNAPSHOT_UNFREEZE _IO(SNAPSHOT_IOC_MAGIC, 2)
@@ -29,6 +54,10 @@ struct resume_swap_area {#define SNAPSHOT_PREF_IMAGE_SIZE _IO(SNAPSHOT_IOC_MAGIC, 18)#define SNAPSHOT_AVAIL_SWAP_SIZE _IOR(SNAPSHOT_IOC_MAGIC, 19, __kernel_loff_t)#define SNAPSHOT_ALLOC_SWAP_PAGE _IOR(SNAPSHOT_IOC_MAGIC, 20, __kernel_loff_t) -#define SNAPSHOT_IOC_MAXNR 20 +#define SNAPSHOT_ENABLE_ENCRYPTION _IOWR(SNAPSHOT_IOC_MAGIC, 21, \ + struct uswsusp_key_blob) +#define SNAPSHOT_SET_USER_KEY _IOWR(SNAPSHOT_IOC_MAGIC, 22, \ + struct uswsusp_user_key) +#define SNAPSHOT_IOC_MAXNR 22#endif /* _LINUX_SUSPEND_IOCTLS_H */
kernel/power/Kconfig +15 -0
@@ -115,6 +115,21 @@ config HIBERNATION_DEF_COMP help Default compressor to be used for hibernation. +config ENCRYPTED_HIBERNATION + bool "Encryption support for userspace snapshots" + depends on HIBERNATION_SNAPSHOT_DEV + select CRYPTO_AES + select CRYPTO_GCM + select CRYPTO_LIB_SHA256 + help + Enable support for kernel-based encryption of hibernation snapshots + created by uswsusp tools. A trusted early userspace component must + provide the snapshot encryption seed before enabling encryption. + + Say N if userspace handles the image encryption. + + If in doubt, say N. + config PM_STD_PARTITION string "Default resume partition" depends on HIBERNATION
kernel/power/Makefile +1 -0
@@ -16,6 +16,7 @@ obj-$(CONFIG_SUSPEND) += suspend.o obj-$(CONFIG_PM_TEST_SUSPEND) += suspend_test.o obj-$(CONFIG_HIBERNATION) += hibernate.o snapshot.o swap.o obj-$(CONFIG_HIBERNATION_SNAPSHOT_DEV) += user.o +obj-$(CONFIG_ENCRYPTED_HIBERNATION) += snapenc.o obj-$(CONFIG_PM_AUTOSLEEP) += autosleep.o obj-$(CONFIG_PM_WAKELOCKS) += wakelock.o
kernel/power/hibernate.c +24 -0
@@ -36,6 +36,7 @@#include <trace/events/power.h> #include "power.h" +#include "user.h" static int nocompress;
@@ -1376,12 +1377,35 @@ static ssize_t reserved_size_store(struct kobject *kobj,power_attr (reserved_size); +#ifdef CONFIG_ENCRYPTED_HIBERNATION +static ssize_t snapshot_seed_store (struct kobject *kobj, +struct kobj_attribute *attr, +const char *buf,size_t n) +{ +int ret; + + ret =snapshot_store_encryption_seed (buf, n); +return ret ? ret : n; +} + +static struct kobj_attribute snapshot_seed_attr = { + .attr = { + .name ="snapshot_seed" , + .mode =0200 , + }, + .store = snapshot_seed_store, +}; +#endif +static struct attribute *g[] = { &disk_attr.attr, &resume_offset_attr.attr, &resume_attr.attr, &image_size_attr.attr, &reserved_size_attr.attr, +#ifdef CONFIG_ENCRYPTED_HIBERNATION + &snapshot_seed_attr.attr, +#endifNULL , };
kernel/power/power.h +1 -0
@@ -160,6 +160,7 @@ struct snapshot_handle {extern unsigned int snapshot_additional_pages (struct zone *zone);extern unsigned long snapshot_get_image_size (void ); +unsigned long snapshot_get_meta_page_count (void );extern int snapshot_read_next (struct snapshot_handle *handle);extern int snapshot_write_next (struct snapshot_handle *handle);int snapshot_write_finalize (struct snapshot_handle *handle);
kernel/power/snapenc.c new file +878 -0
878 lines not on this page · raw message
kernel/power/snapshot.c +5 -0
@@ -2177,6 +2177,11 @@ unsigned long snapshot_get_image_size(void)return nr_copy_pages + nr_meta_pages +1 ; } +unsigned long snapshot_get_meta_page_count (void ) +{ +return nr_meta_pages +1 ; +} +static int init_header (struct swsusp_info *info) {memset (info,0 ,sizeof (struct swsusp_info ));
kernel/power/user.c +41 -17
135 lines not on this page · raw message
kernel/power/user.h new file +132 -0
132 lines not on this page · raw message
PATCH v2 2/4 PM: hibernate: permit encrypted snapshot device under lockdown
In reply to Sean RhodesLockdown disables hibernation because restoring attacker-controlled image data can modify kernel memory. Permit opening the userspace snapshot device under lockdown when encrypted hibernation support is built, but require encryption to be enabled before image data can be read or written and before restore or power-off ioctls can proceed.
Tested on StarFighter MTL with lockdown enabled: encrypted uswsusp hibernate and restore used the snapshot device path.
--- kernel/power/hibernate.c | 8 ++++++++ kernel/power/power.h | 1 + kernel/power/user.c | 36 ++++++++++++++++++++++++++++++++++-- kernel/power/user.h | 1 + 4 files changed, 44 insertions(+), 2 deletions(-)
kernel/power/hibernate.c +8 -0
@@ -114,6 +114,14 @@ bool hibernation_available(void) !secretmem_active () && !cxl_mem_active (); } +bool hibernation_snapshot_dev_available (void ) +{ +return nohibernate ==0 && + (!security_locked_down (LOCKDOWN_HIBERNATION ) || +IS_ENABLED (CONFIG_ENCRYPTED_HIBERNATION )) && + !secretmem_active () && !cxl_mem_active (); +} +/** * hibernation_set_ops - Set the global hibernate operations. * @ops: Hibernation operations to use in subsequent hibernation transitions.
kernel/power/power.h +1 -0
@@ -168,6 +168,7 @@ extern int snapshot_image_loaded(struct snapshot_handle *handle);extern bool hibernate_acquire (void );extern void hibernate_release (void ); +bool hibernation_snapshot_dev_available (void );extern sector_t alloc_swapdev_block (int swap);extern void free_all_swap_pages (int swap);
kernel/power/user.c +34 -2
@@ -21,6 +21,7 @@#include <linux/console.h> #include <linux/cpu.h> #include <linux/freezer.h> +#include <linux/security.h> #include <linux/uaccess.h>
@@ -32,7 +33,12 @@ struct snapshot_data snapshot_state;int is_hibernate_resume_dev (dev_t dev) { -return hibernation_available () && snapshot_state.dev == dev; +return hibernation_snapshot_dev_available () && snapshot_state.dev == dev; +} + +static bool snapshot_encryption_required (void ) +{ +return security_locked_down (LOCKDOWN_HIBERNATION ); }static int snapshot_open (struct inode *inode,struct file *filp)
@@ -41,7 +47,7 @@ static int snapshot_open(struct inode *inode, struct file *filp)unsigned int sleep_flags;int error; -if (!hibernation_available ()) +if (!hibernation_snapshot_dev_available ())return -EPERM ; sleep_flags =lock_system_sleep ();
@@ -90,6 +96,7 @@ static int snapshot_open(struct inode *inode, struct file *filp) data->ready = false; data->platform_support = false; data->dev =0 ; + data->encryption_required =snapshot_encryption_required (); unlock:unlock_system_sleep (sleep_flags);
@@ -141,6 +148,10 @@ static ssize_t snapshot_read(struct file *filp, char __user *buf, res = -ENODATA ; goto unlock; } +if (data->encryption_required && !snapshot_encryption_enabled (data)) { + res = -EPERM ; + goto unlock; + }if (snapshot_encryption_enabled (data)) { res =snapshot_read_encrypted (data, buf, count, offp);
@@ -183,6 +194,11 @@ static ssize_t snapshot_write(struct file *filp, const char __user *buf, data = filp->private_data; +if (data->encryption_required && !snapshot_encryption_enabled (data)) { + res = -EPERM ; + goto unlock; + } +if (snapshot_encryption_enabled (data)) { res =snapshot_write_encrypted (data, buf, count, offp); goto unlock;
@@ -321,6 +337,10 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, error = -EPERM ;break ; } +if (data->encryption_required && !snapshot_encryption_enabled (data)) { + error = -EPERM ; +break ; + }pm_restore_gfp_mask (); error =hibernation_snapshot (data->platform_support);if (!error) {
@@ -331,6 +351,10 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,break ;case SNAPSHOT_ATOMIC_RESTORE : +if (data->encryption_required && !snapshot_encryption_enabled (data)) { + error = -EPERM ; +break ; + }if (snapshot_encryption_enabled (data)) { error =snapshot_finalize_decrypted_image (data);if (error)
@@ -415,6 +439,10 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd, error = -EPERM ;break ; } +if (data->encryption_required && !snapshot_encryption_enabled (data)) { + error = -EPERM ; +break ; + }/* * Tasks are frozen and the notifiers have been called with * PM_HIBERNATION_PREPARE
@@ -428,6 +456,10 @@ static long snapshot_ioctl(struct file *filp, unsigned int cmd,break ;case SNAPSHOT_POWER_OFF : +if (data->encryption_required && !snapshot_encryption_enabled (data)) { + error = -EPERM ; +break ; + }if (data->platform_support) error =hibernation_platform_enter ();break ;
kernel/power/user.h +1 -0
@@ -20,6 +20,7 @@ struct snapshot_data {bool ready;bool platform_support;bool free_bitmaps; +bool encryption_required;dev_t dev;#if defined(CONFIG_ENCRYPTED_HIBERNATION )
PATCH v2 3/4 PM: hibernate: document encrypted snapshot seed ABI
In reply to Sean RhodesDocument the write-only snapshot_seed sysfs file and update the userspace snapshot interface text to describe the opaque wrapped-key flow used by encrypted hibernation.
--- Documentation/ABI/testing/sysfs-power | 14 ++++++++++++++ Documentation/power/userland-swsusp.rst | 15 +++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-)
Documentation/ABI/testing/sysfs-power +14 -0
@@ -470,3 +470,17 @@ Description: Minimum value: 1 Default value: 3 + +What: /sys/power/snapshot_seed +Date: July 2026 +Contact: [email protected] +Description: + Write-only file present when CONFIG_ENCRYPTED_HIBERNATION=y. + + Trusted early userspace writes a 32-byte seed, encoded as + 64 hexadecimal characters plus an optional newline, before + enabling encrypted userspace hibernation snapshots. + + The first successful write locks the seed until the next boot. + Writing the same seed again succeeds. Writing a different seed + fails with EPERM.
Documentation/power/userland-swsusp.rst +9 -6
@@ -116,12 +116,15 @@ SNAPSHOT_S2RAM its state on the basis of the saved suspend image otherwise) SNAPSHOT_ENABLE_ENCRYPTION - Enables encryption of the hibernate image within the kernel. Upon suspend - (ie when the snapshot device was opened for reading), returns a blob - representing the random encryption key the kernel created to encrypt the - hibernate image with. Upon resume (ie when the snapshot device was opened - for writing), receives a blob from usermode containing the key material - previously returned during hibernate. + Enables encryption of the hibernate image within the kernel. Trusted + early userspace must write the 32-byte snapshot encryption seed to + /sys/power/snapshot_seed before calling this ioctl. Upon suspend + (ie when the snapshot device was opened for reading), this ioctl returns + an opaque wrapped key blob and the starting nonce. Upon resume (ie when + the snapshot device was opened for writing), this ioctl receives the + same blob and nonce from usermode after the same seed has been written + to /sys/power/snapshot_seed. The plaintext image key is generated and + unwrapped inside the kernel. SNAPSHOT_SET_USER_KEY Mixes additional user key material into the data portion of an encrypted
PATCH v2 4/4 PM: hibernate: harden encrypted snapshot write path
In reply to Sean RhodesEncrypted uswsusp permits the snapshot device under lockdown only after encryption is enabled, but userspace still writes the image through the normal block path. Track the snapshot owner, encrypted bytes read, swap extents and swap header offset so lockdown only permits writes that match the active encrypted image.
Tighten the encrypted stream bookkeeping while here: frame the metadata boundary only when a user key switch is in use, report userspace copy failures as -EFAULT, and reset encryption state when the snapshot is freed.
--- Documentation/power/userland-swsusp.rst | 7 +- block/fops.c | 55 +++- include/linux/suspend.h | 22 ++ include/linux/swap.h | 16 ++ include/uapi/linux/suspend_ioctls.h | 2 +- kernel/power/power.h | 2 + kernel/power/snapenc.c | 344 ++++++++++++++---------- kernel/power/swap.c | 98 +++++++ kernel/power/user.c | 177 +++++++++++- kernel/power/user.h | 22 +- mm/swapfile.c | 32 +++ 11 files changed, 606 insertions(+), 171 deletions(-)
Documentation/power/userland-swsusp.rst +4 -3
@@ -130,9 +130,10 @@ SNAPSHOT_SET_USER_KEY Mixes additional user key material into the data portion of an encrypted hibernate image. The ioctl argument points to struct uswsusp_user_key. key_len must be between 8 and USWSUSP_USER_KEY_SIZE bytes, and reserved - must be zero. The kernel writes meta_size with the encrypted metadata - size that userspace may transfer before providing the user key during - resume. + must be zero. During hibernation the kernel writes meta_size with the + encrypted metadata size. During resume, userspace passes the saved + meta_size back so the kernel can switch keys at the metadata boundary + before the snapshot header has been decrypted. The device's read() operation can be used to transfer the snapshot image from the kernel. It has the following limitations:
block/fops.c +42 -13
94 lines not on this page · raw message
include/linux/suspend.h +22 -0
@@ -426,10 +426,32 @@ static inline bool pm_hibernation_mode_is_suspend(void) { return false; }int arch_resume_nosmt (void ); +enum hibernate_snapshot_write { +HIBERNATE_SNAPSHOT_WRITE_NONE , +HIBERNATE_SNAPSHOT_WRITE_IMAGE , +HIBERNATE_SNAPSHOT_WRITE_HEADER , +}; +#ifdef CONFIG_HIBERNATION_SNAPSHOT_DEV int is_hibernate_resume_dev (dev_t dev); +enum hibernate_snapshot_write +hibernate_snapshot_write_begin (dev_t dev,loff_t pos,size_t count); +void hibernate_snapshot_write_end (enum hibernate_snapshot_write type, +size_t reserved,ssize_t written);#else static inline int is_hibernate_resume_dev (dev_t dev) {return 0 ; } + +static inline enum hibernate_snapshot_write +hibernate_snapshot_write_begin (dev_t dev,loff_t pos,size_t count) +{ +return HIBERNATE_SNAPSHOT_WRITE_NONE ; +} + +static inline void hibernate_snapshot_write_end (enum hibernate_snapshot_write type, +size_t reserved, +ssize_t written) +{ +}#endif /* Hibernation and suspend events */
include/linux/swap.h +16 -0
@@ -439,6 +439,9 @@ extern int find_hibernation_swap_type(dev_t device, sector_t offset);int find_first_swap (dev_t *device);extern unsigned int count_swap_pages (int ,int );extern sector_t swapdev_block (int ,pgoff_t ); +int swapdev_block_to_offset (int type,sector_t block,pgoff_t *offset); +int swapdev_block_to_extent (int type,sector_t block,pgoff_t *offset, +pgoff_t *nr_pages);extern int __swap_count (swp_entry_t entry);extern bool swap_entry_swapped (struct swap_info_struct *si,swp_entry_t entry);extern int swp_swapcount (swp_entry_t entry);
@@ -535,6 +538,19 @@ static inline int add_swap_extent(struct swap_info_struct *sis, {return -EINVAL ; } + +static inline int swapdev_block_to_offset (int type,sector_t block, +pgoff_t *offset) +{ +return -EINVAL ; +} + +static inline int swapdev_block_to_extent (int type,sector_t block, +pgoff_t *offset, +pgoff_t *nr_pages) +{ +return -EINVAL ; +}#endif /* CONFIG_SWAP */ #ifdef CONFIG_MEMCG static inline int mem_cgroup_swappiness (struct mem_cgroup *memcg)
include/uapi/linux/suspend_ioctls.h +1 -1
@@ -31,7 +31,7 @@ struct uswsusp_key_blob {* image. */ struct uswsusp_user_key { -/* Kernel returns the metadata size. */ +/* Kernel returns the metadata size; resume passes the saved value in. */ __u64 meta_size;__u32 key_len;__u32 reserved;
kernel/power/power.h +2 -0
@@ -171,6 +171,8 @@ extern void hibernate_release(void);bool hibernation_snapshot_dev_available (void );extern sector_t alloc_swapdev_block (int swap); +bool swsusp_swap_range_allocated (int swap,loff_t pos,size_t count); +u64 swsusp_swap_map_bytes (u64 image_bytes);extern void free_all_swap_pages (int swap);extern int swsusp_swap_in_use (void );
kernel/power/snapenc.c +203 -141
497 lines not on this page · raw message
kernel/power/swap.c +98 -0
104 lines not on this page · raw message
kernel/power/user.c +166 -11
270 lines not on this page · raw message
kernel/power/user.h +20 -2
@@ -2,10 +2,13 @@#include <linux/crypto.h> #include <linux/scatterlist.h> +#include <linux/spinlock.h> #include <linux/suspend_ioctls.h> #include <crypto/aead.h> #include <crypto/aes.h> +struct pid ; +#define SNAPSHOT_ENCRYPTION_KEY_SIZE AES_KEYSIZE_128#define SNAPSHOT_AUTH_TAG_SIZE 16
@@ -32,12 +35,25 @@ struct snapshot_data {size_t crypt_offset;size_t crypt_size;u64 crypt_total; +u64 crypt_stream_total;u64 nonce_low;u64 nonce_high; u8 encryption_key[SNAPSHOT_ENCRYPTION_KEY_SIZE] __nonstring; u8 user_key[USWSUSP_USER_KEY_SIZE] __nonstring;bool user_key_valid;u64 meta_size; +u64 crypt_meta_size; +/* +* Protects crypt_bytes_read and the reservation counters below. +* crypt_swap_reserved covers encrypted snapshot bytes and userspace +* generated swap-map pages. +*/ +spinlock_t crypt_lock; +u64 crypt_bytes_read; +u64 crypt_swap_reserved; +u64 crypt_header_reserved; +loff_t swap_header_offset; +struct pid *owner_tgid;#endif };
@@ -66,7 +82,8 @@ int snapshot_set_user_key(struct snapshot_data *data,int snapshot_store_encryption_seed (const char *buf,size_t count); -loff_t snapshot_get_encrypted_image_size (loff_t raw_size); +loff_t snapshot_get_encrypted_image_size (struct snapshot_data *data, +loff_t raw_size);int snapshot_finalize_decrypted_image (struct snapshot_data *data);
@@ -115,7 +132,8 @@ static inline int snapshot_store_encryption_seed(const char *buf, size_t count)return -ENOTTY ; } -static inline loff_t snapshot_get_encrypted_image_size (loff_t raw_size) +static inline loff_t snapshot_get_encrypted_image_size (struct snapshot_data *data, +loff_t raw_size) {return raw_size; }
mm/swapfile.c +32 -0
@@ -2366,6 +2366,38 @@ sector_t swapdev_block(int type, pgoff_t offset)return se->start_block + (offset - se->start_page); } +int swapdev_block_to_extent (int type,sector_t block,pgoff_t *offset, +pgoff_t *nr_pages) +{ +struct swap_info_struct *si =swap_type_to_info (type); +struct swap_extent *se; +struct rb_node *rb; + +if (!si || !(si->flags &SWP_WRITEOK )) +return -ENODEV ; + +for (rb =rb_first (&si->swap_extent_root); rb; rb =rb_next (rb)) { + se = rb_entry(rb, struct swap_extent, rb_node); +if (block >= se->start_block && + block - se->start_block < se->nr_pages) { +pgoff_t page = block - se->start_block; + + *offset = se->start_page + page; + *nr_pages = se->nr_pages - page; +return 0 ; + } + } + +return -ENOENT ; +} + +int swapdev_block_to_offset (int type,sector_t block,pgoff_t *offset) +{ +pgoff_t nr_pages; + +return swapdev_block_to_extent (type, block, offset, &nr_pages); +} +/* * Return either the total number of swap pages of given type, or the number * of free pages of that type (depending on @free)