struct crypto_ahash *tfm)
 {
        loff_t i_size, offset;
-       char *rbuf;
-       int rc, read = 0, rbuf_len;
+       char *rbuf[2] = { NULL, };
+       int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0;
        struct ahash_request *req;
        struct scatterlist sg[1];
        struct ahash_completion res;
-       size_t rbuf_size;
+       size_t rbuf_size[2];
 
        hash->length = crypto_ahash_digestsize(tfm);
 
         * Try to allocate maximum size of memory.
         * Fail if even a single page cannot be allocated.
         */
-       rbuf = ima_alloc_pages(i_size, &rbuf_size, 1);
-       if (!rbuf) {
+       rbuf[0] = ima_alloc_pages(i_size, &rbuf_size[0], 1);
+       if (!rbuf[0]) {
                rc = -ENOMEM;
                goto out1;
        }
 
+       /* Only allocate one buffer if that is enough. */
+       if (i_size > rbuf_size[0]) {
+               /*
+                * Try to allocate secondary buffer. If that fails fallback to
+                * using single buffering. Use previous memory allocation size
+                * as baseline for possible allocation size.
+                */
+               rbuf[1] = ima_alloc_pages(i_size - rbuf_size[0],
+                                         &rbuf_size[1], 0);
+       }
+
        if (!(file->f_mode & FMODE_READ)) {
                file->f_mode |= FMODE_READ;
                read = 1;
        }
 
        for (offset = 0; offset < i_size; offset += rbuf_len) {
-               rbuf_len = ima_kernel_read(file, offset, rbuf, PAGE_SIZE);
-               if (rbuf_len < 0) {
-                       rc = rbuf_len;
-                       break;
+               if (!rbuf[1] && offset) {
+                       /* Not using two buffers, and it is not the first
+                        * read/request, wait for the completion of the
+                        * previous ahash_update() request.
+                        */
+                       rc = ahash_wait(ahash_rc, &res);
+                       if (rc)
+                               goto out3;
+               }
+               /* read buffer */
+               rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]);
+               rc = ima_kernel_read(file, offset, rbuf[active], rbuf_len);
+               if (rc != rbuf_len)
+                       goto out3;
+
+               if (rbuf[1] && offset) {
+                       /* Using two buffers, and it is not the first
+                        * read/request, wait for the completion of the
+                        * previous ahash_update() request.
+                        */
+                       rc = ahash_wait(ahash_rc, &res);
+                       if (rc)
+                               goto out3;
                }
-               if (rbuf_len == 0)
-                       break;
 
-               sg_init_one(&sg[0], rbuf, rbuf_len);
+               sg_init_one(&sg[0], rbuf[active], rbuf_len);
                ahash_request_set_crypt(req, sg, NULL, rbuf_len);
 
-               rc = ahash_wait(crypto_ahash_update(req), &res);
-               if (rc)
-                       break;
+               ahash_rc = crypto_ahash_update(req);
+
+               if (rbuf[1])
+                       active = !active; /* swap buffers, if we use two */
        }
+       /* wait for the last update request to complete */
+       rc = ahash_wait(ahash_rc, &res);
+out3:
        if (read)
                file->f_mode &= ~FMODE_READ;
-       ima_free_pages(rbuf, rbuf_size);
+       ima_free_pages(rbuf[0], rbuf_size[0]);
+       ima_free_pages(rbuf[1], rbuf_size[1]);
 out2:
        if (!rc) {
                ahash_request_set_crypt(req, NULL, hash->digest, 0);