diff options
| author | Enzo Matsumiya <ematsumiya@suse.de> | 2025-12-01 13:19:55 -0300 |
|---|---|---|
| committer | Enzo Matsumiya <ematsumiya@suse.de> | 2025-12-05 11:45:07 -0300 |
| commit | 5b78dec9032da60184262f4e25cf606f057b2083 (patch) | |
| tree | c664431917e7f12f491a376b19c56903d1593b0e | |
| parent | 20823ef36a8ce02f84790543d399daf1fd48006a (diff) | |
| download | linux-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.c | 71 |
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; |
