summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEnzo Matsumiya <ematsumiya@suse.de>2025-12-01 13:19:55 -0300
committerEnzo Matsumiya <ematsumiya@suse.de>2025-12-05 11:45:07 -0300
commit5b78dec9032da60184262f4e25cf606f057b2083 (patch)
treec664431917e7f12f491a376b19c56903d1593b0e
parent20823ef36a8ce02f84790543d399daf1fd48006a (diff)
downloadlinux-5b78dec9032da60184262f4e25cf606f057b2083.tar.gz
linux-5b78dec9032da60184262f4e25cf606f057b2083.tar.bz2
linux-5b78dec9032da60184262f4e25cf606f057b2083.zip
smb: client: compress: use iterate_and_advance_kernel
Move sample collection to use the generic iov_iter API. Signed-off-by: Enzo Matsumiya <ematsumiya@suse.de>
-rw-r--r--fs/smb/client/compress.c71
1 files changed, 38 insertions, 33 deletions
diff --git a/fs/smb/client/compress.c b/fs/smb/client/compress.c
index db18c93f8ee8..7349f1dc6b1f 100644
--- a/fs/smb/client/compress.c
+++ b/fs/smb/client/compress.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/uio.h>
#include <linux/sort.h>
+#include <linux/iov_iter.h>
#include "cifsglob.h"
#include "../common/smb2pdu.h"
@@ -154,32 +155,44 @@ static int cmp_bkt(const void *_a, const void *_b)
return 1;
}
-/*
- * Collect some 2K samples with 2K gaps between.
- */
-static int collect_sample(const struct iov_iter *source, ssize_t max, u8 *sample)
+static size_t collect_step(void *base, size_t progress, size_t len, void *priv_iov, void *priv_len)
{
- struct iov_iter iter = *source;
- size_t s = 0;
+ size_t plen, *slen = priv_len;
+ struct kvec *iov = priv_iov;
- while (iov_iter_count(&iter) >= SZ_2K) {
- size_t part = umin(umin(iov_iter_count(&iter), SZ_2K), max);
- size_t n;
+ if (progress >= iov->iov_len)
+ return len;
- n = copy_from_iter(sample + s, part, &iter);
- if (n != part)
- return -EFAULT;
+ plen = min_t(size_t, len, SZ_2K);
- s += n;
- max -= n;
+ memcpy(iov->iov_base + *slen, base, plen);
- if (iov_iter_count(&iter) < PAGE_SIZE - SZ_2K)
- break;
+ *slen += plen;
- iov_iter_advance(&iter, SZ_2K);
- }
+ if (len < SZ_2K)
+ return len;
+
+ return 0;
+}
+
+/*
+ * Collect sample buffers from @iter.
+ * Return sample size, or 0 if too big (> @max_sample_len).
+ */
+static size_t collect_sample(const struct iov_iter *iter, u8 *sample, ssize_t max_sample_len)
+{
+ struct iov_iter it = *iter;
+ size_t ret, len = 0, max = iov_iter_count(iter);
+ struct kvec iov = {
+ .iov_base = sample,
+ .iov_len = max_sample_len,
+ };
- return s;
+ ret = iterate_and_advance_kernel(&it, max, &iov, &len, collect_step);
+ if (ret > max || ret > max_sample_len)
+ return 0;
+
+ return ret;
}
/**
@@ -193,12 +206,11 @@ static int collect_sample(const struct iov_iter *source, ssize_t max, u8 *sample
*/
static bool is_compressible(const struct iov_iter *data)
{
- const size_t read_size = SZ_2K, bkt_size = 256, max = SZ_4M;
+ const size_t read_size = SZ_2K, bkt_size = 256, max = SZ_2M;
struct bucket *bkt = NULL;
- size_t len;
+ size_t i, len;
u8 *sample;
bool ret = false;
- int i;
/* Preventive double check -- already checked in should_compress(). */
len = iov_iter_count(data);
@@ -208,24 +220,17 @@ static bool is_compressible(const struct iov_iter *data)
if (len - read_size > max)
len = max;
+ len = round_down(len / 2, read_size);
sample = kvzalloc(len, GFP_KERNEL);
- if (!sample) {
- WARN_ON_ONCE(1);
-
+ if (WARN_ON_ONCE(!sample))
return ret;
- }
/* Sample 2K bytes per page of the uncompressed data. */
- i = collect_sample(data, len, sample);
- if (i <= 0) {
- WARN_ON_ONCE(1);
-
+ len = collect_sample(data, sample, len);
+ if (len == 0)
goto out;
- }
- len = i;
ret = true;
-
if (has_repeated_data(sample, len))
goto out;