Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'fuse-fixes-5.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse

Pull fuse fixes from Miklos Szeredi:
"Mostly virtiofs fixes, but also fixes a regression and couple of
longstanding data/metadata writeback ordering issues"

* tag 'fuse-fixes-5.4-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse:
fuse: redundant get_fuse_inode() calls in fuse_writepages_fill()
fuse: Add changelog entries for protocols 7.1 - 7.8
fuse: truncate pending writes on O_TRUNC
fuse: flush dirty data/metadata before non-truncate setattr
virtiofs: Remove set but not used variable 'fc'
virtiofs: Retry request submission from worker context
virtiofs: Count pending forgets as in_flight forgets
virtiofs: Set FR_SENT flag only after request has been sent
virtiofs: No need to check fpq->connected state
virtiofs: Do not end request in submission context
fuse: don't advise readdirplus for negative lookup
fuse: don't dereference req->args on finished request
virtio-fs: don't show mount options
virtio-fs: Change module name to virtiofs.ko

+186 -65
+2 -1
fs/fuse/Makefile
··· 5 5 6 6 obj-$(CONFIG_FUSE_FS) += fuse.o 7 7 obj-$(CONFIG_CUSE) += cuse.o 8 - obj-$(CONFIG_VIRTIO_FS) += virtio_fs.o 8 + obj-$(CONFIG_VIRTIO_FS) += virtiofs.o 9 9 10 10 fuse-objs := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o 11 + virtiofs-y += virtio_fs.o
+3 -1
fs/fuse/dev.c
··· 276 276 void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) 277 277 { 278 278 struct fuse_iqueue *fiq = &fc->iq; 279 - bool async = req->args->end; 279 + bool async; 280 280 281 281 if (test_and_set_bit(FR_FINISHED, &req->flags)) 282 282 goto put_request; 283 + 284 + async = req->args->end; 283 285 /* 284 286 * test_and_set_bit() implies smp_mb() between bit 285 287 * changing and below intr_entry check. Pairs with
+15 -1
fs/fuse/dir.c
··· 405 405 else 406 406 fuse_invalidate_entry_cache(entry); 407 407 408 - fuse_advise_use_readdirplus(dir); 408 + if (inode) 409 + fuse_advise_use_readdirplus(dir); 409 410 return newent; 410 411 411 412 out_iput: ··· 1520 1519 if (WARN_ON(!S_ISREG(inode->i_mode))) 1521 1520 return -EIO; 1522 1521 is_truncate = true; 1522 + } 1523 + 1524 + /* Flush dirty data/metadata before non-truncate SETATTR */ 1525 + if (is_wb && S_ISREG(inode->i_mode) && 1526 + attr->ia_valid & 1527 + (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME_SET | 1528 + ATTR_TIMES_SET)) { 1529 + err = write_inode_now(inode, true); 1530 + if (err) 1531 + return err; 1532 + 1533 + fuse_set_nowrite(inode); 1534 + fuse_release_nowrite(inode); 1523 1535 } 1524 1536 1525 1537 if (is_truncate) {
+8 -6
fs/fuse/file.c
··· 217 217 { 218 218 struct fuse_conn *fc = get_fuse_conn(inode); 219 219 int err; 220 - bool lock_inode = (file->f_flags & O_TRUNC) && 220 + bool is_wb_truncate = (file->f_flags & O_TRUNC) && 221 221 fc->atomic_o_trunc && 222 222 fc->writeback_cache; 223 223 ··· 225 225 if (err) 226 226 return err; 227 227 228 - if (lock_inode) 228 + if (is_wb_truncate) { 229 229 inode_lock(inode); 230 + fuse_set_nowrite(inode); 231 + } 230 232 231 233 err = fuse_do_open(fc, get_node_id(inode), file, isdir); 232 234 233 235 if (!err) 234 236 fuse_finish_open(inode, file); 235 237 236 - if (lock_inode) 238 + if (is_wb_truncate) { 239 + fuse_release_nowrite(inode); 237 240 inode_unlock(inode); 241 + } 238 242 239 243 return err; 240 244 } ··· 2001 1997 2002 1998 if (!data->ff) { 2003 1999 err = -EIO; 2004 - data->ff = fuse_write_file_get(fc, get_fuse_inode(inode)); 2000 + data->ff = fuse_write_file_get(fc, fi); 2005 2001 if (!data->ff) 2006 2002 goto out_unlock; 2007 2003 } ··· 2046 2042 * under writeback, so we can release the page lock. 2047 2043 */ 2048 2044 if (data->wpa == NULL) { 2049 - struct fuse_inode *fi = get_fuse_inode(inode); 2050 - 2051 2045 err = -ENOMEM; 2052 2046 wpa = fuse_writepage_args_alloc(); 2053 2047 if (!wpa) {
+4
fs/fuse/fuse_i.h
··· 479 479 bool destroy:1; 480 480 bool no_control:1; 481 481 bool no_force_umount:1; 482 + bool no_mount_options:1; 482 483 unsigned int max_read; 483 484 unsigned int blksize; 484 485 const char *subtype; ··· 713 712 714 713 /** Do not allow MNT_FORCE umount */ 715 714 unsigned int no_force_umount:1; 715 + 716 + /* Do not show mount options */ 717 + unsigned int no_mount_options:1; 716 718 717 719 /** The number of requests waiting for completion */ 718 720 atomic_t num_waiting;
+4
fs/fuse/inode.c
··· 558 558 struct super_block *sb = root->d_sb; 559 559 struct fuse_conn *fc = get_fuse_conn_super(sb); 560 560 561 + if (fc->no_mount_options) 562 + return 0; 563 + 561 564 seq_printf(m, ",user_id=%u", from_kuid_munged(fc->user_ns, fc->user_id)); 562 565 seq_printf(m, ",group_id=%u", from_kgid_munged(fc->user_ns, fc->group_id)); 563 566 if (fc->default_permissions) ··· 1183 1180 fc->destroy = ctx->destroy; 1184 1181 fc->no_control = ctx->no_control; 1185 1182 fc->no_force_umount = ctx->no_force_umount; 1183 + fc->no_mount_options = ctx->no_mount_options; 1186 1184 1187 1185 err = -ENOMEM; 1188 1186 root = fuse_get_root_inode(sb, ctx->rootmode);
+113 -56
fs/fuse/virtio_fs.c
··· 30 30 struct virtqueue *vq; /* protected by ->lock */ 31 31 struct work_struct done_work; 32 32 struct list_head queued_reqs; 33 + struct list_head end_reqs; /* End these requests */ 33 34 struct delayed_work dispatch_work; 34 35 struct fuse_dev *fud; 35 36 bool connected; ··· 55 54 struct list_head list; 56 55 }; 57 56 57 + static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq, 58 + struct fuse_req *req, bool in_flight); 59 + 58 60 static inline struct virtio_fs_vq *vq_to_fsvq(struct virtqueue *vq) 59 61 { 60 62 struct virtio_fs *fs = vq->vdev->priv; ··· 68 64 static inline struct fuse_pqueue *vq_to_fpq(struct virtqueue *vq) 69 65 { 70 66 return &vq_to_fsvq(vq)->fud->pq; 67 + } 68 + 69 + /* Should be called with fsvq->lock held. */ 70 + static inline void inc_in_flight_req(struct virtio_fs_vq *fsvq) 71 + { 72 + fsvq->in_flight++; 73 + } 74 + 75 + /* Should be called with fsvq->lock held. */ 76 + static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq) 77 + { 78 + WARN_ON(fsvq->in_flight <= 0); 79 + fsvq->in_flight--; 71 80 } 72 81 73 82 static void release_virtio_fs_obj(struct kref *ref) ··· 126 109 flush_delayed_work(&fsvq->dispatch_work); 127 110 } 128 111 129 - static inline void drain_hiprio_queued_reqs(struct virtio_fs_vq *fsvq) 130 - { 131 - struct virtio_fs_forget *forget; 132 - 133 - spin_lock(&fsvq->lock); 134 - while (1) { 135 - forget = list_first_entry_or_null(&fsvq->queued_reqs, 136 - struct virtio_fs_forget, list); 137 - if (!forget) 138 - break; 139 - list_del(&forget->list); 140 - kfree(forget); 141 - } 142 - spin_unlock(&fsvq->lock); 143 - } 144 - 145 112 static void virtio_fs_drain_all_queues(struct virtio_fs *fs) 146 113 { 147 114 struct virtio_fs_vq *fsvq; ··· 133 132 134 133 for (i = 0; i < fs->nvqs; i++) { 135 134 fsvq = &fs->vqs[i]; 136 - if (i == VQ_HIPRIO) 137 - drain_hiprio_queued_reqs(fsvq); 138 - 139 135 virtio_fs_drain_queue(fsvq); 140 136 } 141 137 } ··· 251 253 252 254 while ((req = virtqueue_get_buf(vq, &len)) != NULL) { 253 255 kfree(req); 254 - fsvq->in_flight--; 256 + dec_in_flight_req(fsvq); 255 257 } 256 258 } while (!virtqueue_enable_cb(vq) && likely(!virtqueue_is_broken(vq))); 257 259 spin_unlock(&fsvq->lock); 258 260 } 259 261 260 - static void virtio_fs_dummy_dispatch_work(struct work_struct *work) 262 + static void virtio_fs_request_dispatch_work(struct work_struct *work) 261 263 { 264 + struct fuse_req *req; 265 + struct virtio_fs_vq *fsvq = container_of(work, struct virtio_fs_vq, 266 + dispatch_work.work); 267 + struct fuse_conn *fc = fsvq->fud->fc; 268 + int ret; 269 + 270 + pr_debug("virtio-fs: worker %s called.\n", __func__); 271 + while (1) { 272 + spin_lock(&fsvq->lock); 273 + req = list_first_entry_or_null(&fsvq->end_reqs, struct fuse_req, 274 + list); 275 + if (!req) { 276 + spin_unlock(&fsvq->lock); 277 + break; 278 + } 279 + 280 + list_del_init(&req->list); 281 + spin_unlock(&fsvq->lock); 282 + fuse_request_end(fc, req); 283 + } 284 + 285 + /* Dispatch pending requests */ 286 + while (1) { 287 + spin_lock(&fsvq->lock); 288 + req = list_first_entry_or_null(&fsvq->queued_reqs, 289 + struct fuse_req, list); 290 + if (!req) { 291 + spin_unlock(&fsvq->lock); 292 + return; 293 + } 294 + list_del_init(&req->list); 295 + spin_unlock(&fsvq->lock); 296 + 297 + ret = virtio_fs_enqueue_req(fsvq, req, true); 298 + if (ret < 0) { 299 + if (ret == -ENOMEM || ret == -ENOSPC) { 300 + spin_lock(&fsvq->lock); 301 + list_add_tail(&req->list, &fsvq->queued_reqs); 302 + schedule_delayed_work(&fsvq->dispatch_work, 303 + msecs_to_jiffies(1)); 304 + spin_unlock(&fsvq->lock); 305 + return; 306 + } 307 + req->out.h.error = ret; 308 + spin_lock(&fsvq->lock); 309 + dec_in_flight_req(fsvq); 310 + spin_unlock(&fsvq->lock); 311 + pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", 312 + ret); 313 + fuse_request_end(fc, req); 314 + } 315 + } 262 316 } 263 317 264 318 static void virtio_fs_hiprio_dispatch_work(struct work_struct *work) ··· 336 286 337 287 list_del(&forget->list); 338 288 if (!fsvq->connected) { 289 + dec_in_flight_req(fsvq); 339 290 spin_unlock(&fsvq->lock); 340 291 kfree(forget); 341 292 continue; ··· 358 307 } else { 359 308 pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n", 360 309 ret); 310 + dec_in_flight_req(fsvq); 361 311 kfree(forget); 362 312 } 363 313 spin_unlock(&fsvq->lock); 364 314 return; 365 315 } 366 316 367 - fsvq->in_flight++; 368 317 notify = virtqueue_kick_prepare(vq); 369 318 spin_unlock(&fsvq->lock); 370 319 ··· 503 452 504 453 fuse_request_end(fc, req); 505 454 spin_lock(&fsvq->lock); 506 - fsvq->in_flight--; 455 + dec_in_flight_req(fsvq); 507 456 spin_unlock(&fsvq->lock); 508 457 } 509 458 } ··· 553 502 names[VQ_HIPRIO] = fs->vqs[VQ_HIPRIO].name; 554 503 INIT_WORK(&fs->vqs[VQ_HIPRIO].done_work, virtio_fs_hiprio_done_work); 555 504 INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].queued_reqs); 505 + INIT_LIST_HEAD(&fs->vqs[VQ_HIPRIO].end_reqs); 556 506 INIT_DELAYED_WORK(&fs->vqs[VQ_HIPRIO].dispatch_work, 557 507 virtio_fs_hiprio_dispatch_work); 558 508 spin_lock_init(&fs->vqs[VQ_HIPRIO].lock); ··· 563 511 spin_lock_init(&fs->vqs[i].lock); 564 512 INIT_WORK(&fs->vqs[i].done_work, virtio_fs_requests_done_work); 565 513 INIT_DELAYED_WORK(&fs->vqs[i].dispatch_work, 566 - virtio_fs_dummy_dispatch_work); 514 + virtio_fs_request_dispatch_work); 567 515 INIT_LIST_HEAD(&fs->vqs[i].queued_reqs); 516 + INIT_LIST_HEAD(&fs->vqs[i].end_reqs); 568 517 snprintf(fs->vqs[i].name, sizeof(fs->vqs[i].name), 569 518 "requests.%u", i - VQ_REQUEST); 570 519 callbacks[i] = virtio_fs_vq_done; ··· 761 708 list_add_tail(&forget->list, &fsvq->queued_reqs); 762 709 schedule_delayed_work(&fsvq->dispatch_work, 763 710 msecs_to_jiffies(1)); 711 + inc_in_flight_req(fsvq); 764 712 } else { 765 713 pr_debug("virtio-fs: Could not queue FORGET: err=%d. Dropping it.\n", 766 714 ret); ··· 771 717 goto out; 772 718 } 773 719 774 - fsvq->in_flight++; 720 + inc_in_flight_req(fsvq); 775 721 notify = virtqueue_kick_prepare(vq); 776 722 777 723 spin_unlock(&fsvq->lock); ··· 873 819 874 820 /* Add a request to a virtqueue and kick the device */ 875 821 static int virtio_fs_enqueue_req(struct virtio_fs_vq *fsvq, 876 - struct fuse_req *req) 822 + struct fuse_req *req, bool in_flight) 877 823 { 878 824 /* requests need at least 4 elements */ 879 825 struct scatterlist *stack_sgs[6]; ··· 889 835 unsigned int i; 890 836 int ret; 891 837 bool notify; 838 + struct fuse_pqueue *fpq; 892 839 893 840 /* Does the sglist fit on the stack? */ 894 841 total_sgs = sg_count_fuse_req(req); ··· 944 889 goto out; 945 890 } 946 891 947 - fsvq->in_flight++; 892 + /* Request successfully sent. */ 893 + fpq = &fsvq->fud->pq; 894 + spin_lock(&fpq->lock); 895 + list_add_tail(&req->list, fpq->processing); 896 + spin_unlock(&fpq->lock); 897 + set_bit(FR_SENT, &req->flags); 898 + /* matches barrier in request_wait_answer() */ 899 + smp_mb__after_atomic(); 900 + 901 + if (!in_flight) 902 + inc_in_flight_req(fsvq); 948 903 notify = virtqueue_kick_prepare(vq); 949 904 950 905 spin_unlock(&fsvq->lock); ··· 980 915 { 981 916 unsigned int queue_id = VQ_REQUEST; /* TODO multiqueue */ 982 917 struct virtio_fs *fs; 983 - struct fuse_conn *fc; 984 918 struct fuse_req *req; 985 - struct fuse_pqueue *fpq; 919 + struct virtio_fs_vq *fsvq; 986 920 int ret; 987 921 988 922 WARN_ON(list_empty(&fiq->pending)); ··· 992 928 spin_unlock(&fiq->lock); 993 929 994 930 fs = fiq->priv; 995 - fc = fs->vqs[queue_id].fud->fc; 996 931 997 932 pr_debug("%s: opcode %u unique %#llx nodeid %#llx in.len %u out.len %u\n", 998 933 __func__, req->in.h.opcode, req->in.h.unique, 999 934 req->in.h.nodeid, req->in.h.len, 1000 935 fuse_len_args(req->args->out_numargs, req->args->out_args)); 1001 936 1002 - fpq = &fs->vqs[queue_id].fud->pq; 1003 - spin_lock(&fpq->lock); 1004 - if (!fpq->connected) { 1005 - spin_unlock(&fpq->lock); 1006 - req->out.h.error = -ENODEV; 1007 - pr_err("virtio-fs: %s disconnected\n", __func__); 1008 - fuse_request_end(fc, req); 1009 - return; 1010 - } 1011 - list_add_tail(&req->list, fpq->processing); 1012 - spin_unlock(&fpq->lock); 1013 - set_bit(FR_SENT, &req->flags); 1014 - /* matches barrier in request_wait_answer() */ 1015 - smp_mb__after_atomic(); 1016 - 1017 - retry: 1018 - ret = virtio_fs_enqueue_req(&fs->vqs[queue_id], req); 937 + fsvq = &fs->vqs[queue_id]; 938 + ret = virtio_fs_enqueue_req(fsvq, req, false); 1019 939 if (ret < 0) { 1020 940 if (ret == -ENOMEM || ret == -ENOSPC) { 1021 - /* Virtqueue full. Retry submission */ 1022 - /* TODO use completion instead of timeout */ 1023 - usleep_range(20, 30); 1024 - goto retry; 941 + /* 942 + * Virtqueue full. Retry submission from worker 943 + * context as we might be holding fc->bg_lock. 944 + */ 945 + spin_lock(&fsvq->lock); 946 + list_add_tail(&req->list, &fsvq->queued_reqs); 947 + inc_in_flight_req(fsvq); 948 + schedule_delayed_work(&fsvq->dispatch_work, 949 + msecs_to_jiffies(1)); 950 + spin_unlock(&fsvq->lock); 951 + return; 1025 952 } 1026 953 req->out.h.error = ret; 1027 954 pr_err("virtio-fs: virtio_fs_enqueue_req() failed %d\n", ret); 1028 - spin_lock(&fpq->lock); 1029 - clear_bit(FR_SENT, &req->flags); 1030 - list_del_init(&req->list); 1031 - spin_unlock(&fpq->lock); 1032 - fuse_request_end(fc, req); 955 + 956 + /* Can't end request in submission context. Use a worker */ 957 + spin_lock(&fsvq->lock); 958 + list_add_tail(&req->list, &fsvq->end_reqs); 959 + schedule_delayed_work(&fsvq->dispatch_work, 0); 960 + spin_unlock(&fsvq->lock); 1033 961 return; 1034 962 } 1035 963 } ··· 1048 992 .destroy = true, 1049 993 .no_control = true, 1050 994 .no_force_umount = true, 995 + .no_mount_options = true, 1051 996 }; 1052 997 1053 998 mutex_lock(&virtio_fs_mutex);
+37
include/uapi/linux/fuse.h
··· 38 38 * 39 39 * Protocol changelog: 40 40 * 41 + * 7.1: 42 + * - add the following messages: 43 + * FUSE_SETATTR, FUSE_SYMLINK, FUSE_MKNOD, FUSE_MKDIR, FUSE_UNLINK, 44 + * FUSE_RMDIR, FUSE_RENAME, FUSE_LINK, FUSE_OPEN, FUSE_READ, FUSE_WRITE, 45 + * FUSE_RELEASE, FUSE_FSYNC, FUSE_FLUSH, FUSE_SETXATTR, FUSE_GETXATTR, 46 + * FUSE_LISTXATTR, FUSE_REMOVEXATTR, FUSE_OPENDIR, FUSE_READDIR, 47 + * FUSE_RELEASEDIR 48 + * - add padding to messages to accommodate 32-bit servers on 64-bit kernels 49 + * 50 + * 7.2: 51 + * - add FOPEN_DIRECT_IO and FOPEN_KEEP_CACHE flags 52 + * - add FUSE_FSYNCDIR message 53 + * 54 + * 7.3: 55 + * - add FUSE_ACCESS message 56 + * - add FUSE_CREATE message 57 + * - add filehandle to fuse_setattr_in 58 + * 59 + * 7.4: 60 + * - add frsize to fuse_kstatfs 61 + * - clean up request size limit checking 62 + * 63 + * 7.5: 64 + * - add flags and max_write to fuse_init_out 65 + * 66 + * 7.6: 67 + * - add max_readahead to fuse_init_in and fuse_init_out 68 + * 69 + * 7.7: 70 + * - add FUSE_INTERRUPT message 71 + * - add POSIX file lock support 72 + * 73 + * 7.8: 74 + * - add lock_owner and flags fields to fuse_release_in 75 + * - add FUSE_BMAP message 76 + * - add FUSE_DESTROY message 77 + * 41 78 * 7.9: 42 79 * - new fuse_getattr_in input argument of GETATTR 43 80 * - add lk_flags in fuse_lk_in