Skip to content

Commit 45db3ab

Browse files
committed
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()
2 parents 065a057 + 691aae4 commit 45db3ab

File tree

6 files changed

+60
-51
lines changed

6 files changed

+60
-51
lines changed

fs/smb/server/oplock.c

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ static void opinfo_add(struct oplock_info *opinfo)
207207
{
208208
struct ksmbd_inode *ci = opinfo->o_fp->f_ci;
209209

210-
write_lock(&ci->m_lock);
210+
down_write(&ci->m_lock);
211211
list_add_rcu(&opinfo->op_entry, &ci->m_op_list);
212-
write_unlock(&ci->m_lock);
212+
up_write(&ci->m_lock);
213213
}
214214

215215
static void opinfo_del(struct oplock_info *opinfo)
@@ -221,9 +221,9 @@ static void opinfo_del(struct oplock_info *opinfo)
221221
lease_del_list(opinfo);
222222
write_unlock(&lease_list_lock);
223223
}
224-
write_lock(&ci->m_lock);
224+
down_write(&ci->m_lock);
225225
list_del_rcu(&opinfo->op_entry);
226-
write_unlock(&ci->m_lock);
226+
up_write(&ci->m_lock);
227227
}
228228

229229
static unsigned long opinfo_count(struct ksmbd_file *fp)
@@ -526,21 +526,18 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
526526
* Compare lease key and client_guid to know request from same owner
527527
* of same client
528528
*/
529-
read_lock(&ci->m_lock);
529+
down_read(&ci->m_lock);
530530
list_for_each_entry(opinfo, &ci->m_op_list, op_entry) {
531531
if (!opinfo->is_lease || !opinfo->conn)
532532
continue;
533-
read_unlock(&ci->m_lock);
534533
lease = opinfo->o_lease;
535534

536535
ret = compare_guid_key(opinfo, client_guid, lctx->lease_key);
537536
if (ret) {
538537
m_opinfo = opinfo;
539538
/* 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))
542540
continue;
543-
}
544541

545542
/* upgrading lease */
546543
if ((atomic_read(&ci->op_count) +
@@ -570,9 +567,8 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,
570567
lease_none_upgrade(opinfo, lctx->req_state);
571568
}
572569
}
573-
read_lock(&ci->m_lock);
574570
}
575-
read_unlock(&ci->m_lock);
571+
up_read(&ci->m_lock);
576572

577573
return m_opinfo;
578574
}
@@ -613,13 +609,23 @@ static int oplock_break_pending(struct oplock_info *opinfo, int req_op_level)
613609

614610
if (opinfo->op_state == OPLOCK_CLOSING)
615611
return -ENOENT;
616-
else if (!opinfo->is_lease && opinfo->level <= req_op_level)
617-
return 1;
612+
else if (opinfo->level <= req_op_level) {
613+
if (opinfo->is_lease &&
614+
opinfo->o_lease->state !=
615+
(SMB2_LEASE_HANDLE_CACHING_LE |
616+
SMB2_LEASE_READ_CACHING_LE))
617+
return 1;
618+
}
618619
}
619620

620-
if (!opinfo->is_lease && opinfo->level <= req_op_level) {
621-
wake_up_oplock_break(opinfo);
622-
return 1;
621+
if (opinfo->level <= req_op_level) {
622+
if (opinfo->is_lease &&
623+
opinfo->o_lease->state !=
624+
(SMB2_LEASE_HANDLE_CACHING_LE |
625+
SMB2_LEASE_READ_CACHING_LE)) {
626+
wake_up_oplock_break(opinfo);
627+
return 1;
628+
}
623629
}
624630
return 0;
625631
}
@@ -887,7 +893,6 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level)
887893
struct lease *lease = brk_opinfo->o_lease;
888894

889895
atomic_inc(&brk_opinfo->breaking_cnt);
890-
891896
err = oplock_break_pending(brk_opinfo, req_op_level);
892897
if (err)
893898
return err < 0 ? err : 0;
@@ -1105,7 +1110,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
11051110
if (!p_ci)
11061111
return;
11071112

1108-
read_lock(&p_ci->m_lock);
1113+
down_read(&p_ci->m_lock);
11091114
list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
11101115
if (opinfo->conn == NULL || !opinfo->is_lease)
11111116
continue;
@@ -1123,13 +1128,11 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
11231128
continue;
11241129
}
11251130

1126-
read_unlock(&p_ci->m_lock);
11271131
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
11281132
opinfo_conn_put(opinfo);
1129-
read_lock(&p_ci->m_lock);
11301133
}
11311134
}
1132-
read_unlock(&p_ci->m_lock);
1135+
up_read(&p_ci->m_lock);
11331136

