Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ceph: replace local base64 helpers with lib/base64

Remove the ceph_base64_encode() and ceph_base64_decode() functions and
replace their usage with the generic base64_encode() and base64_decode()
helpers from lib/base64.

This eliminates the custom implementation in Ceph, reduces code
duplication, and relies on the shared Base64 code in lib. The helpers
preserve RFC 3501-compliant Base64 encoding without padding, so there are
no functional changes.

This change also improves performance: encoding is about 2.7x faster and
decoding achieves 43-52x speedups compared to the previous local
implementation.

Link: https://lkml.kernel.org/r/20251114060240.89965-1-409411716@gms.tku.edu.tw
Signed-off-by: Guan-Chun Wu <409411716@gms.tku.edu.tw>
Reviewed-by: Kuan-Wei Chiu <visitorckw@gmail.com>
Reviewed-by: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
Cc: Keith Busch <kbusch@kernel.org>
Cc: Jens Axboe <axboe@kernel.dk>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Sagi Grimberg <sagi@grimberg.me>
Cc: Xiubo Li <xiubli@redhat.com>
Cc: Ilya Dryomov <idryomov@gmail.com>
Cc: Eric Biggers <ebiggers@kernel.org>
Cc: "Theodore Y. Ts'o" <tytso@mit.edu>
Cc: Jaegeuk Kim <jaegeuk@kernel.org>
Cc: David Laight <david.laight.linux@gmail.com>
Cc: Yu-Sheng Huang <home7438072@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Guan-Chun Wu and committed by
Andrew Morton
b1b72ac2 7794510e

+9 -64
+4 -56
fs/ceph/crypto.c
··· 15 15 #include "mds_client.h" 16 16 #include "crypto.h" 17 17 18 - /* 19 - * The base64url encoding used by fscrypt includes the '_' character, which may 20 - * cause problems in snapshot names (which can not start with '_'). Thus, we 21 - * used the base64 encoding defined for IMAP mailbox names (RFC 3501) instead, 22 - * which replaces '-' and '_' by '+' and ','. 23 - */ 24 - static const char base64_table[65] = 25 - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; 26 - 27 - int ceph_base64_encode(const u8 *src, int srclen, char *dst) 28 - { 29 - u32 ac = 0; 30 - int bits = 0; 31 - int i; 32 - char *cp = dst; 33 - 34 - for (i = 0; i < srclen; i++) { 35 - ac = (ac << 8) | src[i]; 36 - bits += 8; 37 - do { 38 - bits -= 6; 39 - *cp++ = base64_table[(ac >> bits) & 0x3f]; 40 - } while (bits >= 6); 41 - } 42 - if (bits) 43 - *cp++ = base64_table[(ac << (6 - bits)) & 0x3f]; 44 - return cp - dst; 45 - } 46 - 47 - int ceph_base64_decode(const char *src, int srclen, u8 *dst) 48 - { 49 - u32 ac = 0; 50 - int bits = 0; 51 - int i; 52 - u8 *bp = dst; 53 - 54 - for (i = 0; i < srclen; i++) { 55 - const char *p = strchr(base64_table, src[i]); 56 - 57 - if (p == NULL || src[i] == 0) 58 - return -1; 59 - ac = (ac << 6) | (p - base64_table); 60 - bits += 6; 61 - if (bits >= 8) { 62 - bits -= 8; 63 - *bp++ = (u8)(ac >> bits); 64 - } 65 - } 66 - if (ac & ((1 << bits) - 1)) 67 - return -1; 68 - return bp - dst; 69 - } 70 - 71 18 static int ceph_crypt_get_context(struct inode *inode, void *ctx, size_t len) 72 19 { 73 20 struct ceph_inode_info *ci = ceph_inode(inode); ··· 265 318 } 266 319 267 320 /* base64 encode the encrypted name */ 268 - elen = ceph_base64_encode(cryptbuf, len, p); 321 + elen = base64_encode(cryptbuf, len, p, false, BASE64_IMAP); 269 322 doutc(cl, "base64-encoded ciphertext name = %.*s\n", elen, p); 270 323 271 324 /* To understand the 240 limit, see CEPH_NOHASH_NAME_MAX comments */ ··· 359 412 tname = &_tname; 360 413 } 361 414 362 - declen = ceph_base64_decode(name, name_len, tname->name); 415 + declen = base64_decode(name, name_len, 416 + tname->name, false, BASE64_IMAP); 363 417 if (declen <= 0) { 364 418 ret = -EIO; 365 419 goto out; ··· 374 426 375 427 ret = fscrypt_fname_disk_to_usr(dir, 0, 0, &iname, oname); 376 428 if (!ret && (dir != fname->dir)) { 377 - char tmp_buf[CEPH_BASE64_CHARS(NAME_MAX)]; 429 + char tmp_buf[BASE64_CHARS(NAME_MAX)]; 378 430 379 431 name_len = snprintf(tmp_buf, sizeof(tmp_buf), "_%.*s_%ld", 380 432 oname->len, oname->name, dir->i_ino);
+1 -5
fs/ceph/crypto.h
··· 8 8 9 9 #include <crypto/sha2.h> 10 10 #include <linux/fscrypt.h> 11 + #include <linux/base64.h> 11 12 12 13 #define CEPH_FSCRYPT_BLOCK_SHIFT 12 13 14 #define CEPH_FSCRYPT_BLOCK_SIZE (_AC(1, UL) << CEPH_FSCRYPT_BLOCK_SHIFT) ··· 89 88 * field). 90 89 */ 91 90 #define CEPH_NOHASH_NAME_MAX (180 - SHA256_DIGEST_SIZE) 92 - 93 - #define CEPH_BASE64_CHARS(nbytes) DIV_ROUND_UP((nbytes) * 4, 3) 94 - 95 - int ceph_base64_encode(const u8 *src, int srclen, char *dst); 96 - int ceph_base64_decode(const char *src, int srclen, u8 *dst); 97 91 98 92 void ceph_fscrypt_set_ops(struct super_block *sb); 99 93
+3 -2
fs/ceph/dir.c
··· 998 998 if (err) 999 999 goto out; 1000 1000 1001 - req->r_path2 = kmalloc(CEPH_BASE64_CHARS(osd_link.len) + 1, GFP_KERNEL); 1001 + req->r_path2 = kmalloc(BASE64_CHARS(osd_link.len) + 1, GFP_KERNEL); 1002 1002 if (!req->r_path2) { 1003 1003 err = -ENOMEM; 1004 1004 goto out; 1005 1005 } 1006 1006 1007 - len = ceph_base64_encode(osd_link.name, osd_link.len, req->r_path2); 1007 + len = base64_encode(osd_link.name, osd_link.len, 1008 + req->r_path2, false, BASE64_IMAP); 1008 1009 req->r_path2[len] = '\0'; 1009 1010 out: 1010 1011 fscrypt_fname_free_buffer(&osd_link);
+1 -1
fs/ceph/inode.c
··· 958 958 if (!sym) 959 959 return -ENOMEM; 960 960 961 - declen = ceph_base64_decode(encsym, enclen, sym); 961 + declen = base64_decode(encsym, enclen, sym, false, BASE64_IMAP); 962 962 if (declen < 0) { 963 963 pr_err_client(cl, 964 964 "can't decode symlink (%d). Content: %.*s\n",