OSDN Git Service

cifs: add support for flock
authorSteve French <stfrench@microsoft.com>
Tue, 16 Jul 2019 23:55:38 +0000 (18:55 -0500)
committerSteve French <stfrench@microsoft.com>
Mon, 25 Nov 2019 07:14:14 +0000 (01:14 -0600)
The flock system call locks the whole file rather than a byte
range and so is currently emulated by various other file systems
by simply sending a byte range lock for the whole file.
Add flock handling for cifs.ko in similar way.

xfstest generic/504 passes with this as well

Signed-off-by: Steve French <stfrench@microsoft.com>
Reviewed-by: Pavel Shilovsky <pshilov@microsoft.com>
Reviewed-by: Ronnie Sahlberg <lsahlber@redhat.com>
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/file.c

index 1a135d1..e4e3b57 100644 (file)
@@ -1219,6 +1219,7 @@ const struct file_operations cifs_file_ops = {
        .open = cifs_open,
        .release = cifs_close,
        .lock = cifs_lock,
+       .flock = cifs_flock,
        .fsync = cifs_fsync,
        .flush = cifs_flush,
        .mmap  = cifs_file_mmap,
@@ -1238,6 +1239,7 @@ const struct file_operations cifs_file_strict_ops = {
        .open = cifs_open,
        .release = cifs_close,
        .lock = cifs_lock,
+       .flock = cifs_flock,
        .fsync = cifs_strict_fsync,
        .flush = cifs_flush,
        .mmap = cifs_file_strict_mmap,
@@ -1257,6 +1259,7 @@ const struct file_operations cifs_file_direct_ops = {
        .open = cifs_open,
        .release = cifs_close,
        .lock = cifs_lock,
+       .flock = cifs_flock,
        .fsync = cifs_fsync,
        .flush = cifs_flush,
        .mmap = cifs_file_mmap,
index bc4ca94..93c7572 100644 (file)
@@ -108,6 +108,7 @@ extern ssize_t cifs_strict_readv(struct kiocb *iocb, struct iov_iter *to);
 extern ssize_t cifs_user_writev(struct kiocb *iocb, struct iov_iter *from);
 extern ssize_t cifs_direct_writev(struct kiocb *iocb, struct iov_iter *from);
 extern ssize_t cifs_strict_writev(struct kiocb *iocb, struct iov_iter *from);
+extern int cifs_flock(struct file *pfile, int cmd, struct file_lock *plock);
 extern int cifs_lock(struct file *, int, struct file_lock *);
 extern int cifs_fsync(struct file *, loff_t, loff_t, int);
 extern int cifs_strict_fsync(struct file *, loff_t, loff_t, int);
index fa7b0fa..f3fd5b6 100644 (file)
@@ -1681,7 +1681,7 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u32 type,
                rc = server->ops->mand_unlock_range(cfile, flock, xid);
 
 out:
-       if (flock->fl_flags & FL_POSIX) {
+       if ((flock->fl_flags & FL_POSIX) || (flock->fl_flags & FL_FLOCK)) {
                /*
                 * If this is a request to remove all locks because we
                 * are closing the file, it doesn't matter if the
@@ -1698,6 +1698,56 @@ out:
        return rc;
 }
 
+int cifs_flock(struct file *file, int cmd, struct file_lock *fl)
+{
+       int rc, xid;
+       int lock = 0, unlock = 0;
+       bool wait_flag = false;
+       bool posix_lck = false;
+       struct cifs_sb_info *cifs_sb;
+       struct cifs_tcon *tcon;
+       struct cifsInodeInfo *cinode;
+       struct cifsFileInfo *cfile;
+       __u16 netfid;
+       __u32 type;
+
+       rc = -EACCES;
+       xid = get_xid();
+
+       if (!(fl->fl_flags & FL_FLOCK))
+               return -ENOLCK;
+
+       cfile = (struct cifsFileInfo *)file->private_data;
+       tcon = tlink_tcon(cfile->tlink);
+
+       cifs_read_flock(fl, &type, &lock, &unlock, &wait_flag,
+                       tcon->ses->server);
+       cifs_sb = CIFS_FILE_SB(file);
+       netfid = cfile->fid.netfid;
+       cinode = CIFS_I(file_inode(file));
+
+       if (cap_unix(tcon->ses) &&
+           (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) &&
+           ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0))
+               posix_lck = true;
+
+       if (!lock && !unlock) {
+               /*
+                * if no lock or unlock then nothing to do since we do not
+                * know what it is
+                */
+               free_xid(xid);
+               return -EOPNOTSUPP;
+       }
+
+       rc = cifs_setlk(file, fl, type, wait_flag, posix_lck, lock, unlock,
+                       xid);
+       free_xid(xid);
+       return rc;
+
+
+}
+
 int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
 {
        int rc, xid;