mirror of
https://github.com/torvalds/linux.git
synced 2026-10-08 03:26:02 +02:00
ksmbd: route stream FileDispositionInformation through stream delete flag
set_file_disposition_info() calls ksmbd_set_inode_pending_delete() / ksmbd_clear_inode_pending_delete() unconditionally, which always sets S_DEL_PENDING on the whole inode (ci->m_flags), regardless of whether the handle being closed is a regular file or an alternate data stream. Requesting delete-pending on a single stream handle (e.g. deleting just an alternate data stream some clients keep alongside a file) would therefore incorrectly schedule deletion of the entire file's data, not just the stream. Add ksmbd_fd_set_delete_pending()/ksmbd_fd_clear_delete_pending(), following the same stream-vs-whole-file routing pattern already used by ksmbd_fd_set_delete_on_close() for the CREATE-time DeleteOnClose option, and switch set_file_disposition_info() to use them. Assisted-by: Claude:claude-sonnet-5 Signed-off-by: Gael Blivet <gael.blivet@gmail.com> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org>
This commit is contained in:
parent
d68d4b3293
commit
495ade881b
|
|
@ -7123,9 +7123,9 @@ static int set_file_disposition_info(struct ksmbd_work *work,
|
|||
ksmbd_vfs_empty_dir(fp) == -ENOTEMPTY)
|
||||
return -EBUSY;
|
||||
smb_break_all_levII_oplock_for_delete(work, fp);
|
||||
ksmbd_set_inode_pending_delete(fp);
|
||||
ksmbd_fd_set_delete_pending(fp);
|
||||
} else {
|
||||
ksmbd_clear_inode_pending_delete(fp);
|
||||
ksmbd_fd_clear_delete_pending(fp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -294,6 +294,38 @@ void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
|
|||
up_write(&ci->m_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* FileDispositionInformation (SET_INFO) on a stream handle must only
|
||||
* mark the stream for deletion, not the whole file -- otherwise
|
||||
* deleting a single alternate data stream (e.g. AFP_AfpInfo) deletes
|
||||
* the entire file's data along with it.
|
||||
*/
|
||||
void ksmbd_fd_set_delete_pending(struct ksmbd_file *fp)
|
||||
{
|
||||
struct ksmbd_inode *ci = fp->f_ci;
|
||||
|
||||
if (ksmbd_stream_fd(fp)) {
|
||||
down_write(&ci->m_lock);
|
||||
ci->m_flags |= S_DEL_ON_CLS_STREAM;
|
||||
up_write(&ci->m_lock);
|
||||
} else {
|
||||
ksmbd_set_inode_pending_delete(fp);
|
||||
}
|
||||
}
|
||||
|
||||
void ksmbd_fd_clear_delete_pending(struct ksmbd_file *fp)
|
||||
{
|
||||
struct ksmbd_inode *ci = fp->f_ci;
|
||||
|
||||
if (ksmbd_stream_fd(fp)) {
|
||||
down_write(&ci->m_lock);
|
||||
ci->m_flags &= ~S_DEL_ON_CLS_STREAM;
|
||||
up_write(&ci->m_lock);
|
||||
} else {
|
||||
ksmbd_clear_inode_pending_delete(fp);
|
||||
}
|
||||
}
|
||||
|
||||
static void ksmbd_inode_hash(struct ksmbd_inode *ci)
|
||||
{
|
||||
struct hlist_head *b = inode_hashtable +
|
||||
|
|
|
|||
|
|
@ -214,6 +214,8 @@ void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp);
|
|||
void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp);
|
||||
void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp,
|
||||
int file_info);
|
||||
void ksmbd_fd_set_delete_pending(struct ksmbd_file *fp);
|
||||
void ksmbd_fd_clear_delete_pending(struct ksmbd_file *fp);
|
||||
int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp);
|
||||
int ksmbd_validate_name_reconnect(struct ksmbd_share_config *share,
|
||||
struct ksmbd_file *fp, char *name);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user