]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - fs/fuse/file.c
[PATCH] Streamline generic_file_* interfaces and filemap cleanups
[net-next-2.6.git] / fs / fuse / file.c
index d9a8289297c0c17da3d3d8e35b62b72c5d42cde5..183626868eea602d4658e5395ec31f46130c0afe 100644 (file)
@@ -48,8 +48,8 @@ struct fuse_file *fuse_file_alloc(void)
        struct fuse_file *ff;
        ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL);
        if (ff) {
-               ff->release_req = fuse_request_alloc();
-               if (!ff->release_req) {
+               ff->reserved_req = fuse_request_alloc();
+               if (!ff->reserved_req) {
                        kfree(ff);
                        ff = NULL;
                }
@@ -59,7 +59,7 @@ struct fuse_file *fuse_file_alloc(void)
 
 void fuse_file_free(struct fuse_file *ff)
 {
-       fuse_request_free(ff->release_req);
+       fuse_request_free(ff->reserved_req);
        kfree(ff);
 }
 
@@ -115,7 +115,7 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir)
 struct fuse_req *fuse_release_fill(struct fuse_file *ff, u64 nodeid, int flags,
                                   int opcode)
 {
-       struct fuse_req *req = ff->release_req;
+       struct fuse_req *req = ff->reserved_req;
        struct fuse_release_in *inarg = &req->misc.release_in;
 
        inarg->fh = ff->fh;
@@ -161,15 +161,25 @@ static int fuse_release(struct inode *inode, struct file *file)
 }
 
 /*
- * It would be nice to scramble the ID space, so that the value of the
- * files_struct pointer is not exposed to userspace.  Symmetric crypto
- * functions are overkill, since the inverse function doesn't need to
- * be implemented (though it does have to exist).  Is there something
- * simpler?
+ * Scramble the ID space with XTEA, so that the value of the files_struct
+ * pointer is not exposed to userspace.
  */
-static inline u64 fuse_lock_owner_id(fl_owner_t id)
+static u64 fuse_lock_owner_id(struct fuse_conn *fc, fl_owner_t id)
 {
-       return (unsigned long) id;
+       u32 *k = fc->scramble_key;
+       u64 v = (unsigned long) id;
+       u32 v0 = v;
+       u32 v1 = v >> 32;
+       u32 sum = 0;
+       int i;
+
+       for (i = 0; i < 32; i++) {
+               v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
+               sum += 0x9E3779B9;
+               v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[sum>>11 & 3]);
+       }
+
+       return (u64) v0 + ((u64) v1 << 32);
 }
 
 static int fuse_flush(struct file *file, fl_owner_t id)
@@ -187,13 +197,10 @@ static int fuse_flush(struct file *file, fl_owner_t id)
        if (fc->no_flush)
                return 0;
 
-       req = fuse_get_req(fc);
-       if (IS_ERR(req))
-               return PTR_ERR(req);
-
+       req = fuse_get_req_nofail(fc, file);
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
-       inarg.lock_owner = fuse_lock_owner_id(id);
+       inarg.lock_owner = fuse_lock_owner_id(fc, id);
        req->in.h.opcode = FUSE_FLUSH;
        req->in.h.nodeid = get_node_id(inode);
        req->in.numargs = 1;
@@ -388,14 +395,16 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
        struct fuse_readpages_data data;
        int err;
 
+       err = -EIO;
        if (is_bad_inode(inode))
-               return -EIO;
+               goto clean_pages_up;
 
        data.file = file;
        data.inode = inode;
        data.req = fuse_get_req(fc);
+       err = PTR_ERR(data.req);
        if (IS_ERR(data.req))
-               return PTR_ERR(data.req);
+               goto clean_pages_up;
 
        err = read_cache_pages(mapping, pages, fuse_readpages_fill, &data);
        if (!err) {
@@ -405,6 +414,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping,
                        fuse_put_request(fc, data.req);
        }
        return err;
+
+clean_pages_up:
+       put_pages_list(pages);
+       return err;
 }
 
 static size_t fuse_send_write(struct fuse_req *req, struct file *file,
@@ -647,11 +660,12 @@ static void fuse_lk_fill(struct fuse_req *req, struct file *file,
                         const struct file_lock *fl, int opcode, pid_t pid)
 {
        struct inode *inode = file->f_dentry->d_inode;
+       struct fuse_conn *fc = get_fuse_conn(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_lk_in *arg = &req->misc.lk_in;
 
        arg->fh = ff->fh;
-       arg->owner = fuse_lock_owner_id(fl->fl_owner);
+       arg->owner = fuse_lock_owner_id(fc, fl->fl_owner);
        arg->lk.start = fl->fl_start;
        arg->lk.end = fl->fl_end;
        arg->lk.type = fl->fl_type;
@@ -708,6 +722,9 @@ static int fuse_setlk(struct file *file, struct file_lock *fl)
        fuse_lk_fill(req, file, fl, opcode, pid);
        request_send(fc, req);
        err = req->out.h.error;
+       /* locking is restartable */
+       if (err == -EINTR)
+               err = -ERESTARTSYS;
        fuse_put_request(fc, req);
        return err;
 }
@@ -736,8 +753,10 @@ static int fuse_file_lock(struct file *file, int cmd, struct file_lock *fl)
 
 static const struct file_operations fuse_file_operations = {
        .llseek         = generic_file_llseek,
-       .read           = generic_file_read,
-       .write          = generic_file_write,
+       .read           = do_sync_read,
+       .aio_read       = generic_file_aio_read,
+       .write          = do_sync_write,
+       .aio_write      = generic_file_aio_write,
        .mmap           = fuse_file_mmap,
        .open           = fuse_open,
        .flush          = fuse_flush,
@@ -759,7 +778,7 @@ static const struct file_operations fuse_direct_io_file_operations = {
        /* no mmap and sendfile */
 };
 
-static struct address_space_operations fuse_file_aops  = {
+static const struct address_space_operations fuse_file_aops  = {
        .readpage       = fuse_readpage,
        .prepare_write  = fuse_prepare_write,
        .commit_write   = fuse_commit_write,