@@ -457,14 +457,6 @@ static void fuse_send_destroy(struct fuse_mount *fm)
457
457
}
458
458
}
459
459
460
- static void fuse_put_super (struct super_block * sb )
461
- {
462
- struct fuse_mount * fm = get_fuse_mount_super (sb );
463
-
464
- fuse_conn_put (fm -> fc );
465
- kfree (fm );
466
- }
467
-
468
460
static void convert_fuse_statfs (struct kstatfs * stbuf , struct fuse_kstatfs * attr )
469
461
{
470
462
stbuf -> f_type = FUSE_SUPER_MAGIC ;
@@ -1003,7 +995,6 @@ static const struct super_operations fuse_super_operations = {
1003
995
.evict_inode = fuse_evict_inode ,
1004
996
.write_inode = fuse_write_inode ,
1005
997
.drop_inode = generic_delete_inode ,
1006
- .put_super = fuse_put_super ,
1007
998
.umount_begin = fuse_umount_begin ,
1008
999
.statfs = fuse_statfs ,
1009
1000
.sync_fs = fuse_sync_fs ,
@@ -1424,20 +1415,17 @@ static int fuse_get_tree_submount(struct fs_context *fsc)
1424
1415
if (!fm )
1425
1416
return - ENOMEM ;
1426
1417
1418
+ fm -> fc = fuse_conn_get (fc );
1427
1419
fsc -> s_fs_info = fm ;
1428
1420
sb = sget_fc (fsc , NULL , set_anon_super_fc );
1429
- if (IS_ERR (sb )) {
1430
- kfree (fm );
1421
+ if (fsc -> s_fs_info )
1422
+ fuse_mount_destroy (fm );
1423
+ if (IS_ERR (sb ))
1431
1424
return PTR_ERR (sb );
1432
- }
1433
- fm -> fc = fuse_conn_get (fc );
1434
1425
1435
1426
/* Initialize superblock, making @mp_fi its root */
1436
1427
err = fuse_fill_super_submount (sb , mp_fi );
1437
1428
if (err ) {
1438
- fuse_conn_put (fc );
1439
- kfree (fm );
1440
- sb -> s_fs_info = NULL ;
1441
1429
deactivate_locked_super (sb );
1442
1430
return err ;
1443
1431
}
@@ -1569,8 +1557,6 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
1569
1557
{
1570
1558
struct fuse_fs_context * ctx = fsc -> fs_private ;
1571
1559
int err ;
1572
- struct fuse_conn * fc ;
1573
- struct fuse_mount * fm ;
1574
1560
1575
1561
if (!ctx -> file || !ctx -> rootmode_present ||
1576
1562
!ctx -> user_id_present || !ctx -> group_id_present )
@@ -1580,42 +1566,18 @@ static int fuse_fill_super(struct super_block *sb, struct fs_context *fsc)
1580
1566
* Require mount to happen from the same user namespace which
1581
1567
* opened /dev/fuse to prevent potential attacks.
1582
1568
*/
1583
- err = - EINVAL ;
1584
1569
if ((ctx -> file -> f_op != & fuse_dev_operations ) ||
1585
1570
(ctx -> file -> f_cred -> user_ns != sb -> s_user_ns ))
1586
- goto err ;
1571
+ return - EINVAL ;
1587
1572
ctx -> fudptr = & ctx -> file -> private_data ;
1588
1573
1589
- fc = kmalloc (sizeof (* fc ), GFP_KERNEL );
1590
- err = - ENOMEM ;
1591
- if (!fc )
1592
- goto err ;
1593
-
1594
- fm = kzalloc (sizeof (* fm ), GFP_KERNEL );
1595
- if (!fm ) {
1596
- kfree (fc );
1597
- goto err ;
1598
- }
1599
-
1600
- fuse_conn_init (fc , fm , sb -> s_user_ns , & fuse_dev_fiq_ops , NULL );
1601
- fc -> release = fuse_free_conn ;
1602
-
1603
- sb -> s_fs_info = fm ;
1604
-
1605
1574
err = fuse_fill_super_common (sb , ctx );
1606
1575
if (err )
1607
- goto err_put_conn ;
1576
+ return err ;
1608
1577
/* file->private_data shall be visible on all CPUs after this */
1609
1578
smp_mb ();
1610
1579
fuse_send_init (get_fuse_mount_super (sb ));
1611
1580
return 0 ;
1612
-
1613
- err_put_conn :
1614
- fuse_conn_put (fc );
1615
- kfree (fm );
1616
- sb -> s_fs_info = NULL ;
1617
- err :
1618
- return err ;
1619
1581
}
1620
1582
1621
1583
/*
@@ -1637,22 +1599,40 @@ static int fuse_get_tree(struct fs_context *fsc)
1637
1599
{
1638
1600
struct fuse_fs_context * ctx = fsc -> fs_private ;
1639
1601
struct fuse_dev * fud ;
1602
+ struct fuse_conn * fc ;
1603
+ struct fuse_mount * fm ;
1640
1604
struct super_block * sb ;
1641
1605
int err ;
1642
1606
1607
+ fc = kmalloc (sizeof (* fc ), GFP_KERNEL );
1608
+ if (!fc )
1609
+ return - ENOMEM ;
1610
+
1611
+ fm = kzalloc (sizeof (* fm ), GFP_KERNEL );
1612
+ if (!fm ) {
1613
+ kfree (fc );
1614
+ return - ENOMEM ;
1615
+ }
1616
+
1617
+ fuse_conn_init (fc , fm , fsc -> user_ns , & fuse_dev_fiq_ops , NULL );
1618
+ fc -> release = fuse_free_conn ;
1619
+
1620
+ fsc -> s_fs_info = fm ;
1621
+
1643
1622
if (ctx -> fd_present )
1644
1623
ctx -> file = fget (ctx -> fd );
1645
1624
1646
1625
if (IS_ENABLED (CONFIG_BLOCK ) && ctx -> is_bdev ) {
1647
1626
err = get_tree_bdev (fsc , fuse_fill_super );
1648
- goto out_fput ;
1627
+ goto out ;
1649
1628
}
1650
1629
/*
1651
1630
* While block dev mount can be initialized with a dummy device fd
1652
1631
* (found by device name), normal fuse mounts can't
1653
1632
*/
1633
+ err = - EINVAL ;
1654
1634
if (!ctx -> file )
1655
- return - EINVAL ;
1635
+ goto out ;
1656
1636
1657
1637
/*
1658
1638
* Allow creating a fuse mount with an already initialized fuse
@@ -1668,7 +1648,9 @@ static int fuse_get_tree(struct fs_context *fsc)
1668
1648
} else {
1669
1649
err = get_tree_nodev (fsc , fuse_fill_super );
1670
1650
}
1671
- out_fput :
1651
+ out :
1652
+ if (fsc -> s_fs_info )
1653
+ fuse_mount_destroy (fm );
1672
1654
if (ctx -> file )
1673
1655
fput (ctx -> file );
1674
1656
return err ;
@@ -1747,17 +1729,25 @@ static void fuse_sb_destroy(struct super_block *sb)
1747
1729
struct fuse_mount * fm = get_fuse_mount_super (sb );
1748
1730
bool last ;
1749
1731
1750
- if (fm ) {
1732
+ if (sb -> s_root ) {
1751
1733
last = fuse_mount_remove (fm );
1752
1734
if (last )
1753
1735
fuse_conn_destroy (fm );
1754
1736
}
1755
1737
}
1756
1738
1739
+ void fuse_mount_destroy (struct fuse_mount * fm )
1740
+ {
1741
+ fuse_conn_put (fm -> fc );
1742
+ kfree (fm );
1743
+ }
1744
+ EXPORT_SYMBOL (fuse_mount_destroy );
1745
+
1757
1746
static void fuse_kill_sb_anon (struct super_block * sb )
1758
1747
{
1759
1748
fuse_sb_destroy (sb );
1760
1749
kill_anon_super (sb );
1750
+ fuse_mount_destroy (get_fuse_mount_super (sb ));
1761
1751
}
1762
1752
1763
1753
static struct file_system_type fuse_fs_type = {
@@ -1775,6 +1765,7 @@ static void fuse_kill_sb_blk(struct super_block *sb)
1775
1765
{
1776
1766
fuse_sb_destroy (sb );
1777
1767
kill_block_super (sb );
1768
+ fuse_mount_destroy (get_fuse_mount_super (sb ));
1778
1769
}
1779
1770
1780
1771
static struct file_system_type fuseblk_fs_type = {
0 commit comments