|
19 | 19 | #include "volumes.h"
|
20 | 20 | #include "space-info.h"
|
21 | 21 | #include "block-group.h"
|
| 22 | +#include "qgroup.h" |
22 | 23 |
|
23 | 24 | struct btrfs_feature_attr {
|
24 | 25 | struct kobj_attribute kobj_attr;
|
@@ -1455,6 +1456,153 @@ int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info)
|
1455 | 1456 | return error;
|
1456 | 1457 | }
|
1457 | 1458 |
|
| 1459 | +static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj) |
| 1460 | +{ |
| 1461 | + return to_fs_info(kobj->parent->parent); |
| 1462 | +} |
| 1463 | + |
| 1464 | +#define QGROUP_ATTR(_member, _show_name) \ |
| 1465 | +static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj, \ |
| 1466 | + struct kobj_attribute *a, \ |
| 1467 | + char *buf) \ |
| 1468 | +{ \ |
| 1469 | + struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ |
| 1470 | + struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ |
| 1471 | + struct btrfs_qgroup, kobj); \ |
| 1472 | + return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf); \ |
| 1473 | +} \ |
| 1474 | +BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member) |
| 1475 | + |
| 1476 | +#define QGROUP_RSV_ATTR(_name, _type) \ |
| 1477 | +static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj, \ |
| 1478 | + struct kobj_attribute *a, \ |
| 1479 | + char *buf) \ |
| 1480 | +{ \ |
| 1481 | + struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ |
| 1482 | + struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ |
| 1483 | + struct btrfs_qgroup, kobj); \ |
| 1484 | + return btrfs_show_u64(&qgroup->rsv.values[_type], \ |
| 1485 | + &fs_info->qgroup_lock, buf); \ |
| 1486 | +} \ |
| 1487 | +BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name) |
| 1488 | + |
| 1489 | +QGROUP_ATTR(rfer, referenced); |
| 1490 | +QGROUP_ATTR(excl, exclusive); |
| 1491 | +QGROUP_ATTR(max_rfer, max_referenced); |
| 1492 | +QGROUP_ATTR(max_excl, max_exclusive); |
| 1493 | +QGROUP_ATTR(lim_flags, limit_flags); |
| 1494 | +QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA); |
| 1495 | +QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS); |
| 1496 | +QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC); |
| 1497 | + |
| 1498 | +static struct attribute *qgroup_attrs[] = { |
| 1499 | + BTRFS_ATTR_PTR(qgroup, referenced), |
| 1500 | + BTRFS_ATTR_PTR(qgroup, exclusive), |
| 1501 | + BTRFS_ATTR_PTR(qgroup, max_referenced), |
| 1502 | + BTRFS_ATTR_PTR(qgroup, max_exclusive), |
| 1503 | + BTRFS_ATTR_PTR(qgroup, limit_flags), |
| 1504 | + BTRFS_ATTR_PTR(qgroup, rsv_data), |
| 1505 | + BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans), |
| 1506 | + BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc), |
| 1507 | + NULL |
| 1508 | +}; |
| 1509 | +ATTRIBUTE_GROUPS(qgroup); |
| 1510 | + |
| 1511 | +static void qgroup_release(struct kobject *kobj) |
| 1512 | +{ |
| 1513 | + struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj); |
| 1514 | + |
| 1515 | + memset(&qgroup->kobj, 0, sizeof(*kobj)); |
| 1516 | +} |
| 1517 | + |
| 1518 | +static struct kobj_type qgroup_ktype = { |
| 1519 | + .sysfs_ops = &kobj_sysfs_ops, |
| 1520 | + .release = qgroup_release, |
| 1521 | + .default_groups = qgroup_groups, |
| 1522 | +}; |
| 1523 | + |
| 1524 | +int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info, |
| 1525 | + struct btrfs_qgroup *qgroup) |
| 1526 | +{ |
| 1527 | + struct kobject *qgroups_kobj = fs_info->qgroups_kobj; |
| 1528 | + int ret; |
| 1529 | + |
| 1530 | + if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) |
| 1531 | + return 0; |
| 1532 | + if (qgroup->kobj.state_initialized) |
| 1533 | + return 0; |
| 1534 | + if (!qgroups_kobj) |
| 1535 | + return -EINVAL; |
| 1536 | + |
| 1537 | + ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj, |
| 1538 | + "%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid), |
| 1539 | + btrfs_qgroup_subvolid(qgroup->qgroupid)); |
| 1540 | + if (ret < 0) |
| 1541 | + kobject_put(&qgroup->kobj); |
| 1542 | + |
| 1543 | + return ret; |
| 1544 | +} |
| 1545 | + |
| 1546 | +void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info) |
| 1547 | +{ |
| 1548 | + struct btrfs_qgroup *qgroup; |
| 1549 | + struct btrfs_qgroup *next; |
| 1550 | + |
| 1551 | + if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) |
| 1552 | + return; |
| 1553 | + |
| 1554 | + rbtree_postorder_for_each_entry_safe(qgroup, next, |
| 1555 | + &fs_info->qgroup_tree, node) |
| 1556 | + btrfs_sysfs_del_one_qgroup(fs_info, qgroup); |
| 1557 | + kobject_del(fs_info->qgroups_kobj); |
| 1558 | + kobject_put(fs_info->qgroups_kobj); |
| 1559 | + fs_info->qgroups_kobj = NULL; |
| 1560 | +} |
| 1561 | + |
| 1562 | +/* Called when qgroups get initialized, thus there is no need for locking */ |
| 1563 | +int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info) |
| 1564 | +{ |
| 1565 | + struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; |
| 1566 | + struct btrfs_qgroup *qgroup; |
| 1567 | + struct btrfs_qgroup *next; |
| 1568 | + int ret = 0; |
| 1569 | + |
| 1570 | + if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) |
| 1571 | + return 0; |
| 1572 | + |
| 1573 | + ASSERT(fsid_kobj); |
| 1574 | + if (fs_info->qgroups_kobj) |
| 1575 | + return 0; |
| 1576 | + |
| 1577 | + fs_info->qgroups_kobj = kobject_create_and_add("qgroups", fsid_kobj); |
| 1578 | + if (!fs_info->qgroups_kobj) { |
| 1579 | + ret = -ENOMEM; |
| 1580 | + goto out; |
| 1581 | + } |
| 1582 | + rbtree_postorder_for_each_entry_safe(qgroup, next, |
| 1583 | + &fs_info->qgroup_tree, node) { |
| 1584 | + ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup); |
| 1585 | + if (ret < 0) |
| 1586 | + goto out; |
| 1587 | + } |
| 1588 | + |
| 1589 | +out: |
| 1590 | + if (ret < 0) |
| 1591 | + btrfs_sysfs_del_qgroups(fs_info); |
| 1592 | + return ret; |
| 1593 | +} |
| 1594 | + |
| 1595 | +void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info, |
| 1596 | + struct btrfs_qgroup *qgroup) |
| 1597 | +{ |
| 1598 | + if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) |
| 1599 | + return; |
| 1600 | + |
| 1601 | + if (qgroup->kobj.state_initialized) { |
| 1602 | + kobject_del(&qgroup->kobj); |
| 1603 | + kobject_put(&qgroup->kobj); |
| 1604 | + } |
| 1605 | +} |
1458 | 1606 |
|
1459 | 1607 | /*
|
1460 | 1608 | * Change per-fs features in /sys/fs/btrfs/UUID/features to match current
|
|
0 commit comments