Merge tag 'ceph-for-6.18-rc1' of https://github.com/ceph/ceph-client

Pull ceph updates from Ilya Dryomov:

- some messenger improvements (Eric and Max)

- address an issue (also affected userspace) of incorrect permissions
being granted to users who have access to multiple different CephFS
instances within the same cluster (Kotresh)

- a bunch of assorted CephFS fixes (Slava)

* tag 'ceph-for-6.18-rc1' of https://github.com/ceph/ceph-client:
ceph: add bug tracking system info to MAINTAINERS
ceph: fix multifs mds auth caps issue
ceph: cleanup in ceph_alloc_readdir_reply_buffer()
ceph: fix potential NULL dereference issue in ceph_fill_trace()
libceph: add empty check to ceph_con_get_out_msg()
libceph: pass the message pointer instead of loading con->out_msg
libceph: make ceph_con_get_out_msg() return the message pointer
ceph: fix potential race condition on operations with CEPH_I_ODIRECT flag
ceph: refactor wake_up_bit() pattern of calling
ceph: fix potential race condition in ceph_ioctl_lazyio()
ceph: fix overflowed constant issue in ceph_do_objects_copy()
ceph: fix wrong sizeof argument issue in register_session()
ceph: add checking of wait_for_completion_killable() return value
ceph: make ceph_start_io_*() killable
libceph: Use HMAC-SHA256 library instead of crypto_shash

+323 -248
+3
MAINTAINERS
··· 5694 5694 L: ceph-devel@vger.kernel.org 5695 5695 S: Supported 5696 5696 W: http://ceph.com/ 5697 + B: https://tracker.ceph.com/ 5697 5698 T: git https://github.com/ceph/ceph-client.git 5698 5699 F: include/linux/ceph/ 5699 5700 F: include/linux/crush/ ··· 5706 5705 L: ceph-devel@vger.kernel.org 5707 5706 S: Supported 5708 5707 W: http://ceph.com/ 5708 + B: https://tracker.ceph.com/ 5709 5709 T: git https://github.com/ceph/ceph-client.git 5710 5710 F: Documentation/filesystems/ceph.rst 5711 5711 F: fs/ceph/ ··· 21359 21357 L: ceph-devel@vger.kernel.org 21360 21358 S: Supported 21361 21359 W: http://ceph.com/ 21360 + B: https://tracker.ceph.com/ 21362 21361 T: git https://github.com/ceph/ceph-client.git 21363 21362 F: Documentation/ABI/testing/sysfs-bus-rbd 21364 21363 F: drivers/block/rbd.c
+1 -2
fs/ceph/dir.c
··· 1260 1260 spin_unlock(&fsc->async_unlink_conflict_lock); 1261 1261 1262 1262 spin_lock(&dentry->d_lock); 1263 - di->flags &= ~CEPH_DENTRY_ASYNC_UNLINK; 1264 - wake_up_bit(&di->flags, CEPH_DENTRY_ASYNC_UNLINK_BIT); 1263 + clear_and_wake_up_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags); 1265 1264 spin_unlock(&dentry->d_lock); 1266 1265 1267 1266 synchronize_rcu();
+15 -15
fs/ceph/file.c
··· 579 579 580 580 spin_lock(&ci->i_ceph_lock); 581 581 if (ci->i_ceph_flags & CEPH_I_ASYNC_CREATE) { 582 - ci->i_ceph_flags &= ~CEPH_I_ASYNC_CREATE; 583 - wake_up_bit(&ci->i_ceph_flags, CEPH_ASYNC_CREATE_BIT); 582 + clear_and_wake_up_bit(CEPH_ASYNC_CREATE_BIT, &ci->i_ceph_flags); 584 583 585 584 if (ci->i_ceph_flags & CEPH_I_ASYNC_CHECK_CAPS) { 586 585 ci->i_ceph_flags &= ~CEPH_I_ASYNC_CHECK_CAPS; ··· 761 762 } 762 763 763 764 spin_lock(&dentry->d_lock); 764 - di->flags &= ~CEPH_DENTRY_ASYNC_CREATE; 765 - wake_up_bit(&di->flags, CEPH_DENTRY_ASYNC_CREATE_BIT); 765 + clear_and_wake_up_bit(CEPH_DENTRY_ASYNC_CREATE_BIT, &di->flags); 766 766 spin_unlock(&dentry->d_lock); 767 767 768 768 return ret; ··· 2119 2121 if (ceph_inode_is_shutdown(inode)) 2120 2122 return -ESTALE; 2121 2123 2122 - if (direct_lock) 2123 - ceph_start_io_direct(inode); 2124 - else 2125 - ceph_start_io_read(inode); 2124 + ret = direct_lock ? ceph_start_io_direct(inode) : 2125 + ceph_start_io_read(inode); 2126 + if (ret) 2127 + return ret; 2126 2128 2127 2129 if (!(fi->flags & CEPH_F_SYNC) && !direct_lock) 2128 2130 want |= CEPH_CAP_FILE_CACHE; ··· 2275 2277 (fi->flags & CEPH_F_SYNC)) 2276 2278 return copy_splice_read(in, ppos, pipe, len, flags); 2277 2279 2278 - ceph_start_io_read(inode); 2280 + ret = ceph_start_io_read(inode); 2281 + if (ret) 2282 + return ret; 2279 2283 2280 2284 want = CEPH_CAP_FILE_CACHE; 2281 2285 if (fi->fmode & CEPH_FILE_MODE_LAZY) ··· 2356 2356 direct_lock = true; 2357 2357 2358 2358 retry_snap: 2359 - if (direct_lock) 2360 - ceph_start_io_direct(inode); 2361 - else 2362 - ceph_start_io_write(inode); 2359 + err = direct_lock ? ceph_start_io_direct(inode) : 2360 + ceph_start_io_write(inode); 2361 + if (err) 2362 + goto out_unlocked; 2363 2363 2364 2364 if (iocb->ki_flags & IOCB_APPEND) { 2365 2365 err = ceph_do_getattr(inode, CEPH_STAT_CAP_SIZE, false); ··· 2878 2878 struct ceph_object_id src_oid, dst_oid; 2879 2879 struct ceph_osd_client *osdc; 2880 2880 struct ceph_osd_request *req; 2881 - size_t bytes = 0; 2881 + ssize_t bytes = 0; 2882 2882 u64 src_objnum, src_objoff, dst_objnum, dst_objoff; 2883 2883 u32 src_objlen, dst_objlen; 2884 2884 u32 object_size = src_ci->i_layout.object_size; ··· 2928 2928 "OSDs don't support copy-from2; disabling copy offload\n"); 2929 2929 } 2930 2930 doutc(cl, "returned %d\n", ret); 2931 - if (!bytes) 2931 + if (bytes <= 0) 2932 2932 bytes = ret; 2933 2933 goto out; 2934 2934 }
+11
fs/ceph/inode.c
··· 1794 1794 goto done; 1795 1795 } 1796 1796 1797 + if (unlikely(!in)) { 1798 + err = -EINVAL; 1799 + goto done; 1800 + } 1801 + 1797 1802 /* attach proper inode */ 1798 1803 if (d_really_is_negative(dn)) { 1799 1804 ceph_dir_clear_ordered(dir); ··· 1834 1829 doutc(cl, " linking snapped dir %p to dn %p\n", in, 1835 1830 req->r_dentry); 1836 1831 ceph_dir_clear_ordered(dir); 1832 + 1833 + if (unlikely(!in)) { 1834 + err = -EINVAL; 1835 + goto done; 1836 + } 1837 + 1837 1838 ihold(in); 1838 1839 err = splice_dentry(&req->r_dentry, in); 1839 1840 if (err < 0)
+75 -25
fs/ceph/io.c
··· 21 21 /* Call with exclusively locked inode->i_rwsem */ 22 22 static void ceph_block_o_direct(struct ceph_inode_info *ci, struct inode *inode) 23 23 { 24 + bool is_odirect; 25 + 24 26 lockdep_assert_held_write(&inode->i_rwsem); 25 27 26 - if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT) { 27 - spin_lock(&ci->i_ceph_lock); 28 - ci->i_ceph_flags &= ~CEPH_I_ODIRECT; 29 - spin_unlock(&ci->i_ceph_lock); 30 - inode_dio_wait(inode); 28 + spin_lock(&ci->i_ceph_lock); 29 + /* ensure that bit state is consistent */ 30 + smp_mb__before_atomic(); 31 + is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT; 32 + if (is_odirect) { 33 + clear_bit(CEPH_I_ODIRECT_BIT, &ci->i_ceph_flags); 34 + /* ensure modified bit is visible */ 35 + smp_mb__after_atomic(); 31 36 } 37 + spin_unlock(&ci->i_ceph_lock); 38 + 39 + if (is_odirect) 40 + inode_dio_wait(inode); 32 41 } 33 42 34 43 /** ··· 56 47 * Note that buffered writes and truncates both take a write lock on 57 48 * inode->i_rwsem, meaning that those are serialised w.r.t. the reads. 58 49 */ 59 - void 60 - ceph_start_io_read(struct inode *inode) 50 + int ceph_start_io_read(struct inode *inode) 61 51 { 62 52 struct ceph_inode_info *ci = ceph_inode(inode); 53 + bool is_odirect; 54 + int err; 63 55 64 56 /* Be an optimist! */ 65 - down_read(&inode->i_rwsem); 66 - if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)) 67 - return; 57 + err = down_read_killable(&inode->i_rwsem); 58 + if (err) 59 + return err; 60 + 61 + spin_lock(&ci->i_ceph_lock); 62 + /* ensure that bit state is consistent */ 63 + smp_mb__before_atomic(); 64 + is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT; 65 + spin_unlock(&ci->i_ceph_lock); 66 + if (!is_odirect) 67 + return 0; 68 68 up_read(&inode->i_rwsem); 69 + 69 70 /* Slow path.... */ 70 - down_write(&inode->i_rwsem); 71 + err = down_write_killable(&inode->i_rwsem); 72 + if (err) 73 + return err; 74 + 71 75 ceph_block_o_direct(ci, inode); 72 76 downgrade_write(&inode->i_rwsem); 77 + 78 + return 0; 73 79 } 74 80 75 81 /** ··· 107 83 * Declare that a buffered write operation is about to start, and ensure 108 84 * that we block all direct I/O. 109 85 */ 110 - void 111 - ceph_start_io_write(struct inode *inode) 86 + int ceph_start_io_write(struct inode *inode) 112 87 { 113 - down_write(&inode->i_rwsem); 114 - ceph_block_o_direct(ceph_inode(inode), inode); 88 + int err = down_write_killable(&inode->i_rwsem); 89 + if (!err) 90 + ceph_block_o_direct(ceph_inode(inode), inode); 91 + return err; 115 92 } 116 93 117 94 /** ··· 131 106 /* Call with exclusively locked inode->i_rwsem */ 132 107 static void ceph_block_buffered(struct ceph_inode_info *ci, struct inode *inode) 133 108 { 109 + bool is_odirect; 110 + 134 111 lockdep_assert_held_write(&inode->i_rwsem); 135 112 136 - if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT)) { 137 - spin_lock(&ci->i_ceph_lock); 138 - ci->i_ceph_flags |= CEPH_I_ODIRECT; 139 - spin_unlock(&ci->i_ceph_lock); 113 + spin_lock(&ci->i_ceph_lock); 114 + /* ensure that bit state is consistent */ 115 + smp_mb__before_atomic(); 116 + is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT; 117 + if (!is_odirect) { 118 + set_bit(CEPH_I_ODIRECT_BIT, &ci->i_ceph_flags); 119 + /* ensure modified bit is visible */ 120 + smp_mb__after_atomic(); 121 + } 122 + spin_unlock(&ci->i_ceph_lock); 123 + 124 + if (!is_odirect) { 140 125 /* FIXME: unmap_mapping_range? */ 141 126 filemap_write_and_wait(inode->i_mapping); 142 127 } ··· 168 133 * Note that buffered writes and truncates both take a write lock on 169 134 * inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT. 170 135 */ 171 - void 172 - ceph_start_io_direct(struct inode *inode) 136 + int ceph_start_io_direct(struct inode *inode) 173 137 { 174 138 struct ceph_inode_info *ci = ceph_inode(inode); 139 + bool is_odirect; 140 + int err; 175 141 176 142 /* Be an optimist! */ 177 - down_read(&inode->i_rwsem); 178 - if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT) 179 - return; 143 + err = down_read_killable(&inode->i_rwsem); 144 + if (err) 145 + return err; 146 + 147 + spin_lock(&ci->i_ceph_lock); 148 + /* ensure that bit state is consistent */ 149 + smp_mb__before_atomic(); 150 + is_odirect = READ_ONCE(ci->i_ceph_flags) & CEPH_I_ODIRECT; 151 + spin_unlock(&ci->i_ceph_lock); 152 + if (is_odirect) 153 + return 0; 180 154 up_read(&inode->i_rwsem); 155 + 181 156 /* Slow path.... */ 182 - down_write(&inode->i_rwsem); 157 + err = down_write_killable(&inode->i_rwsem); 158 + if (err) 159 + return err; 160 + 183 161 ceph_block_buffered(ci, inode); 184 162 downgrade_write(&inode->i_rwsem); 163 + 164 + return 0; 185 165 } 186 166 187 167 /**
+5 -3
fs/ceph/io.h
··· 2 2 #ifndef _FS_CEPH_IO_H 3 3 #define _FS_CEPH_IO_H 4 4 5 - void ceph_start_io_read(struct inode *inode); 5 + #include <linux/compiler_attributes.h> 6 + 7 + int __must_check ceph_start_io_read(struct inode *inode); 6 8 void ceph_end_io_read(struct inode *inode); 7 - void ceph_start_io_write(struct inode *inode); 9 + int __must_check ceph_start_io_write(struct inode *inode); 8 10 void ceph_end_io_write(struct inode *inode); 9 - void ceph_start_io_direct(struct inode *inode); 11 + int __must_check ceph_start_io_direct(struct inode *inode); 10 12 void ceph_end_io_direct(struct inode *inode); 11 13 12 14 #endif /* FS_CEPH_IO_H */
+12 -5
fs/ceph/ioctl.c
··· 246 246 struct ceph_inode_info *ci = ceph_inode(inode); 247 247 struct ceph_mds_client *mdsc = ceph_inode_to_fs_client(inode)->mdsc; 248 248 struct ceph_client *cl = mdsc->fsc->client; 249 + bool is_file_already_lazy = false; 249 250 251 + spin_lock(&ci->i_ceph_lock); 250 252 if ((fi->fmode & CEPH_FILE_MODE_LAZY) == 0) { 251 - spin_lock(&ci->i_ceph_lock); 252 253 fi->fmode |= CEPH_FILE_MODE_LAZY; 253 254 ci->i_nr_by_mode[ffs(CEPH_FILE_MODE_LAZY)]++; 254 255 __ceph_touch_fmode(ci, mdsc, fi->fmode); 255 - spin_unlock(&ci->i_ceph_lock); 256 + } else { 257 + is_file_already_lazy = true; 258 + } 259 + spin_unlock(&ci->i_ceph_lock); 260 + 261 + if (is_file_already_lazy) { 262 + doutc(cl, "file %p %p %llx.%llx already lazy\n", file, inode, 263 + ceph_vinop(inode)); 264 + } else { 256 265 doutc(cl, "file %p %p %llx.%llx marked lazy\n", file, inode, 257 266 ceph_vinop(inode)); 258 267 259 268 ceph_check_caps(ci, 0); 260 - } else { 261 - doutc(cl, "file %p %p %llx.%llx already lazy\n", file, inode, 262 - ceph_vinop(inode)); 263 269 } 270 + 264 271 return 0; 265 272 } 266 273
+4 -1
fs/ceph/locks.c
··· 221 221 if (err && err != -ERESTARTSYS) 222 222 return err; 223 223 224 - wait_for_completion_killable(&req->r_safe_completion); 224 + err = wait_for_completion_killable(&req->r_safe_completion); 225 + if (err) 226 + return err; 227 + 225 228 return 0; 226 229 } 227 230
+18 -4
fs/ceph/mds_client.c
··· 979 979 if (mds >= mdsc->max_sessions) { 980 980 int newmax = 1 << get_count_order(mds + 1); 981 981 struct ceph_mds_session **sa; 982 + size_t ptr_size = sizeof(struct ceph_mds_session *); 982 983 983 984 doutc(cl, "realloc to %d\n", newmax); 984 - sa = kcalloc(newmax, sizeof(void *), GFP_NOFS); 985 + sa = kcalloc(newmax, ptr_size, GFP_NOFS); 985 986 if (!sa) 986 987 goto fail_realloc; 987 988 if (mdsc->sessions) { 988 989 memcpy(sa, mdsc->sessions, 989 - mdsc->max_sessions * sizeof(void *)); 990 + mdsc->max_sessions * ptr_size); 990 991 kfree(mdsc->sessions); 991 992 } 992 993 mdsc->sessions = sa; ··· 2533 2532 struct ceph_mount_options *opt = req->r_mdsc->fsc->mount_options; 2534 2533 size_t size = sizeof(struct ceph_mds_reply_dir_entry); 2535 2534 unsigned int num_entries; 2535 + u64 bytes_count; 2536 2536 int order; 2537 2537 2538 2538 spin_lock(&ci->i_ceph_lock); ··· 2542 2540 num_entries = max(num_entries, 1U); 2543 2541 num_entries = min(num_entries, opt->max_readdir); 2544 2542 2545 - order = get_order(size * num_entries); 2543 + bytes_count = (u64)size * num_entries; 2544 + if (unlikely(bytes_count > ULONG_MAX)) 2545 + bytes_count = ULONG_MAX; 2546 + 2547 + order = get_order((unsigned long)bytes_count); 2546 2548 while (order >= 0) { 2547 2549 rinfo->dir_entries = (void*)__get_free_pages(GFP_KERNEL | 2548 2550 __GFP_NOWARN | ··· 2556 2550 break; 2557 2551 order--; 2558 2552 } 2559 - if (!rinfo->dir_entries) 2553 + if (!rinfo->dir_entries || unlikely(order < 0)) 2560 2554 return -ENOMEM; 2561 2555 2562 2556 num_entries = (PAGE_SIZE << order) / size; ··· 5655 5649 u32 caller_uid = from_kuid(&init_user_ns, cred->fsuid); 5656 5650 u32 caller_gid = from_kgid(&init_user_ns, cred->fsgid); 5657 5651 struct ceph_client *cl = mdsc->fsc->client; 5652 + const char *fs_name = mdsc->fsc->mount_options->mds_namespace; 5658 5653 const char *spath = mdsc->fsc->mount_options->server_path; 5659 5654 bool gid_matched = false; 5660 5655 u32 gid, tlen, len; 5661 5656 int i, j; 5657 + 5658 + doutc(cl, "fsname check fs_name=%s match.fs_name=%s\n", 5659 + fs_name, auth->match.fs_name ? auth->match.fs_name : ""); 5660 + if (auth->match.fs_name && strcmp(auth->match.fs_name, fs_name)) { 5661 + /* fsname mismatch, try next one */ 5662 + return 0; 5663 + } 5662 5664 5663 5665 doutc(cl, "match.uid %lld\n", auth->match.uid); 5664 5666 if (auth->match.uid != MDS_AUTH_UID_ANY) {
+13 -1
fs/ceph/mdsmap.c
··· 353 353 __decode_and_drop_type(p, end, u8, bad_ext); 354 354 } 355 355 if (mdsmap_ev >= 8) { 356 + u32 fsname_len; 356 357 /* enabled */ 357 358 ceph_decode_8_safe(p, end, m->m_enabled, bad_ext); 358 359 /* fs_name */ 359 - ceph_decode_skip_string(p, end, bad_ext); 360 + ceph_decode_32_safe(p, end, fsname_len, bad_ext); 361 + 362 + /* validate fsname against mds_namespace */ 363 + if (!namespace_equals(mdsc->fsc->mount_options, *p, 364 + fsname_len)) { 365 + pr_warn_client(cl, "fsname %*pE doesn't match mds_namespace %s\n", 366 + (int)fsname_len, (char *)*p, 367 + mdsc->fsc->mount_options->mds_namespace); 368 + goto bad; 369 + } 370 + /* skip fsname after validation */ 371 + ceph_decode_skip_n(p, end, fsname_len, bad); 360 372 } 361 373 /* damaged */ 362 374 if (mdsmap_ev >= 9) {
-14
fs/ceph/super.c
··· 246 246 path[j] = '\0'; 247 247 } 248 248 249 - /* 250 - * Check if the mds namespace in ceph_mount_options matches 251 - * the passed in namespace string. First time match (when 252 - * ->mds_namespace is NULL) is treated specially, since 253 - * ->mds_namespace needs to be initialized by the caller. 254 - */ 255 - static int namespace_equals(struct ceph_mount_options *fsopt, 256 - const char *namespace, size_t len) 257 - { 258 - return !(fsopt->mds_namespace && 259 - (strlen(fsopt->mds_namespace) != len || 260 - strncmp(fsopt->mds_namespace, namespace, len))); 261 - } 262 - 263 249 static int ceph_parse_old_source(const char *dev_name, const char *dev_name_end, 264 250 struct fs_context *fc) 265 251 {
+16 -1
fs/ceph/super.h
··· 104 104 struct fscrypt_dummy_policy dummy_enc_policy; 105 105 }; 106 106 107 + /* 108 + * Check if the mds namespace in ceph_mount_options matches 109 + * the passed in namespace string. First time match (when 110 + * ->mds_namespace is NULL) is treated specially, since 111 + * ->mds_namespace needs to be initialized by the caller. 112 + */ 113 + static inline int namespace_equals(struct ceph_mount_options *fsopt, 114 + const char *namespace, size_t len) 115 + { 116 + return !(fsopt->mds_namespace && 117 + (strlen(fsopt->mds_namespace) != len || 118 + strncmp(fsopt->mds_namespace, namespace, len))); 119 + } 120 + 107 121 /* mount state */ 108 122 enum { 109 123 CEPH_MOUNT_MOUNTING, ··· 653 639 #define CEPH_I_FLUSH_SNAPS (1 << 8) /* need flush snapss */ 654 640 #define CEPH_I_ERROR_WRITE (1 << 9) /* have seen write errors */ 655 641 #define CEPH_I_ERROR_FILELOCK (1 << 10) /* have seen file lock errors */ 656 - #define CEPH_I_ODIRECT (1 << 11) /* inode in direct I/O mode */ 642 + #define CEPH_I_ODIRECT_BIT (11) /* inode in direct I/O mode */ 643 + #define CEPH_I_ODIRECT (1 << CEPH_I_ODIRECT_BIT) 657 644 #define CEPH_ASYNC_CREATE_BIT (12) /* async create in flight for this */ 658 645 #define CEPH_I_ASYNC_CREATE (1 << CEPH_ASYNC_CREATE_BIT) 659 646 #define CEPH_I_SHUTDOWN (1 << 13) /* inode is no longer usable */
+6 -4
include/linux/ceph/messenger.h
··· 2 2 #ifndef __FS_CEPH_MESSENGER_H 3 3 #define __FS_CEPH_MESSENGER_H 4 4 5 + #include <crypto/sha2.h> 5 6 #include <linux/bvec.h> 6 7 #include <linux/crypto.h> 7 8 #include <linux/kref.h> ··· 413 412 struct ceph_msg_data_cursor in_cursor; 414 413 struct ceph_msg_data_cursor out_cursor; 415 414 416 - struct crypto_shash *hmac_tfm; /* post-auth signature */ 415 + struct hmac_sha256_key hmac_key; /* post-auth signature */ 416 + bool hmac_key_set; 417 417 struct crypto_aead *gcm_tfm; /* on-wire encryption */ 418 418 struct aead_request *gcm_req; 419 419 struct crypto_wait gcm_wait; ··· 550 548 void ceph_con_process_message(struct ceph_connection *con); 551 549 int ceph_con_in_msg_alloc(struct ceph_connection *con, 552 550 struct ceph_msg_header *hdr, int *skip); 553 - void ceph_con_get_out_msg(struct ceph_connection *con); 551 + struct ceph_msg *ceph_con_get_out_msg(struct ceph_connection *con); 554 552 555 553 /* messenger_v1.c */ 556 554 int ceph_con_v1_try_read(struct ceph_connection *con); 557 555 int ceph_con_v1_try_write(struct ceph_connection *con); 558 - void ceph_con_v1_revoke(struct ceph_connection *con); 556 + void ceph_con_v1_revoke(struct ceph_connection *con, struct ceph_msg *msg); 559 557 void ceph_con_v1_revoke_incoming(struct ceph_connection *con); 560 558 bool ceph_con_v1_opened(struct ceph_connection *con); 561 559 void ceph_con_v1_reset_session(struct ceph_connection *con); ··· 564 562 /* messenger_v2.c */ 565 563 int ceph_con_v2_try_read(struct ceph_connection *con); 566 564 int ceph_con_v2_try_write(struct ceph_connection *con); 567 - void ceph_con_v2_revoke(struct ceph_connection *con); 565 + void ceph_con_v2_revoke(struct ceph_connection *con, struct ceph_msg *msg); 568 566 void ceph_con_v2_revoke_incoming(struct ceph_connection *con); 569 567 bool ceph_con_v2_opened(struct ceph_connection *con); 570 568 void ceph_con_v2_reset_session(struct ceph_connection *con);
+1 -2
net/ceph/Kconfig
··· 6 6 select CRYPTO_AES 7 7 select CRYPTO_CBC 8 8 select CRYPTO_GCM 9 - select CRYPTO_HMAC 10 - select CRYPTO_SHA256 9 + select CRYPTO_LIB_SHA256 11 10 select CRYPTO 12 11 select KEYS 13 12 default n
+7 -5
net/ceph/messenger.c
··· 1794 1794 WARN_ON(con->state != CEPH_CON_S_OPEN); 1795 1795 dout("%s con %p msg %p was sending\n", __func__, con, msg); 1796 1796 if (ceph_msgr2(from_msgr(con->msgr))) 1797 - ceph_con_v2_revoke(con); 1797 + ceph_con_v2_revoke(con, msg); 1798 1798 else 1799 - ceph_con_v1_revoke(con); 1799 + ceph_con_v1_revoke(con, msg); 1800 1800 ceph_msg_put(con->out_msg); 1801 1801 con->out_msg = NULL; 1802 1802 } else { ··· 2111 2111 return ret; 2112 2112 } 2113 2113 2114 - void ceph_con_get_out_msg(struct ceph_connection *con) 2114 + struct ceph_msg *ceph_con_get_out_msg(struct ceph_connection *con) 2115 2115 { 2116 2116 struct ceph_msg *msg; 2117 2117 2118 - BUG_ON(list_empty(&con->out_queue)); 2118 + if (list_empty(&con->out_queue)) 2119 + return NULL; 2120 + 2119 2121 msg = list_first_entry(&con->out_queue, struct ceph_msg, list_head); 2120 2122 WARN_ON(msg->con != con); 2121 2123 ··· 2144 2142 * message or in case of a fault. 2145 2143 */ 2146 2144 WARN_ON(con->out_msg); 2147 - con->out_msg = ceph_msg_get(msg); 2145 + return con->out_msg = ceph_msg_get(msg); 2148 2146 } 2149 2147 2150 2148 /*
+26 -30
net/ceph/messenger_v1.c
··· 169 169 * Prepare footer for currently outgoing message, and finish things 170 170 * off. Assumes out_kvec* are already valid.. we just add on to the end. 171 171 */ 172 - static void prepare_write_message_footer(struct ceph_connection *con) 172 + static void prepare_write_message_footer(struct ceph_connection *con, 173 + struct ceph_msg *m) 173 174 { 174 - struct ceph_msg *m = con->out_msg; 175 - 176 175 m->footer.flags |= CEPH_MSG_FOOTER_COMPLETE; 177 176 178 177 dout("prepare_write_message_footer %p\n", con); ··· 191 192 /* 192 193 * Prepare headers for the next outgoing message. 193 194 */ 194 - static void prepare_write_message(struct ceph_connection *con) 195 + static void prepare_write_message(struct ceph_connection *con, 196 + struct ceph_msg *m) 195 197 { 196 - struct ceph_msg *m; 197 198 u32 crc; 198 199 199 200 con_out_kvec_reset(con); ··· 208 209 con_out_kvec_add(con, sizeof(con->v1.out_temp_ack), 209 210 &con->v1.out_temp_ack); 210 211 } 211 - 212 - ceph_con_get_out_msg(con); 213 - m = con->out_msg; 214 212 215 213 dout("prepare_write_message %p seq %lld type %d len %d+%d+%zd\n", 216 214 m, con->out_seq, le16_to_cpu(m->hdr.type), ··· 227 231 228 232 /* fill in hdr crc and finalize hdr */ 229 233 crc = crc32c(0, &m->hdr, offsetof(struct ceph_msg_header, crc)); 230 - con->out_msg->hdr.crc = cpu_to_le32(crc); 231 - memcpy(&con->v1.out_hdr, &con->out_msg->hdr, sizeof(con->v1.out_hdr)); 234 + m->hdr.crc = cpu_to_le32(crc); 235 + memcpy(&con->v1.out_hdr, &m->hdr, sizeof(con->v1.out_hdr)); 232 236 233 237 /* fill in front and middle crc, footer */ 234 238 crc = crc32c(0, m->front.iov_base, m->front.iov_len); 235 - con->out_msg->footer.front_crc = cpu_to_le32(crc); 239 + m->footer.front_crc = cpu_to_le32(crc); 236 240 if (m->middle) { 237 241 crc = crc32c(0, m->middle->vec.iov_base, 238 242 m->middle->vec.iov_len); 239 - con->out_msg->footer.middle_crc = cpu_to_le32(crc); 243 + m->footer.middle_crc = cpu_to_le32(crc); 240 244 } else 241 - con->out_msg->footer.middle_crc = 0; 245 + m->footer.middle_crc = 0; 242 246 dout("%s front_crc %u middle_crc %u\n", __func__, 243 - le32_to_cpu(con->out_msg->footer.front_crc), 244 - le32_to_cpu(con->out_msg->footer.middle_crc)); 245 - con->out_msg->footer.flags = 0; 247 + le32_to_cpu(m->footer.front_crc), 248 + le32_to_cpu(m->footer.middle_crc)); 249 + m->footer.flags = 0; 246 250 247 251 /* is there a data payload? */ 248 - con->out_msg->footer.data_crc = 0; 252 + m->footer.data_crc = 0; 249 253 if (m->data_length) { 250 - prepare_message_data(con->out_msg, m->data_length); 254 + prepare_message_data(m, m->data_length); 251 255 con->v1.out_more = 1; /* data + footer will follow */ 252 256 } else { 253 257 /* no, queue up footer too and be done */ 254 - prepare_write_message_footer(con); 258 + prepare_write_message_footer(con, m); 255 259 } 256 260 257 261 ceph_con_flag_set(con, CEPH_CON_F_WRITE_PENDING); ··· 458 462 * 0 -> socket full, but more to do 459 463 * <0 -> error 460 464 */ 461 - static int write_partial_message_data(struct ceph_connection *con) 465 + static int write_partial_message_data(struct ceph_connection *con, 466 + struct ceph_msg *msg) 462 467 { 463 - struct ceph_msg *msg = con->out_msg; 464 468 struct ceph_msg_data_cursor *cursor = &msg->cursor; 465 469 bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC); 466 470 u32 crc; ··· 512 516 else 513 517 msg->footer.flags |= CEPH_MSG_FOOTER_NOCRC; 514 518 con_out_kvec_reset(con); 515 - prepare_write_message_footer(con); 519 + prepare_write_message_footer(con, msg); 516 520 517 521 return 1; /* must return > 0 to indicate success */ 518 522 } ··· 1468 1472 */ 1469 1473 int ceph_con_v1_try_write(struct ceph_connection *con) 1470 1474 { 1475 + struct ceph_msg *msg; 1471 1476 int ret = 1; 1472 1477 1473 1478 dout("try_write start %p state %d\n", con, con->state); ··· 1515 1518 } 1516 1519 1517 1520 /* msg pages? */ 1518 - if (con->out_msg) { 1521 + msg = con->out_msg; 1522 + if (msg) { 1519 1523 if (con->v1.out_msg_done) { 1520 - ceph_msg_put(con->out_msg); 1524 + ceph_msg_put(msg); 1521 1525 con->out_msg = NULL; /* we're done with this one */ 1522 1526 goto do_next; 1523 1527 } 1524 1528 1525 - ret = write_partial_message_data(con); 1529 + ret = write_partial_message_data(con, msg); 1526 1530 if (ret == 1) 1527 1531 goto more; /* we need to send the footer, too! */ 1528 1532 if (ret == 0) ··· 1543 1545 goto more; 1544 1546 } 1545 1547 /* is anything else pending? */ 1546 - if (!list_empty(&con->out_queue)) { 1547 - prepare_write_message(con); 1548 + if ((msg = ceph_con_get_out_msg(con)) != NULL) { 1549 + prepare_write_message(con, msg); 1548 1550 goto more; 1549 1551 } 1550 1552 if (con->in_seq > con->in_seq_acked) { ··· 1562 1564 return ret; 1563 1565 } 1564 1566 1565 - void ceph_con_v1_revoke(struct ceph_connection *con) 1567 + void ceph_con_v1_revoke(struct ceph_connection *con, struct ceph_msg *msg) 1566 1568 { 1567 - struct ceph_msg *msg = con->out_msg; 1568 - 1569 1569 WARN_ON(con->v1.out_skip); 1570 1570 /* footer */ 1571 1571 if (con->v1.out_msg_done) {
+110 -136
net/ceph/messenger_v2.c
··· 709 709 710 710 dout("%s con %p con_mode %d session_key_len %d con_secret_len %d\n", 711 711 __func__, con, con->v2.con_mode, session_key_len, con_secret_len); 712 - WARN_ON(con->v2.hmac_tfm || con->v2.gcm_tfm || con->v2.gcm_req); 712 + WARN_ON(con->v2.hmac_key_set || con->v2.gcm_tfm || con->v2.gcm_req); 713 713 714 714 if (con->v2.con_mode != CEPH_CON_MODE_CRC && 715 715 con->v2.con_mode != CEPH_CON_MODE_SECURE) { ··· 723 723 return 0; /* auth_none */ 724 724 } 725 725 726 - noio_flag = memalloc_noio_save(); 727 - con->v2.hmac_tfm = crypto_alloc_shash("hmac(sha256)", 0, 0); 728 - memalloc_noio_restore(noio_flag); 729 - if (IS_ERR(con->v2.hmac_tfm)) { 730 - ret = PTR_ERR(con->v2.hmac_tfm); 731 - con->v2.hmac_tfm = NULL; 732 - pr_err("failed to allocate hmac tfm context: %d\n", ret); 733 - return ret; 734 - } 735 - 736 - ret = crypto_shash_setkey(con->v2.hmac_tfm, session_key, 737 - session_key_len); 738 - if (ret) { 739 - pr_err("failed to set hmac key: %d\n", ret); 740 - return ret; 741 - } 726 + hmac_sha256_preparekey(&con->v2.hmac_key, session_key, session_key_len); 727 + con->v2.hmac_key_set = true; 742 728 743 729 if (con->v2.con_mode == CEPH_CON_MODE_CRC) { 744 730 WARN_ON(con_secret_len); ··· 779 793 return 0; /* auth_x, secure mode */ 780 794 } 781 795 782 - static int ceph_hmac_sha256(struct ceph_connection *con, 783 - const struct kvec *kvecs, int kvec_cnt, u8 *hmac) 796 + static void ceph_hmac_sha256(struct ceph_connection *con, 797 + const struct kvec *kvecs, int kvec_cnt, 798 + u8 hmac[SHA256_DIGEST_SIZE]) 784 799 { 785 - SHASH_DESC_ON_STACK(desc, con->v2.hmac_tfm); /* tfm arg is ignored */ 786 - int ret; 800 + struct hmac_sha256_ctx ctx; 787 801 int i; 788 802 789 - dout("%s con %p hmac_tfm %p kvec_cnt %d\n", __func__, con, 790 - con->v2.hmac_tfm, kvec_cnt); 803 + dout("%s con %p hmac_key_set %d kvec_cnt %d\n", __func__, con, 804 + con->v2.hmac_key_set, kvec_cnt); 791 805 792 - if (!con->v2.hmac_tfm) { 806 + if (!con->v2.hmac_key_set) { 793 807 memset(hmac, 0, SHA256_DIGEST_SIZE); 794 - return 0; /* auth_none */ 808 + return; /* auth_none */ 795 809 } 796 810 797 - desc->tfm = con->v2.hmac_tfm; 798 - ret = crypto_shash_init(desc); 799 - if (ret) 800 - goto out; 801 - 802 - for (i = 0; i < kvec_cnt; i++) { 803 - ret = crypto_shash_update(desc, kvecs[i].iov_base, 804 - kvecs[i].iov_len); 805 - if (ret) 806 - goto out; 807 - } 808 - 809 - ret = crypto_shash_final(desc, hmac); 810 - 811 - out: 812 - shash_desc_zero(desc); 813 - return ret; /* auth_x, both plain and secure modes */ 811 + /* auth_x, both plain and secure modes */ 812 + hmac_sha256_init(&ctx, &con->v2.hmac_key); 813 + for (i = 0; i < kvec_cnt; i++) 814 + hmac_sha256_update(&ctx, kvecs[i].iov_base, kvecs[i].iov_len); 815 + hmac_sha256_final(&ctx, hmac); 814 816 } 815 817 816 818 static void gcm_inc_nonce(struct ceph_gcm_nonce *nonce) ··· 1429 1455 static int prepare_auth_signature(struct ceph_connection *con) 1430 1456 { 1431 1457 void *buf; 1432 - int ret; 1433 1458 1434 1459 buf = alloc_conn_buf(con, head_onwire_len(SHA256_DIGEST_SIZE, 1435 1460 con_secure(con))); 1436 1461 if (!buf) 1437 1462 return -ENOMEM; 1438 1463 1439 - ret = ceph_hmac_sha256(con, con->v2.in_sign_kvecs, 1440 - con->v2.in_sign_kvec_cnt, CTRL_BODY(buf)); 1441 - if (ret) 1442 - return ret; 1464 + ceph_hmac_sha256(con, con->v2.in_sign_kvecs, con->v2.in_sign_kvec_cnt, 1465 + CTRL_BODY(buf)); 1443 1466 1444 1467 return prepare_control(con, FRAME_TAG_AUTH_SIGNATURE, buf, 1445 1468 SHA256_DIGEST_SIZE); ··· 1560 1589 return prepare_control(con, FRAME_TAG_ACK, con->v2.out_buf, 8); 1561 1590 } 1562 1591 1563 - static void prepare_epilogue_plain(struct ceph_connection *con, bool aborted) 1592 + static void prepare_epilogue_plain(struct ceph_connection *con, 1593 + struct ceph_msg *msg, bool aborted) 1564 1594 { 1565 1595 dout("%s con %p msg %p aborted %d crcs %u %u %u\n", __func__, con, 1566 - con->out_msg, aborted, con->v2.out_epil.front_crc, 1596 + msg, aborted, con->v2.out_epil.front_crc, 1567 1597 con->v2.out_epil.middle_crc, con->v2.out_epil.data_crc); 1568 1598 1569 1599 encode_epilogue_plain(con, aborted); ··· 1575 1603 * For "used" empty segments, crc is -1. For unused (trailing) 1576 1604 * segments, crc is 0. 1577 1605 */ 1578 - static void prepare_message_plain(struct ceph_connection *con) 1606 + static void prepare_message_plain(struct ceph_connection *con, 1607 + struct ceph_msg *msg) 1579 1608 { 1580 - struct ceph_msg *msg = con->out_msg; 1581 - 1582 1609 prepare_head_plain(con, con->v2.out_buf, 1583 1610 sizeof(struct ceph_msg_header2), NULL, 0, false); 1584 1611 ··· 1618 1647 con->v2.out_state = OUT_S_QUEUE_DATA; 1619 1648 } else { 1620 1649 con->v2.out_epil.data_crc = 0; 1621 - prepare_epilogue_plain(con, false); 1650 + prepare_epilogue_plain(con, msg, false); 1622 1651 con->v2.out_state = OUT_S_FINISH_MESSAGE; 1623 1652 } 1624 1653 } ··· 1630 1659 * allocate pages for the entire tail of the message (currently up 1631 1660 * to ~32M) and two sgs arrays (up to ~256K each)... 1632 1661 */ 1633 - static int prepare_message_secure(struct ceph_connection *con) 1662 + static int prepare_message_secure(struct ceph_connection *con, 1663 + struct ceph_msg *msg) 1634 1664 { 1635 1665 void *zerop = page_address(ceph_zero_page); 1636 1666 struct sg_table enc_sgt = {}; ··· 1646 1674 if (ret) 1647 1675 return ret; 1648 1676 1649 - tail_len = tail_onwire_len(con->out_msg, true); 1677 + tail_len = tail_onwire_len(msg, true); 1650 1678 if (!tail_len) { 1651 1679 /* 1652 1680 * Empty message: once the head is written, ··· 1657 1685 } 1658 1686 1659 1687 encode_epilogue_secure(con, false); 1660 - ret = setup_message_sgs(&sgt, con->out_msg, zerop, zerop, zerop, 1688 + ret = setup_message_sgs(&sgt, msg, zerop, zerop, zerop, 1661 1689 &con->v2.out_epil, NULL, 0, false); 1662 1690 if (ret) 1663 1691 goto out; ··· 1686 1714 goto out; 1687 1715 1688 1716 dout("%s con %p msg %p sg_cnt %d enc_page_cnt %d\n", __func__, con, 1689 - con->out_msg, sgt.orig_nents, enc_page_cnt); 1717 + msg, sgt.orig_nents, enc_page_cnt); 1690 1718 con->v2.out_state = OUT_S_QUEUE_ENC_PAGE; 1691 1719 1692 1720 out: ··· 1695 1723 return ret; 1696 1724 } 1697 1725 1698 - static int prepare_message(struct ceph_connection *con) 1726 + static int prepare_message(struct ceph_connection *con, struct ceph_msg *msg) 1699 1727 { 1700 1728 int lens[] = { 1701 1729 sizeof(struct ceph_msg_header2), 1702 - front_len(con->out_msg), 1703 - middle_len(con->out_msg), 1704 - data_len(con->out_msg) 1730 + front_len(msg), 1731 + middle_len(msg), 1732 + data_len(msg) 1705 1733 }; 1706 1734 struct ceph_frame_desc desc; 1707 1735 int ret; 1708 1736 1709 1737 dout("%s con %p msg %p logical %d+%d+%d+%d\n", __func__, con, 1710 - con->out_msg, lens[0], lens[1], lens[2], lens[3]); 1738 + msg, lens[0], lens[1], lens[2], lens[3]); 1711 1739 1712 1740 if (con->in_seq > con->in_seq_acked) { 1713 1741 dout("%s con %p in_seq_acked %llu -> %llu\n", __func__, con, ··· 1718 1746 reset_out_kvecs(con); 1719 1747 init_frame_desc(&desc, FRAME_TAG_MESSAGE, lens, 4); 1720 1748 encode_preamble(&desc, con->v2.out_buf); 1721 - fill_header2(CTRL_BODY(con->v2.out_buf), &con->out_msg->hdr, 1749 + fill_header2(CTRL_BODY(con->v2.out_buf), &msg->hdr, 1722 1750 con->in_seq_acked); 1723 1751 1724 1752 if (con_secure(con)) { 1725 - ret = prepare_message_secure(con); 1753 + ret = prepare_message_secure(con, msg); 1726 1754 if (ret) 1727 1755 return ret; 1728 1756 } else { 1729 - prepare_message_plain(con); 1757 + prepare_message_plain(con, msg); 1730 1758 } 1731 1759 1732 1760 ceph_con_flag_set(con, CEPH_CON_F_WRITE_PENDING); ··· 2432 2460 return -EINVAL; 2433 2461 } 2434 2462 2435 - ret = ceph_hmac_sha256(con, con->v2.out_sign_kvecs, 2436 - con->v2.out_sign_kvec_cnt, hmac); 2437 - if (ret) 2438 - return ret; 2463 + ceph_hmac_sha256(con, con->v2.out_sign_kvecs, con->v2.out_sign_kvec_cnt, 2464 + hmac); 2439 2465 2440 2466 ceph_decode_need(&p, end, SHA256_DIGEST_SIZE, bad); 2441 2467 if (crypto_memneq(p, hmac, SHA256_DIGEST_SIZE)) { ··· 3154 3184 } 3155 3185 } 3156 3186 3157 - static void queue_data(struct ceph_connection *con) 3187 + static void queue_data(struct ceph_connection *con, struct ceph_msg *msg) 3158 3188 { 3159 3189 struct bio_vec bv; 3160 3190 3161 3191 con->v2.out_epil.data_crc = -1; 3162 - ceph_msg_data_cursor_init(&con->v2.out_cursor, con->out_msg, 3163 - data_len(con->out_msg)); 3192 + ceph_msg_data_cursor_init(&con->v2.out_cursor, msg, 3193 + data_len(msg)); 3164 3194 3165 3195 get_bvec_at(&con->v2.out_cursor, &bv); 3166 3196 set_out_bvec(con, &bv, true); 3167 3197 con->v2.out_state = OUT_S_QUEUE_DATA_CONT; 3168 3198 } 3169 3199 3170 - static void queue_data_cont(struct ceph_connection *con) 3200 + static void queue_data_cont(struct ceph_connection *con, struct ceph_msg *msg) 3171 3201 { 3172 3202 struct bio_vec bv; 3173 3203 ··· 3188 3218 * we are done. 3189 3219 */ 3190 3220 reset_out_kvecs(con); 3191 - prepare_epilogue_plain(con, false); 3221 + prepare_epilogue_plain(con, msg, false); 3192 3222 con->v2.out_state = OUT_S_FINISH_MESSAGE; 3193 3223 } 3194 3224 ··· 3220 3250 con->v2.out_state = OUT_S_FINISH_MESSAGE; 3221 3251 } 3222 3252 3223 - static void queue_zeros(struct ceph_connection *con) 3253 + static void queue_zeros(struct ceph_connection *con, struct ceph_msg *msg) 3224 3254 { 3225 3255 dout("%s con %p out_zero %d\n", __func__, con, con->v2.out_zero); 3226 3256 ··· 3237 3267 * Once it's written, we are done patching up for the revoke. 3238 3268 */ 3239 3269 reset_out_kvecs(con); 3240 - prepare_epilogue_plain(con, true); 3270 + prepare_epilogue_plain(con, msg, true); 3241 3271 con->v2.out_state = OUT_S_FINISH_MESSAGE; 3242 3272 } 3243 3273 ··· 3264 3294 3265 3295 static int populate_out_iter(struct ceph_connection *con) 3266 3296 { 3297 + struct ceph_msg *msg; 3267 3298 int ret; 3268 3299 3269 3300 dout("%s con %p state %d out_state %d\n", __func__, con, con->state, ··· 3280 3309 switch (con->v2.out_state) { 3281 3310 case OUT_S_QUEUE_DATA: 3282 3311 WARN_ON(!con->out_msg); 3283 - queue_data(con); 3312 + queue_data(con, con->out_msg); 3284 3313 goto populated; 3285 3314 case OUT_S_QUEUE_DATA_CONT: 3286 3315 WARN_ON(!con->out_msg); 3287 - queue_data_cont(con); 3316 + queue_data_cont(con, con->out_msg); 3288 3317 goto populated; 3289 3318 case OUT_S_QUEUE_ENC_PAGE: 3290 3319 queue_enc_page(con); 3291 3320 goto populated; 3292 3321 case OUT_S_QUEUE_ZEROS: 3293 3322 WARN_ON(con->out_msg); /* revoked */ 3294 - queue_zeros(con); 3323 + queue_zeros(con, con->out_msg); 3295 3324 goto populated; 3296 3325 case OUT_S_FINISH_MESSAGE: 3297 3326 finish_message(con); ··· 3310 3339 pr_err("prepare_keepalive2 failed: %d\n", ret); 3311 3340 return ret; 3312 3341 } 3313 - } else if (!list_empty(&con->out_queue)) { 3314 - ceph_con_get_out_msg(con); 3315 - ret = prepare_message(con); 3342 + } else if ((msg = ceph_con_get_out_msg(con)) != NULL) { 3343 + ret = prepare_message(con, msg); 3316 3344 if (ret) { 3317 3345 pr_err("prepare_message failed: %d\n", ret); 3318 3346 return ret; ··· 3423 3453 return crc; 3424 3454 } 3425 3455 3426 - static void prepare_zero_front(struct ceph_connection *con, int resid) 3456 + static void prepare_zero_front(struct ceph_connection *con, 3457 + struct ceph_msg *msg, int resid) 3427 3458 { 3428 3459 int sent; 3429 3460 3430 - WARN_ON(!resid || resid > front_len(con->out_msg)); 3431 - sent = front_len(con->out_msg) - resid; 3461 + WARN_ON(!resid || resid > front_len(msg)); 3462 + sent = front_len(msg) - resid; 3432 3463 dout("%s con %p sent %d resid %d\n", __func__, con, sent, resid); 3433 3464 3434 3465 if (sent) { 3435 3466 con->v2.out_epil.front_crc = 3436 - crc32c(-1, con->out_msg->front.iov_base, sent); 3467 + crc32c(-1, msg->front.iov_base, sent); 3437 3468 con->v2.out_epil.front_crc = 3438 3469 crc32c_zeros(con->v2.out_epil.front_crc, resid); 3439 3470 } else { ··· 3445 3474 out_zero_add(con, resid); 3446 3475 } 3447 3476 3448 - static void prepare_zero_middle(struct ceph_connection *con, int resid) 3477 + static void prepare_zero_middle(struct ceph_connection *con, 3478 + struct ceph_msg *msg, int resid) 3449 3479 { 3450 3480 int sent; 3451 3481 3452 - WARN_ON(!resid || resid > middle_len(con->out_msg)); 3453 - sent = middle_len(con->out_msg) - resid; 3482 + WARN_ON(!resid || resid > middle_len(msg)); 3483 + sent = middle_len(msg) - resid; 3454 3484 dout("%s con %p sent %d resid %d\n", __func__, con, sent, resid); 3455 3485 3456 3486 if (sent) { 3457 3487 con->v2.out_epil.middle_crc = 3458 - crc32c(-1, con->out_msg->middle->vec.iov_base, sent); 3488 + crc32c(-1, msg->middle->vec.iov_base, sent); 3459 3489 con->v2.out_epil.middle_crc = 3460 3490 crc32c_zeros(con->v2.out_epil.middle_crc, resid); 3461 3491 } else { ··· 3467 3495 out_zero_add(con, resid); 3468 3496 } 3469 3497 3470 - static void prepare_zero_data(struct ceph_connection *con) 3498 + static void prepare_zero_data(struct ceph_connection *con, 3499 + struct ceph_msg *msg) 3471 3500 { 3472 3501 dout("%s con %p\n", __func__, con); 3473 - con->v2.out_epil.data_crc = crc32c_zeros(-1, data_len(con->out_msg)); 3474 - out_zero_add(con, data_len(con->out_msg)); 3502 + con->v2.out_epil.data_crc = crc32c_zeros(-1, data_len(msg)); 3503 + out_zero_add(con, data_len(msg)); 3475 3504 } 3476 3505 3477 - static void revoke_at_queue_data(struct ceph_connection *con) 3506 + static void revoke_at_queue_data(struct ceph_connection *con, 3507 + struct ceph_msg *msg) 3478 3508 { 3479 3509 int boundary; 3480 3510 int resid; 3481 3511 3482 - WARN_ON(!data_len(con->out_msg)); 3512 + WARN_ON(!data_len(msg)); 3483 3513 WARN_ON(!iov_iter_is_kvec(&con->v2.out_iter)); 3484 3514 resid = iov_iter_count(&con->v2.out_iter); 3485 3515 3486 - boundary = front_len(con->out_msg) + middle_len(con->out_msg); 3516 + boundary = front_len(msg) + middle_len(msg); 3487 3517 if (resid > boundary) { 3488 3518 resid -= boundary; 3489 3519 WARN_ON(resid > MESSAGE_HEAD_PLAIN_LEN); 3490 3520 dout("%s con %p was sending head\n", __func__, con); 3491 - if (front_len(con->out_msg)) 3492 - prepare_zero_front(con, front_len(con->out_msg)); 3493 - if (middle_len(con->out_msg)) 3494 - prepare_zero_middle(con, middle_len(con->out_msg)); 3495 - prepare_zero_data(con); 3521 + if (front_len(msg)) 3522 + prepare_zero_front(con, msg, front_len(msg)); 3523 + if (middle_len(msg)) 3524 + prepare_zero_middle(con, msg, middle_len(msg)); 3525 + prepare_zero_data(con, msg); 3496 3526 WARN_ON(iov_iter_count(&con->v2.out_iter) != resid); 3497 3527 con->v2.out_state = OUT_S_QUEUE_ZEROS; 3498 3528 return; 3499 3529 } 3500 3530 3501 - boundary = middle_len(con->out_msg); 3531 + boundary = middle_len(msg); 3502 3532 if (resid > boundary) { 3503 3533 resid -= boundary; 3504 3534 dout("%s con %p was sending front\n", __func__, con); 3505 - prepare_zero_front(con, resid); 3506 - if (middle_len(con->out_msg)) 3507 - prepare_zero_middle(con, middle_len(con->out_msg)); 3508 - prepare_zero_data(con); 3509 - queue_zeros(con); 3535 + prepare_zero_front(con, msg, resid); 3536 + if (middle_len(msg)) 3537 + prepare_zero_middle(con, msg, middle_len(msg)); 3538 + prepare_zero_data(con, msg); 3539 + queue_zeros(con, msg); 3510 3540 return; 3511 3541 } 3512 3542 3513 3543 WARN_ON(!resid); 3514 3544 dout("%s con %p was sending middle\n", __func__, con); 3515 - prepare_zero_middle(con, resid); 3516 - prepare_zero_data(con); 3517 - queue_zeros(con); 3545 + prepare_zero_middle(con, msg, resid); 3546 + prepare_zero_data(con, msg); 3547 + queue_zeros(con, msg); 3518 3548 } 3519 3549 3520 - static void revoke_at_queue_data_cont(struct ceph_connection *con) 3550 + static void revoke_at_queue_data_cont(struct ceph_connection *con, 3551 + struct ceph_msg *msg) 3521 3552 { 3522 3553 int sent, resid; /* current piece of data */ 3523 3554 3524 - WARN_ON(!data_len(con->out_msg)); 3555 + WARN_ON(!data_len(msg)); 3525 3556 WARN_ON(!iov_iter_is_bvec(&con->v2.out_iter)); 3526 3557 resid = iov_iter_count(&con->v2.out_iter); 3527 3558 WARN_ON(!resid || resid > con->v2.out_bvec.bv_len); ··· 3543 3568 3544 3569 con->v2.out_iter.count -= resid; 3545 3570 out_zero_add(con, con->v2.out_cursor.total_resid); 3546 - queue_zeros(con); 3571 + queue_zeros(con, msg); 3547 3572 } 3548 3573 3549 - static void revoke_at_finish_message(struct ceph_connection *con) 3574 + static void revoke_at_finish_message(struct ceph_connection *con, 3575 + struct ceph_msg *msg) 3550 3576 { 3551 3577 int boundary; 3552 3578 int resid; ··· 3555 3579 WARN_ON(!iov_iter_is_kvec(&con->v2.out_iter)); 3556 3580 resid = iov_iter_count(&con->v2.out_iter); 3557 3581 3558 - if (!front_len(con->out_msg) && !middle_len(con->out_msg) && 3559 - !data_len(con->out_msg)) { 3582 + if (!front_len(msg) && !middle_len(msg) && 3583 + !data_len(msg)) { 3560 3584 WARN_ON(!resid || resid > MESSAGE_HEAD_PLAIN_LEN); 3561 3585 dout("%s con %p was sending head (empty message) - noop\n", 3562 3586 __func__, con); 3563 3587 return; 3564 3588 } 3565 3589 3566 - boundary = front_len(con->out_msg) + middle_len(con->out_msg) + 3590 + boundary = front_len(msg) + middle_len(msg) + 3567 3591 CEPH_EPILOGUE_PLAIN_LEN; 3568 3592 if (resid > boundary) { 3569 3593 resid -= boundary; 3570 3594 WARN_ON(resid > MESSAGE_HEAD_PLAIN_LEN); 3571 3595 dout("%s con %p was sending head\n", __func__, con); 3572 - if (front_len(con->out_msg)) 3573 - prepare_zero_front(con, front_len(con->out_msg)); 3574 - if (middle_len(con->out_msg)) 3575 - prepare_zero_middle(con, middle_len(con->out_msg)); 3596 + if (front_len(msg)) 3597 + prepare_zero_front(con, msg, front_len(msg)); 3598 + if (middle_len(msg)) 3599 + prepare_zero_middle(con, msg, middle_len(msg)); 3576 3600 con->v2.out_iter.count -= CEPH_EPILOGUE_PLAIN_LEN; 3577 3601 WARN_ON(iov_iter_count(&con->v2.out_iter) != resid); 3578 3602 con->v2.out_state = OUT_S_QUEUE_ZEROS; 3579 3603 return; 3580 3604 } 3581 3605 3582 - boundary = middle_len(con->out_msg) + CEPH_EPILOGUE_PLAIN_LEN; 3606 + boundary = middle_len(msg) + CEPH_EPILOGUE_PLAIN_LEN; 3583 3607 if (resid > boundary) { 3584 3608 resid -= boundary; 3585 3609 dout("%s con %p was sending front\n", __func__, con); 3586 - prepare_zero_front(con, resid); 3587 - if (middle_len(con->out_msg)) 3588 - prepare_zero_middle(con, middle_len(con->out_msg)); 3610 + prepare_zero_front(con, msg, resid); 3611 + if (middle_len(msg)) 3612 + prepare_zero_middle(con, msg, middle_len(msg)); 3589 3613 con->v2.out_iter.count -= CEPH_EPILOGUE_PLAIN_LEN; 3590 - queue_zeros(con); 3614 + queue_zeros(con, msg); 3591 3615 return; 3592 3616 } 3593 3617 ··· 3595 3619 if (resid > boundary) { 3596 3620 resid -= boundary; 3597 3621 dout("%s con %p was sending middle\n", __func__, con); 3598 - prepare_zero_middle(con, resid); 3622 + prepare_zero_middle(con, msg, resid); 3599 3623 con->v2.out_iter.count -= CEPH_EPILOGUE_PLAIN_LEN; 3600 - queue_zeros(con); 3624 + queue_zeros(con, msg); 3601 3625 return; 3602 3626 } 3603 3627 ··· 3605 3629 dout("%s con %p was sending epilogue - noop\n", __func__, con); 3606 3630 } 3607 3631 3608 - void ceph_con_v2_revoke(struct ceph_connection *con) 3632 + void ceph_con_v2_revoke(struct ceph_connection *con, struct ceph_msg *msg) 3609 3633 { 3610 3634 WARN_ON(con->v2.out_zero); 3611 3635 ··· 3618 3642 3619 3643 switch (con->v2.out_state) { 3620 3644 case OUT_S_QUEUE_DATA: 3621 - revoke_at_queue_data(con); 3645 + revoke_at_queue_data(con, msg); 3622 3646 break; 3623 3647 case OUT_S_QUEUE_DATA_CONT: 3624 - revoke_at_queue_data_cont(con); 3648 + revoke_at_queue_data_cont(con, msg); 3625 3649 break; 3626 3650 case OUT_S_FINISH_MESSAGE: 3627 - revoke_at_finish_message(con); 3651 + revoke_at_finish_message(con, msg); 3628 3652 break; 3629 3653 default: 3630 3654 WARN(1, "bad out_state %d", con->v2.out_state); ··· 3790 3814 memzero_explicit(&con->v2.in_gcm_nonce, CEPH_GCM_IV_LEN); 3791 3815 memzero_explicit(&con->v2.out_gcm_nonce, CEPH_GCM_IV_LEN); 3792 3816 3793 - if (con->v2.hmac_tfm) { 3794 - crypto_free_shash(con->v2.hmac_tfm); 3795 - con->v2.hmac_tfm = NULL; 3796 - } 3817 + memzero_explicit(&con->v2.hmac_key, sizeof(con->v2.hmac_key)); 3818 + con->v2.hmac_key_set = false; 3797 3819 if (con->v2.gcm_req) { 3798 3820 aead_request_free(con->v2.gcm_req); 3799 3821 con->v2.gcm_req = NULL;