diff options
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/dev.c | 32 | ||||
-rw-r--r-- | fs/fuse/dir.c | 7 | ||||
-rw-r--r-- | fs/fuse/file.c | 43 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 3 | ||||
-rw-r--r-- | fs/fuse/inode.c | 8 |
5 files changed, 26 insertions, 67 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index cbece1221..a94d2ed81 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -99,19 +99,6 @@ void fuse_request_free(struct fuse_req *req) kmem_cache_free(fuse_req_cachep, req); } -static void block_sigs(sigset_t *oldset) -{ - sigset_t mask; - - siginitsetinv(&mask, sigmask(SIGKILL)); - sigprocmask(SIG_BLOCK, &mask, oldset); -} - -static void restore_sigs(sigset_t *oldset) -{ - sigprocmask(SIG_SETMASK, oldset, NULL); -} - void __fuse_get_request(struct fuse_req *req) { atomic_inc(&req->count); @@ -151,15 +138,9 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages, atomic_inc(&fc->num_waiting); if (fuse_block_alloc(fc, for_background)) { - sigset_t oldset; - int intr; - - block_sigs(&oldset); - intr = wait_event_interruptible_exclusive(fc->blocked_waitq, - !fuse_block_alloc(fc, for_background)); - restore_sigs(&oldset); err = -EINTR; - if (intr) + if (wait_event_killable_exclusive(fc->blocked_waitq, + !fuse_block_alloc(fc, for_background))) goto out; } /* Matches smp_wmb() in fuse_set_initialized() */ @@ -446,14 +427,9 @@ static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) } if (!test_bit(FR_FORCE, &req->flags)) { - sigset_t oldset; - /* Only fatal signals may interrupt this */ - block_sigs(&oldset); - err = wait_event_interruptible(req->waitq, + err = wait_event_killable(req->waitq, test_bit(FR_FINISHED, &req->flags)); - restore_sigs(&oldset); - if (!err) return; @@ -1525,7 +1501,6 @@ static int fuse_notify_inval_entry(struct fuse_conn *fc, unsigned int size, goto err; fuse_copy_finish(cs); buf[outarg.namelen] = 0; - name.hash = full_name_hash(name.name, name.len); down_read(&fc->killsb); err = -ENOENT; @@ -1576,7 +1551,6 @@ static int fuse_notify_delete(struct fuse_conn *fc, unsigned int size, goto err; fuse_copy_finish(cs); buf[outarg.namelen] = 0; - name.hash = full_name_hash(name.name, name.len); down_read(&fc->killsb); err = -ENOENT; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index cca7b048c..c47b7780c 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -146,7 +146,7 @@ static void fuse_invalidate_entry(struct dentry *entry) } static void fuse_lookup_init(struct fuse_conn *fc, struct fuse_args *args, - u64 nodeid, struct qstr *name, + u64 nodeid, const struct qstr *name, struct fuse_entry_out *outarg) { memset(outarg, 0, sizeof(struct fuse_entry_out)); @@ -282,7 +282,7 @@ int fuse_valid_type(int m) S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m); } -int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, +int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, struct fuse_entry_out *outarg, struct inode **inode) { struct fuse_conn *fc = get_fuse_conn_super(sb); @@ -955,6 +955,7 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, if (!dir) goto unlock; + name->hash = full_name_hash(dir, name->name, name->len); entry = d_lookup(dir, name); dput(dir); if (!entry) @@ -1204,7 +1205,7 @@ static int fuse_direntplus_link(struct file *file, fc = get_fuse_conn(dir); - name.hash = full_name_hash(name.name, name.len); + name.hash = full_name_hash(parent, name.name, name.len); dentry = d_lookup(parent, &name); if (!dentry) { retry: diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 76962a349..3988b43c2 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -417,12 +417,7 @@ static int fuse_flush(struct file *file, fl_owner_t id) fuse_sync_writes(inode); inode_unlock(inode); - if (test_bit(AS_ENOSPC, &file->f_mapping->flags) && - test_and_clear_bit(AS_ENOSPC, &file->f_mapping->flags)) - err = -ENOSPC; - if (test_bit(AS_EIO, &file->f_mapping->flags) && - test_and_clear_bit(AS_EIO, &file->f_mapping->flags)) - err = -EIO; + err = filemap_check_errors(file->f_mapping); if (err) return err; @@ -477,12 +472,7 @@ int fuse_fsync_common(struct file *file, loff_t start, loff_t end, * filemap_write_and_wait_range() does not catch errors. * We have to do this directly after fuse_sync_writes() */ - if (test_bit(AS_ENOSPC, &file->f_mapping->flags) && - test_and_clear_bit(AS_ENOSPC, &file->f_mapping->flags)) - err = -ENOSPC; - if (test_bit(AS_EIO, &file->f_mapping->flags) && - test_and_clear_bit(AS_EIO, &file->f_mapping->flags)) - err = -EIO; + err = filemap_check_errors(file->f_mapping); if (err) goto out; @@ -586,7 +576,6 @@ static ssize_t fuse_get_res_by_io(struct fuse_io_priv *io) */ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) { - bool is_sync = is_sync_kiocb(io->iocb); int left; spin_lock(&io->lock); @@ -596,11 +585,11 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) io->bytes = pos; left = --io->reqs; - if (!left && is_sync) + if (!left && io->blocking) complete(io->done); spin_unlock(&io->lock); - if (!left && !is_sync) { + if (!left && !io->blocking) { ssize_t res = fuse_get_res_by_io(io); if (res >= 0) { @@ -1477,7 +1466,7 @@ static void fuse_writepage_finish(struct fuse_conn *fc, struct fuse_req *req) list_del(&req->writepages_entry); for (i = 0; i < req->num_pages; i++) { dec_wb_stat(&bdi->wb, WB_WRITEBACK); - dec_zone_page_state(req->pages[i], NR_WRITEBACK_TEMP); + dec_node_page_state(req->pages[i], NR_WRITEBACK_TEMP); wb_writeout_inc(&bdi->wb); } wake_up(&fi->page_waitq); @@ -1667,7 +1656,7 @@ static int fuse_writepage_locked(struct page *page) req->inode = inode; inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK); - inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP); + inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP); spin_lock(&fc->lock); list_add(&req->writepages_entry, &fi->writepages); @@ -1781,7 +1770,7 @@ static bool fuse_writepage_in_flight(struct fuse_req *new_req, spin_unlock(&fc->lock); dec_wb_stat(&bdi->wb, WB_WRITEBACK); - dec_zone_page_state(page, NR_WRITEBACK_TEMP); + dec_node_page_state(page, NR_WRITEBACK_TEMP); wb_writeout_inc(&bdi->wb); fuse_writepage_free(fc, new_req); fuse_request_free(new_req); @@ -1880,7 +1869,7 @@ static int fuse_writepages_fill(struct page *page, req->page_descs[req->num_pages].length = PAGE_SIZE; inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK); - inc_zone_page_state(tmp_page, NR_WRITEBACK_TEMP); + inc_node_page_state(tmp_page, NR_WRITEBACK_TEMP); err = 0; if (is_writeback && fuse_writepage_in_flight(req, page)) { @@ -2875,7 +2864,6 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter) size_t count = iov_iter_count(iter); loff_t offset = iocb->ki_pos; struct fuse_io_priv *io; - bool is_sync = is_sync_kiocb(iocb); pos = offset; inode = file->f_mapping->host; @@ -2910,17 +2898,16 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter) */ io->async = async_dio; io->iocb = iocb; + io->blocking = is_sync_kiocb(iocb); /* - * We cannot asynchronously extend the size of a file. We have no method - * to wait on real async I/O requests, so we must submit this request - * synchronously. + * We cannot asynchronously extend the size of a file. + * In such case the aio will behave exactly like sync io. */ - if (!is_sync && (offset + count > i_size) && - iov_iter_rw(iter) == WRITE) - io->async = false; + if ((offset + count > i_size) && iov_iter_rw(iter) == WRITE) + io->blocking = true; - if (io->async && is_sync) { + if (io->async && io->blocking) { /* * Additional reference to keep io around after * calling fuse_aio_complete() @@ -2940,7 +2927,7 @@ fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter) fuse_aio_complete(io, ret < 0 ? ret : 0, -1); /* we have a non-extending, async request, so return */ - if (!is_sync) + if (!io->blocking) return -EIOCBQUEUED; wait_for_completion(&wait); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 929c38343..d98d8cc84 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -259,6 +259,7 @@ struct fuse_io_priv { struct kiocb *iocb; struct file *file; struct completion *done; + bool blocking; }; #define FUSE_IO_PRIV_SYNC(f) \ @@ -703,7 +704,7 @@ struct inode *fuse_iget(struct super_block *sb, u64 nodeid, int generation, struct fuse_attr *attr, u64 attr_valid, u64 attr_version); -int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name, +int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name, struct fuse_entry_out *outarg, struct inode **inode); /** diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 9b7cb37b4..4e05b5112 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -673,13 +673,11 @@ static struct dentry *fuse_get_dentry(struct super_block *sb, inode = ilookup5(sb, handle->nodeid, fuse_inode_eq, &handle->nodeid); if (!inode) { struct fuse_entry_out outarg; - struct qstr name; + const struct qstr name = QSTR_INIT(".", 1); if (!fc->export_support) goto out_err; - name.len = 1; - name.name = "."; err = fuse_lookup_name(sb, handle->nodeid, &name, &outarg, &inode); if (err && err != -ENOENT) @@ -775,14 +773,12 @@ static struct dentry *fuse_get_parent(struct dentry *child) struct inode *inode; struct dentry *parent; struct fuse_entry_out outarg; - struct qstr name; + const struct qstr name = QSTR_INIT("..", 2); int err; if (!fc->export_support) return ERR_PTR(-ESTALE); - name.len = 2; - name.name = ".."; err = fuse_lookup_name(child_inode->i_sb, get_node_id(child_inode), &name, &outarg, &inode); if (err) { |