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 '6.9-rc7-ksmbd-fixes' of git://git.samba.org/ksmbd

Pull smb server fixes from Steve French:
"Five ksmbd server fixes, all also for stable

- Three fixes related to SMB3 leases (fixes two xfstests, and a
locking issue)

- Unitialized variable fix

- Socket creation fix when bindv6only is set"

* tag '6.9-rc7-ksmbd-fixes' of git://git.samba.org/ksmbd:
ksmbd: do not grant v2 lease if parent lease key and epoch are not set
ksmbd: use rwsem instead of rwlock for lease break
ksmbd: avoid to send duplicate lease break notifications
ksmbd: off ipv6only for both ipv4/ipv6 binding
ksmbd: fix uninitialized symbol 'share' in smb2_tree_connect()

+60 -51
+35 -30
fs/smb/server/oplock.c
··· 207 207 { 208 208 struct ksmbd_inode *ci = opinfo->o_fp->f_ci; 209 209 210 - write_lock(&ci->m_lock); 210 + down_write(&ci->m_lock); 211 211 list_add_rcu(&opinfo->op_entry, &ci->m_op_list); 212 - write_unlock(&ci->m_lock); 212 + up_write(&ci->m_lock); 213 213 } 214 214 215 215 static void opinfo_del(struct oplock_info *opinfo) ··· 221 221 lease_del_list(opinfo); 222 222 write_unlock(&lease_list_lock); 223 223 } 224 - write_lock(&ci->m_lock); 224 + down_write(&ci->m_lock); 225 225 list_del_rcu(&opinfo->op_entry); 226 - write_unlock(&ci->m_lock); 226 + up_write(&ci->m_lock); 227 227 } 228 228 229 229 static unsigned long opinfo_count(struct ksmbd_file *fp) ··· 526 526 * Compare lease key and client_guid to know request from same owner 527 527 * of same client 528 528 */ 529 - read_lock(&ci->m_lock); 529 + down_read(&ci->m_lock); 530 530 list_for_each_entry(opinfo, &ci->m_op_list, op_entry) { 531 531 if (!opinfo->is_lease || !opinfo->conn) 532 532 continue; 533 - read_unlock(&ci->m_lock); 534 533 lease = opinfo->o_lease; 535 534 536 535 ret = compare_guid_key(opinfo, client_guid, lctx->lease_key); 537 536 if (ret) { 538 537 m_opinfo = opinfo; 539 538 /* skip upgrading lease about breaking lease */ 540 - if (atomic_read(&opinfo->breaking_cnt)) { 541 - read_lock(&ci->m_lock); 539 + if (atomic_read(&opinfo->breaking_cnt)) 542 540 continue; 543 - } 544 541 545 542 /* upgrading lease */ 546 543 if ((atomic_read(&ci->op_count) + ··· 567 570 lease_none_upgrade(opinfo, lctx->req_state); 568 571 } 569 572 } 570 - read_lock(&ci->m_lock); 571 573 } 572 - read_unlock(&ci->m_lock); 574 + up_read(&ci->m_lock); 573 575 574 576 return m_opinfo; 575 577 } ··· 609 613 610 614 if (opinfo->op_state == OPLOCK_CLOSING) 611 615 return -ENOENT; 612 - else if (!opinfo->is_lease && opinfo->level <= req_op_level) 613 - return 1; 616 + else if (opinfo->level <= req_op_level) { 617 + if (opinfo->is_lease && 618 + opinfo->o_lease->state != 619 + (SMB2_LEASE_HANDLE_CACHING_LE | 620 + SMB2_LEASE_READ_CACHING_LE)) 621 + return 1; 622 + } 614 623 } 615 624 616 - if (!opinfo->is_lease && opinfo->level <= req_op_level) { 617 - wake_up_oplock_break(opinfo); 618 - return 1; 625 + if (opinfo->level <= req_op_level) { 626 + if (opinfo->is_lease && 627 + opinfo->o_lease->state != 628 + (SMB2_LEASE_HANDLE_CACHING_LE | 629 + SMB2_LEASE_READ_CACHING_LE)) { 630 + wake_up_oplock_break(opinfo); 631 + return 1; 632 + } 619 633 } 620 634 return 0; 621 635 } ··· 893 887 struct lease *lease = brk_opinfo->o_lease; 894 888 895 889 atomic_inc(&brk_opinfo->breaking_cnt); 896 - 897 890 err = oplock_break_pending(brk_opinfo, req_op_level); 898 891 if (err) 899 892 return err < 0 ? err : 0; ··· 1110 1105 if (!p_ci) 1111 1106 return; 1112 1107 1113 - read_lock(&p_ci->m_lock); 1108 + down_read(&p_ci->m_lock); 1114 1109 list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) { 1115 1110 if (opinfo->conn == NULL || !opinfo->is_lease) 1116 1111 continue; ··· 1128 1123 continue; 1129 1124 } 1130 1125 1131 - read_unlock(&p_ci->m_lock); 1132 1126 oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE); 1133 1127 opinfo_conn_put(opinfo); 1134 - read_lock(&p_ci->m_lock); 1135 1128 } 1136 1129 } 1137 - read_unlock(&p_ci->m_lock); 1130 + up_read(&p_ci->m_lock); 1138 1131 1139 1132 ksmbd_inode_put(p_ci); 1140 1133 } ··· 1153 1150 if (!p_ci) 1154 1151 return; 1155 1152 1156 - read_lock(&p_ci->m_lock); 1153 + down_read(&p_ci->m_lock); 1157 1154 list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) { 1158 1155 if (opinfo->conn == NULL || !opinfo->is_lease) 1159 1156 continue; ··· 1167 1164 atomic_dec(&opinfo->conn->r_count); 1168 1165 continue; 1169 1166 } 1170 - read_unlock(&p_ci->m_lock); 1171 1167 oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE); 1172 1168 opinfo_conn_put(opinfo); 1173 - read_lock(&p_ci->m_lock); 1174 1169 } 1175 1170 } 1176 - read_unlock(&p_ci->m_lock); 1171 + up_read(&p_ci->m_lock); 1177 1172 1178 1173 ksmbd_inode_put(p_ci); 1179 1174 } ··· 1201 1200 1202 1201 /* Only v2 leases handle the directory */ 1203 1202 if (S_ISDIR(file_inode(fp->filp)->i_mode)) { 1204 - if (!lctx || lctx->version != 2) 1203 + if (!lctx || lctx->version != 2 || 1204 + (lctx->flags != SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE && 1205 + !lctx->epoch)) 1205 1206 return 0; 1206 1207 } 1207 1208 ··· 1468 1465 buf->lcontext.LeaseFlags = lease->flags; 1469 1466 buf->lcontext.Epoch = cpu_to_le16(lease->epoch); 1470 1467 buf->lcontext.LeaseState = lease->state; 1471 - memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key, 1472 - SMB2_LEASE_KEY_SIZE); 1468 + if (lease->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) 1469 + memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key, 1470 + SMB2_LEASE_KEY_SIZE); 1473 1471 buf->ccontext.DataOffset = cpu_to_le16(offsetof 1474 1472 (struct create_lease_v2, lcontext)); 1475 1473 buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2)); ··· 1529 1525 lreq->flags = lc->lcontext.LeaseFlags; 1530 1526 lreq->epoch = lc->lcontext.Epoch; 1531 1527 lreq->duration = lc->lcontext.LeaseDuration; 1532 - memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey, 1533 - SMB2_LEASE_KEY_SIZE); 1528 + if (lreq->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) 1529 + memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey, 1530 + SMB2_LEASE_KEY_SIZE); 1534 1531 lreq->version = 2; 1535 1532 } else { 1536 1533 struct create_lease *lc = (struct create_lease *)cc;
+4 -4
fs/smb/server/smb2pdu.c
··· 1926 1926 struct ksmbd_session *sess = work->sess; 1927 1927 char *treename = NULL, *name = NULL; 1928 1928 struct ksmbd_tree_conn_status status; 1929 - struct ksmbd_share_config *share; 1929 + struct ksmbd_share_config *share = NULL; 1930 1930 int rc = -EINVAL; 1931 1931 1932 1932 WORK_BUFFERS(work, req, rsp); ··· 1988 1988 write_unlock(&sess->tree_conns_lock); 1989 1989 rsp->StructureSize = cpu_to_le16(16); 1990 1990 out_err1: 1991 - if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE && 1991 + if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE && share && 1992 1992 test_share_config_flag(share, 1993 1993 KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY)) 1994 1994 rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY; ··· 3376 3376 * after daccess, saccess, attrib_only, and stream are 3377 3377 * initialized. 3378 3378 */ 3379 - write_lock(&fp->f_ci->m_lock); 3379 + down_write(&fp->f_ci->m_lock); 3380 3380 list_add(&fp->node, &fp->f_ci->m_fp_list); 3381 - write_unlock(&fp->f_ci->m_lock); 3381 + up_write(&fp->f_ci->m_lock); 3382 3382 3383 3383 /* Check delete pending among previous fp before oplock break */ 3384 3384 if (ksmbd_inode_pending_delete(fp)) {
+2 -2
fs/smb/server/smb_common.c
··· 646 646 * Lookup fp in master fp list, and check desired access and 647 647 * shared mode between previous open and current open. 648 648 */ 649 - read_lock(&curr_fp->f_ci->m_lock); 649 + down_read(&curr_fp->f_ci->m_lock); 650 650 list_for_each_entry(prev_fp, &curr_fp->f_ci->m_fp_list, node) { 651 651 if (file_inode(filp) != file_inode(prev_fp->filp)) 652 652 continue; ··· 722 722 break; 723 723 } 724 724 } 725 - read_unlock(&curr_fp->f_ci->m_lock); 725 + up_read(&curr_fp->f_ci->m_lock); 726 726 727 727 return rc; 728 728 }
+4
fs/smb/server/transport_tcp.c
··· 448 448 sin6.sin6_family = PF_INET6; 449 449 sin6.sin6_addr = in6addr_any; 450 450 sin6.sin6_port = htons(server_conf.tcp_port); 451 + 452 + lock_sock(ksmbd_socket->sk); 453 + ksmbd_socket->sk->sk_ipv6only = false; 454 + release_sock(ksmbd_socket->sk); 451 455 } 452 456 453 457 ksmbd_tcp_nodelay(ksmbd_socket);
+14 -14
fs/smb/server/vfs_cache.c
··· 165 165 ci->m_fattr = 0; 166 166 INIT_LIST_HEAD(&ci->m_fp_list); 167 167 INIT_LIST_HEAD(&ci->m_op_list); 168 - rwlock_init(&ci->m_lock); 168 + init_rwsem(&ci->m_lock); 169 169 ci->m_de = fp->filp->f_path.dentry; 170 170 return 0; 171 171 } ··· 261 261 } 262 262 263 263 if (atomic_dec_and_test(&ci->m_count)) { 264 - write_lock(&ci->m_lock); 264 + down_write(&ci->m_lock); 265 265 if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) { 266 266 ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING); 267 - write_unlock(&ci->m_lock); 267 + up_write(&ci->m_lock); 268 268 ksmbd_vfs_unlink(filp); 269 - write_lock(&ci->m_lock); 269 + down_write(&ci->m_lock); 270 270 } 271 - write_unlock(&ci->m_lock); 271 + up_write(&ci->m_lock); 272 272 273 273 ksmbd_inode_free(ci); 274 274 } ··· 289 289 if (!has_file_id(fp->volatile_id)) 290 290 return; 291 291 292 - write_lock(&fp->f_ci->m_lock); 292 + down_write(&fp->f_ci->m_lock); 293 293 list_del_init(&fp->node); 294 - write_unlock(&fp->f_ci->m_lock); 294 + up_write(&fp->f_ci->m_lock); 295 295 296 296 write_lock(&ft->lock); 297 297 idr_remove(ft->idr, fp->volatile_id); ··· 523 523 if (!ci) 524 524 return NULL; 525 525 526 - read_lock(&ci->m_lock); 526 + down_read(&ci->m_lock); 527 527 list_for_each_entry(lfp, &ci->m_fp_list, node) { 528 528 if (inode == file_inode(lfp->filp)) { 529 529 atomic_dec(&ci->m_count); 530 530 lfp = ksmbd_fp_get(lfp); 531 - read_unlock(&ci->m_lock); 531 + up_read(&ci->m_lock); 532 532 return lfp; 533 533 } 534 534 } 535 535 atomic_dec(&ci->m_count); 536 - read_unlock(&ci->m_lock); 536 + up_read(&ci->m_lock); 537 537 return NULL; 538 538 } 539 539 ··· 705 705 706 706 conn = fp->conn; 707 707 ci = fp->f_ci; 708 - write_lock(&ci->m_lock); 708 + down_write(&ci->m_lock); 709 709 list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) { 710 710 if (op->conn != conn) 711 711 continue; 712 712 op->conn = NULL; 713 713 } 714 - write_unlock(&ci->m_lock); 714 + up_write(&ci->m_lock); 715 715 716 716 fp->conn = NULL; 717 717 fp->tcon = NULL; ··· 801 801 fp->tcon = work->tcon; 802 802 803 803 ci = fp->f_ci; 804 - write_lock(&ci->m_lock); 804 + down_write(&ci->m_lock); 805 805 list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) { 806 806 if (op->conn) 807 807 continue; 808 808 op->conn = fp->conn; 809 809 } 810 - write_unlock(&ci->m_lock); 810 + up_write(&ci->m_lock); 811 811 812 812 __open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID); 813 813 if (!has_file_id(fp->volatile_id)) {
+1 -1
fs/smb/server/vfs_cache.h
··· 47 47 }; 48 48 49 49 struct ksmbd_inode { 50 - rwlock_t m_lock; 50 + struct rw_semaphore m_lock; 51 51 atomic_t m_count; 52 52 atomic_t op_count; 53 53 /* opinfo count for streams */