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.

fuse: create fuse_dev on /dev/fuse open instead of mount

Allocate struct fuse_dev when opening the device. This means that unlike
before, ->private_data is always set to a valid pointer.

The use of USE_DEV_SYNC_INIT magic pointer for the private_data is now
replaced with a simple bool sync_init member.

If sync INIT is not set, I/O on the device returns error before mount.
Keep this behavior by checking for the ->fc member. If fud->fc is set, the
mount has succeeded. Testing this used READ_ONCE(file->private_data) and
smp_mb() to try and provide the necessary semantics. Switch this to
smp_store_release() and smp_load_acquire().

Setting fud->fc is protected by fuse_mutex, this is unchanged.

Will need this later so the /dev/fuse open file reference is not held
during FSCONFIG_CMD_CREATE.

Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Reviewed-by: "Darrick J. Wong" <djwong@kernel.org>

+57 -66
+18 -29
fs/fuse/dev.c
··· 1548 1548 1549 1549 static int fuse_dev_open(struct inode *inode, struct file *file) 1550 1550 { 1551 - /* 1552 - * The fuse device's file's private_data is used to hold 1553 - * the fuse_conn(ection) when it is mounted, and is used to 1554 - * keep track of whether the file has been mounted already. 1555 - */ 1556 - file->private_data = NULL; 1551 + struct fuse_dev *fud = fuse_dev_alloc(); 1552 + 1553 + if (!fud) 1554 + return -ENOMEM; 1555 + 1556 + file->private_data = fud; 1557 1557 return 0; 1558 1558 } 1559 1559 1560 1560 struct fuse_dev *fuse_get_dev(struct file *file) 1561 1561 { 1562 - struct fuse_dev *fud = __fuse_get_dev(file); 1562 + struct fuse_dev *fud = fuse_file_to_fud(file); 1563 1563 int err; 1564 1564 1565 - if (likely(fud)) 1566 - return fud; 1567 - 1568 - err = wait_event_interruptible(fuse_dev_waitq, 1569 - READ_ONCE(file->private_data) != FUSE_DEV_SYNC_INIT); 1565 + err = wait_event_interruptible(fuse_dev_waitq, fuse_dev_fc_get(fud) != NULL); 1570 1566 if (err) 1571 1567 return ERR_PTR(err); 1572 - 1573 - fud = __fuse_get_dev(file); 1574 - if (!fud) 1575 - return ERR_PTR(-EPERM); 1576 1568 1577 1569 return fud; 1578 1570 } ··· 2539 2547 2540 2548 int fuse_dev_release(struct inode *inode, struct file *file) 2541 2549 { 2542 - struct fuse_dev *fud = __fuse_get_dev(file); 2550 + struct fuse_dev *fud = fuse_file_to_fud(file); 2551 + struct fuse_conn *fc = fuse_dev_fc_get(fud); 2543 2552 2544 - if (fud) { 2545 - struct fuse_conn *fc = fud->fc; 2553 + if (fc) { 2546 2554 struct fuse_pqueue *fpq = &fud->pq; 2547 2555 LIST_HEAD(to_end); 2548 2556 unsigned int i; ··· 2560 2568 WARN_ON(fc->iq.fasync != NULL); 2561 2569 fuse_abort_conn(fc); 2562 2570 } 2563 - fuse_dev_free(fud); 2564 2571 } 2572 + fuse_dev_free(fud); 2565 2573 return 0; 2566 2574 } 2567 2575 EXPORT_SYMBOL_GPL(fuse_dev_release); ··· 2579 2587 2580 2588 static int fuse_device_clone(struct fuse_conn *fc, struct file *new) 2581 2589 { 2582 - struct fuse_dev *fud; 2590 + struct fuse_dev *new_fud = fuse_file_to_fud(new); 2583 2591 2584 - if (__fuse_get_dev(new)) 2592 + if (fuse_dev_fc_get(new_fud)) 2585 2593 return -EINVAL; 2586 2594 2587 - fud = fuse_dev_alloc_install(fc); 2588 - if (!fud) 2589 - return -ENOMEM; 2590 - 2591 - new->private_data = fud; 2595 + fuse_dev_install(new_fud, fc); 2592 2596 atomic_inc(&fc->dev_count); 2593 2597 2594 2598 return 0; ··· 2655 2667 static long fuse_dev_ioctl_sync_init(struct file *file) 2656 2668 { 2657 2669 int err = -EINVAL; 2670 + struct fuse_dev *fud = fuse_file_to_fud(file); 2658 2671 2659 2672 mutex_lock(&fuse_mutex); 2660 - if (!__fuse_get_dev(file)) { 2661 - WRITE_ONCE(file->private_data, FUSE_DEV_SYNC_INIT); 2673 + if (!fuse_dev_fc_get(fud)) { 2674 + fud->sync_init = true; 2662 2675 err = 0; 2663 2676 } 2664 2677 mutex_unlock(&fuse_mutex);
+25 -8
fs/fuse/fuse_dev_i.h
··· 39 39 } ring; 40 40 }; 41 41 42 - #define FUSE_DEV_SYNC_INIT ((struct fuse_dev *) 1) 43 - #define FUSE_DEV_PTR_MASK (~1UL) 42 + /* 43 + * Lockless access is OK, because fud->fc is set once during mount and is valid 44 + * until the file is released. 45 + */ 46 + static inline struct fuse_conn *fuse_dev_fc_get(struct fuse_dev *fud) 47 + { 48 + /* Pairs with smp_store_release() in fuse_dev_fc_set() */ 49 + return smp_load_acquire(&fud->fc); 50 + } 51 + 52 + static inline void fuse_dev_fc_set(struct fuse_dev *fud, struct fuse_conn *fc) 53 + { 54 + /* Pairs with smp_load_acquire() in fuse_dev_fc_get() */ 55 + smp_store_release(&fud->fc, fc); 56 + } 57 + 58 + static inline struct fuse_dev *fuse_file_to_fud(struct file *file) 59 + { 60 + return file->private_data; 61 + } 44 62 45 63 static inline struct fuse_dev *__fuse_get_dev(struct file *file) 46 64 { 47 - /* 48 - * Lockless access is OK, because file->private data is set 49 - * once during mount and is valid until the file is released. 50 - */ 51 - struct fuse_dev *fud = READ_ONCE(file->private_data); 65 + struct fuse_dev *fud = fuse_file_to_fud(file); 52 66 53 - return (typeof(fud)) ((unsigned long) fud & FUSE_DEV_PTR_MASK); 67 + if (!fuse_dev_fc_get(fud)) 68 + return NULL; 69 + 70 + return fud; 54 71 } 55 72 56 73 struct fuse_dev *fuse_get_dev(struct file *file);
+3 -3
fs/fuse/fuse_i.h
··· 577 577 * Fuse device instance 578 578 */ 579 579 struct fuse_dev { 580 + /** Issue FUSE_INIT synchronously */ 581 + bool sync_init; 582 + 580 583 /** Fuse connection for this device */ 581 584 struct fuse_conn *fc; 582 585 ··· 626 623 627 624 /* DAX device, may be NULL */ 628 625 struct dax_device *dax_dev; 629 - 630 - /* fuse_dev pointer to fill in, should contain NULL on entry */ 631 - void **fudptr; 632 626 }; 633 627 634 628 struct fuse_sync_bucket {
+11 -24
fs/fuse/inode.c
··· 1641 1641 1642 1642 void fuse_dev_install(struct fuse_dev *fud, struct fuse_conn *fc) 1643 1643 { 1644 - fud->fc = fuse_conn_get(fc); 1644 + fuse_dev_fc_set(fud, fuse_conn_get(fc)); 1645 1645 spin_lock(&fc->lock); 1646 1646 list_add_tail(&fud->entry, &fc->devices); 1647 1647 spin_unlock(&fc->lock); ··· 1663 1663 1664 1664 void fuse_dev_free(struct fuse_dev *fud) 1665 1665 { 1666 - struct fuse_conn *fc = fud->fc; 1666 + struct fuse_conn *fc = fuse_dev_fc_get(fud); 1667 1667 1668 1668 if (fc) { 1669 1669 spin_lock(&fc->lock); ··· 1826 1826 1827 1827 int fuse_fill_super_common(struct super_block *sb, struct fuse_fs_context *ctx) 1828 1828 { 1829 - struct fuse_dev *fud = NULL; 1829 + struct fuse_dev *fud = ctx->file ? fuse_file_to_fud(ctx->file) : NULL; 1830 1830 struct fuse_mount *fm = get_fuse_mount_super(sb); 1831 1831 struct fuse_conn *fc = fm->fc; 1832 1832 struct inode *root; ··· 1860 1860 goto err; 1861 1861 } 1862 1862 1863 - if (ctx->fudptr) { 1864 - err = -ENOMEM; 1865 - fud = fuse_dev_alloc_install(fc); 1866 - if (!fud) 1867 - goto err_free_dax; 1868 - } 1869 - 1870 1863 fc->dev = sb->s_dev; 1871 1864 fm->sb = sb; 1872 1865 err = fuse_bdi_init(fc, sb); 1873 1866 if (err) 1874 - goto err_dev_free; 1867 + goto err_free_dax; 1875 1868 1876 1869 /* Handle umasking inside the fuse code */ 1877 1870 if (sb->s_flags & SB_POSIXACL) ··· 1886 1893 set_default_d_op(sb, &fuse_dentry_operations); 1887 1894 root_dentry = d_make_root(root); 1888 1895 if (!root_dentry) 1889 - goto err_dev_free; 1896 + goto err_free_dax; 1890 1897 1891 1898 mutex_lock(&fuse_mutex); 1892 1899 err = -EINVAL; 1893 - if (ctx->fudptr && *ctx->fudptr) { 1894 - if (*ctx->fudptr == FUSE_DEV_SYNC_INIT) 1895 - fc->sync_init = 1; 1896 - else 1900 + if (fud) { 1901 + if (fuse_dev_fc_get(fud)) 1897 1902 goto err_unlock; 1903 + if (fud->sync_init) 1904 + fc->sync_init = 1; 1898 1905 } 1899 1906 1900 1907 err = fuse_ctl_add_conn(fc); ··· 1903 1910 1904 1911 list_add_tail(&fc->entry, &fuse_conn_list); 1905 1912 sb->s_root = root_dentry; 1906 - if (ctx->fudptr) { 1907 - *ctx->fudptr = fud; 1913 + if (fud) { 1914 + fuse_dev_install(fud, fc); 1908 1915 wake_up_all(&fuse_dev_waitq); 1909 1916 } 1910 1917 mutex_unlock(&fuse_mutex); ··· 1913 1920 err_unlock: 1914 1921 mutex_unlock(&fuse_mutex); 1915 1922 dput(root_dentry); 1916 - err_dev_free: 1917 - if (fud) 1918 - fuse_dev_free(fud); 1919 1923 err_free_dax: 1920 1924 if (IS_ENABLED(CONFIG_FUSE_DAX)) 1921 1925 fuse_dax_conn_free(fc); ··· 1938 1948 if ((ctx->file->f_op != &fuse_dev_operations) || 1939 1949 (ctx->file->f_cred->user_ns != sb->s_user_ns)) 1940 1950 return -EINVAL; 1941 - ctx->fudptr = &ctx->file->private_data; 1942 1951 1943 1952 err = fuse_fill_super_common(sb, ctx); 1944 1953 if (err) 1945 1954 return err; 1946 - /* file->private_data shall be visible on all CPUs after this */ 1947 - smp_mb(); 1948 1955 1949 1956 fm = get_fuse_mount_super(sb); 1950 1957
-2
fs/fuse/virtio_fs.c
··· 1590 1590 goto err_free_fuse_devs; 1591 1591 } 1592 1592 1593 - /* virtiofs allocates and installs its own fuse devices */ 1594 - ctx->fudptr = NULL; 1595 1593 if (ctx->dax_mode != FUSE_DAX_NEVER) { 1596 1594 if (ctx->dax_mode == FUSE_DAX_ALWAYS && !fs->dax_dev) { 1597 1595 err = -EINVAL;