Re: [PATCH] Add support for flock over a cifs mount.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2011/11/8 Sachin Prabhu <sprabhu@xxxxxxxxxx>:
> Allow flock over a cifs mount.
>
> Signed-off-by: Sachin Prabhu <sprabhu@xxxxxxxxxx>
>
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index 8f1fe32..56d3b36 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -830,6 +830,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,
> @@ -849,6 +850,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,
> @@ -869,6 +871,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,
> diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h
> index 30ff560..e119e9d 100644
> --- a/fs/cifs/cifsfs.h
> +++ b/fs/cifs/cifsfs.h
> @@ -87,6 +87,7 @@ extern ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov,
>  extern ssize_t cifs_strict_writev(struct kiocb *iocb, const struct iovec *iov,
>                                  unsigned long nr_segs, loff_t pos);
>  extern int cifs_lock(struct file *, int, struct file_lock *);
> +extern int cifs_flock(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);
>  extern int cifs_flush(struct file *, fl_owner_t id);
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index c1f063c..dd34f0b 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -43,6 +43,23 @@
>  #include "cifs_fs_sb.h"
>  #include "fscache.h"
>
> +static int do_vfs_lock(struct file *file, struct file_lock *fl)
> +{
> +       int res = 0;
> +
> +       switch (fl->fl_flags & (FL_POSIX|FL_FLOCK)) {
> +       case FL_POSIX:
> +               res = posix_lock_file_wait(file, fl);
> +               break;
> +       case FL_FLOCK:
> +               res = flock_lock_file_wait(file, fl);
> +               break;
> +       default:
> +               BUG();
> +       }
> +       return res;
> +}
> +
>  static inline int cifs_convert_flags(unsigned int flags)
>  {
>        if ((flags & O_ACCMODE) == O_RDONLY)
> @@ -814,7 +831,7 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock)
>        struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
>        int rc = 1;
>
> -       if ((flock->fl_flags & FL_POSIX) == 0)
> +       if ((flock->fl_flags & (FL_POSIX | FL_FLOCK)) == 0)
>                return rc;
>
>        mutex_lock(&cinode->lock_mutex);
> @@ -822,7 +839,7 @@ cifs_posix_lock_set(struct file *file, struct file_lock *flock)
>                mutex_unlock(&cinode->lock_mutex);
>                return rc;
>        }
> -       rc = posix_lock_file_wait(file, flock);
> +       rc = do_vfs_lock(file, flock);
>        mutex_unlock(&cinode->lock_mutex);
>        return rc;
>  }
> @@ -1231,12 +1248,27 @@ cifs_setlk(struct file *file,  struct file_lock *flock, __u8 type,
>        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
>        struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode);
>        __u16 netfid = cfile->netfid;
> +       unsigned char fl_flags = flock->fl_flags;
> +
> +       if (unlock) {
> +               /*Check for existance of lock*/
> +               flock->fl_flags |= FL_EXISTS;
> +               if (do_vfs_lock(flock->fl_file, flock) == -ENOENT)
> +                       goto out;
> +       } else {
> +               /*Check if we can obtain lock*/
> +               flock->fl_flags |= FL_ACCESS;
> +               rc = do_vfs_lock(flock->fl_file, flock);
> +               if (rc < 0)
> +                       goto out;
> +       }
> +       flock->fl_flags = fl_flags;

I think this should be skipped for non-posix locks. These locks have
their own cache (cifs_lock_* functions) associated with cifsInodeInfo
structure - so, we can't make a solution to 'goto out;' without
looking at this cache.

>
>        if (posix_lck) {
>                int posix_lock_type;
>
>                rc = cifs_posix_lock_set(file, flock);
> -               if (!rc || rc < 0)
> +               if (rc <= 0)
>                        return rc;
>
>                if (type & LOCKING_ANDX_SHARED_LOCK)
> @@ -1250,7 +1282,7 @@ cifs_setlk(struct file *file,  struct file_lock *flock, __u8 type,
>                rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid,
>                                      0 /* set */, length, flock,
>                                      posix_lock_type, wait_flag);
> -               goto out;
> +               goto out_lock;
>        }
>
>        if (lock) {
> @@ -1259,7 +1291,7 @@ cifs_setlk(struct file *file,  struct file_lock *flock, __u8 type,
>                if (rc < 0)
>                        return rc;
>                else if (!rc)
> -                       goto out;
> +                       goto out_lock;
>
>                rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length,
>                                 flock->fl_start, 0, 1, type, wait_flag, 0);
> @@ -1271,9 +1303,14 @@ cifs_setlk(struct file *file,  struct file_lock *flock, __u8 type,
>        } else if (unlock)
>                rc = cifs_unlock_range(cfile, flock, xid);
>
> +out_lock:
> +       if (rc == 0 && lock) {
> +               /*We have to sleep here*/
> +               flock->fl_flags |= FL_SLEEP;

It's not clear why we should sleep here - the patch description
doesn't tell anything about it.

> +               do_vfs_lock(file, flock);
> +       }

What's about unlock case here?

>  out:
> -       if (flock->fl_flags & FL_POSIX)
> -               posix_lock_file_wait(file, flock);
> +       flock->fl_flags = fl_flags;
>        return rc;
>  }
>
> @@ -1334,6 +1371,22 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *flock)
>        return rc;
>  }
>
> +int cifs_flock(struct file *file, int cmd, struct file_lock *flock)
> +{
> +       int rc;
> +
> +       rc = cifs_lock(file, cmd, flock);
> +
> +       /*
> +        * flock requires -EWOULDBLOCK in case of conflicting locks
> +        * and LOCK_NB is used
> +        */
> +       if ((rc == -EACCES) && !(flock->fl_flags & FL_SLEEP))
> +               rc = -EWOULDBLOCK;
> +
> +       return rc;
> +}
> +
>  /* update the file size (if needed) after a write */
>  void
>  cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset,
>
>
>

In general, I think that this patch does much more than it's mentioned
in the description and brings a lot of changes in the existing lock
code.

It seems like we should only change posix_file_lock_wait to your
do_vfs_lock in 'out' label and cifs_posix_lock_set for posix_lck case
and map flock to brlock from 0 to INF for !posix_lck case.

-- 
Best regards,
Pavel Shilovsky.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux