 3dbb5eb9a3
			
		
	
	
	3dbb5eb9a3
	
	
	
		
			
			Previously we allocated bounce pages using a combination of alloc_page() and mempool_alloc() with the __GFP_WAIT bit set. Instead, use mempool_alloc() with GFP_NOWAIT. The mempool_alloc() function will try using alloc_pages() initially, and then only use the mempool reserve of pages if alloc_pages() is unable to fulfill the request. This minimizes the the impact on the mm layer when we need to do a large amount of writeback of encrypted files, as Jaeguk Kim had reported that under a heavy fio workload on a system with restricted amounts memory (which unfortunately, includes many mobile handsets), he had observed the the OOM killer getting triggered several times. Using GFP_NOWAIT If the mempool_alloc() function fails, we will retry the page writeback at a later time; the function of the mempool is to ensure that we can writeback at least 32 pages at a time, so we can more efficiently dispatch I/O under high memory pressure situations. In the future we should make this be a tunable so we can determine the best tradeoff between permanently sequestering memory and the ability to quickly launder pages so we can free up memory quickly when necessary. Signed-off-by: Theodore Ts'o <tytso@mit.edu>
		
			
				
	
	
		
			159 lines
		
	
	
	
		
			4 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			159 lines
		
	
	
	
		
			4 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * linux/fs/ext4/ext4_crypto.h
 | |
|  *
 | |
|  * Copyright (C) 2015, Google, Inc.
 | |
|  *
 | |
|  * This contains encryption header content for ext4
 | |
|  *
 | |
|  * Written by Michael Halcrow, 2015.
 | |
|  */
 | |
| 
 | |
| #ifndef _EXT4_CRYPTO_H
 | |
| #define _EXT4_CRYPTO_H
 | |
| 
 | |
| #include <linux/fs.h>
 | |
| 
 | |
| #define EXT4_KEY_DESCRIPTOR_SIZE 8
 | |
| 
 | |
| /* Policy provided via an ioctl on the topmost directory */
 | |
| struct ext4_encryption_policy {
 | |
| 	char version;
 | |
| 	char contents_encryption_mode;
 | |
| 	char filenames_encryption_mode;
 | |
| 	char flags;
 | |
| 	char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
 | |
| } __attribute__((__packed__));
 | |
| 
 | |
| #define EXT4_ENCRYPTION_CONTEXT_FORMAT_V1 1
 | |
| #define EXT4_KEY_DERIVATION_NONCE_SIZE 16
 | |
| 
 | |
| #define EXT4_POLICY_FLAGS_PAD_4		0x00
 | |
| #define EXT4_POLICY_FLAGS_PAD_8		0x01
 | |
| #define EXT4_POLICY_FLAGS_PAD_16	0x02
 | |
| #define EXT4_POLICY_FLAGS_PAD_32	0x03
 | |
| #define EXT4_POLICY_FLAGS_PAD_MASK	0x03
 | |
| #define EXT4_POLICY_FLAGS_VALID		0x03
 | |
| 
 | |
| /**
 | |
|  * Encryption context for inode
 | |
|  *
 | |
|  * Protector format:
 | |
|  *  1 byte: Protector format (1 = this version)
 | |
|  *  1 byte: File contents encryption mode
 | |
|  *  1 byte: File names encryption mode
 | |
|  *  1 byte: Reserved
 | |
|  *  8 bytes: Master Key descriptor
 | |
|  *  16 bytes: Encryption Key derivation nonce
 | |
|  */
 | |
| struct ext4_encryption_context {
 | |
| 	char format;
 | |
| 	char contents_encryption_mode;
 | |
| 	char filenames_encryption_mode;
 | |
| 	char flags;
 | |
| 	char master_key_descriptor[EXT4_KEY_DESCRIPTOR_SIZE];
 | |
| 	char nonce[EXT4_KEY_DERIVATION_NONCE_SIZE];
 | |
| } __attribute__((__packed__));
 | |
| 
 | |
| /* Encryption parameters */
 | |
| #define EXT4_XTS_TWEAK_SIZE 16
 | |
| #define EXT4_AES_128_ECB_KEY_SIZE 16
 | |
| #define EXT4_AES_256_GCM_KEY_SIZE 32
 | |
| #define EXT4_AES_256_CBC_KEY_SIZE 32
 | |
| #define EXT4_AES_256_CTS_KEY_SIZE 32
 | |
| #define EXT4_AES_256_XTS_KEY_SIZE 64
 | |
