Merge tag 'fuse-update-5.10' of git://git.kernel.org/pub/scm/linux/kernel/git/mszered...
[linux-2.6-microblaze.git] / fs / fuse / file.c
index 43c165e..c03034e 100644 (file)
@@ -32,7 +32,7 @@ static struct page **fuse_pages_alloc(unsigned int npages, gfp_t flags,
        return pages;
 }
 
-static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
+static int fuse_send_open(struct fuse_mount *fm, u64 nodeid, struct file *file,
                          int opcode, struct fuse_open_out *outargp)
 {
        struct fuse_open_in inarg;
@@ -40,7 +40,7 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
 
        memset(&inarg, 0, sizeof(inarg));
        inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY);
-       if (!fc->atomic_o_trunc)
+       if (!fm->fc->atomic_o_trunc)
                inarg.flags &= ~O_TRUNC;
        args.opcode = opcode;
        args.nodeid = nodeid;
@@ -51,7 +51,7 @@ static int fuse_send_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
        args.out_args[0].size = sizeof(*outargp);
        args.out_args[0].value = outargp;
 
-       return fuse_simple_request(fc, &args);
+       return fuse_simple_request(fm, &args);
 }
 
 struct fuse_release_args {
@@ -60,7 +60,7 @@ struct fuse_release_args {
        struct inode *inode;
 };
 
-struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
+struct fuse_file *fuse_file_alloc(struct fuse_mount *fm)
 {
        struct fuse_file *ff;
 
@@ -68,7 +68,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
        if (unlikely(!ff))
                return NULL;
 
-       ff->fc = fc;
+       ff->fm = fm;
        ff->release_args = kzalloc(sizeof(*ff->release_args),
                                   GFP_KERNEL_ACCOUNT);
        if (!ff->release_args) {
@@ -82,7 +82,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
        RB_CLEAR_NODE(&ff->polled_node);
        init_waitqueue_head(&ff->poll_wait);
 
-       ff->kh = atomic64_inc_return(&fc->khctr);
+       ff->kh = atomic64_inc_return(&fm->fc->khctr);
 
        return ff;
 }
@@ -100,7 +100,7 @@ static struct fuse_file *fuse_file_get(struct fuse_file *ff)
        return ff;
 }
 
-static void fuse_release_end(struct fuse_conn *fc, struct fuse_args *args,
+static void fuse_release_end(struct fuse_mount *fm, struct fuse_args *args,
                             int error)
 {
        struct fuse_release_args *ra = container_of(args, typeof(*ra), args);
@@ -114,29 +114,30 @@ static void fuse_file_put(struct fuse_file *ff, bool sync, bool isdir)
        if (refcount_dec_and_test(&ff->count)) {
                struct fuse_args *args = &ff->release_args->args;
 
-               if (isdir ? ff->fc->no_opendir : ff->fc->no_open) {
+               if (isdir ? ff->fm->fc->no_opendir : ff->fm->fc->no_open) {
                        /* Do nothing when client does not implement 'open' */
-                       fuse_release_end(ff->fc, args, 0);
+                       fuse_release_end(ff->fm, args, 0);
                } else if (sync) {
-                       fuse_simple_request(ff->fc, args);
-                       fuse_release_end(ff->fc, args, 0);
+                       fuse_simple_request(ff->fm, args);
+                       fuse_release_end(ff->fm, args, 0);
                } else {
                        args->end = fuse_release_end;
-                       if (fuse_simple_background(ff->fc, args,
+                       if (fuse_simple_background(ff->fm, args,
                                                   GFP_KERNEL | __GFP_NOFAIL))
-                               fuse_release_end(ff->fc, args, -ENOTCONN);
+                               fuse_release_end(ff->fm, args, -ENOTCONN);
                }
                kfree(ff);
        }
 }
 
-int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
+int fuse_do_open(struct fuse_mount *fm, u64 nodeid, struct file *file,
                 bool isdir)
 {
+       struct fuse_conn *fc = fm->fc;
        struct fuse_file *ff;
        int opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN;
 
-       ff = fuse_file_alloc(fc);
+       ff = fuse_file_alloc(fm);
        if (!ff)
                return -ENOMEM;
 
@@ -147,7 +148,7 @@ int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file,
                struct fuse_open_out outarg;
                int err;
 
-               err = fuse_send_open(fc, nodeid, file, opcode, &outarg);
+               err = fuse_send_open(fm, nodeid, file, opcode, &outarg);
                if (!err) {
                        ff->fh = outarg.fh;
                        ff->open_flags = outarg.open_flags;
@@ -216,27 +217,40 @@ void fuse_finish_open(struct inode *inode, struct file *file)
 
 int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
 {
-       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_mount *fm = get_fuse_mount(inode);
+       struct fuse_conn *fc = fm->fc;
        int err;
        bool is_wb_truncate = (file->f_flags & O_TRUNC) &&
                          fc->atomic_o_trunc &&
                          fc->writeback_cache;
+       bool dax_truncate = (file->f_flags & O_TRUNC) &&
+                         fc->atomic_o_trunc && FUSE_IS_DAX(inode);
 
        err = generic_file_open(inode, file);
        if (err)
                return err;
 
-       if (is_wb_truncate) {
+       if (is_wb_truncate || dax_truncate) {
                inode_lock(inode);
                fuse_set_nowrite(inode);
        }
 
-       err = fuse_do_open(fc, get_node_id(inode), file, isdir);
+       if (dax_truncate) {
+               down_write(&get_fuse_inode(inode)->i_mmap_sem);
+               err = fuse_dax_break_layouts(inode, 0, 0);
+               if (err)
+                       goto out;
+       }
 
+       err = fuse_do_open(fm, get_node_id(inode), file, isdir);
        if (!err)
                fuse_finish_open(inode, file);
 
-       if (is_wb_truncate) {
+out:
+       if (dax_truncate)
+               up_write(&get_fuse_inode(inode)->i_mmap_sem);
+
+       if (is_wb_truncate | dax_truncate) {
                fuse_release_nowrite(inode);
                inode_unlock(inode);
        }
@@ -247,7 +261,7 @@ int fuse_open_common(struct inode *inode, struct file *file, bool isdir)
 static void fuse_prepare_release(struct fuse_inode *fi, struct fuse_file *ff,
                                 int flags, int opcode)
 {
-       struct fuse_conn *fc = ff->fc;
+       struct fuse_conn *fc = ff->fm->fc;
        struct fuse_release_args *ra = ff->release_args;
 
        /* Inode is NULL on error path of fuse_create_open() */
@@ -285,7 +299,7 @@ void fuse_release_common(struct file *file, bool isdir)
 
        if (ff->flock) {
                ra->inarg.release_flags |= FUSE_RELEASE_FLOCK_UNLOCK;
-               ra->inarg.lock_owner = fuse_lock_owner_id(ff->fc,
+               ra->inarg.lock_owner = fuse_lock_owner_id(ff->fm->fc,
                                                          (fl_owner_t) file);
        }
        /* Hold inode until release is finished */
@@ -300,7 +314,7 @@ void fuse_release_common(struct file *file, bool isdir)
         * synchronous RELEASE is allowed (and desirable) in this case
         * because the server can be trusted not to screw up.
         */
-       fuse_file_put(ff, ff->fc->destroy, isdir);
+       fuse_file_put(ff, ff->fm->fc->destroy, isdir);
 }
 
 static int fuse_open(struct inode *inode, struct file *file)
@@ -443,7 +457,7 @@ static void fuse_sync_writes(struct inode *inode)
 static int fuse_flush(struct file *file, fl_owner_t id)
 {
        struct inode *inode = file_inode(file);
-       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_mount *fm = get_fuse_mount(inode);
        struct fuse_file *ff = file->private_data;
        struct fuse_flush_in inarg;
        FUSE_ARGS(args);
@@ -465,12 +479,12 @@ static int fuse_flush(struct file *file, fl_owner_t id)
                return err;
 
        err = 0;
-       if (fc->no_flush)
+       if (fm->fc->no_flush)
                goto inval_attr_out;
 
        memset(&inarg, 0, sizeof(inarg));
        inarg.fh = ff->fh;
-       inarg.lock_owner = fuse_lock_owner_id(fc, id);
+       inarg.lock_owner = fuse_lock_owner_id(fm->fc, id);
        args.opcode = FUSE_FLUSH;
        args.nodeid = get_node_id(inode);
        args.in_numargs = 1;
@@ -478,9 +492,9 @@ static int fuse_flush(struct file *file, fl_owner_t id)
        args.in_args[0].value = &inarg;
        args.force = true;
 
-       err = fuse_simple_request(fc, &args);
+       err = fuse_simple_request(fm, &args);
        if (err == -ENOSYS) {
-               fc->no_flush = 1;
+               fm->fc->no_flush = 1;
                err = 0;
        }
 
@@ -489,7 +503,7 @@ inval_attr_out:
         * In memory i_blocks is not maintained by fuse, if writeback cache is
         * enabled, i_blocks from cached attr may not be accurate.
         */
-       if (!err && fc->writeback_cache)
+       if (!err && fm->fc->writeback_cache)
                fuse_invalidate_attr(inode);
        return err;
 }
@@ -498,7 +512,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
                      int datasync, int opcode)
 {
        struct inode *inode = file->f_mapping->host;
-       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_mount *fm = get_fuse_mount(inode);
        struct fuse_file *ff = file->private_data;
        FUSE_ARGS(args);
        struct fuse_fsync_in inarg;
@@ -511,7 +525,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end,
        args.in_numargs = 1;
        args.in_args[0].size = sizeof(inarg);
        args.in_args[0].value = &inarg;
-       return fuse_simple_request(fc, &args);
+       return fuse_simple_request(fm, &args);
 }
 
 static int fuse_fsync(struct file *file, loff_t start, loff_t end,
@@ -686,7 +700,7 @@ static void fuse_io_free(struct fuse_io_args *ia)
        kfree(ia);
 }
 
-static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_args *args,
+static void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args,
                                  int err)
 {
        struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args);
@@ -715,7 +729,7 @@ static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_args *args,
        fuse_io_free(ia);
 }
 
-static ssize_t fuse_async_req_send(struct fuse_conn *fc,
+static ssize_t fuse_async_req_send(struct fuse_mount *fm,
                                   struct fuse_io_args *ia, size_t num_bytes)
 {
        ssize_t err;
@@ -729,9 +743,9 @@ static ssize_t fuse_async_req_send(struct fuse_conn *fc,
 
        ia->ap.args.end = fuse_aio_complete_req;
        ia->ap.args.may_block = io->should_dirty;
-       err = fuse_simple_background(fc, &ia->ap.args, GFP_KERNEL);
+       err = fuse_simple_background(fm, &ia->ap.args, GFP_KERNEL);
        if (err)
-               fuse_aio_complete_req(fc, &ia->ap.args, err);
+               fuse_aio_complete_req(fm, &ia->ap.args, err);
 
        return num_bytes;
 }
@@ -741,18 +755,18 @@ static ssize_t fuse_send_read(struct fuse_io_args *ia, loff_t pos, size_t count,
 {
        struct file *file = ia->io->iocb->ki_filp;
        struct fuse_file *ff = file->private_data;
-       struct fuse_conn *fc = ff->fc;
+       struct fuse_mount *fm = ff->fm;
 
        fuse_read_args_fill(ia, file, pos, count, FUSE_READ);
        if (owner != NULL) {
                ia->read.in.read_flags |= FUSE_READ_LOCKOWNER;
-               ia->read.in.lock_owner = fuse_lock_owner_id(fc, owner);
+               ia->read.in.lock_owner = fuse_lock_owner_id(fm->fc, owner);
        }
 
        if (ia->io->async)
-               return fuse_async_req_send(fc, ia, count);
+               return fuse_async_req_send(fm, ia, count);
 
-       return fuse_simple_request(fc, &ia->ap.args);
+       return fuse_simple_request(fm, &ia->ap.args);
 }
 
 static void fuse_read_update_size(struct inode *inode, loff_t size,
@@ -798,7 +812,7 @@ static void fuse_short_read(struct inode *inode, u64 attr_ver, size_t num_read,
 static int fuse_do_readpage(struct file *file, struct page *page)
 {
        struct inode *inode = page->mapping->host;
-       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_mount *fm = get_fuse_mount(inode);
        loff_t pos = page_offset(page);
        struct fuse_page_desc desc = { .length = PAGE_SIZE };
        struct fuse_io_args ia = {
@@ -818,14 +832,14 @@ static int fuse_do_readpage(struct file *file, struct page *page)
         */
        fuse_wait_on_page_writeback(inode, page->index);
 
-       attr_ver = fuse_get_attr_version(fc);
+       attr_ver = fuse_get_attr_version(fm->fc);
 
        /* Don't overflow end offset */
        if (pos + (desc.length - 1) == LLONG_MAX)
                desc.length--;
 
        fuse_read_args_fill(&ia, file, pos, desc.length, FUSE_READ);
-       res = fuse_simple_request(fc, &ia.ap.args);
+       res = fuse_simple_request(fm, &ia.ap.args);
        if (res < 0)
                return res;
        /*
@@ -855,7 +869,7 @@ static int fuse_readpage(struct file *file, struct page *page)
        return err;
 }
 
-static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_args *args,
+static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
                               int err)
 {
        int i;
@@ -899,7 +913,7 @@ static void fuse_readpages_end(struct fuse_conn *fc, struct fuse_args *args,
 static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
 {
        struct fuse_file *ff = file->private_data;
-       struct fuse_conn *fc = ff->fc;
+       struct fuse_mount *fm = ff->fm;
        struct fuse_args_pages *ap = &ia->ap;
        loff_t pos = page_offset(ap->pages[0]);
        size_t count = ap->num_pages << PAGE_SHIFT;
@@ -918,18 +932,18 @@ static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
        WARN_ON((loff_t) (pos + count) < 0);
 
        fuse_read_args_fill(ia, file, pos, count, FUSE_READ);
-       ia->read.attr_ver = fuse_get_attr_version(fc);
-       if (fc->async_read) {
+       ia->read.attr_ver = fuse_get_attr_version(fm->fc);
+       if (fm->fc->async_read) {
                ia->ff = fuse_file_get(ff);
                ap->args.end = fuse_readpages_end;
-               err = fuse_simple_background(fc, &ap->args, GFP_KERNEL);
+               err = fuse_simple_background(fm, &ap->args, GFP_KERNEL);
                if (!err)
                        return;
        } else {
-               res = fuse_simple_request(fc, &ap->args);
+               res = fuse_simple_request(fm, &ap->args);
                err = res < 0 ? res : 0;
        }
-       fuse_readpages_end(fc, &ap->args, err);
+       fuse_readpages_end(fm, &ap->args, err);
 }
 
 static void fuse_readahead(struct readahead_control *rac)
@@ -1000,7 +1014,7 @@ static void fuse_write_args_fill(struct fuse_io_args *ia, struct fuse_file *ff,
        args->opcode = FUSE_WRITE;
        args->nodeid = ff->nodeid;
        args->in_numargs = 2;
-       if (ff->fc->minor < 9)
+       if (ff->fm->fc->minor < 9)
                args->in_args[0].size = FUSE_COMPAT_WRITE_IN_SIZE;
        else
                args->in_args[0].size = sizeof(ia->write.in);
@@ -1029,7 +1043,7 @@ static ssize_t fuse_send_write(struct fuse_io_args *ia, loff_t pos,
        struct kiocb *iocb = ia->io->iocb;
        struct file *file = iocb->ki_filp;
        struct fuse_file *ff = file->private_data;
-       struct fuse_conn *fc = ff->fc;
+       struct fuse_mount *fm = ff->fm;
        struct fuse_write_in *inarg = &ia->write.in;
        ssize_t err;
 
@@ -1037,13 +1051,13 @@ static ssize_t fuse_send_write(struct fuse_io_args *ia, loff_t pos,
        inarg->flags = fuse_write_flags(iocb);
        if (owner != NULL) {
                inarg->write_flags |= FUSE_WRITE_LOCKOWNER;
-               inarg->lock_owner = fuse_lock_owner_id(fc, owner);
+               inarg->lock_owner = fuse_lock_owner_id(fm->fc, owner);
        }
 
        if (ia->io->async)
-               return fuse_async_req_send(fc, ia, count);
+               return fuse_async_req_send(fm, ia, count);
 
-       err = fuse_simple_request(fc, &ia->ap.args);
+       err = fuse_simple_request(fm, &ia->ap.args);
        if (!err && ia->write.out.size > count)
                err = -EIO;
 
@@ -1074,7 +1088,7 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
        struct fuse_args_pages *ap = &ia->ap;
        struct file *file = iocb->ki_filp;
        struct fuse_file *ff = file->private_data;
-       struct fuse_conn *fc = ff->fc;
+       struct fuse_mount *fm = ff->fm;
        unsigned int offset, i;
        int err;
 
@@ -1084,7 +1098,7 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
        fuse_write_args_fill(ia, ff, pos, count);
        ia->write.in.flags = fuse_write_flags(iocb);
 
-       err = fuse_simple_request(fc, &ap->args);
+       err = fuse_simple_request(fm, &ap->args);
        if (!err && ia->write.out.size > count)
                err = -EIO;
 
@@ -1399,7 +1413,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
        struct file *file = io->iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
        struct fuse_file *ff = file->private_data;
-       struct fuse_conn *fc = ff->fc;
+       struct fuse_conn *fc = ff->fm->fc;
        size_t nmax = write ? fc->max_write : fc->max_read;
        loff_t pos = *ppos;
        size_t count = iov_iter_count(iter);
@@ -1539,10 +1553,14 @@ static ssize_t fuse_file_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
        struct file *file = iocb->ki_filp;
        struct fuse_file *ff = file->private_data;
+       struct inode *inode = file_inode(file);
 
-       if (is_bad_inode(file_inode(file)))
+       if (is_bad_inode(inode))
                return -EIO;
 
+       if (FUSE_IS_DAX(inode))
+               return fuse_dax_read_iter(iocb, to);
+
        if (!(ff->open_flags & FOPEN_DIRECT_IO))
                return fuse_cache_read_iter(iocb, to);
        else
@@ -1553,10 +1571,14 @@ static ssize_t fuse_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
 {
        struct file *file = iocb->ki_filp;
        struct fuse_file *ff = file->private_data;
+       struct inode *inode = file_inode(file);
 
-       if (is_bad_inode(file_inode(file)))
+       if (is_bad_inode(inode))
                return -EIO;
 
+       if (FUSE_IS_DAX(inode))
+               return fuse_dax_write_iter(iocb, from);
+
        if (!(ff->open_flags & FOPEN_DIRECT_IO))
                return fuse_cache_write_iter(iocb, from);
        else
@@ -1578,7 +1600,7 @@ static void fuse_writepage_free(struct fuse_writepage_args *wpa)
        kfree(wpa);
 }
 
-static void fuse_writepage_finish(struct fuse_conn *fc,
+static void fuse_writepage_finish(struct fuse_mount *fm,
                                  struct fuse_writepage_args *wpa)
 {
        struct fuse_args_pages *ap = &wpa->ia.ap;
@@ -1596,7 +1618,7 @@ static void fuse_writepage_finish(struct fuse_conn *fc,
 }
 
 /* Called under fi->lock, may release and reacquire it */
-static void fuse_send_writepage(struct fuse_conn *fc,
+static void fuse_send_writepage(struct fuse_mount *fm,
                                struct fuse_writepage_args *wpa, loff_t size)
 __releases(fi->lock)
 __acquires(fi->lock)
@@ -1622,10 +1644,10 @@ __acquires(fi->lock)
        args->force = true;
        args->nocreds = true;
 
-       err = fuse_simple_background(fc, args, GFP_ATOMIC);
+       err = fuse_simple_background(fm, args, GFP_ATOMIC);
        if (err == -ENOMEM) {
                spin_unlock(&fi->lock);
-               err = fuse_simple_background(fc, args, GFP_NOFS | __GFP_NOFAIL);
+               err = fuse_simple_background(fm, args, GFP_NOFS | __GFP_NOFAIL);
                spin_lock(&fi->lock);
        }
 
@@ -1638,7 +1660,7 @@ __acquires(fi->lock)
  out_free:
        fi->writectr--;
        rb_erase(&wpa->writepages_entry, &fi->writepages);
-       fuse_writepage_finish(fc, wpa);
+       fuse_writepage_finish(fm, wpa);
        spin_unlock(&fi->lock);
 
        /* After fuse_writepage_finish() aux request list is private */
@@ -1662,7 +1684,7 @@ void fuse_flush_writepages(struct inode *inode)
 __releases(fi->lock)
 __acquires(fi->lock)
 {
-       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_mount *fm = get_fuse_mount(inode);
        struct fuse_inode *fi = get_fuse_inode(inode);
        loff_t crop = i_size_read(inode);
        struct fuse_writepage_args *wpa;
@@ -1671,7 +1693,7 @@ __acquires(fi->lock)
                wpa = list_entry(fi->queued_writes.next,
                                 struct fuse_writepage_args, queue_entry);
                list_del_init(&wpa->queue_entry);
-               fuse_send_writepage(fc, wpa, crop);
+               fuse_send_writepage(fm, wpa, crop);
        }
 }
 
@@ -1712,7 +1734,7 @@ static void tree_insert(struct rb_root *root, struct fuse_writepage_args *wpa)
        WARN_ON(fuse_insert_writeback(root, wpa));
 }
 
-static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_args *args,
+static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args,
                               int error)
 {
        struct fuse_writepage_args *wpa =
@@ -1724,7 +1746,7 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_args *args,
        spin_lock(&fi->lock);
        rb_erase(&wpa->writepages_entry, &fi->writepages);
        while (wpa->next) {
-               struct fuse_conn *fc = get_fuse_conn(inode);
+               struct fuse_mount *fm = get_fuse_mount(inode);
                struct fuse_write_in *inarg = &wpa->ia.write.in;
                struct fuse_writepage_args *next = wpa->next;
 
@@ -1756,10 +1778,10 @@ static void fuse_writepage_end(struct fuse_conn *fc, struct fuse_args *args,
                 * no invocations of fuse_writepage_end() while we're in
                 * fuse_set_nowrite..fuse_release_nowrite section.
                 */
-               fuse_send_writepage(fc, next, inarg->offset + inarg->size);
+               fuse_send_writepage(fm, next, inarg->offset + inarg->size);
        }
        fi->writectr--;
-       fuse_writepage_finish(fc, wpa);
+       fuse_writepage_finish(fm, wpa);
        spin_unlock(&fi->lock);
        fuse_writepage_free(wpa);
 }
@@ -2317,6 +2339,10 @@ static int fuse_file_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct fuse_file *ff = file->private_data;
 
+       /* DAX mmap is superior to direct_io mmap */
+       if (FUSE_IS_DAX(file_inode(file)))
+               return fuse_dax_mmap(file, vma);
+
        if (ff->open_flags & FOPEN_DIRECT_IO) {
                /* Can't provide the coherency needed for MAP_SHARED */
                if (vma->vm_flags & VM_MAYSHARE)
@@ -2395,7 +2421,7 @@ static void fuse_lk_fill(struct fuse_args *args, struct file *file,
 static int fuse_getlk(struct file *file, struct file_lock *fl)
 {
        struct inode *inode = file_inode(file);
-       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_mount *fm = get_fuse_mount(inode);
        FUSE_ARGS(args);
        struct fuse_lk_in inarg;
        struct fuse_lk_out outarg;
@@ -2405,9 +2431,9 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
        args.out_numargs = 1;
        args.out_args[0].size = sizeof(outarg);
        args.out_args[0].value = &outarg;
-       err = fuse_simple_request(fc, &args);
+       err = fuse_simple_request(fm, &args);
        if (!err)
-               err = convert_fuse_file_lock(fc, &outarg.lk, fl);
+               err = convert_fuse_file_lock(fm->fc, &outarg.lk, fl);
 
        return err;
 }
@@ -2415,12 +2441,12 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
 static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
 {
        struct inode *inode = file_inode(file);
-       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_mount *fm = get_fuse_mount(inode);
        FUSE_ARGS(args);
        struct fuse_lk_in inarg;
        int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
        struct pid *pid = fl->fl_type != F_UNLCK ? task_tgid(current) : NULL;
-       pid_t pid_nr = pid_nr_ns(pid, fc->pid_ns);
+       pid_t pid_nr = pid_nr_ns(pid, fm->fc->pid_ns);
        int err;
 
        if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
@@ -2433,7 +2459,7 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
                return 0;
 
        fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg);
-       err = fuse_simple_request(fc, &args);
+       err = fuse_simple_request(fm, &args);
 
        /* locking is restartable */
        if (err == -EINTR)
@@ -2487,13 +2513,13 @@ static int fuse_file_flock(struct file *file, int cmd, struct file_lock *fl)
 static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
 {
        struct inode *inode = mapping->host;
-       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_mount *fm = get_fuse_mount(inode);
        FUSE_ARGS(args);
        struct fuse_bmap_in inarg;
        struct fuse_bmap_out outarg;
        int err;
 
-       if (!inode->i_sb->s_bdev || fc->no_bmap)
+       if (!inode->i_sb->s_bdev || fm->fc->no_bmap)
                return 0;
 
        memset(&inarg, 0, sizeof(inarg));
@@ -2507,9 +2533,9 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
        args.out_numargs = 1;
        args.out_args[0].size = sizeof(outarg);
        args.out_args[0].value = &outarg;
-       err = fuse_simple_request(fc, &args);
+       err = fuse_simple_request(fm, &args);
        if (err == -ENOSYS)
-               fc->no_bmap = 1;
+               fm->fc->no_bmap = 1;
 
        return err ? 0 : outarg.block;
 }
@@ -2517,7 +2543,7 @@ static sector_t fuse_bmap(struct address_space *mapping, sector_t block)
 static loff_t fuse_lseek(struct file *file, loff_t offset, int whence)
 {
        struct inode *inode = file->f_mapping->host;
-       struct fuse_conn *fc = get_fuse_conn(inode);
+       struct fuse_mount *fm = get_fuse_mount(inode);
        struct fuse_file *ff = file->private_data;
        FUSE_ARGS(args);
        struct fuse_lseek_in inarg = {
@@ -2528,7 +2554,7 @@ static loff_t fuse_lseek(struct file *file, loff_t offset, int whence)
        struct fuse_lseek_out outarg;
        int err;
 
-       if (fc->no_lseek)
+       if (fm->fc->no_lseek)
                goto fallback;
 
        args.opcode = FUSE_LSEEK;
@@ -2539,10 +2565,10 @@ static loff_t fuse_lseek(struct file *file, loff_t offset, int whence)
        args.out_numargs = 1;
        args.out_args[0].size = sizeof(outarg);
        args.out_args[0].value = &outarg;
-       err = fuse_simple_request(fc, &args);
+       err = fuse_simple_request(fm, &args);
        if (err) {
                if (err == -ENOSYS) {
-                       fc->no_lseek = 1;
+                       fm->fc->no_lseek = 1;
                        goto fallback;
                }
                return err;
@@ -2728,7 +2754,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
                   unsigned int flags)
 {
        struct fuse_file *ff = file->private_data;
-       struct fuse_conn *fc = ff->fc;
+       struct fuse_mount *fm = ff->fm;
        struct fuse_ioctl_in inarg = {
                .fh = ff->fh,
                .cmd = cmd,
@@ -2761,12 +2787,12 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
        BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE);
 
        err = -ENOMEM;
-       ap.pages = fuse_pages_alloc(fc->max_pages, GFP_KERNEL, &ap.descs);
+       ap.pages = fuse_pages_alloc(fm->fc->max_pages, GFP_KERNEL, &ap.descs);
        iov_page = (struct iovec *) __get_free_page(GFP_KERNEL);
        if (!ap.pages || !iov_page)
                goto out;
 
-       fuse_page_descs_length_init(ap.descs, 0, fc->max_pages);
+       fuse_page_descs_length_init(ap.descs, 0, fm->fc->max_pages);
 
        /*
         * If restricted, initialize IO parameters as encoded in @cmd.
@@ -2811,7 +2837,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
 
        /* make sure there are enough buffer pages and init request with them */
        err = -ENOMEM;
-       if (max_pages > fc->max_pages)
+       if (max_pages > fm->fc->max_pages)
                goto out;
        while (ap.num_pages < max_pages) {
                ap.pages[ap.num_pages] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
@@ -2848,7 +2874,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
        ap.args.out_pages = true;
        ap.args.out_argvar = true;
 
-       transferred = fuse_simple_request(fc, &ap.args);
+       transferred = fuse_simple_request(fm, &ap.args);
        err = transferred;
        if (transferred < 0)
                goto out;
@@ -2876,7 +2902,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
                        goto out;
 
                vaddr = kmap_atomic(ap.pages[0]);
-               err = fuse_copy_ioctl_iovec(fc, iov_page, vaddr,
+               err = fuse_copy_ioctl_iovec(fm->fc, iov_page, vaddr,
                                            transferred, in_iovs + out_iovs,
                                            (flags & FUSE_IOCTL_COMPAT) != 0);
                kunmap_atomic(vaddr);
@@ -2886,11 +2912,11 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
                in_iov = iov_page;
                out_iov = in_iov + in_iovs;
 
-               err = fuse_verify_ioctl_iov(fc, in_iov, in_iovs);
+               err = fuse_verify_ioctl_iov(fm->fc, in_iov, in_iovs);
                if (err)
                        goto out;
 
-               err = fuse_verify_ioctl_iov(fc, out_iov, out_iovs);
+               err = fuse_verify_ioctl_iov(fm->fc, out_iov, out_iovs);
                if (err)
                        goto out;
 
@@ -3000,13 +3026,13 @@ static void fuse_register_polled_file(struct fuse_conn *fc,
 __poll_t fuse_file_poll(struct file *file, poll_table *wait)
 {
        struct fuse_file *ff = file->private_data;
-       struct fuse_conn *fc = ff->fc;
+       struct fuse_mount *fm = ff->fm;
        struct fuse_poll_in inarg = { .fh = ff->fh, .kh = ff->kh };
        struct fuse_poll_out outarg;
        FUSE_ARGS(args);
        int err;
 
-       if (fc->no_poll)
+       if (fm->fc->no_poll)
                return DEFAULT_POLLMASK;
 
        poll_wait(file, &ff->poll_wait, wait);
@@ -3018,7 +3044,7 @@ __poll_t fuse_file_poll(struct file *file, poll_table *wait)
         */
        if (waitqueue_active(&ff->poll_wait)) {
                inarg.flags |= FUSE_POLL_SCHEDULE_NOTIFY;
-               fuse_register_polled_file(fc, ff);
+               fuse_register_polled_file(fm->fc, ff);
        }
 
        args.opcode = FUSE_POLL;
@@ -3029,12 +3055,12 @@ __poll_t fuse_file_poll(struct file *file, poll_table *wait)
        args.out_numargs = 1;
        args.out_args[0].size = sizeof(outarg);
        args.out_args[0].value = &outarg;
-       err = fuse_simple_request(fc, &args);
+       err = fuse_simple_request(fm, &args);
 
        if (!err)
                return demangle_poll(outarg.revents);
        if (err == -ENOSYS) {
-               fc->no_poll = 1;
+               fm->fc->no_poll = 1;
                return DEFAULT_POLLMASK;
        }
        return EPOLLERR;
@@ -3120,13 +3146,13 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
         * By default, we want to optimize all I/Os with async request
         * submission to the client filesystem if supported.
         */
-       io->async = ff->fc->async_dio;
+       io->async = ff->fm->fc->async_dio;
        io->iocb = iocb;
        io->blocking = is_sync_kiocb(iocb);
 
        /* optimization for short read */
        if (io->async && !io->write && offset + count > i_size) {
-               iov_iter_truncate(iter, fuse_round_up(ff->fc, i_size - offset));
+               iov_iter_truncate(iter, fuse_round_up(ff->fm->fc, i_size - offset));
                shortened = count - iov_iter_count(iter);
                count -= shortened;
        }
@@ -3196,7 +3222,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        struct fuse_file *ff = file->private_data;
        struct inode *inode = file_inode(file);
        struct fuse_inode *fi = get_fuse_inode(inode);
-       struct fuse_conn *fc = ff->fc;
+       struct fuse_mount *fm = ff->fm;
        FUSE_ARGS(args);
        struct fuse_fallocate_in inarg = {
                .fh = ff->fh,
@@ -3208,14 +3234,23 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        bool lock_inode = !(mode & FALLOC_FL_KEEP_SIZE) ||
                           (mode & FALLOC_FL_PUNCH_HOLE);
 
+       bool block_faults = FUSE_IS_DAX(inode) && lock_inode;
+
        if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
                return -EOPNOTSUPP;
 
-       if (fc->no_fallocate)
+       if (fm->fc->no_fallocate)
                return -EOPNOTSUPP;
 
        if (lock_inode) {
                inode_lock(inode);
+               if (block_faults) {
+                       down_write(&fi->i_mmap_sem);
+                       err = fuse_dax_break_layouts(inode, 0, 0);
+                       if (err)
+                               goto out;
+               }
+
                if (mode & FALLOC_FL_PUNCH_HOLE) {
                        loff_t endbyte = offset + length - 1;
 
@@ -3240,9 +3275,9 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        args.in_numargs = 1;
        args.in_args[0].size = sizeof(inarg);
        args.in_args[0].value = &inarg;
-       err = fuse_simple_request(fc, &args);
+       err = fuse_simple_request(fm, &args);
        if (err == -ENOSYS) {
-               fc->no_fallocate = 1;
+               fm->fc->no_fallocate = 1;
                err = -EOPNOTSUPP;
        }
        if (err)
@@ -3252,7 +3287,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
        if (!(mode & FALLOC_FL_KEEP_SIZE)) {
                bool changed = fuse_write_update_size(inode, offset + length);
 
-               if (changed && fc->writeback_cache)
+               if (changed && fm->fc->writeback_cache)
                        file_update_time(file);
        }
 
@@ -3265,6 +3300,9 @@ out:
        if (!(mode & FALLOC_FL_KEEP_SIZE))
                clear_bit(FUSE_I_SIZE_UNSTABLE, &fi->state);
 
+       if (block_faults)
+               up_write(&fi->i_mmap_sem);
+
        if (lock_inode)
                inode_unlock(inode);
 
@@ -3280,7 +3318,8 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
        struct inode *inode_in = file_inode(file_in);
        struct inode *inode_out = file_inode(file_out);
        struct fuse_inode *fi_out = get_fuse_inode(inode_out);
-       struct fuse_conn *fc = ff_in->fc;
+       struct fuse_mount *fm = ff_in->fm;
+       struct fuse_conn *fc = fm->fc;
        FUSE_ARGS(args);
        struct fuse_copy_file_range_in inarg = {
                .fh_in = ff_in->fh,
@@ -3349,7 +3388,7 @@ static ssize_t __fuse_copy_file_range(struct file *file_in, loff_t pos_in,
        args.out_numargs = 1;
        args.out_args[0].size = sizeof(outarg);
        args.out_args[0].value = &outarg;
-       err = fuse_simple_request(fc, &args);
+       err = fuse_simple_request(fm, &args);
        if (err == -ENOSYS) {
                fc->no_copy_file_range = 1;
                err = -EOPNOTSUPP;
@@ -3404,6 +3443,7 @@ static const struct file_operations fuse_file_operations = {
        .release        = fuse_release,
        .fsync          = fuse_fsync,
        .lock           = fuse_file_lock,
+       .get_unmapped_area = thp_get_unmapped_area,
        .flock          = fuse_file_flock,
        .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
@@ -3439,4 +3479,7 @@ void fuse_init_file_inode(struct inode *inode)
        fi->writectr = 0;
        init_waitqueue_head(&fi->page_waitq);
        fi->writepages = RB_ROOT;
+
+       if (IS_ENABLED(CONFIG_FUSE_DAX))
+               fuse_dax_inode_init(inode);
 }