diff options
Diffstat (limited to 'fs/fuse')
-rw-r--r-- | fs/fuse/cuse.c | 10 | ||||
-rw-r--r-- | fs/fuse/dev.c | 80 | ||||
-rw-r--r-- | fs/fuse/dir.c | 17 | ||||
-rw-r--r-- | fs/fuse/file.c | 272 | ||||
-rw-r--r-- | fs/fuse/fuse_i.h | 36 | ||||
-rw-r--r-- | fs/fuse/inode.c | 12 |
6 files changed, 356 insertions, 71 deletions
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 06b5e086ab3a..aef34b1e635e 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c | |||
@@ -93,8 +93,9 @@ static ssize_t cuse_read(struct file *file, char __user *buf, size_t count, | |||
93 | { | 93 | { |
94 | loff_t pos = 0; | 94 | loff_t pos = 0; |
95 | struct iovec iov = { .iov_base = buf, .iov_len = count }; | 95 | struct iovec iov = { .iov_base = buf, .iov_len = count }; |
96 | struct fuse_io_priv io = { .async = 0, .file = file }; | ||
96 | 97 | ||
97 | return fuse_direct_io(file, &iov, 1, count, &pos, 0); | 98 | return fuse_direct_io(&io, &iov, 1, count, &pos, 0); |
98 | } | 99 | } |
99 | 100 | ||
100 | static ssize_t cuse_write(struct file *file, const char __user *buf, | 101 | static ssize_t cuse_write(struct file *file, const char __user *buf, |
@@ -102,12 +103,13 @@ static ssize_t cuse_write(struct file *file, const char __user *buf, | |||
102 | { | 103 | { |
103 | loff_t pos = 0; | 104 | loff_t pos = 0; |
104 | struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; | 105 | struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; |
106 | struct fuse_io_priv io = { .async = 0, .file = file }; | ||
105 | 107 | ||
106 | /* | 108 | /* |
107 | * No locking or generic_write_checks(), the server is | 109 | * No locking or generic_write_checks(), the server is |
108 | * responsible for locking and sanity checks. | 110 | * responsible for locking and sanity checks. |
109 | */ | 111 | */ |
110 | return fuse_direct_io(file, &iov, 1, count, &pos, 1); | 112 | return fuse_direct_io(&io, &iov, 1, count, &pos, 1); |
111 | } | 113 | } |
112 | 114 | ||
113 | static int cuse_open(struct inode *inode, struct file *file) | 115 | static int cuse_open(struct inode *inode, struct file *file) |
@@ -423,7 +425,7 @@ static int cuse_send_init(struct cuse_conn *cc) | |||
423 | 425 | ||
424 | BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE); | 426 | BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE); |
425 | 427 | ||
426 | req = fuse_get_req(fc, 1); | 428 | req = fuse_get_req_for_background(fc, 1); |
427 | if (IS_ERR(req)) { | 429 | if (IS_ERR(req)) { |
428 | rc = PTR_ERR(req); | 430 | rc = PTR_ERR(req); |
429 | goto err; | 431 | goto err; |
@@ -505,7 +507,7 @@ static int cuse_channel_open(struct inode *inode, struct file *file) | |||
505 | cc->fc.release = cuse_fc_release; | 507 | cc->fc.release = cuse_fc_release; |
506 | 508 | ||
507 | cc->fc.connected = 1; | 509 | cc->fc.connected = 1; |
508 | cc->fc.blocked = 0; | 510 | cc->fc.initialized = 1; |
509 | rc = cuse_send_init(cc); | 511 | rc = cuse_send_init(cc); |
510 | if (rc) { | 512 | if (rc) { |
511 | fuse_conn_put(&cc->fc); | 513 | fuse_conn_put(&cc->fc); |
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a45c19093eb4..1d55f9465400 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c | |||
@@ -112,7 +112,7 @@ static void restore_sigs(sigset_t *oldset) | |||
112 | sigprocmask(SIG_SETMASK, oldset, NULL); | 112 | sigprocmask(SIG_SETMASK, oldset, NULL); |
113 | } | 113 | } |
114 | 114 | ||
115 | static void __fuse_get_request(struct fuse_req *req) | 115 | void __fuse_get_request(struct fuse_req *req) |
116 | { | 116 | { |
117 | atomic_inc(&req->count); | 117 | atomic_inc(&req->count); |
118 | } | 118 | } |
@@ -131,20 +131,30 @@ static void fuse_req_init_context(struct fuse_req *req) | |||
131 | req->in.h.pid = current->pid; | 131 | req->in.h.pid = current->pid; |
132 | } | 132 | } |
133 | 133 | ||
134 | struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages) | 134 | static bool fuse_block_alloc(struct fuse_conn *fc, bool for_background) |
135 | { | ||
136 | return !fc->initialized || (for_background && fc->blocked); | ||
137 | } | ||
138 | |||
139 | static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages, | ||
140 | bool for_background) | ||
135 | { | 141 | { |
136 | struct fuse_req *req; | 142 | struct fuse_req *req; |
137 | sigset_t oldset; | ||
138 | int intr; | ||
139 | int err; | 143 | int err; |
140 | |||
141 | atomic_inc(&fc->num_waiting); | 144 | atomic_inc(&fc->num_waiting); |
142 | block_sigs(&oldset); | 145 | |
143 | intr = wait_event_interruptible(fc->blocked_waitq, !fc->blocked); | 146 | if (fuse_block_alloc(fc, for_background)) { |
144 | restore_sigs(&oldset); | 147 | sigset_t oldset; |
145 | err = -EINTR; | 148 | int intr; |
146 | if (intr) | 149 | |
147 | goto out; | 150 | block_sigs(&oldset); |
151 | intr = wait_event_interruptible_exclusive(fc->blocked_waitq, | ||
152 | !fuse_block_alloc(fc, for_background)); | ||
153 | restore_sigs(&oldset); | ||
154 | err = -EINTR; | ||
155 | if (intr) | ||
156 | goto out; | ||
157 | } | ||
148 | 158 | ||
149 | err = -ENOTCONN; | 159 | err = -ENOTCONN; |
150 | if (!fc->connected) | 160 | if (!fc->connected) |
@@ -152,19 +162,35 @@ struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages) | |||
152 | 162 | ||
153 | req = fuse_request_alloc(npages); | 163 | req = fuse_request_alloc(npages); |
154 | err = -ENOMEM; | 164 | err = -ENOMEM; |
155 | if (!req) | 165 | if (!req) { |
166 | if (for_background) | ||
167 | wake_up(&fc->blocked_waitq); | ||
156 | goto out; | 168 | goto out; |
169 | } | ||
157 | 170 | ||
158 | fuse_req_init_context(req); | 171 | fuse_req_init_context(req); |
159 | req->waiting = 1; | 172 | req->waiting = 1; |
173 | req->background = for_background; | ||
160 | return req; | 174 | return req; |
161 | 175 | ||
162 | out: | 176 | out: |
163 | atomic_dec(&fc->num_waiting); | 177 | atomic_dec(&fc->num_waiting); |
164 | return ERR_PTR(err); | 178 | return ERR_PTR(err); |
165 | } | 179 | } |
180 | |||
181 | struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages) | ||
182 | { | ||
183 | return __fuse_get_req(fc, npages, false); | ||
184 | } | ||
166 | EXPORT_SYMBOL_GPL(fuse_get_req); | 185 | EXPORT_SYMBOL_GPL(fuse_get_req); |
167 | 186 | ||
187 | struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc, | ||
188 | unsigned npages) | ||
189 | { | ||
190 | return __fuse_get_req(fc, npages, true); | ||
191 | } | ||
192 | EXPORT_SYMBOL_GPL(fuse_get_req_for_background); | ||
193 | |||
168 | /* | 194 | /* |
169 | * Return request in fuse_file->reserved_req. However that may | 195 | * Return request in fuse_file->reserved_req. However that may |
170 | * currently be in use. If that is the case, wait for it to become | 196 | * currently be in use. If that is the case, wait for it to become |
@@ -226,19 +252,31 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc, | |||
226 | struct fuse_req *req; | 252 | struct fuse_req *req; |
227 | 253 | ||
228 | atomic_inc(&fc->num_waiting); | 254 | atomic_inc(&fc->num_waiting); |
229 | wait_event(fc->blocked_waitq, !fc->blocked); | 255 | wait_event(fc->blocked_waitq, fc->initialized); |
230 | req = fuse_request_alloc(0); | 256 | req = fuse_request_alloc(0); |
231 | if (!req) | 257 | if (!req) |
232 | req = get_reserved_req(fc, file); | 258 | req = get_reserved_req(fc, file); |
233 | 259 | ||
234 | fuse_req_init_context(req); | 260 | fuse_req_init_context(req); |
235 | req->waiting = 1; | 261 | req->waiting = 1; |
262 | req->background = 0; | ||
236 | return req; | 263 | return req; |
237 | } | 264 | } |
238 | 265 | ||
239 | void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) | 266 | void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) |
240 | { | 267 | { |
241 | if (atomic_dec_and_test(&req->count)) { | 268 | if (atomic_dec_and_test(&req->count)) { |
269 | if (unlikely(req->background)) { | ||
270 | /* | ||
271 | * We get here in the unlikely case that a background | ||
272 | * request was allocated but not sent | ||
273 | */ | ||
274 | spin_lock(&fc->lock); | ||
275 | if (!fc->blocked) | ||
276 | wake_up(&fc->blocked_waitq); | ||
277 | spin_unlock(&fc->lock); | ||
278 | } | ||
279 | |||
242 | if (req->waiting) | 280 | if (req->waiting) |
243 | atomic_dec(&fc->num_waiting); | 281 | atomic_dec(&fc->num_waiting); |
244 | 282 | ||
@@ -336,10 +374,15 @@ __releases(fc->lock) | |||
336 | list_del(&req->intr_entry); | 374 | list_del(&req->intr_entry); |
337 | req->state = FUSE_REQ_FINISHED; | 375 | req->state = FUSE_REQ_FINISHED; |
338 | if (req->background) { | 376 | if (req->background) { |
339 | if (fc->num_background == fc->max_background) { | 377 | req->background = 0; |
378 | |||
379 | if (fc->num_background == fc->max_background) | ||
340 | fc->blocked = 0; | 380 | fc->blocked = 0; |
341 | wake_up_all(&fc->blocked_waitq); | 381 | |
342 | } | 382 | /* Wake up next waiter, if any */ |
383 | if (!fc->blocked && waitqueue_active(&fc->blocked_waitq)) | ||
384 | wake_up(&fc->blocked_waitq); | ||
385 | |||
343 | if (fc->num_background == fc->congestion_threshold && | 386 | if (fc->num_background == fc->congestion_threshold && |
344 | fc->connected && fc->bdi_initialized) { | 387 | fc->connected && fc->bdi_initialized) { |
345 | clear_bdi_congested(&fc->bdi, BLK_RW_SYNC); | 388 | clear_bdi_congested(&fc->bdi, BLK_RW_SYNC); |
@@ -443,6 +486,7 @@ __acquires(fc->lock) | |||
443 | 486 | ||
444 | static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) | 487 | static void __fuse_request_send(struct fuse_conn *fc, struct fuse_req *req) |
445 | { | 488 | { |
489 | BUG_ON(req->background); | ||
446 | spin_lock(&fc->lock); | 490 | spin_lock(&fc->lock); |
447 | if (!fc->connected) | 491 | if (!fc->connected) |
448 | req->out.h.error = -ENOTCONN; | 492 | req->out.h.error = -ENOTCONN; |
@@ -470,7 +514,7 @@ EXPORT_SYMBOL_GPL(fuse_request_send); | |||
470 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, | 514 | static void fuse_request_send_nowait_locked(struct fuse_conn *fc, |
471 | struct fuse_req *req) | 515 | struct fuse_req *req) |
472 | { | 516 | { |
473 | req->background = 1; | 517 | BUG_ON(!req->background); |
474 | fc->num_background++; | 518 | fc->num_background++; |
475 | if (fc->num_background == fc->max_background) | 519 | if (fc->num_background == fc->max_background) |
476 | fc->blocked = 1; | 520 | fc->blocked = 1; |
@@ -2072,6 +2116,7 @@ void fuse_abort_conn(struct fuse_conn *fc) | |||
2072 | if (fc->connected) { | 2116 | if (fc->connected) { |
2073 | fc->connected = 0; | 2117 | fc->connected = 0; |
2074 | fc->blocked = 0; | 2118 | fc->blocked = 0; |
2119 | fc->initialized = 1; | ||
2075 | end_io_requests(fc); | 2120 | end_io_requests(fc); |
2076 | end_queued_requests(fc); | 2121 | end_queued_requests(fc); |
2077 | end_polls(fc); | 2122 | end_polls(fc); |
@@ -2090,6 +2135,7 @@ int fuse_dev_release(struct inode *inode, struct file *file) | |||
2090 | spin_lock(&fc->lock); | 2135 | spin_lock(&fc->lock); |
2091 | fc->connected = 0; | 2136 | fc->connected = 0; |
2092 | fc->blocked = 0; | 2137 | fc->blocked = 0; |
2138 | fc->initialized = 1; | ||
2093 | end_queued_requests(fc); | 2139 | end_queued_requests(fc); |
2094 | end_polls(fc); | 2140 | end_polls(fc); |
2095 | wake_up_all(&fc->blocked_waitq); | 2141 | wake_up_all(&fc->blocked_waitq); |
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index ff15522481d4..254df56b847b 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c | |||
@@ -1562,10 +1562,9 @@ void fuse_release_nowrite(struct inode *inode) | |||
1562 | * vmtruncate() doesn't allow for this case, so do the rlimit checking | 1562 | * vmtruncate() doesn't allow for this case, so do the rlimit checking |
1563 | * and the actual truncation by hand. | 1563 | * and the actual truncation by hand. |
1564 | */ | 1564 | */ |
1565 | static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, | 1565 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, |
1566 | struct file *file) | 1566 | struct file *file) |
1567 | { | 1567 | { |
1568 | struct inode *inode = entry->d_inode; | ||
1569 | struct fuse_conn *fc = get_fuse_conn(inode); | 1568 | struct fuse_conn *fc = get_fuse_conn(inode); |
1570 | struct fuse_req *req; | 1569 | struct fuse_req *req; |
1571 | struct fuse_setattr_in inarg; | 1570 | struct fuse_setattr_in inarg; |
@@ -1574,9 +1573,6 @@ static int fuse_do_setattr(struct dentry *entry, struct iattr *attr, | |||
1574 | loff_t oldsize; | 1573 | loff_t oldsize; |
1575 | int err; | 1574 | int err; |
1576 | 1575 | ||
1577 | if (!fuse_allow_current_process(fc)) | ||
1578 | return -EACCES; | ||
1579 | |||
1580 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) | 1576 | if (!(fc->flags & FUSE_DEFAULT_PERMISSIONS)) |
1581 | attr->ia_valid |= ATTR_FORCE; | 1577 | attr->ia_valid |= ATTR_FORCE; |
1582 | 1578 | ||
@@ -1671,10 +1667,15 @@ error: | |||
1671 | 1667 | ||
1672 | static int fuse_setattr(struct dentry *entry, struct iattr *attr) | 1668 | static int fuse_setattr(struct dentry *entry, struct iattr *attr) |
1673 | { | 1669 | { |
1670 | struct inode *inode = entry->d_inode; | ||
1671 | |||
1672 | if (!fuse_allow_current_process(get_fuse_conn(inode))) | ||
1673 | return -EACCES; | ||
1674 | |||
1674 | if (attr->ia_valid & ATTR_FILE) | 1675 | if (attr->ia_valid & ATTR_FILE) |
1675 | return fuse_do_setattr(entry, attr, attr->ia_file); | 1676 | return fuse_do_setattr(inode, attr, attr->ia_file); |
1676 | else | 1677 | else |
1677 | return fuse_do_setattr(entry, attr, NULL); | 1678 | return fuse_do_setattr(inode, attr, NULL); |
1678 | } | 1679 | } |
1679 | 1680 | ||
1680 | static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, | 1681 | static int fuse_getattr(struct vfsmount *mnt, struct dentry *entry, |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 82f7ee581245..d1c9b85b3f58 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -127,11 +127,13 @@ static void fuse_file_put(struct fuse_file *ff, bool sync) | |||
127 | struct fuse_req *req = ff->reserved_req; | 127 | struct fuse_req *req = ff->reserved_req; |
128 | 128 | ||
129 | if (sync) { | 129 | if (sync) { |
130 | req->background = 0; | ||
130 | fuse_request_send(ff->fc, req); | 131 | fuse_request_send(ff->fc, req); |
131 | path_put(&req->misc.release.path); | 132 | path_put(&req->misc.release.path); |
132 | fuse_put_request(ff->fc, req); | 133 | fuse_put_request(ff->fc, req); |
133 | } else { | 134 | } else { |
134 | req->end = fuse_release_end; | 135 | req->end = fuse_release_end; |
136 | req->background = 1; | ||
135 | fuse_request_send_background(ff->fc, req); | 137 | fuse_request_send_background(ff->fc, req); |
136 | } | 138 | } |
137 | kfree(ff); | 139 | kfree(ff); |
@@ -283,6 +285,7 @@ void fuse_sync_release(struct fuse_file *ff, int flags) | |||
283 | WARN_ON(atomic_read(&ff->count) > 1); | 285 | WARN_ON(atomic_read(&ff->count) > 1); |
284 | fuse_prepare_release(ff, flags, FUSE_RELEASE); | 286 | fuse_prepare_release(ff, flags, FUSE_RELEASE); |
285 | ff->reserved_req->force = 1; | 287 | ff->reserved_req->force = 1; |
288 | ff->reserved_req->background = 0; | ||
286 | fuse_request_send(ff->fc, ff->reserved_req); | 289 | fuse_request_send(ff->fc, ff->reserved_req); |
287 | fuse_put_request(ff->fc, ff->reserved_req); | 290 | fuse_put_request(ff->fc, ff->reserved_req); |
288 | kfree(ff); | 291 | kfree(ff); |
@@ -492,9 +495,115 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos, | |||
492 | req->out.args[0].size = count; | 495 | req->out.args[0].size = count; |
493 | } | 496 | } |
494 | 497 | ||
495 | static size_t fuse_send_read(struct fuse_req *req, struct file *file, | 498 | static void fuse_release_user_pages(struct fuse_req *req, int write) |
499 | { | ||
500 | unsigned i; | ||
501 | |||
502 | for (i = 0; i < req->num_pages; i++) { | ||
503 | struct page *page = req->pages[i]; | ||
504 | if (write) | ||
505 | set_page_dirty_lock(page); | ||
506 | put_page(page); | ||
507 | } | ||
508 | } | ||
509 | |||
510 | /** | ||
511 | * In case of short read, the caller sets 'pos' to the position of | ||
512 | * actual end of fuse request in IO request. Otherwise, if bytes_requested | ||
513 | * == bytes_transferred or rw == WRITE, the caller sets 'pos' to -1. | ||
514 | * | ||
515 | * An example: | ||
516 | * User requested DIO read of 64K. It was splitted into two 32K fuse requests, | ||
517 | * both submitted asynchronously. The first of them was ACKed by userspace as | ||
518 | * fully completed (req->out.args[0].size == 32K) resulting in pos == -1. The | ||
519 | * second request was ACKed as short, e.g. only 1K was read, resulting in | ||
520 | * pos == 33K. | ||
521 | * | ||
522 | * Thus, when all fuse requests are completed, the minimal non-negative 'pos' | ||
523 | * will be equal to the length of the longest contiguous fragment of | ||
524 | * transferred data starting from the beginning of IO request. | ||
525 | */ | ||
526 | static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) | ||
527 | { | ||
528 | int left; | ||
529 | |||
530 | spin_lock(&io->lock); | ||
531 | if (err) | ||
532 | io->err = io->err ? : err; | ||
533 | else if (pos >= 0 && (io->bytes < 0 || pos < io->bytes)) | ||
534 | io->bytes = pos; | ||
535 | |||
536 | left = --io->reqs; | ||
537 | spin_unlock(&io->lock); | ||
538 | |||
539 | if (!left) { | ||
540 | long res; | ||
541 | |||
542 | if (io->err) | ||
543 | res = io->err; | ||
544 | else if (io->bytes >= 0 && io->write) | ||
545 | res = -EIO; | ||
546 | else { | ||
547 | res = io->bytes < 0 ? io->size : io->bytes; | ||
548 | |||
549 | if (!is_sync_kiocb(io->iocb)) { | ||
550 | struct path *path = &io->iocb->ki_filp->f_path; | ||
551 | struct inode *inode = path->dentry->d_inode; | ||
552 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
553 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
554 | |||
555 | spin_lock(&fc->lock); | ||
556 | fi->attr_version = ++fc->attr_version; | ||
557 | spin_unlock(&fc->lock); | ||
558 | } | ||
559 | } | ||
560 | |||
561 | aio_complete(io->iocb, res, 0); | ||
562 | kfree(io); | ||
563 | } | ||
564 | } | ||
565 | |||
566 | static void fuse_aio_complete_req(struct fuse_conn *fc, struct fuse_req *req) | ||
567 | { | ||
568 | struct fuse_io_priv *io = req->io; | ||
569 | ssize_t pos = -1; | ||
570 | |||
571 | fuse_release_user_pages(req, !io->write); | ||
572 | |||
573 | if (io->write) { | ||
574 | if (req->misc.write.in.size != req->misc.write.out.size) | ||
575 | pos = req->misc.write.in.offset - io->offset + | ||
576 | req->misc.write.out.size; | ||
577 | } else { | ||
578 | if (req->misc.read.in.size != req->out.args[0].size) | ||
579 | pos = req->misc.read.in.offset - io->offset + | ||
580 | req->out.args[0].size; | ||
581 | } | ||
582 | |||
583 | fuse_aio_complete(io, req->out.h.error, pos); | ||
584 | } | ||
585 | |||
586 | static size_t fuse_async_req_send(struct fuse_conn *fc, struct fuse_req *req, | ||
587 | size_t num_bytes, struct fuse_io_priv *io) | ||
588 | { | ||
589 | spin_lock(&io->lock); | ||
590 | io->size += num_bytes; | ||
591 | io->reqs++; | ||
592 | spin_unlock(&io->lock); | ||
593 | |||
594 | req->io = io; | ||
595 | req->end = fuse_aio_complete_req; | ||
596 | |||
597 | __fuse_get_request(req); | ||
598 | fuse_request_send_background(fc, req); | ||
599 | |||
600 | return num_bytes; | ||
601 | } | ||
602 | |||
603 | static size_t fuse_send_read(struct fuse_req *req, struct fuse_io_priv *io, | ||
496 | loff_t pos, size_t count, fl_owner_t owner) | 604 | loff_t pos, size_t count, fl_owner_t owner) |
497 | { | 605 | { |
606 | struct file *file = io->file; | ||
498 | struct fuse_file *ff = file->private_data; | 607 | struct fuse_file *ff = file->private_data; |
499 | struct fuse_conn *fc = ff->fc; | 608 | struct fuse_conn *fc = ff->fc; |
500 | 609 | ||
@@ -505,6 +614,10 @@ static size_t fuse_send_read(struct fuse_req *req, struct file *file, | |||
505 | inarg->read_flags |= FUSE_READ_LOCKOWNER; | 614 | inarg->read_flags |= FUSE_READ_LOCKOWNER; |
506 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); | 615 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); |
507 | } | 616 | } |
617 | |||
618 | if (io->async) | ||
619 | return fuse_async_req_send(fc, req, count, io); | ||
620 | |||
508 | fuse_request_send(fc, req); | 621 | fuse_request_send(fc, req); |
509 | return req->out.args[0].size; | 622 | return req->out.args[0].size; |
510 | } | 623 | } |
@@ -525,6 +638,7 @@ static void fuse_read_update_size(struct inode *inode, loff_t size, | |||
525 | 638 | ||
526 | static int fuse_readpage(struct file *file, struct page *page) | 639 | static int fuse_readpage(struct file *file, struct page *page) |
527 | { | 640 | { |
641 | struct fuse_io_priv io = { .async = 0, .file = file }; | ||
528 | struct inode *inode = page->mapping->host; | 642 | struct inode *inode = page->mapping->host; |
529 | struct fuse_conn *fc = get_fuse_conn(inode); | 643 | struct fuse_conn *fc = get_fuse_conn(inode); |
530 | struct fuse_req *req; | 644 | struct fuse_req *req; |
@@ -557,7 +671,7 @@ static int fuse_readpage(struct file *file, struct page *page) | |||
557 | req->num_pages = 1; | 671 | req->num_pages = 1; |
558 | req->pages[0] = page; | 672 | req->pages[0] = page; |
559 | req->page_descs[0].length = count; | 673 | req->page_descs[0].length = count; |
560 | num_read = fuse_send_read(req, file, pos, count, NULL); | 674 | num_read = fuse_send_read(req, &io, pos, count, NULL); |
561 | err = req->out.h.error; | 675 | err = req->out.h.error; |
562 | fuse_put_request(fc, req); | 676 | fuse_put_request(fc, req); |
563 | 677 | ||
@@ -662,7 +776,12 @@ static int fuse_readpages_fill(void *_data, struct page *page) | |||
662 | int nr_alloc = min_t(unsigned, data->nr_pages, | 776 | int nr_alloc = min_t(unsigned, data->nr_pages, |
663 | FUSE_MAX_PAGES_PER_REQ); | 777 | FUSE_MAX_PAGES_PER_REQ); |
664 | fuse_send_readpages(req, data->file); | 778 | fuse_send_readpages(req, data->file); |
665 | data->req = req = fuse_get_req(fc, nr_alloc); | 779 | if (fc->async_read) |
780 | req = fuse_get_req_for_background(fc, nr_alloc); | ||
781 | else | ||
782 | req = fuse_get_req(fc, nr_alloc); | ||
783 | |||
784 | data->req = req; | ||
666 | if (IS_ERR(req)) { | 785 | if (IS_ERR(req)) { |
667 | unlock_page(page); | 786 | unlock_page(page); |
668 | return PTR_ERR(req); | 787 | return PTR_ERR(req); |
@@ -697,7 +816,10 @@ static int fuse_readpages(struct file *file, struct address_space *mapping, | |||
697 | 816 | ||
698 | data.file = file; | 817 | data.file = file; |
699 | data.inode = inode; | 818 | data.inode = inode; |
700 | data.req = fuse_get_req(fc, nr_alloc); | 819 | if (fc->async_read) |
820 | data.req = fuse_get_req_for_background(fc, nr_alloc); | ||
821 | else | ||
822 | data.req = fuse_get_req(fc, nr_alloc); | ||
701 | data.nr_pages = nr_pages; | 823 | data.nr_pages = nr_pages; |
702 | err = PTR_ERR(data.req); | 824 | err = PTR_ERR(data.req); |
703 | if (IS_ERR(data.req)) | 825 | if (IS_ERR(data.req)) |
@@ -759,9 +881,10 @@ static void fuse_write_fill(struct fuse_req *req, struct fuse_file *ff, | |||
759 | req->out.args[0].value = outarg; | 881 | req->out.args[0].value = outarg; |
760 | } | 882 | } |
761 | 883 | ||
762 | static size_t fuse_send_write(struct fuse_req *req, struct file *file, | 884 | static size_t fuse_send_write(struct fuse_req *req, struct fuse_io_priv *io, |
763 | loff_t pos, size_t count, fl_owner_t owner) | 885 | loff_t pos, size_t count, fl_owner_t owner) |
764 | { | 886 | { |
887 | struct file *file = io->file; | ||
765 | struct fuse_file *ff = file->private_data; | 888 | struct fuse_file *ff = file->private_data; |
766 | struct fuse_conn *fc = ff->fc; | 889 | struct fuse_conn *fc = ff->fc; |
767 | struct fuse_write_in *inarg = &req->misc.write.in; | 890 | struct fuse_write_in *inarg = &req->misc.write.in; |
@@ -772,6 +895,10 @@ static size_t fuse_send_write(struct fuse_req *req, struct file *file, | |||
772 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; | 895 | inarg->write_flags |= FUSE_WRITE_LOCKOWNER; |
773 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); | 896 | inarg->lock_owner = fuse_lock_owner_id(fc, owner); |
774 | } | 897 | } |
898 | |||
899 | if (io->async) | ||
900 | return fuse_async_req_send(fc, req, count, io); | ||
901 | |||
775 | fuse_request_send(fc, req); | 902 | fuse_request_send(fc, req); |
776 | return req->misc.write.out.size; | 903 | return req->misc.write.out.size; |
777 | } | 904 | } |
@@ -795,11 +922,12 @@ static size_t fuse_send_write_pages(struct fuse_req *req, struct file *file, | |||
795 | size_t res; | 922 | size_t res; |
796 | unsigned offset; | 923 | unsigned offset; |
797 | unsigned i; | 924 | unsigned i; |
925 | struct fuse_io_priv io = { .async = 0, .file = file }; | ||
798 | 926 | ||
799 | for (i = 0; i < req->num_pages; i++) | 927 | for (i = 0; i < req->num_pages; i++) |
800 | fuse_wait_on_page_writeback(inode, req->pages[i]->index); | 928 | fuse_wait_on_page_writeback(inode, req->pages[i]->index); |
801 | 929 | ||
802 | res = fuse_send_write(req, file, pos, count, NULL); | 930 | res = fuse_send_write(req, &io, pos, count, NULL); |
803 | 931 | ||
804 | offset = req->page_descs[0].offset; | 932 | offset = req->page_descs[0].offset; |
805 | count = res; | 933 | count = res; |
@@ -1034,18 +1162,6 @@ out: | |||
1034 | return written ? written : err; | 1162 | return written ? written : err; |
1035 | } | 1163 | } |
1036 | 1164 | ||
1037 | static void fuse_release_user_pages(struct fuse_req *req, int write) | ||
1038 | { | ||
1039 | unsigned i; | ||
1040 | |||
1041 | for (i = 0; i < req->num_pages; i++) { | ||
1042 | struct page *page = req->pages[i]; | ||
1043 | if (write) | ||
1044 | set_page_dirty_lock(page); | ||
1045 | put_page(page); | ||
1046 | } | ||
1047 | } | ||
1048 | |||
1049 | static inline void fuse_page_descs_length_init(struct fuse_req *req, | 1165 | static inline void fuse_page_descs_length_init(struct fuse_req *req, |
1050 | unsigned index, unsigned nr_pages) | 1166 | unsigned index, unsigned nr_pages) |
1051 | { | 1167 | { |
@@ -1147,10 +1263,11 @@ static inline int fuse_iter_npages(const struct iov_iter *ii_p) | |||
1147 | return min(npages, FUSE_MAX_PAGES_PER_REQ); | 1263 | return min(npages, FUSE_MAX_PAGES_PER_REQ); |
1148 | } | 1264 | } |
1149 | 1265 | ||
1150 | ssize_t fuse_direct_io(struct file *file, const struct iovec *iov, | 1266 | ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov, |
1151 | unsigned long nr_segs, size_t count, loff_t *ppos, | 1267 | unsigned long nr_segs, size_t count, loff_t *ppos, |
1152 | int write) | 1268 | int write) |
1153 | { | 1269 | { |
1270 | struct file *file = io->file; | ||
1154 | struct fuse_file *ff = file->private_data; | 1271 | struct fuse_file *ff = file->private_data; |
1155 | struct fuse_conn *fc = ff->fc; | 1272 | struct fuse_conn *fc = ff->fc; |
1156 | size_t nmax = write ? fc->max_write : fc->max_read; | 1273 | size_t nmax = write ? fc->max_write : fc->max_read; |
@@ -1176,11 +1293,12 @@ ssize_t fuse_direct_io(struct file *file, const struct iovec *iov, | |||
1176 | } | 1293 | } |
1177 | 1294 | ||
1178 | if (write) | 1295 | if (write) |
1179 | nres = fuse_send_write(req, file, pos, nbytes, owner); | 1296 | nres = fuse_send_write(req, io, pos, nbytes, owner); |
1180 | else | 1297 | else |
1181 | nres = fuse_send_read(req, file, pos, nbytes, owner); | 1298 | nres = fuse_send_read(req, io, pos, nbytes, owner); |
1182 | 1299 | ||
1183 | fuse_release_user_pages(req, !write); | 1300 | if (!io->async) |
1301 | fuse_release_user_pages(req, !write); | ||
1184 | if (req->out.h.error) { | 1302 | if (req->out.h.error) { |
1185 | if (!res) | 1303 | if (!res) |
1186 | res = req->out.h.error; | 1304 | res = req->out.h.error; |
@@ -1210,17 +1328,19 @@ ssize_t fuse_direct_io(struct file *file, const struct iovec *iov, | |||
1210 | } | 1328 | } |
1211 | EXPORT_SYMBOL_GPL(fuse_direct_io); | 1329 | EXPORT_SYMBOL_GPL(fuse_direct_io); |
1212 | 1330 | ||
1213 | static ssize_t __fuse_direct_read(struct file *file, const struct iovec *iov, | 1331 | static ssize_t __fuse_direct_read(struct fuse_io_priv *io, |
1214 | unsigned long nr_segs, loff_t *ppos) | 1332 | const struct iovec *iov, |
1333 | unsigned long nr_segs, loff_t *ppos, | ||
1334 | size_t count) | ||
1215 | { | 1335 | { |
1216 | ssize_t res; | 1336 | ssize_t res; |
1337 | struct file *file = io->file; | ||
1217 | struct inode *inode = file_inode(file); | 1338 | struct inode *inode = file_inode(file); |
1218 | 1339 | ||
1219 | if (is_bad_inode(inode)) | 1340 | if (is_bad_inode(inode)) |
1220 | return -EIO; | 1341 | return -EIO; |
1221 | 1342 | ||
1222 | res = fuse_direct_io(file, iov, nr_segs, iov_length(iov, nr_segs), | 1343 | res = fuse_direct_io(io, iov, nr_segs, count, ppos, 0); |
1223 | ppos, 0); | ||
1224 | 1344 | ||
1225 | fuse_invalidate_attr(inode); | 1345 | fuse_invalidate_attr(inode); |
1226 | 1346 | ||
@@ -1230,23 +1350,23 @@ static ssize_t __fuse_direct_read(struct file *file, const struct iovec *iov, | |||
1230 | static ssize_t fuse_direct_read(struct file *file, char __user *buf, | 1350 | static ssize_t fuse_direct_read(struct file *file, char __user *buf, |
1231 | size_t count, loff_t *ppos) | 1351 | size_t count, loff_t *ppos) |
1232 | { | 1352 | { |
1353 | struct fuse_io_priv io = { .async = 0, .file = file }; | ||
1233 | struct iovec iov = { .iov_base = buf, .iov_len = count }; | 1354 | struct iovec iov = { .iov_base = buf, .iov_len = count }; |
1234 | return __fuse_direct_read(file, &iov, 1, ppos); | 1355 | return __fuse_direct_read(&io, &iov, 1, ppos, count); |
1235 | } | 1356 | } |
1236 | 1357 | ||
1237 | static ssize_t __fuse_direct_write(struct file *file, const struct iovec *iov, | 1358 | static ssize_t __fuse_direct_write(struct fuse_io_priv *io, |
1359 | const struct iovec *iov, | ||
1238 | unsigned long nr_segs, loff_t *ppos) | 1360 | unsigned long nr_segs, loff_t *ppos) |
1239 | { | 1361 | { |
1362 | struct file *file = io->file; | ||
1240 | struct inode *inode = file_inode(file); | 1363 | struct inode *inode = file_inode(file); |
1241 | size_t count = iov_length(iov, nr_segs); | 1364 | size_t count = iov_length(iov, nr_segs); |
1242 | ssize_t res; | 1365 | ssize_t res; |
1243 | 1366 | ||
1244 | res = generic_write_checks(file, ppos, &count, 0); | 1367 | res = generic_write_checks(file, ppos, &count, 0); |
1245 | if (!res) { | 1368 | if (!res) |
1246 | res = fuse_direct_io(file, iov, nr_segs, count, ppos, 1); | 1369 | res = fuse_direct_io(io, iov, nr_segs, count, ppos, 1); |
1247 | if (res > 0) | ||
1248 | fuse_write_update_size(inode, *ppos); | ||
1249 | } | ||
1250 | 1370 | ||
1251 | fuse_invalidate_attr(inode); | 1371 | fuse_invalidate_attr(inode); |
1252 | 1372 | ||
@@ -1259,13 +1379,16 @@ static ssize_t fuse_direct_write(struct file *file, const char __user *buf, | |||
1259 | struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; | 1379 | struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = count }; |
1260 | struct inode *inode = file_inode(file); | 1380 | struct inode *inode = file_inode(file); |
1261 | ssize_t res; | 1381 | ssize_t res; |
1382 | struct fuse_io_priv io = { .async = 0, .file = file }; | ||
1262 | 1383 | ||
1263 | if (is_bad_inode(inode)) | 1384 | if (is_bad_inode(inode)) |
1264 | return -EIO; | 1385 | return -EIO; |
1265 | 1386 | ||
1266 | /* Don't allow parallel writes to the same file */ | 1387 | /* Don't allow parallel writes to the same file */ |
1267 | mutex_lock(&inode->i_mutex); | 1388 | mutex_lock(&inode->i_mutex); |
1268 | res = __fuse_direct_write(file, &iov, 1, ppos); | 1389 | res = __fuse_direct_write(&io, &iov, 1, ppos); |
1390 | if (res > 0) | ||
1391 | fuse_write_update_size(inode, *ppos); | ||
1269 | mutex_unlock(&inode->i_mutex); | 1392 | mutex_unlock(&inode->i_mutex); |
1270 | 1393 | ||
1271 | return res; | 1394 | return res; |
@@ -1374,6 +1497,7 @@ static int fuse_writepage_locked(struct page *page) | |||
1374 | if (!req) | 1497 | if (!req) |
1375 | goto err; | 1498 | goto err; |
1376 | 1499 | ||
1500 | req->background = 1; /* writeback always goes to bg_queue */ | ||
1377 | tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); | 1501 | tmp_page = alloc_page(GFP_NOFS | __GFP_HIGHMEM); |
1378 | if (!tmp_page) | 1502 | if (!tmp_page) |
1379 | goto err_free; | 1503 | goto err_free; |
@@ -2227,21 +2351,93 @@ int fuse_notify_poll_wakeup(struct fuse_conn *fc, | |||
2227 | return 0; | 2351 | return 0; |
2228 | } | 2352 | } |
2229 | 2353 | ||
2354 | static void fuse_do_truncate(struct file *file) | ||
2355 | { | ||
2356 | struct inode *inode = file->f_mapping->host; | ||
2357 | struct iattr attr; | ||
2358 | |||
2359 | attr.ia_valid = ATTR_SIZE; | ||
2360 | attr.ia_size = i_size_read(inode); | ||
2361 | |||
2362 | attr.ia_file = file; | ||
2363 | attr.ia_valid |= ATTR_FILE; | ||
2364 | |||
2365 | fuse_do_setattr(inode, &attr, file); | ||
2366 | } | ||
2367 | |||
2230 | static ssize_t | 2368 | static ssize_t |
2231 | fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, | 2369 | fuse_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, |
2232 | loff_t offset, unsigned long nr_segs) | 2370 | loff_t offset, unsigned long nr_segs) |
2233 | { | 2371 | { |
2234 | ssize_t ret = 0; | 2372 | ssize_t ret = 0; |
2235 | struct file *file = NULL; | 2373 | struct file *file = iocb->ki_filp; |
2374 | struct fuse_file *ff = file->private_data; | ||
2236 | loff_t pos = 0; | 2375 | loff_t pos = 0; |
2376 | struct inode *inode; | ||
2377 | loff_t i_size; | ||
2378 | size_t count = iov_length(iov, nr_segs); | ||
2379 | struct fuse_io_priv *io; | ||
2237 | 2380 | ||
2238 | file = iocb->ki_filp; | ||
2239 | pos = offset; | 2381 | pos = offset; |
2382 | inode = file->f_mapping->host; | ||
2383 | i_size = i_size_read(inode); | ||
2384 | |||
2385 | /* optimization for short read */ | ||
2386 | if (rw != WRITE && offset + count > i_size) { | ||
2387 | if (offset >= i_size) | ||
2388 | return 0; | ||
2389 | count = i_size - offset; | ||
2390 | } | ||
2391 | |||
2392 | io = kmalloc(sizeof(struct fuse_io_priv), GFP_KERNEL); | ||
2393 | if (!io) | ||
2394 | return -ENOMEM; | ||
2395 | spin_lock_init(&io->lock); | ||
2396 | io->reqs = 1; | ||
2397 | io->bytes = -1; | ||
2398 | io->size = 0; | ||
2399 | io->offset = offset; | ||
2400 | io->write = (rw == WRITE); | ||
2401 | io->err = 0; | ||
2402 | io->file = file; | ||
2403 | /* | ||
2404 | * By default, we want to optimize all I/Os with async request | ||
2405 | * submission to the client filesystem if supported. | ||
2406 | */ | ||
2407 | io->async = ff->fc->async_dio; | ||
2408 | io->iocb = iocb; | ||
2409 | |||
2410 | /* | ||
2411 | * We cannot asynchronously extend the size of a file. We have no method | ||
2412 | * to wait on real async I/O requests, so we must submit this request | ||
2413 | * synchronously. | ||
2414 | */ | ||
2415 | if (!is_sync_kiocb(iocb) && (offset + count > i_size)) | ||
2416 | io->async = false; | ||
2240 | 2417 | ||
2241 | if (rw == WRITE) | 2418 | if (rw == WRITE) |
2242 | ret = __fuse_direct_write(file, iov, nr_segs, &pos); | 2419 | ret = __fuse_direct_write(io, iov, nr_segs, &pos); |
2243 | else | 2420 | else |
2244 | ret = __fuse_direct_read(file, iov, nr_segs, &pos); | 2421 | ret = __fuse_direct_read(io, iov, nr_segs, &pos, count); |
2422 | |||
2423 | if (io->async) { | ||
2424 | fuse_aio_complete(io, ret < 0 ? ret : 0, -1); | ||
2425 | |||
2426 | /* we have a non-extending, async request, so return */ | ||
2427 | if (ret > 0 && !is_sync_kiocb(iocb)) | ||
2428 | return -EIOCBQUEUED; | ||
2429 | |||
2430 | ret = wait_on_sync_kiocb(iocb); | ||
2431 | } else { | ||
2432 | kfree(io); | ||
2433 | } | ||
2434 | |||
2435 | if (rw == WRITE) { | ||
2436 | if (ret > 0) | ||
2437 | fuse_write_update_size(inode, pos); | ||
2438 | else if (ret < 0 && offset + count > i_size) | ||
2439 | fuse_do_truncate(file); | ||
2440 | } | ||
2245 | 2441 | ||
2246 | return ret; | 2442 | return ret; |
2247 | } | 2443 | } |
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 6aeba864f070..fde7249a3a96 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h | |||
@@ -228,6 +228,20 @@ enum fuse_req_state { | |||
228 | FUSE_REQ_FINISHED | 228 | FUSE_REQ_FINISHED |
229 | }; | 229 | }; |
230 | 230 | ||
231 | /** The request IO state (for asynchronous processing) */ | ||
232 | struct fuse_io_priv { | ||
233 | int async; | ||
234 | spinlock_t lock; | ||
235 | unsigned reqs; | ||
236 | ssize_t bytes; | ||
237 | size_t size; | ||
238 | __u64 offset; | ||
239 | bool write; | ||
240 | int err; | ||
241 | struct kiocb *iocb; | ||
242 | struct file *file; | ||
243 | }; | ||
244 | |||
231 | /** | 245 | /** |
232 | * A request to the client | 246 | * A request to the client |
233 | */ | 247 | */ |
@@ -332,6 +346,9 @@ struct fuse_req { | |||
332 | /** Inode used in the request or NULL */ | 346 | /** Inode used in the request or NULL */ |
333 | struct inode *inode; | 347 | struct inode *inode; |
334 | 348 | ||
349 | /** AIO control block */ | ||
350 | struct fuse_io_priv *io; | ||
351 | |||
335 | /** Link on fi->writepages */ | 352 | /** Link on fi->writepages */ |
336 | struct list_head writepages_entry; | 353 | struct list_head writepages_entry; |
337 | 354 | ||
@@ -417,6 +434,10 @@ struct fuse_conn { | |||
417 | /** Batching of FORGET requests (positive indicates FORGET batch) */ | 434 | /** Batching of FORGET requests (positive indicates FORGET batch) */ |
418 | int forget_batch; | 435 | int forget_batch; |
419 | 436 | ||
437 | /** Flag indicating that INIT reply has been received. Allocating | ||
438 | * any fuse request will be suspended until the flag is set */ | ||
439 | int initialized; | ||
440 | |||
420 | /** Flag indicating if connection is blocked. This will be | 441 | /** Flag indicating if connection is blocked. This will be |
421 | the case before the INIT reply is received, and if there | 442 | the case before the INIT reply is received, and if there |
422 | are too many outstading backgrounds requests */ | 443 | are too many outstading backgrounds requests */ |
@@ -520,6 +541,9 @@ struct fuse_conn { | |||
520 | /** Does the filesystem want adaptive readdirplus? */ | 541 | /** Does the filesystem want adaptive readdirplus? */ |
521 | unsigned readdirplus_auto:1; | 542 | unsigned readdirplus_auto:1; |
522 | 543 | ||
544 | /** Does the filesystem support asynchronous direct-IO submission? */ | ||
545 | unsigned async_dio:1; | ||
546 | |||
523 | /** The number of requests waiting for completion */ | 547 | /** The number of requests waiting for completion */ |
524 | atomic_t num_waiting; | 548 | atomic_t num_waiting; |
525 | 549 | ||
@@ -708,6 +732,13 @@ void fuse_request_free(struct fuse_req *req); | |||
708 | * caller should specify # elements in req->pages[] explicitly | 732 | * caller should specify # elements in req->pages[] explicitly |
709 | */ | 733 | */ |
710 | struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages); | 734 | struct fuse_req *fuse_get_req(struct fuse_conn *fc, unsigned npages); |
735 | struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc, | ||
736 | unsigned npages); | ||
737 | |||
738 | /* | ||
739 | * Increment reference count on request | ||
740 | */ | ||
741 | void __fuse_get_request(struct fuse_req *req); | ||
711 | 742 | ||
712 | /** | 743 | /** |
713 | * Get a request, may fail with -ENOMEM, | 744 | * Get a request, may fail with -ENOMEM, |
@@ -823,7 +854,7 @@ int fuse_reverse_inval_entry(struct super_block *sb, u64 parent_nodeid, | |||
823 | 854 | ||
824 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, | 855 | int fuse_do_open(struct fuse_conn *fc, u64 nodeid, struct file *file, |
825 | bool isdir); | 856 | bool isdir); |
826 | ssize_t fuse_direct_io(struct file *file, const struct iovec *iov, | 857 | ssize_t fuse_direct_io(struct fuse_io_priv *io, const struct iovec *iov, |
827 | unsigned long nr_segs, size_t count, loff_t *ppos, | 858 | unsigned long nr_segs, size_t count, loff_t *ppos, |
828 | int write); | 859 | int write); |
829 | long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | 860 | long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, |
@@ -835,4 +866,7 @@ int fuse_dev_release(struct inode *inode, struct file *file); | |||
835 | 866 | ||
836 | void fuse_write_update_size(struct inode *inode, loff_t pos); | 867 | void fuse_write_update_size(struct inode *inode, loff_t pos); |
837 | 868 | ||
869 | int fuse_do_setattr(struct inode *inode, struct iattr *attr, | ||
870 | struct file *file); | ||
871 | |||
838 | #endif /* _FS_FUSE_I_H */ | 872 | #endif /* _FS_FUSE_I_H */ |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 137185c3884f..6201f81e4d3a 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -346,6 +346,7 @@ static void fuse_send_destroy(struct fuse_conn *fc) | |||
346 | fc->destroy_req = NULL; | 346 | fc->destroy_req = NULL; |
347 | req->in.h.opcode = FUSE_DESTROY; | 347 | req->in.h.opcode = FUSE_DESTROY; |
348 | req->force = 1; | 348 | req->force = 1; |
349 | req->background = 0; | ||
349 | fuse_request_send(fc, req); | 350 | fuse_request_send(fc, req); |
350 | fuse_put_request(fc, req); | 351 | fuse_put_request(fc, req); |
351 | } | 352 | } |
@@ -362,6 +363,7 @@ void fuse_conn_kill(struct fuse_conn *fc) | |||
362 | spin_lock(&fc->lock); | 363 | spin_lock(&fc->lock); |
363 | fc->connected = 0; | 364 | fc->connected = 0; |
364 | fc->blocked = 0; | 365 | fc->blocked = 0; |
366 | fc->initialized = 1; | ||
365 | spin_unlock(&fc->lock); | 367 | spin_unlock(&fc->lock); |
366 | /* Flush all readers on this fs */ | 368 | /* Flush all readers on this fs */ |
367 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); | 369 | kill_fasync(&fc->fasync, SIGIO, POLL_IN); |
@@ -581,7 +583,8 @@ void fuse_conn_init(struct fuse_conn *fc) | |||
581 | fc->khctr = 0; | 583 | fc->khctr = 0; |
582 | fc->polled_files = RB_ROOT; | 584 | fc->polled_files = RB_ROOT; |
583 | fc->reqctr = 0; | 585 | fc->reqctr = 0; |
584 | fc->blocked = 1; | 586 | fc->blocked = 0; |
587 | fc->initialized = 0; | ||
585 | fc->attr_version = 1; | 588 | fc->attr_version = 1; |
586 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); | 589 | get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key)); |
587 | } | 590 | } |
@@ -868,6 +871,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
868 | fc->do_readdirplus = 1; | 871 | fc->do_readdirplus = 1; |
869 | if (arg->flags & FUSE_READDIRPLUS_AUTO) | 872 | if (arg->flags & FUSE_READDIRPLUS_AUTO) |
870 | fc->readdirplus_auto = 1; | 873 | fc->readdirplus_auto = 1; |
874 | if (arg->flags & FUSE_ASYNC_DIO) | ||
875 | fc->async_dio = 1; | ||
871 | } else { | 876 | } else { |
872 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; | 877 | ra_pages = fc->max_read / PAGE_CACHE_SIZE; |
873 | fc->no_lock = 1; | 878 | fc->no_lock = 1; |
@@ -880,7 +885,7 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) | |||
880 | fc->max_write = max_t(unsigned, 4096, fc->max_write); | 885 | fc->max_write = max_t(unsigned, 4096, fc->max_write); |
881 | fc->conn_init = 1; | 886 | fc->conn_init = 1; |
882 | } | 887 | } |
883 | fc->blocked = 0; | 888 | fc->initialized = 1; |
884 | wake_up_all(&fc->blocked_waitq); | 889 | wake_up_all(&fc->blocked_waitq); |
885 | } | 890 | } |
886 | 891 | ||
@@ -895,7 +900,7 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) | |||
895 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | | 900 | FUSE_EXPORT_SUPPORT | FUSE_BIG_WRITES | FUSE_DONT_MASK | |
896 | FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | | 901 | FUSE_SPLICE_WRITE | FUSE_SPLICE_MOVE | FUSE_SPLICE_READ | |
897 | FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | | 902 | FUSE_FLOCK_LOCKS | FUSE_IOCTL_DIR | FUSE_AUTO_INVAL_DATA | |
898 | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO; | 903 | FUSE_DO_READDIRPLUS | FUSE_READDIRPLUS_AUTO | FUSE_ASYNC_DIO; |
899 | req->in.h.opcode = FUSE_INIT; | 904 | req->in.h.opcode = FUSE_INIT; |
900 | req->in.numargs = 1; | 905 | req->in.numargs = 1; |
901 | req->in.args[0].size = sizeof(*arg); | 906 | req->in.args[0].size = sizeof(*arg); |
@@ -1043,6 +1048,7 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
1043 | init_req = fuse_request_alloc(0); | 1048 | init_req = fuse_request_alloc(0); |
1044 | if (!init_req) | 1049 | if (!init_req) |
1045 | goto err_put_root; | 1050 | goto err_put_root; |
1051 | init_req->background = 1; | ||
1046 | 1052 | ||
1047 | if (is_bdev) { | 1053 | if (is_bdev) { |
1048 | fc->destroy_req = fuse_request_alloc(0); | 1054 | fc->destroy_req = fuse_request_alloc(0); |