Skip to content
Snippets Groups Projects
Commit c36fca86 authored by Namjae Jeon's avatar Namjae Jeon Committed by Steve French
Browse files

cifsd: add the check to work file lock and rename behaviors like Windows...

cifsd: add the check to work file lock and rename behaviors like Windows unless POSIX extensions are negotiated

This patch add the check to work file lock and rename behaviors
like Windows if POSIX extensions are not negotiated.

Signed-off-by: default avatarNamjae Jeon <namjae.jeon@samsung.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 20ea7fd2
No related branches found
No related tags found
No related merge requests found
...@@ -370,7 +370,6 @@ int ksmbd_vfs_read(struct ksmbd_work *work, ...@@ -370,7 +370,6 @@ int ksmbd_vfs_read(struct ksmbd_work *work,
char *rbuf, *name; char *rbuf, *name;
struct inode *inode; struct inode *inode;
char namebuf[NAME_MAX]; char namebuf[NAME_MAX];
int ret;
rbuf = work->aux_payload_buf; rbuf = work->aux_payload_buf;
filp = fp->filp; filp = fp->filp;
...@@ -391,11 +390,15 @@ int ksmbd_vfs_read(struct ksmbd_work *work, ...@@ -391,11 +390,15 @@ int ksmbd_vfs_read(struct ksmbd_work *work,
if (ksmbd_stream_fd(fp)) if (ksmbd_stream_fd(fp))
return ksmbd_vfs_stream_read(fp, rbuf, pos, count); return ksmbd_vfs_stream_read(fp, rbuf, pos, count);
ret = check_lock_range(filp, *pos, *pos + count - 1, if (!work->tcon->posix_extensions) {
READ); int ret;
if (ret) {
ksmbd_err("unable to read due to lock\n"); ret = check_lock_range(filp, *pos, *pos + count - 1,
return -EAGAIN; READ);
if (ret) {
ksmbd_err("unable to read due to lock\n");
return -EAGAIN;
}
} }
nbytes = kernel_read(filp, rbuf, count, pos); nbytes = kernel_read(filp, rbuf, count, pos);
...@@ -504,11 +507,13 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, ...@@ -504,11 +507,13 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp,
goto out; goto out;
} }
err = check_lock_range(filp, *pos, *pos + count - 1, WRITE); if (!work->tcon->posix_extensions) {
if (err) { err = check_lock_range(filp, *pos, *pos + count - 1, WRITE);
ksmbd_err("unable to write due to lock\n"); if (err) {
err = -EAGAIN; ksmbd_err("unable to write due to lock\n");
goto out; err = -EAGAIN;
goto out;
}
} }
/* Do we need to break any of a levelII oplock? */ /* Do we need to break any of a levelII oplock? */
...@@ -706,21 +711,23 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work, ...@@ -706,21 +711,23 @@ static int __ksmbd_vfs_rename(struct ksmbd_work *work,
struct dentry *dst_dent; struct dentry *dst_dent;
int err; int err;
spin_lock(&src_dent->d_lock); if (!work->tcon->posix_extensions) {
list_for_each_entry(dst_dent, &src_dent->d_subdirs, d_child) { spin_lock(&src_dent->d_lock);
struct ksmbd_file *child_fp; list_for_each_entry(dst_dent, &src_dent->d_subdirs, d_child) {
struct ksmbd_file *child_fp;
if (d_really_is_negative(dst_dent)) if (d_really_is_negative(dst_dent))
continue; continue;
child_fp = ksmbd_lookup_fd_inode(d_inode(dst_dent)); child_fp = ksmbd_lookup_fd_inode(d_inode(dst_dent));
if (child_fp) { if (child_fp) {
spin_unlock(&src_dent->d_lock); spin_unlock(&src_dent->d_lock);
ksmbd_debug(VFS, "Forbid rename, sub file/dir is in use\n"); ksmbd_debug(VFS, "Forbid rename, sub file/dir is in use\n");
return -EACCES; return -EACCES;
}
} }
spin_unlock(&src_dent->d_lock);
} }
spin_unlock(&src_dent->d_lock);
if (d_really_is_negative(src_dent_parent)) if (d_really_is_negative(src_dent_parent))
return -ENOENT; return -ENOENT;
...@@ -820,7 +827,6 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work, const char *name, ...@@ -820,7 +827,6 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work, const char *name,
{ {
struct path path; struct path path;
int err = 0; int err = 0;
struct inode *inode;
if (name) { if (name) {
err = kern_path(name, 0, &path); err = kern_path(name, 0, &path);
...@@ -842,18 +848,21 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work, const char *name, ...@@ -842,18 +848,21 @@ int ksmbd_vfs_truncate(struct ksmbd_work *work, const char *name,
/* Do we need to break any of a levelII oplock? */ /* Do we need to break any of a levelII oplock? */
smb_break_all_levII_oplock(work, fp, 1); smb_break_all_levII_oplock(work, fp, 1);
inode = file_inode(filp); if (!work->tcon->posix_extensions) {
if (size < inode->i_size) { struct inode *inode = file_inode(filp);
err = check_lock_range(filp, size,
inode->i_size - 1, WRITE);
} else {
err = check_lock_range(filp, inode->i_size,
size - 1, WRITE);
}
if (err) { if (size < inode->i_size) {
ksmbd_err("failed due to lock\n"); err = check_lock_range(filp, size,
return -EAGAIN; inode->i_size - 1, WRITE);
} else {
err = check_lock_range(filp, inode->i_size,
size - 1, WRITE);
}
if (err) {
ksmbd_err("failed due to lock\n");
return -EAGAIN;
}
} }
err = vfs_truncate(&filp->f_path, size); err = vfs_truncate(&filp->f_path, size);
...@@ -1860,17 +1869,19 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work, ...@@ -1860,17 +1869,19 @@ int ksmbd_vfs_copy_file_ranges(struct ksmbd_work *work,
smb_break_all_levII_oplock(work, dst_fp, 1); smb_break_all_levII_oplock(work, dst_fp, 1);
for (i = 0; i < chunk_count; i++) { if (!work->tcon->posix_extensions) {
src_off = le64_to_cpu(chunks[i].SourceOffset); for (i = 0; i < chunk_count; i++) {
dst_off = le64_to_cpu(chunks[i].TargetOffset); src_off = le64_to_cpu(chunks[i].SourceOffset);
len = le32_to_cpu(chunks[i].Length); dst_off = le64_to_cpu(chunks[i].TargetOffset);
len = le32_to_cpu(chunks[i].Length);
if (check_lock_range(src_fp->filp, src_off,
src_off + len - 1, READ)) if (check_lock_range(src_fp->filp, src_off,
return -EAGAIN; src_off + len - 1, READ))
if (check_lock_range(dst_fp->filp, dst_off, return -EAGAIN;
dst_off + len - 1, WRITE)) if (check_lock_range(dst_fp->filp, dst_off,
return -EAGAIN; dst_off + len - 1, WRITE))
return -EAGAIN;
}
} }
src_file_size = i_size_read(file_inode(src_fp->filp)); src_file_size = i_size_read(file_inode(src_fp->filp));
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment