ksmbd: break RH leases before delete-on-close

The delete paths only marked the opened file delete pending or
delete-on-close.  When another client still held a read/handle lease, no
lease break was sent before the delete state changed.

smb2.lease.unlink uses a create request with FILE_DELETE_ON_CLOSE and
expects the second client's unlink to break the first client's RH lease to
R with ACK_REQUIRED set.  SetInfo(FileDispositionInformation) has the same
lease-breaking requirement.

Break level-II/read-handle leases before setting delete pending or
delete-on-close so clients are notified before the file is removed.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
Namjae Jeon 2026-06-18 21:33:07 +09:00 committed by Steve French
parent dc2264a9ef
commit 1f1083c36f

View File

@ -3653,8 +3653,10 @@ int smb2_open(struct ksmbd_work *work)
goto err_out1;
}
if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE)
if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) {
smb_break_all_levII_oplock(work, fp, 0);
ksmbd_fd_set_delete_on_close(fp, file_info);
}
if (need_truncate) {
rc = smb2_create_truncate(&fp->filp->f_path);
@ -6584,7 +6586,8 @@ static int set_rename_info(struct ksmbd_work *work, struct ksmbd_file *fp,
return smb2_rename(work, fp, rename_info, work->conn->local_nls);
}
static int set_file_disposition_info(struct ksmbd_file *fp,
static int set_file_disposition_info(struct ksmbd_work *work,
struct ksmbd_file *fp,
struct smb2_file_disposition_info *file_info)
{
struct inode *inode;
@ -6599,6 +6602,7 @@ static int set_file_disposition_info(struct ksmbd_file *fp,
if (S_ISDIR(inode->i_mode) &&
ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY)
return -EBUSY;
smb_break_all_levII_oplock(work, fp, 0);
ksmbd_set_inode_pending_delete(fp);
} else {
ksmbd_clear_inode_pending_delete(fp);
@ -6725,7 +6729,7 @@ static int smb2_set_info_file(struct ksmbd_work *work, struct ksmbd_file *fp,
if (buf_len < sizeof(struct smb2_file_disposition_info))
return -EMSGSIZE;
return set_file_disposition_info(fp,
return set_file_disposition_info(work, fp,
(struct smb2_file_disposition_info *)buffer);
}
case FILE_FULL_EA_INFORMATION: