Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f33321141b273d60cbb3a8f56a5489baad82ba5e
Commit:     f33321141b273d60cbb3a8f56a5489baad82ba5e
Parent:     b25e82e5673c750116e8b01a4fc7d09be7809f8c
Author:     Miklos Szeredi <[EMAIL PROTECTED]>
AuthorDate: Thu Oct 18 03:07:04 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Thu Oct 18 14:37:31 2007 -0700

    fuse: add support for mandatory locking
    
    For mandatory locking the userspace filesystem needs to know the lock
    ownership for read, write and truncate operations.
    
    This patch adds the necessary fields to the protocol.
    
    Signed-off-by: Miklos Szeredi <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/fuse/dir.c        |    5 +++++
 fs/fuse/file.c       |   37 +++++++++++++++++++++++++++++--------
 fs/fuse/fuse_i.h     |    2 ++
 include/linux/fuse.h |   17 +++++++++++++++--
 4 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 052327b..6c83ed0 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1108,6 +1108,11 @@ static int fuse_do_setattr(struct dentry *entry, struct 
iattr *attr,
                inarg.valid |= FATTR_FH;
                inarg.fh = ff->fh;
        }
+       if (attr->ia_valid & ATTR_SIZE) {
+               /* For mandatory locking in truncate */
+               inarg.valid |= FATTR_LOCKOWNER;
+               inarg.lock_owner = fuse_lock_owner_id(fc, current->files);
+       }
        req->in.h.opcode = FUSE_SETATTR;
        req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 2b589de..0fcdba9 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -189,7 +189,7 @@ static int fuse_release(struct inode *inode, struct file 
*file)
  * Scramble the ID space with XTEA, so that the value of the files_struct
  * pointer is not exposed to userspace.
  */
-static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
+u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
 {
        u32 *k = fc->scramble_key;
        u64 v = (unsigned long) id;
@@ -308,11 +308,19 @@ void fuse_read_fill(struct fuse_req *req, struct 
fuse_file *ff,
 }
 
 static size_t fuse_send_read(struct fuse_req *req, struct file *file,
-                            struct inode *inode, loff_t pos, size_t count)
+                            struct inode *inode, loff_t pos, size_t count,
+                            fl_owner_t owner)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
+
        fuse_read_fill(req, ff, inode, pos, count, FUSE_READ);
+       if (owner != NULL) {
+               struct fuse_read_in *inarg = &req->misc.read_in;
+
+               inarg->read_flags |= FUSE_READ_LOCKOWNER;
+               inarg->lock_owner = fuse_lock_owner_id(fc, owner);
+       }
        request_send(fc, req);
        return req->out.args[0].size;
 }
@@ -336,7 +344,8 @@ static int fuse_readpage(struct file *file, struct page 
*page)
        req->out.page_zeroing = 1;
        req->num_pages = 1;
        req->pages[0] = page;
-       fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE);
+       fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE,
+                      NULL);
        err = req->out.h.error;
        fuse_put_request(fc, req);
        if (!err)
@@ -447,6 +456,7 @@ static void fuse_write_fill(struct fuse_req *req, struct 
fuse_file *ff,
                            struct inode *inode, loff_t pos, size_t count,
                            int writepage)
 {
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_write_in *inarg = &req->misc.write.in;
        struct fuse_write_out *outarg = &req->misc.write.out;
 
@@ -459,7 +469,10 @@ static void fuse_write_fill(struct fuse_req *req, struct 
fuse_file *ff,
        req->in.h.nodeid = get_node_id(inode);
        req->in.argpages = 1;
        req->in.numargs = 2;
-       req->in.args[0].size = sizeof(struct fuse_write_in);
+       if (fc->minor < 9)
+               req->in.args[0].size = FUSE_COMPAT_WRITE_IN_SIZE;
+       else
+               req->in.args[0].size = sizeof(struct fuse_write_in);
        req->in.args[0].value = inarg;
        req->in.args[1].size = count;
        req->out.numargs = 1;
@@ -468,10 +481,16 @@ static void fuse_write_fill(struct fuse_req *req, struct 
fuse_file *ff,
 }
 
 static size_t fuse_send_write(struct fuse_req *req, struct file *file,
-                             struct inode *inode, loff_t pos, size_t count)
+                             struct inode *inode, loff_t pos, size_t count,
+                             fl_owner_t owner)
 {
        struct fuse_conn *fc = get_fuse_conn(inode);
        fuse_write_fill(req, file->private_data, inode, pos, count, 0);
+       if (owner != NULL) {
+               struct fuse_write_in *inarg = &req->misc.write.in;
+               inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
+               inarg->lock_owner = fuse_lock_owner_id(fc, owner);
+       }
        request_send(fc, req);
        return req->misc.write.out.size;
 }
@@ -508,7 +527,7 @@ static int fuse_buffered_write(struct file *file, struct 
inode *inode,
        req->num_pages = 1;
        req->pages[0] = page;
        req->page_offset = offset;
-       nres = fuse_send_write(req, file, inode, pos, count);
+       nres = fuse_send_write(req, file, inode, pos, count, NULL);
        err = req->out.h.error;
        fuse_put_request(fc, req);
        if (!err && !nres)
@@ -609,9 +628,11 @@ static ssize_t fuse_direct_io(struct file *file, const 
char __user *buf,
                nbytes = (req->num_pages << PAGE_SHIFT) - req->page_offset;
                nbytes = min(count, nbytes);
                if (write)
-                       nres = fuse_send_write(req, file, inode, pos, nbytes);
+                       nres = fuse_send_write(req, file, inode, pos, nbytes,
+                                              current->files);
                else
-                       nres = fuse_send_read(req, file, inode, pos, nbytes);
+                       nres = fuse_send_read(req, file, inode, pos, nbytes,
+                                             current->files);
                fuse_release_user_pages(req, !write);
                if (req->out.h.error) {
                        if (!res)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 8b64a63..6c5461d 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -591,3 +591,5 @@ int fuse_valid_type(int m);
  * Is task allowed to perform filesystem operation?
  */
 int fuse_allow_task(struct fuse_conn *fc, struct task_struct *task);
+
+u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id);
diff --git a/include/linux/fuse.h b/include/linux/fuse.h
index 6f4a312..7d4fa5b 100644
--- a/include/linux/fuse.h
+++ b/include/linux/fuse.h
@@ -14,6 +14,7 @@
  * 7.9:
  *  - new fuse_getattr_in input argument of GETATTR
  *  - add lk_flags in fuse_lk_in
+ *  - add lock_owner field to fuse_setattr_in, fuse_read_in and fuse_write_in
  */
 
 #include <asm/types.h>
@@ -86,6 +87,7 @@ struct fuse_file_lock {
 #define FATTR_FH       (1 << 6)
 #define FATTR_ATIME_NOW        (1 << 7)
 #define FATTR_MTIME_NOW        (1 << 8)
+#define FATTR_LOCKOWNER        (1 << 9)
 
 /**
  * Flags returned by the OPEN request
@@ -123,8 +125,15 @@ struct fuse_file_lock {
  * WRITE flags
  *
  * FUSE_WRITE_CACHE: delayed write from page cache, file handle is guessed
+ * FUSE_WRITE_LOCKOWNER: lock_owner field is valid
  */
 #define FUSE_WRITE_CACHE       (1 << 0)
+#define FUSE_WRITE_LOCKOWNER   (1 << 1)
+
+/**
+ * Read flags
+ */
+#define FUSE_READ_LOCKOWNER    (1 << 1)
 
 enum fuse_opcode {
        FUSE_LOOKUP        = 1,
@@ -219,7 +228,7 @@ struct fuse_setattr_in {
        __u32   padding;
        __u64   fh;
        __u64   size;
-       __u64   unused1;
+       __u64   lock_owner;
        __u64   atime;
        __u64   mtime;
        __u64   unused2;
@@ -262,14 +271,18 @@ struct fuse_read_in {
        __u64   fh;
        __u64   offset;
        __u32   size;
-       __u32   padding;
+       __u32   read_flags;
+       __u64   lock_owner;
 };
 
+#define FUSE_COMPAT_WRITE_IN_SIZE 24
+
 struct fuse_write_in {
        __u64   fh;
        __u64   offset;
        __u32   size;
        __u32   write_flags;
+       __u64   lock_owner;
 };
 
 struct fuse_write_out {
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to