11341137
ksmbd_inode_put(p_ci);
11351138
}
@@ -1150,7 +1153,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
11501153
if (!p_ci)
11511154
return;
11521155

1153-
read_lock(&p_ci->m_lock);
1156+
down_read(&p_ci->m_lock);
11541157
list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
11551158
if (opinfo->conn == NULL || !opinfo->is_lease)
11561159
continue;
@@ -1164,13 +1167,11 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)
11641167
atomic_dec(&opinfo->conn->r_count);
11651168
continue;
11661169
}
1167-
read_unlock(&p_ci->m_lock);
11681170
oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
11691171
opinfo_conn_put(opinfo);
1170-
read_lock(&p_ci->m_lock);
11711172
}
11721173
}
1173-
read_unlock(&p_ci->m_lock);
1174+
up_read(&p_ci->m_lock);
11741175

11751176
ksmbd_inode_put(p_ci);
11761177
}
@@ -1200,7 +1201,9 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid,
12001201

12011202
/* Only v2 leases handle the directory */
12021203
if (S_ISDIR(file_inode(fp->filp)->i_mode)) {
1203-
if (!lctx || lctx->version != 2)
1204+
if (!lctx || lctx->version != 2 ||
1205+
(lctx->flags != SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE &&
1206+
!lctx->epoch))
12041207
return 0;
12051208
}
12061209

@@ -1465,8 +1468,9 @@ void create_lease_buf(u8 *rbuf, struct lease *lease)
14651468
buf->lcontext.LeaseFlags = lease->flags;
14661469
buf->lcontext.Epoch = cpu_to_le16(lease->epoch);
14671470
buf->lcontext.LeaseState = lease->state;
1468-
memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
1469-
SMB2_LEASE_KEY_SIZE);
1471+
if (lease->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)
1472+
memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key,
1473+
SMB2_LEASE_KEY_SIZE);
14701474
buf->ccontext.DataOffset = cpu_to_le16(offsetof
14711475
(struct create_lease_v2, lcontext));
14721476
buf->ccontext.DataLength = cpu_to_le32(sizeof(struct lease_context_v2));
@@ -1525,8 +1529,9 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
15251529
lreq->flags = lc->lcontext.LeaseFlags;
15261530
lreq->epoch = lc->lcontext.Epoch;
15271531
lreq->duration = lc->lcontext.LeaseDuration;
1528-
memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
1529-
SMB2_LEASE_KEY_SIZE);
1532+
if (lreq->flags == SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE)
1533+
memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey,
1534+
SMB2_LEASE_KEY_SIZE);
15301535
lreq->version = 2;
15311536
} else {
15321537
struct create_lease *lc = (struct create_lease *)cc;

fs/smb/server/smb2pdu.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1926,7 +1926,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
19261926
struct ksmbd_session *sess = work->sess;
19271927
char *treename = NULL, *name = NULL;
19281928
struct ksmbd_tree_conn_status status;
1929-
struct ksmbd_share_config *share;
1929+
struct ksmbd_share_config *share = NULL;
19301930
int rc = -EINVAL;
19311931

19321932
WORK_BUFFERS(work, req, rsp);
@@ -1988,7 +1988,7 @@ int smb2_tree_connect(struct ksmbd_work *work)
19881988
write_unlock(&sess->tree_conns_lock);
19891989
rsp->StructureSize = cpu_to_le16(16);
19901990
out_err1:
1991-
if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE &&
1991+
if (server_conf.flags & KSMBD_GLOBAL_FLAG_DURABLE_HANDLE && share &&
19921992
test_share_config_flag(share,
19931993
KSMBD_SHARE_FLAG_CONTINUOUS_AVAILABILITY))
19941994
rsp->Capabilities = SMB2_SHARE_CAP_CONTINUOUS_AVAILABILITY;
@@ -3376,9 +3376,9 @@ int smb2_open(struct ksmbd_work *work)
33763376
* after daccess, saccess, attrib_only, and stream are
33773377
* initialized.
33783378
*/
3379-
write_lock(&fp->f_ci->m_lock);
3379+
down_write(&fp->f_ci->m_lock);
33803380
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);
33823382

33833383
/* Check delete pending among previous fp before oplock break */
33843384
if (ksmbd_inode_pending_delete(fp)) {

fs/smb/server/smb_common.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
646646
* Lookup fp in master fp list, and check desired access and
647647
* shared mode between previous open and current open.
648648
*/
649-
read_lock(&curr_fp->f_ci->m_lock);
649+
down_read(&curr_fp->f_ci->m_lock);
650650
list_for_each_entry(prev_fp, &curr_fp->f_ci->m_fp_list, node) {
651651
if (file_inode(filp) != file_inode(prev_fp->filp))
652652
continue;
@@ -722,7 +722,7 @@ int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)
722722
break;
723723
}
724724
}
725-
read_unlock(&curr_fp->f_ci->m_lock);
725+
up_read(&curr_fp->f_ci->m_lock);
726726

