|
65 | 65 | #include <trace/events/btrfs.h>
|
66 | 66 |
|
67 | 67 | static const struct super_operations btrfs_super_ops;
|
| 68 | + |
| 69 | +/* |
| 70 | + * Types for mounting the default subvolume and a subvolume explicitly |
| 71 | + * requested by subvol=/path. That way the callchain is straightforward and we |
| 72 | + * don't have to play tricks with the mount options and recursive calls to |
| 73 | + * btrfs_mount. |
| 74 | + */ |
68 | 75 | static struct file_system_type btrfs_fs_type;
|
| 76 | +static struct file_system_type btrfs_root_fs_type; |
69 | 77 |
|
70 | 78 | static int btrfs_remount(struct super_block *sb, int *flags, char *data);
|
71 | 79 |
|
@@ -1549,6 +1557,112 @@ static int setup_security_options(struct btrfs_fs_info *fs_info,
|
1549 | 1557 | return ret;
|
1550 | 1558 | }
|
1551 | 1559 |
|
| 1560 | +static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, |
| 1561 | + int flags, const char *device_name, void *data) |
| 1562 | +{ |
| 1563 | + struct block_device *bdev = NULL; |
| 1564 | + struct super_block *s; |
| 1565 | + struct btrfs_fs_devices *fs_devices = NULL; |
| 1566 | + struct btrfs_fs_info *fs_info = NULL; |
| 1567 | + struct security_mnt_opts new_sec_opts; |
| 1568 | + fmode_t mode = FMODE_READ; |
| 1569 | + char *subvol_name = NULL; |
| 1570 | + u64 subvol_objectid = 0; |
| 1571 | + int error = 0; |
| 1572 | + |
| 1573 | + if (!(flags & SB_RDONLY)) |
| 1574 | + mode |= FMODE_WRITE; |
| 1575 | + |
| 1576 | + error = btrfs_parse_early_options(data, mode, fs_type, |
| 1577 | + &subvol_name, &subvol_objectid, |
| 1578 | + &fs_devices); |
| 1579 | + if (error) { |
| 1580 | + kfree(subvol_name); |
| 1581 | + return ERR_PTR(error); |
| 1582 | + } |
| 1583 | + |
| 1584 | + security_init_mnt_opts(&new_sec_opts); |
| 1585 | + if (data) { |
| 1586 | + error = parse_security_options(data, &new_sec_opts); |
| 1587 | + if (error) |
| 1588 | + return ERR_PTR(error); |
| 1589 | + } |
| 1590 | + |
| 1591 | + error = btrfs_scan_one_device(device_name, mode, fs_type, &fs_devices); |
| 1592 | + if (error) |
| 1593 | + goto error_sec_opts; |
| 1594 | + |
| 1595 | + /* |
| 1596 | + * Setup a dummy root and fs_info for test/set super. This is because |
| 1597 | + * we don't actually fill this stuff out until open_ctree, but we need |
| 1598 | + * it for searching for existing supers, so this lets us do that and |
| 1599 | + * then open_ctree will properly initialize everything later. |
| 1600 | + */ |
| 1601 | + fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_KERNEL); |
| 1602 | + if (!fs_info) { |
| 1603 | + error = -ENOMEM; |
| 1604 | + goto error_sec_opts; |
| 1605 | + } |
| 1606 | + |
| 1607 | + fs_info->fs_devices = fs_devices; |
| 1608 | + |
| 1609 | + fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL); |
| 1610 | + fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_KERNEL); |
| 1611 | + security_init_mnt_opts(&fs_info->security_opts); |
| 1612 | + if (!fs_info->super_copy || !fs_info->super_for_commit) { |
| 1613 | + error = -ENOMEM; |
| 1614 | + goto error_fs_info; |
| 1615 | + } |
| 1616 | + |
| 1617 | + error = btrfs_open_devices(fs_devices, mode, fs_type); |
| 1618 | + if (error) |
| 1619 | + goto error_fs_info; |
| 1620 | + |
| 1621 | + if (!(flags & SB_RDONLY) && fs_devices->rw_devices == 0) { |
| 1622 | + error = -EACCES; |
| 1623 | + goto error_close_devices; |
| 1624 | + } |
| 1625 | + |
| 1626 | + bdev = fs_devices->latest_bdev; |
| 1627 | + s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | SB_NOSEC, |
| 1628 | + fs_info); |
| 1629 | + if (IS_ERR(s)) { |
| 1630 | + error = PTR_ERR(s); |
| 1631 | + goto error_close_devices; |
| 1632 | + } |
| 1633 | + |
| 1634 | + if (s->s_root) { |
| 1635 | + btrfs_close_devices(fs_devices); |
| 1636 | + free_fs_info(fs_info); |
| 1637 | + if ((flags ^ s->s_flags) & SB_RDONLY) |
| 1638 | + error = -EBUSY; |
| 1639 | + } else { |
| 1640 | + snprintf(s->s_id, sizeof(s->s_id), "%pg", bdev); |
| 1641 | + btrfs_sb(s)->bdev_holder = fs_type; |
| 1642 | + error = btrfs_fill_super(s, fs_devices, data); |
| 1643 | + } |
| 1644 | + if (error) { |
| 1645 | + deactivate_locked_super(s); |
| 1646 | + goto error_sec_opts; |
| 1647 | + } |
| 1648 | + |
| 1649 | + fs_info = btrfs_sb(s); |
| 1650 | + error = setup_security_options(fs_info, s, &new_sec_opts); |
| 1651 | + if (error) { |
| 1652 | + deactivate_locked_super(s); |
| 1653 | + goto error_sec_opts; |
| 1654 | + } |
| 1655 | + |
| 1656 | + return dget(s->s_root); |
| 1657 | + |
| 1658 | +error_close_devices: |
| 1659 | + btrfs_close_devices(fs_devices); |
| 1660 | +error_fs_info: |
| 1661 | + free_fs_info(fs_info); |
| 1662 | +error_sec_opts: |
| 1663 | + security_free_mnt_opts(&new_sec_opts); |
| 1664 | + return ERR_PTR(error); |
| 1665 | +} |
1552 | 1666 | /*
|
1553 | 1667 | * Find a superblock for the given device / mount point.
|
1554 | 1668 | *
|
@@ -2170,6 +2284,15 @@ static struct file_system_type btrfs_fs_type = {
|
2170 | 2284 | .kill_sb = btrfs_kill_super,
|
2171 | 2285 | .fs_flags = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA,
|
2172 | 2286 | };
|
| 2287 | + |
| 2288 | +static struct file_system_type btrfs_root_fs_type = { |
| 2289 | + .owner = THIS_MODULE, |
| 2290 | + .name = "btrfs", |
| 2291 | + .mount = btrfs_mount_root, |
| 2292 | + .kill_sb = btrfs_kill_super, |
| 2293 | + .fs_flags = FS_REQUIRES_DEV | FS_BINARY_MOUNTDATA, |
| 2294 | +}; |
| 2295 | + |
2173 | 2296 | MODULE_ALIAS_FS("btrfs");
|
2174 | 2297 |
|
2175 | 2298 | static int btrfs_control_open(struct inode *inode, struct file *file)
|
|
0 commit comments