If a flock is emulated on the server side with mandatory locks (which is what we only have for SMB2 without POSIX extensions) then we should maintain the same logic on the client. Otherwise you get different behavior depending on the caching policies currently in effect on the client side. You may consider testing with both modes when leases/oplocks are on and off. -- Best regards, Pavel Shilovsky вт, 23 февр. 2021 г. в 10:30, Aurélien Aptel <aaptel@xxxxxxxx>: > > From: Aurelien Aptel <aaptel@xxxxxxxx> > > flock(2)-type locks are advisory, they are not supposed to prevent IO > if mode would otherwise allow it. From man page: > > flock() places advisory locks only; given suitable permissions on a > file, a process is free to ignore the use of flock() and perform I/O on > the file. > > Simple reproducer: > > #include <stdlib.h> > #include <stdio.h> > #include <errno.h> > #include <sys/file.h> > #include <sys/types.h> > #include <sys/wait.h> > #include <unistd.h> > > int main(int argc, char** argv) > { > const char* fn = argv[1] ? argv[1] : "aaa"; > int fd, status, rc; > pid_t pid; > > fd = open(fn, O_RDWR|O_CREAT, S_IRWXU); > pid = fork(); > > if (pid == 0) { > flock(fd, LOCK_SH); > exit(0); > } > > waitpid(pid, &status, 0); > rc = write(fd, "xxx\n", 4); > if (rc < 0) { > perror("write"); > return 1; > } > > puts("ok"); > return 0; > } > > If the locks are advisory the write() call is supposed to work > otherwise we are trying to write with only a read lock (aka shared > lock) so it fails. > > Signed-off-by: Aurelien Aptel <aaptel@xxxxxxxx> > --- > fs/cifs/file.c | 6 ++++-- > 1 file changed, 4 insertions(+), 2 deletions(-) > > diff --git a/fs/cifs/file.c b/fs/cifs/file.c > index 6d001905c8e5..3e351a534720 100644 > --- a/fs/cifs/file.c > +++ b/fs/cifs/file.c > @@ -3242,6 +3242,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) > struct inode *inode = file->f_mapping->host; > struct cifsInodeInfo *cinode = CIFS_I(inode); > struct TCP_Server_Info *server = tlink_tcon(cfile->tlink)->ses->server; > + struct cifsLockInfo *lock; > ssize_t rc; > > inode_lock(inode); > @@ -3257,7 +3258,7 @@ cifs_writev(struct kiocb *iocb, struct iov_iter *from) > > if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(from), > server->vals->exclusive_lock_type, 0, > - NULL, CIFS_WRITE_OP)) > + &lock, CIFS_WRITE_OP) || (lock->flags & FL_FLOCK)) > rc = __generic_file_write_iter(iocb, from); > else > rc = -EACCES; > @@ -3975,6 +3976,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) > struct cifsFileInfo *cfile = (struct cifsFileInfo *) > iocb->ki_filp->private_data; > struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); > + struct cifsLockInfo *lock; > int rc = -EACCES; > > /* > @@ -4000,7 +4002,7 @@ cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to) > down_read(&cinode->lock_sem); > if (!cifs_find_lock_conflict(cfile, iocb->ki_pos, iov_iter_count(to), > tcon->ses->server->vals->shared_lock_type, > - 0, NULL, CIFS_READ_OP)) > + 0, &lock, CIFS_READ_OP) || (lock->flags & FL_FLOCK)) > rc = generic_file_read_iter(iocb, to); > up_read(&cinode->lock_sem); > return rc; > -- > 2.30.0 >