Whamcloud - gitweb
LU-16202 build: bio_alloc takes struct block_device
[fs/lustre-release.git] / libcfs / libcfs / crypto / bio.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * This contains encryption functions for per-file encryption.
4  *
5  * Copyright (C) 2015, Google, Inc.
6  * Copyright (C) 2015, Motorola Mobility
7  *
8  * Written by Michael Halcrow, 2014.
9  *
10  * Filename encryption additions
11  *      Uday Savagaonkar, 2014
12  * Encryption policy handling additions
13  *      Ildar Muslukhov, 2014
14  * Add llcrypt_pullback_bio_page()
15  *      Jaegeuk Kim, 2015.
16  *
17  * This has not yet undergone a rigorous security audit.
18  *
19  * The usage of AES-XTS should conform to recommendations in NIST
20  * Special Publication 800-38E and IEEE P1619/D16.
21  */
22 /*
23  * Linux commit 219d54332a09
24  * tags/v5.4
25  */
26
27 #include <linux/pagemap.h>
28 #include <linux/module.h>
29 #include <linux/bio.h>
30 #include <linux/namei.h>
31 #include <lustre_compat.h>
32 #include "llcrypt_private.h"
33
34 static void __llcrypt_decrypt_bio(struct bio *bio, bool done)
35 {
36         struct bio_vec *bv;
37 #ifdef HAVE_BVEC_ITER_ALL
38         struct bvec_iter_all iter_all;
39 #else
40         int iter_all;
41 #endif
42
43         bio_for_each_segment_all(bv, bio, iter_all) {
44                 struct page *page = bv->bv_page;
45                 int ret = llcrypt_decrypt_pagecache_blocks(page, bv->bv_len,
46                                                            bv->bv_offset);
47                 if (ret)
48                         SetPageError(page);
49                 else if (done)
50                         SetPageUptodate(page);
51                 if (done)
52                         unlock_page(page);
53         }
54 }
55
56 void llcrypt_decrypt_bio(struct bio *bio)
57 {
58         __llcrypt_decrypt_bio(bio, false);
59 }
60 EXPORT_SYMBOL(llcrypt_decrypt_bio);
61
62 static void completion_pages(struct work_struct *work)
63 {
64         struct llcrypt_ctx *ctx = container_of(work, struct llcrypt_ctx, work);
65         struct bio *bio = ctx->bio;
66
67         __llcrypt_decrypt_bio(bio, true);
68         llcrypt_release_ctx(ctx);
69         bio_put(bio);
70 }
71
72 void llcrypt_enqueue_decrypt_bio(struct llcrypt_ctx *ctx, struct bio *bio)
73 {
74         INIT_WORK(&ctx->work, completion_pages);
75         ctx->bio = bio;
76         llcrypt_enqueue_decrypt_work(&ctx->work);
77 }
78 EXPORT_SYMBOL(llcrypt_enqueue_decrypt_bio);
79
80 int llcrypt_zeroout_range(const struct inode *inode, pgoff_t lblk,
81                                 sector_t pblk, unsigned int len)
82 {
83         const unsigned int blockbits = inode->i_blkbits;
84         const unsigned int blocksize = 1 << blockbits;
85         struct page *ciphertext_page;
86         struct bio *bio;
87         int ret, err = 0;
88
89         ciphertext_page = llcrypt_alloc_bounce_page(GFP_NOWAIT);
90         if (!ciphertext_page)
91                 return -ENOMEM;
92
93         while (len--) {
94                 err = llcrypt_crypt_block(inode, FS_ENCRYPT, lblk,
95                                           ZERO_PAGE(0), ciphertext_page,
96                                           blocksize, 0, GFP_NOFS);
97                 if (err)
98                         goto errout;
99
100                 bio = cfs_bio_alloc(inode->i_sb->s_bdev, 1, REQ_OP_WRITE,
101                                     GFP_NOWAIT);
102                 if (!bio) {
103                         err = -ENOMEM;
104                         goto errout;
105                 }
106                 bio->bi_iter.bi_sector = pblk << (blockbits - 9);
107                 ret = bio_add_page(bio, ciphertext_page, blocksize, 0);
108                 if (WARN_ON(ret != blocksize)) {
109                         /* should never happen! */
110                         bio_put(bio);
111                         err = -EIO;
112                         goto errout;
113                 }
114                 err = submit_bio_wait(bio);
115                 if (err == 0 && bio->bi_status)
116                         err = -EIO;
117                 bio_put(bio);
118                 if (err)
119                         goto errout;
120                 lblk++;
121                 pblk++;
122         }
123         err = 0;
124 errout:
125         llcrypt_free_bounce_page(ciphertext_page);
126         return err;
127 }
128 EXPORT_SYMBOL(llcrypt_zeroout_range);