*/
static void __smb_break_all_levII_oplock(struct ksmbd_work *work,
struct ksmbd_file *fp, int is_trunc,
- bool send_interim)
+ bool send_interim, bool send_oplock_break)
{
struct oplock_info *op, *brk_op;
struct ksmbd_inode *ci;
SMB2_LEASE_KEY_SIZE))
goto next;
brk_op->open_trunc = is_trunc;
- oplock_break(brk_op,
- brk_op->is_lease && !is_trunc ?
- SMB2_OPLOCK_LEVEL_II : SMB2_OPLOCK_LEVEL_NONE,
- send_interim && !sent_interim ? work : NULL);
+ if (!brk_op->is_lease && !send_oplock_break) {
+ brk_op->level = SMB2_OPLOCK_LEVEL_NONE;
+ brk_op->op_state = OPLOCK_STATE_NONE;
+ } else {
+ oplock_break(brk_op,
+ brk_op->is_lease && !is_trunc ?
+ SMB2_OPLOCK_LEVEL_II : SMB2_OPLOCK_LEVEL_NONE,
+ send_interim && !sent_interim ? work : NULL);
+ }
sent_interim = true;
next:
opinfo_put(brk_op);
void smb_break_all_levII_oplock(struct ksmbd_work *work, struct ksmbd_file *fp,
int is_trunc)
{
- __smb_break_all_levII_oplock(work, fp, is_trunc, true);
+ __smb_break_all_levII_oplock(work, fp, is_trunc, true, true);
+}
+
+void smb_break_all_levII_oplock_no_interim(struct ksmbd_work *work,
+ struct ksmbd_file *fp, int is_trunc)
+{
+ __smb_break_all_levII_oplock(work, fp, is_trunc, false, true);
+}
+
+void smb_break_all_levII_oplock_for_delete(struct ksmbd_work *work,
+ struct ksmbd_file *fp)
+{
+ __smb_break_all_levII_oplock(work, fp, 0, false, false);
}
/**
return;
sent_break = smb_break_all_write_oplock(work, fp, 1);
- __smb_break_all_levII_oplock(work, fp, 1, !sent_break);
+ __smb_break_all_levII_oplock(work, fp, 1, !sent_break, true);
}
/**
struct lease_ctx_info *lctx, int share_ret);
void smb_break_all_levII_oplock(struct ksmbd_work *work,
struct ksmbd_file *fp, int is_trunc);
+void smb_break_all_levII_oplock_no_interim(struct ksmbd_work *work,
+ struct ksmbd_file *fp, int is_trunc);
+void smb_break_all_levII_oplock_for_delete(struct ksmbd_work *work,
+ struct ksmbd_file *fp);
int opinfo_write_to_read(struct oplock_info *opinfo);
int opinfo_read_handle_to_read(struct oplock_info *opinfo);
int opinfo_write_to_none(struct oplock_info *opinfo);
}
if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) {
- smb_break_all_levII_oplock(work, fp, 0);
+ smb_break_all_levII_oplock_for_delete(work, fp);
ksmbd_fd_set_delete_on_close(fp, file_info);
}
if (S_ISDIR(inode->i_mode) &&
ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY)
return -EBUSY;
- smb_break_all_levII_oplock(work, fp, 0);
+ smb_break_all_levII_oplock_for_delete(work, fp);
ksmbd_set_inode_pending_delete(fp);
} else {
ksmbd_clear_inode_pending_delete(fp);