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

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'ceph-for-6.8-rc4' of https://github.com/ceph/ceph-client

Pull ceph fixes from Ilya Dryomov:
"Some fscrypt-related fixups (sparse reads are used only for encrypted
files) and two cap handling fixes from Xiubo and Rishabh"

* tag 'ceph-for-6.8-rc4' of https://github.com/ceph/ceph-client:
ceph: always check dir caps asynchronously
ceph: prevent use-after-free in encode_cap_msg()
ceph: always set initial i_blkbits to CEPH_FSCRYPT_BLOCK_SHIFT
libceph: just wait for more data to be available on the socket
libceph: rename read_sparse_msg_*() to read_partial_sparse_msg_*()
libceph: fail sparse-read if the data length doesn't match

+49 -44
+2 -7
fs/ceph/caps.c
··· 1452 1452 if (flushing & CEPH_CAP_XATTR_EXCL) { 1453 1453 arg->old_xattr_buf = __ceph_build_xattrs_blob(ci); 1454 1454 arg->xattr_version = ci->i_xattrs.version; 1455 - arg->xattr_buf = ci->i_xattrs.blob; 1455 + arg->xattr_buf = ceph_buffer_get(ci->i_xattrs.blob); 1456 1456 } else { 1457 1457 arg->xattr_buf = NULL; 1458 1458 arg->old_xattr_buf = NULL; ··· 1553 1553 encode_cap_msg(msg, arg); 1554 1554 ceph_con_send(&arg->session->s_con, msg); 1555 1555 ceph_buffer_put(arg->old_xattr_buf); 1556 + ceph_buffer_put(arg->xattr_buf); 1556 1557 if (arg->wake) 1557 1558 wake_up_all(&ci->i_cap_wq); 1558 1559 } ··· 3216 3215 3217 3216 enum put_cap_refs_mode { 3218 3217 PUT_CAP_REFS_SYNC = 0, 3219 - PUT_CAP_REFS_NO_CHECK, 3220 3218 PUT_CAP_REFS_ASYNC, 3221 3219 }; 3222 3220 ··· 3329 3329 void ceph_put_cap_refs_async(struct ceph_inode_info *ci, int had) 3330 3330 { 3331 3331 __ceph_put_cap_refs(ci, had, PUT_CAP_REFS_ASYNC); 3332 - } 3333 - 3334 - void ceph_put_cap_refs_no_check_caps(struct ceph_inode_info *ci, int had) 3335 - { 3336 - __ceph_put_cap_refs(ci, had, PUT_CAP_REFS_NO_CHECK); 3337 3332 } 3338 3333 3339 3334 /*
+2
fs/ceph/inode.c
··· 78 78 if (!inode) 79 79 return ERR_PTR(-ENOMEM); 80 80 81 + inode->i_blkbits = CEPH_FSCRYPT_BLOCK_SHIFT; 82 + 81 83 if (!S_ISLNK(*mode)) { 82 84 err = ceph_pre_init_acls(dir, mode, as_ctx); 83 85 if (err < 0)
+4 -5
fs/ceph/mds_client.c
··· 1089 1089 struct ceph_mds_request *req = container_of(kref, 1090 1090 struct ceph_mds_request, 1091 1091 r_kref); 1092 - ceph_mdsc_release_dir_caps_no_check(req); 1092 + ceph_mdsc_release_dir_caps_async(req); 1093 1093 destroy_reply_info(&req->r_reply_info); 1094 1094 if (req->r_request) 1095 1095 ceph_msg_put(req->r_request); ··· 4261 4261 } 4262 4262 } 4263 4263 4264 - void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req) 4264 + void ceph_mdsc_release_dir_caps_async(struct ceph_mds_request *req) 4265 4265 { 4266 4266 struct ceph_client *cl = req->r_mdsc->fsc->client; 4267 4267 int dcaps; ··· 4269 4269 dcaps = xchg(&req->r_dir_caps, 0); 4270 4270 if (dcaps) { 4271 4271 doutc(cl, "releasing r_dir_caps=%s\n", ceph_cap_string(dcaps)); 4272 - ceph_put_cap_refs_no_check_caps(ceph_inode(req->r_parent), 4273 - dcaps); 4272 + ceph_put_cap_refs_async(ceph_inode(req->r_parent), dcaps); 4274 4273 } 4275 4274 } 4276 4275 ··· 4305 4306 if (req->r_session->s_mds != session->s_mds) 4306 4307 continue; 4307 4308 4308 - ceph_mdsc_release_dir_caps_no_check(req); 4309 + ceph_mdsc_release_dir_caps_async(req); 4309 4310 4310 4311 __send_request(session, req, true); 4311 4312 }
+1 -1
fs/ceph/mds_client.h
··· 552 552 struct inode *dir, 553 553 struct ceph_mds_request *req); 554 554 extern void ceph_mdsc_release_dir_caps(struct ceph_mds_request *req); 555 - extern void ceph_mdsc_release_dir_caps_no_check(struct ceph_mds_request *req); 555 + extern void ceph_mdsc_release_dir_caps_async(struct ceph_mds_request *req); 556 556 static inline void ceph_mdsc_get_request(struct ceph_mds_request *req) 557 557 { 558 558 kref_get(&req->r_kref);
-2
fs/ceph/super.h
··· 1255 1255 extern void ceph_get_cap_refs(struct ceph_inode_info *ci, int caps); 1256 1256 extern void ceph_put_cap_refs(struct ceph_inode_info *ci, int had); 1257 1257 extern void ceph_put_cap_refs_async(struct ceph_inode_info *ci, int had); 1258 - extern void ceph_put_cap_refs_no_check_caps(struct ceph_inode_info *ci, 1259 - int had); 1260 1258 extern void ceph_put_wrbuffer_cap_refs(struct ceph_inode_info *ci, int nr, 1261 1259 struct ceph_snap_context *snapc); 1262 1260 extern void __ceph_remove_capsnap(struct inode *inode,
+1 -1
include/linux/ceph/messenger.h
··· 283 283 struct kref kref; 284 284 bool more_to_follow; 285 285 bool needs_out_seq; 286 - bool sparse_read; 286 + u64 sparse_read_total; 287 287 int front_alloc_len; 288 288 289 289 struct ceph_msgpool *pool;
+2 -1
include/linux/ceph/osd_client.h
··· 45 45 CEPH_SPARSE_READ_HDR = 0, 46 46 CEPH_SPARSE_READ_EXTENTS, 47 47 CEPH_SPARSE_READ_DATA_LEN, 48 + CEPH_SPARSE_READ_DATA_PRE, 48 49 CEPH_SPARSE_READ_DATA, 49 50 }; 50 51 ··· 65 64 u64 sr_req_len; /* orig request length */ 66 65 u64 sr_pos; /* current pos in buffer */ 67 66 int sr_index; /* current extent index */ 68 - __le32 sr_datalen; /* length of actual data */ 67 + u32 sr_datalen; /* length of actual data */ 69 68 u32 sr_count; /* extent count in reply */ 70 69 int sr_ext_len; /* length of extent array */ 71 70 struct ceph_sparse_extent *sr_extent; /* extent array */
+17 -16
net/ceph/messenger_v1.c
··· 160 160 static void prepare_message_data(struct ceph_msg *msg, u32 data_len) 161 161 { 162 162 /* Initialize data cursor if it's not a sparse read */ 163 - if (!msg->sparse_read) 164 - ceph_msg_data_cursor_init(&msg->cursor, msg, data_len); 163 + u64 len = msg->sparse_read_total ? : data_len; 164 + 165 + ceph_msg_data_cursor_init(&msg->cursor, msg, len); 165 166 } 166 167 167 168 /* ··· 992 991 return read_partial_message_chunk(con, section, sec_len, crc); 993 992 } 994 993 995 - static int read_sparse_msg_extent(struct ceph_connection *con, u32 *crc) 994 + static int read_partial_sparse_msg_extent(struct ceph_connection *con, u32 *crc) 996 995 { 997 996 struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor; 998 997 bool do_bounce = ceph_test_opt(from_msgr(con->msgr), RXBOUNCE); ··· 1027 1026 return 1; 1028 1027 } 1029 1028 1030 - static int read_sparse_msg_data(struct ceph_connection *con) 1029 + static int read_partial_sparse_msg_data(struct ceph_connection *con) 1031 1030 { 1032 1031 struct ceph_msg_data_cursor *cursor = &con->in_msg->cursor; 1033 1032 bool do_datacrc = !ceph_test_opt(from_msgr(con->msgr), NOCRC); ··· 1037 1036 if (do_datacrc) 1038 1037 crc = con->in_data_crc; 1039 1038 1040 - do { 1039 + while (cursor->total_resid) { 1041 1040 if (con->v1.in_sr_kvec.iov_base) 1042 1041 ret = read_partial_message_chunk(con, 1043 1042 &con->v1.in_sr_kvec, 1044 1043 con->v1.in_sr_len, 1045 1044 &crc); 1046 1045 else if (cursor->sr_resid > 0) 1047 - ret = read_sparse_msg_extent(con, &crc); 1048 - 1049 - if (ret <= 0) { 1050 - if (do_datacrc) 1051 - con->in_data_crc = crc; 1052 - return ret; 1053 - } 1046 + ret = read_partial_sparse_msg_extent(con, &crc); 1047 + if (ret <= 0) 1048 + break; 1054 1049 1055 1050 memset(&con->v1.in_sr_kvec, 0, sizeof(con->v1.in_sr_kvec)); 1056 1051 ret = con->ops->sparse_read(con, cursor, 1057 1052 (char **)&con->v1.in_sr_kvec.iov_base); 1053 + if (ret <= 0) { 1054 + ret = ret ? ret : 1; /* must return > 0 to indicate success */ 1055 + break; 1056 + } 1058 1057 con->v1.in_sr_len = ret; 1059 - } while (ret > 0); 1058 + } 1060 1059 1061 1060 if (do_datacrc) 1062 1061 con->in_data_crc = crc; 1063 1062 1064 - return ret < 0 ? ret : 1; /* must return > 0 to indicate success */ 1063 + return ret; 1065 1064 } 1066 1065 1067 1066 static int read_partial_msg_data(struct ceph_connection *con) ··· 1254 1253 if (!m->num_data_items) 1255 1254 return -EIO; 1256 1255 1257 - if (m->sparse_read) 1258 - ret = read_sparse_msg_data(con); 1256 + if (m->sparse_read_total) 1257 + ret = read_partial_sparse_msg_data(con); 1259 1258 else if (ceph_test_opt(from_msgr(con->msgr), RXBOUNCE)) 1260 1259 ret = read_partial_msg_data_bounce(con); 1261 1260 else
+2 -2
net/ceph/messenger_v2.c
··· 1128 1128 struct sg_table enc_sgt = {}; 1129 1129 struct sg_table sgt = {}; 1130 1130 struct page **pages = NULL; 1131 - bool sparse = con->in_msg->sparse_read; 1131 + bool sparse = !!con->in_msg->sparse_read_total; 1132 1132 int dpos = 0; 1133 1133 int tail_len; 1134 1134 int ret; ··· 2060 2060 } 2061 2061 2062 2062 if (data_len(msg)) { 2063 - if (msg->sparse_read) 2063 + if (msg->sparse_read_total) 2064 2064 con->v2.in_state = IN_S_PREPARE_SPARSE_DATA; 2065 2065 else 2066 2066 con->v2.in_state = IN_S_PREPARE_READ_DATA;
+18 -9
net/ceph/osd_client.c
··· 5510 5510 } 5511 5511 5512 5512 m = ceph_msg_get(req->r_reply); 5513 - m->sparse_read = (bool)srlen; 5513 + m->sparse_read_total = srlen; 5514 5514 5515 5515 dout("get_reply tid %lld %p\n", tid, m); 5516 5516 ··· 5777 5777 } 5778 5778 5779 5779 if (o->o_sparse_op_idx < 0) { 5780 - u64 srlen = sparse_data_requested(req); 5781 - 5782 - dout("%s: [%d] starting new sparse read req. srlen=0x%llx\n", 5783 - __func__, o->o_osd, srlen); 5784 - ceph_msg_data_cursor_init(cursor, con->in_msg, srlen); 5780 + dout("%s: [%d] starting new sparse read req\n", 5781 + __func__, o->o_osd); 5785 5782 } else { 5786 5783 u64 end; 5787 5784 ··· 5854 5857 struct ceph_osd *o = con->private; 5855 5858 struct ceph_sparse_read *sr = &o->o_sparse_read; 5856 5859 u32 count = sr->sr_count; 5857 - u64 eoff, elen; 5858 - int ret; 5860 + u64 eoff, elen, len = 0; 5861 + int i, ret; 5859 5862 5860 5863 switch (sr->sr_state) { 5861 5864 case CEPH_SPARSE_READ_HDR: ··· 5900 5903 convert_extent_map(sr); 5901 5904 ret = sizeof(sr->sr_datalen); 5902 5905 *pbuf = (char *)&sr->sr_datalen; 5903 - sr->sr_state = CEPH_SPARSE_READ_DATA; 5906 + sr->sr_state = CEPH_SPARSE_READ_DATA_PRE; 5904 5907 break; 5908 + case CEPH_SPARSE_READ_DATA_PRE: 5909 + /* Convert sr_datalen to host-endian */ 5910 + sr->sr_datalen = le32_to_cpu((__force __le32)sr->sr_datalen); 5911 + for (i = 0; i < count; i++) 5912 + len += sr->sr_extent[i].len; 5913 + if (sr->sr_datalen != len) { 5914 + pr_warn_ratelimited("data len %u != extent len %llu\n", 5915 + sr->sr_datalen, len); 5916 + return -EREMOTEIO; 5917 + } 5918 + sr->sr_state = CEPH_SPARSE_READ_DATA; 5919 + fallthrough; 5905 5920 case CEPH_SPARSE_READ_DATA: 5906 5921 if (sr->sr_index >= count) { 5907 5922 sr->sr_state = CEPH_SPARSE_READ_HDR;