| #define EXT4_MAX_KEY_SIZE 64
 | |
| 
 | |
| #define EXT4_KEY_DESC_PREFIX "ext4:"
 | |
| #define EXT4_KEY_DESC_PREFIX_SIZE 5
 | |
| 
 | |
| /* This is passed in from userspace into the kernel keyring */
 | |
| struct ext4_encryption_key {
 | |
|         __u32 mode;
 | |
|         char raw[EXT4_MAX_KEY_SIZE];
 | |
|         __u32 size;
 | |
| } __attribute__((__packed__));
 | |
| 
 | |
| struct ext4_crypt_info {
 | |
| 	char		ci_data_mode;
 | |
| 	char		ci_filename_mode;
 | |
| 	char		ci_flags;
 | |
| 	struct crypto_ablkcipher *ci_ctfm;
 | |
| 	struct key	*ci_keyring_key;
 | |
| 	char		ci_master_key[EXT4_KEY_DESCRIPTOR_SIZE];
 | |
| };
 | |
| 
 | |
| #define EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL             0x00000001
 | |
| #define EXT4_WRITE_PATH_FL			      0x00000002
 | |
| 
 | |
| struct ext4_crypto_ctx {
 | |
| 	union {
 | |
| 		struct {
 | |
| 			struct page *bounce_page;       /* Ciphertext page */
 | |
| 			struct page *control_page;      /* Original page  */
 | |
| 		} w;
 | |
| 		struct {
 | |
| 			struct bio *bio;
 | |
| 			struct work_struct work;
 | |
| 		} r;
 | |
| 		struct list_head free_list;     /* Free list */
 | |
| 	};
 | |
| 	char flags;                      /* Flags */
 | |
| 	char mode;                       /* Encryption mode for tfm */
 | |
| };
 | |
| 
 | |
| struct ext4_completion_result {
 | |
| 	struct completion completion;
 | |
| 	int res;
 | |
| };
 | |
| 
 | |
| #define DECLARE_EXT4_COMPLETION_RESULT(ecr) \
 | |
| 	struct ext4_completion_result ecr = { \
 | |
| 		COMPLETION_INITIALIZER((ecr).completion), 0 }
 | |
| 
 | |
| static inline int ext4_encryption_key_size(int mode)
 | |
| {
 | |
| 	switch (mode) {
 | |
| 	case EXT4_ENCRYPTION_MODE_AES_256_XTS:
 | |
| 		return EXT4_AES_256_XTS_KEY_SIZE;
 | |
| 	case EXT4_ENCRYPTION_MODE_AES_256_GCM:
 | |
| 		return EXT4_AES_256_GCM_KEY_SIZE;
 | |
| 	case EXT4_ENCRYPTION_MODE_AES_256_CBC:
 | |
| 		return EXT4_AES_256_CBC_KEY_SIZE;
 | |
| 	case EXT4_ENCRYPTION_MODE_AES_256_CTS:
 | |
| 		return EXT4_AES_256_CTS_KEY_SIZE;
 | |
| 	default:
 | |
| 		BUG();
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| #define EXT4_FNAME_NUM_SCATTER_ENTRIES	4
 | |
| #define EXT4_CRYPTO_BLOCK_SIZE		16
 | |
| #define EXT4_FNAME_CRYPTO_DIGEST_SIZE	32
 | |
| 
 | |
| struct ext4_str {
 | |
| 	unsigned char *name;
 | |
| 	u32 len;
 | |
| };
 | |
| 
 | |
| /**
 | |
|  * For encrypted symlinks, the ciphertext length is stored at the beginning
 | |
|  * of the string in little-endian format.
 | |
|  */
 | |
| struct ext4_encrypted_symlink_data {
 | |
| 	__le16 len;
 | |
| 	char encrypted_path[1];
 | |
| } __attribute__((__packed__));
 | |
| 
 | |
| /**
 | |
|  * This function is used to calculate the disk space required to
 | |
|  * store a filename of length l in encrypted symlink format.
 | |
|  */
 | |
| static inline u32 encrypted_symlink_data_len(u32 l)
 | |
| {
 | |
| 	if (l < EXT4_CRYPTO_BLOCK_SIZE)
 | |
| 		l = EXT4_CRYPTO_BLOCK_SIZE;
 | |
| 	return (l + sizeof(struct ext4_encrypted_symlink_data) - 1);
 | |
| }
 | |
| 
 | |
| #endif	/* _EXT4_CRYPTO_H */
 |