727727
return rc;
728728
}

fs/smb/server/transport_tcp.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,10 @@ static int create_socket(struct interface *iface)
448448
sin6.sin6_family = PF_INET6;
449449
sin6.sin6_addr = in6addr_any;
450450
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);
451455
}
452456

453457
ksmbd_tcp_nodelay(ksmbd_socket);

fs/smb/server/vfs_cache.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp)
165165
ci->m_fattr = 0;
166166
INIT_LIST_HEAD(&ci->m_fp_list);
167167
INIT_LIST_HEAD(&ci->m_op_list);
168-
rwlock_init(&ci->m_lock);
168+
init_rwsem(&ci->m_lock);
169169
ci->m_de = fp->filp->f_path.dentry;
170170
return 0;
171171
}
@@ -261,14 +261,14 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp)
261261
}
262262

263263
if (atomic_dec_and_test(&ci->m_count)) {
264-
write_lock(&ci->m_lock);
264+
down_write(&ci->m_lock);
265265
if (ci->m_flags & (S_DEL_ON_CLS | S_DEL_PENDING)) {
266266
ci->m_flags &= ~(S_DEL_ON_CLS | S_DEL_PENDING);
267-
write_unlock(&ci->m_lock);
267+
up_write(&ci->m_lock);
268268
ksmbd_vfs_unlink(filp);
269-
write_lock(&ci->m_lock);
269+
down_write(&ci->m_lock);
270270
}
271-
write_unlock(&ci->m_lock);
271+
up_write(&ci->m_lock);
272272

273273
ksmbd_inode_free(ci);
274274
}
@@ -289,9 +289,9 @@ static void __ksmbd_remove_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fp
289289
if (!has_file_id(fp->volatile_id))
290290
return;
291291

292-
write_lock(&fp->f_ci->m_lock);
292+
down_write(&fp->f_ci->m_lock);
293293
list_del_init(&fp->node);
294-
write_unlock(&fp->f_ci->m_lock);
294+
up_write(&fp->f_ci->m_lock);
295295

296296
write_lock(&ft->lock);
297297
idr_remove(ft->idr, fp->volatile_id);
@@ -523,17 +523,17 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry)
523523
if (!ci)
524524
return NULL;
525525

526-
read_lock(&ci->m_lock);
526+
down_read(&ci->m_lock);
527527
list_for_each_entry(lfp, &ci->m_fp_list, node) {
528528
if (inode == file_inode(lfp->filp)) {
529529
atomic_dec(&ci->m_count);
530530
lfp = ksmbd_fp_get(lfp);
531-
read_unlock(&ci->m_lock);
531+
up_read(&ci->m_lock);
532532
return lfp;
533533
}
534534
}
535535
atomic_dec(&ci->m_count);
536-
read_unlock(&ci->m_lock);
536+
up_read(&ci->m_lock);
537537
return NULL;
538538
}
539539

@@ -705,13 +705,13 @@ static bool session_fd_check(struct ksmbd_tree_connect *tcon,
705705

706706
conn = fp->conn;
707707
ci = fp->f_ci;
708-
write_lock(&ci->m_lock);
708+
down_write(&ci->m_lock);
709709
list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
710710
if (op->conn != conn)
711711
continue;
712712
op->conn = NULL;
713713
}
714-
write_unlock(&ci->m_lock);
714+
up_write(&ci->m_lock);
715715

716716
fp->conn = NULL;
717717
fp->tcon = NULL;
@@ -801,13 +801,13 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
801801
fp->tcon = work->tcon;
802802

803803
ci = fp->f_ci;
804-
write_lock(&ci->m_lock);
804+
down_write(&ci->m_lock);
805805
list_for_each_entry_rcu(op, &ci->m_op_list, op_entry) {
806806
if (op->conn)
807807
continue;
808808
op->conn = fp->conn;
809809
}
810-
write_unlock(&ci->m_lock);
810+
up_write(&ci->m_lock);
811811

812812
__open_id(&work->sess->file_table, fp, OPEN_ID_TYPE_VOLATILE_ID);
813813
if (!has_file_id(fp->volatile_id)) {

fs/smb/server/vfs_cache.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ struct stream {
4747
};
4848

4949
struct ksmbd_inode {
50-
rwlock_t m_lock;
50+
struct rw_semaphore m_lock;
5151
atomic_t m_count;
5252
atomic_t op_count;
5353
/* opinfo count for streams */

0 commit comments

Comments
 (0)