ksmbd: check base file delete pending for stream opens

A base file that has been marked for deletion remains present while stream
handles are open. Name-based opens of either the base file or one of its
streams must return STATUS_DELETE_PENDING during that interval.

ksmbd_inode_pending_delete() returned only the per-handle stream state for
stream handles. It therefore skipped the inode-wide S_DEL_PENDING state set
by the base file delete-on-close path. As a result, a new stream open
incorrectly succeeded.

Check the inode-wide pending-delete state first for every handle. Only when
the base file is not pending, check the per-handle stream state.

Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
Namjae Jeon 2026-07-12 14:03:23 +09:00
parent 7f8029591b
commit 8dd5ca858d

View File

@ -229,25 +229,15 @@ bool ksmbd_inode_pending_delete(struct ksmbd_file *fp)
struct ksmbd_inode *ci = fp->f_ci;
int ret;
/*
* Stream delete-pending is tracked per-handle (see
* ksmbd_fd_set_delete_pending()), not on the shared inode -- the
* whole-file flags checked below would never see it set, and would
* also incorrectly report a whole-file pending-delete as applying
* to an unrelated stream handle on the same inode.
*/
if (ksmbd_stream_fd(fp)) {
bool pending;
spin_lock(&fp->f_lock);
pending = fp->stream_del_pending;
spin_unlock(&fp->f_lock);
return pending;
}
down_read(&ci->m_lock);
ret = (ci->m_flags & S_DEL_PENDING);
up_read(&ci->m_lock);
if (ret || !ksmbd_stream_fd(fp))
return ret;
spin_lock(&fp->f_lock);
ret = fp->stream_del_pending;
spin_unlock(&fp->f_lock);
return ret;
}