.. | .. |
---|
4 | 4 | */ |
---|
5 | 5 | |
---|
6 | 6 | #include <linux/sched.h> |
---|
| 7 | +#include <linux/sched/mm.h> |
---|
7 | 8 | #include <linux/slab.h> |
---|
8 | 9 | #include <linux/spinlock.h> |
---|
9 | 10 | #include <linux/completion.h> |
---|
10 | | -#include <linux/kobject.h> |
---|
11 | 11 | #include <linux/bug.h> |
---|
12 | | -#include <linux/debugfs.h> |
---|
13 | | -#include <linux/sched/mm.h> |
---|
| 12 | +#include <crypto/hash.h> |
---|
14 | 13 | |
---|
15 | 14 | #include "ctree.h" |
---|
| 15 | +#include "discard.h" |
---|
16 | 16 | #include "disk-io.h" |
---|
| 17 | +#include "send.h" |
---|
17 | 18 | #include "transaction.h" |
---|
18 | 19 | #include "sysfs.h" |
---|
19 | 20 | #include "volumes.h" |
---|
| 21 | +#include "space-info.h" |
---|
| 22 | +#include "block-group.h" |
---|
| 23 | +#include "qgroup.h" |
---|
| 24 | + |
---|
| 25 | +struct btrfs_feature_attr { |
---|
| 26 | + struct kobj_attribute kobj_attr; |
---|
| 27 | + enum btrfs_feature_set feature_set; |
---|
| 28 | + u64 feature_bit; |
---|
| 29 | +}; |
---|
| 30 | + |
---|
| 31 | +/* For raid type sysfs entries */ |
---|
| 32 | +struct raid_kobject { |
---|
| 33 | + u64 flags; |
---|
| 34 | + struct kobject kobj; |
---|
| 35 | +}; |
---|
| 36 | + |
---|
| 37 | +#define __INIT_KOBJ_ATTR(_name, _mode, _show, _store) \ |
---|
| 38 | +{ \ |
---|
| 39 | + .attr = { .name = __stringify(_name), .mode = _mode }, \ |
---|
| 40 | + .show = _show, \ |
---|
| 41 | + .store = _store, \ |
---|
| 42 | +} |
---|
| 43 | + |
---|
| 44 | +#define BTRFS_ATTR_RW(_prefix, _name, _show, _store) \ |
---|
| 45 | + static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ |
---|
| 46 | + __INIT_KOBJ_ATTR(_name, 0644, _show, _store) |
---|
| 47 | + |
---|
| 48 | +#define BTRFS_ATTR(_prefix, _name, _show) \ |
---|
| 49 | + static struct kobj_attribute btrfs_attr_##_prefix##_##_name = \ |
---|
| 50 | + __INIT_KOBJ_ATTR(_name, 0444, _show, NULL) |
---|
| 51 | + |
---|
| 52 | +#define BTRFS_ATTR_PTR(_prefix, _name) \ |
---|
| 53 | + (&btrfs_attr_##_prefix##_##_name.attr) |
---|
| 54 | + |
---|
| 55 | +#define BTRFS_FEAT_ATTR(_name, _feature_set, _feature_prefix, _feature_bit) \ |
---|
| 56 | +static struct btrfs_feature_attr btrfs_attr_features_##_name = { \ |
---|
| 57 | + .kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO, \ |
---|
| 58 | + btrfs_feature_attr_show, \ |
---|
| 59 | + btrfs_feature_attr_store), \ |
---|
| 60 | + .feature_set = _feature_set, \ |
---|
| 61 | + .feature_bit = _feature_prefix ##_## _feature_bit, \ |
---|
| 62 | +} |
---|
| 63 | +#define BTRFS_FEAT_ATTR_PTR(_name) \ |
---|
| 64 | + (&btrfs_attr_features_##_name.kobj_attr.attr) |
---|
| 65 | + |
---|
| 66 | +#define BTRFS_FEAT_ATTR_COMPAT(name, feature) \ |
---|
| 67 | + BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature) |
---|
| 68 | +#define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \ |
---|
| 69 | + BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT_RO, feature) |
---|
| 70 | +#define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \ |
---|
| 71 | + BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature) |
---|
20 | 72 | |
---|
21 | 73 | static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); |
---|
22 | 74 | static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); |
---|
| 75 | + |
---|
| 76 | +static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a) |
---|
| 77 | +{ |
---|
| 78 | + return container_of(a, struct btrfs_feature_attr, kobj_attr); |
---|
| 79 | +} |
---|
| 80 | + |
---|
| 81 | +static struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr) |
---|
| 82 | +{ |
---|
| 83 | + return container_of(attr, struct kobj_attribute, attr); |
---|
| 84 | +} |
---|
| 85 | + |
---|
| 86 | +static struct btrfs_feature_attr *attr_to_btrfs_feature_attr( |
---|
| 87 | + struct attribute *attr) |
---|
| 88 | +{ |
---|
| 89 | + return to_btrfs_feature_attr(attr_to_btrfs_attr(attr)); |
---|
| 90 | +} |
---|
23 | 91 | |
---|
24 | 92 | static u64 get_features(struct btrfs_fs_info *fs_info, |
---|
25 | 93 | enum btrfs_feature_set set) |
---|
.. | .. |
---|
89 | 157 | } else |
---|
90 | 158 | val = can_modify_feature(fa); |
---|
91 | 159 | |
---|
92 | | - return snprintf(buf, PAGE_SIZE, "%d\n", val); |
---|
| 160 | + return scnprintf(buf, PAGE_SIZE, "%d\n", val); |
---|
93 | 161 | } |
---|
94 | 162 | |
---|
95 | 163 | static ssize_t btrfs_feature_attr_store(struct kobject *kobj, |
---|
.. | .. |
---|
192 | 260 | BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); |
---|
193 | 261 | BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); |
---|
194 | 262 | BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); |
---|
| 263 | +BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID); |
---|
195 | 264 | BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); |
---|
| 265 | +BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34); |
---|
196 | 266 | |
---|
197 | 267 | static struct attribute *btrfs_supported_feature_attrs[] = { |
---|
198 | 268 | BTRFS_FEAT_ATTR_PTR(mixed_backref), |
---|
.. | .. |
---|
205 | 275 | BTRFS_FEAT_ATTR_PTR(raid56), |
---|
206 | 276 | BTRFS_FEAT_ATTR_PTR(skinny_metadata), |
---|
207 | 277 | BTRFS_FEAT_ATTR_PTR(no_holes), |
---|
| 278 | + BTRFS_FEAT_ATTR_PTR(metadata_uuid), |
---|
208 | 279 | BTRFS_FEAT_ATTR_PTR(free_space_tree), |
---|
| 280 | + BTRFS_FEAT_ATTR_PTR(raid1c34), |
---|
209 | 281 | NULL |
---|
210 | 282 | }; |
---|
211 | 283 | |
---|
.. | .. |
---|
225 | 297 | static ssize_t rmdir_subvol_show(struct kobject *kobj, |
---|
226 | 298 | struct kobj_attribute *ka, char *buf) |
---|
227 | 299 | { |
---|
228 | | - return snprintf(buf, PAGE_SIZE, "0\n"); |
---|
| 300 | + return scnprintf(buf, PAGE_SIZE, "0\n"); |
---|
229 | 301 | } |
---|
230 | 302 | BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show); |
---|
231 | 303 | |
---|
| 304 | +static ssize_t supported_checksums_show(struct kobject *kobj, |
---|
| 305 | + struct kobj_attribute *a, char *buf) |
---|
| 306 | +{ |
---|
| 307 | + ssize_t ret = 0; |
---|
| 308 | + int i; |
---|
| 309 | + |
---|
| 310 | + for (i = 0; i < btrfs_get_num_csums(); i++) { |
---|
| 311 | + /* |
---|
| 312 | + * This "trick" only works as long as 'enum btrfs_csum_type' has |
---|
| 313 | + * no holes in it |
---|
| 314 | + */ |
---|
| 315 | + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s", |
---|
| 316 | + (i == 0 ? "" : " "), btrfs_super_csum_name(i)); |
---|
| 317 | + |
---|
| 318 | + } |
---|
| 319 | + |
---|
| 320 | + ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n"); |
---|
| 321 | + return ret; |
---|
| 322 | +} |
---|
| 323 | +BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show); |
---|
| 324 | + |
---|
| 325 | +static ssize_t send_stream_version_show(struct kobject *kobj, |
---|
| 326 | + struct kobj_attribute *ka, char *buf) |
---|
| 327 | +{ |
---|
| 328 | + return snprintf(buf, PAGE_SIZE, "%d\n", BTRFS_SEND_STREAM_VERSION); |
---|
| 329 | +} |
---|
| 330 | +BTRFS_ATTR(static_feature, send_stream_version, send_stream_version_show); |
---|
| 331 | + |
---|
232 | 332 | static struct attribute *btrfs_supported_static_feature_attrs[] = { |
---|
233 | 333 | BTRFS_ATTR_PTR(static_feature, rmdir_subvol), |
---|
| 334 | + BTRFS_ATTR_PTR(static_feature, supported_checksums), |
---|
| 335 | + BTRFS_ATTR_PTR(static_feature, send_stream_version), |
---|
234 | 336 | NULL |
---|
235 | 337 | }; |
---|
236 | 338 | |
---|
.. | .. |
---|
245 | 347 | .attrs = btrfs_supported_static_feature_attrs, |
---|
246 | 348 | }; |
---|
247 | 349 | |
---|
| 350 | +#ifdef CONFIG_BTRFS_DEBUG |
---|
| 351 | + |
---|
| 352 | +/* |
---|
| 353 | + * Discard statistics and tunables |
---|
| 354 | + */ |
---|
| 355 | +#define discard_to_fs_info(_kobj) to_fs_info((_kobj)->parent->parent) |
---|
| 356 | + |
---|
| 357 | +static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj, |
---|
| 358 | + struct kobj_attribute *a, |
---|
| 359 | + char *buf) |
---|
| 360 | +{ |
---|
| 361 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 362 | + |
---|
| 363 | + return scnprintf(buf, PAGE_SIZE, "%lld\n", |
---|
| 364 | + atomic64_read(&fs_info->discard_ctl.discardable_bytes)); |
---|
| 365 | +} |
---|
| 366 | +BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show); |
---|
| 367 | + |
---|
| 368 | +static ssize_t btrfs_discardable_extents_show(struct kobject *kobj, |
---|
| 369 | + struct kobj_attribute *a, |
---|
| 370 | + char *buf) |
---|
| 371 | +{ |
---|
| 372 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 373 | + |
---|
| 374 | + return scnprintf(buf, PAGE_SIZE, "%d\n", |
---|
| 375 | + atomic_read(&fs_info->discard_ctl.discardable_extents)); |
---|
| 376 | +} |
---|
| 377 | +BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show); |
---|
| 378 | + |
---|
| 379 | +static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj, |
---|
| 380 | + struct kobj_attribute *a, |
---|
| 381 | + char *buf) |
---|
| 382 | +{ |
---|
| 383 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 384 | + |
---|
| 385 | + return scnprintf(buf, PAGE_SIZE, "%llu\n", |
---|
| 386 | + fs_info->discard_ctl.discard_bitmap_bytes); |
---|
| 387 | +} |
---|
| 388 | +BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show); |
---|
| 389 | + |
---|
| 390 | +static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj, |
---|
| 391 | + struct kobj_attribute *a, |
---|
| 392 | + char *buf) |
---|
| 393 | +{ |
---|
| 394 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 395 | + |
---|
| 396 | + return scnprintf(buf, PAGE_SIZE, "%lld\n", |
---|
| 397 | + atomic64_read(&fs_info->discard_ctl.discard_bytes_saved)); |
---|
| 398 | +} |
---|
| 399 | +BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show); |
---|
| 400 | + |
---|
| 401 | +static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj, |
---|
| 402 | + struct kobj_attribute *a, |
---|
| 403 | + char *buf) |
---|
| 404 | +{ |
---|
| 405 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 406 | + |
---|
| 407 | + return scnprintf(buf, PAGE_SIZE, "%llu\n", |
---|
| 408 | + fs_info->discard_ctl.discard_extent_bytes); |
---|
| 409 | +} |
---|
| 410 | +BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show); |
---|
| 411 | + |
---|
| 412 | +static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj, |
---|
| 413 | + struct kobj_attribute *a, |
---|
| 414 | + char *buf) |
---|
| 415 | +{ |
---|
| 416 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 417 | + |
---|
| 418 | + return scnprintf(buf, PAGE_SIZE, "%u\n", |
---|
| 419 | + READ_ONCE(fs_info->discard_ctl.iops_limit)); |
---|
| 420 | +} |
---|
| 421 | + |
---|
| 422 | +static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj, |
---|
| 423 | + struct kobj_attribute *a, |
---|
| 424 | + const char *buf, size_t len) |
---|
| 425 | +{ |
---|
| 426 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 427 | + struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; |
---|
| 428 | + u32 iops_limit; |
---|
| 429 | + int ret; |
---|
| 430 | + |
---|
| 431 | + ret = kstrtou32(buf, 10, &iops_limit); |
---|
| 432 | + if (ret) |
---|
| 433 | + return -EINVAL; |
---|
| 434 | + |
---|
| 435 | + WRITE_ONCE(discard_ctl->iops_limit, iops_limit); |
---|
| 436 | + |
---|
| 437 | + return len; |
---|
| 438 | +} |
---|
| 439 | +BTRFS_ATTR_RW(discard, iops_limit, btrfs_discard_iops_limit_show, |
---|
| 440 | + btrfs_discard_iops_limit_store); |
---|
| 441 | + |
---|
| 442 | +static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj, |
---|
| 443 | + struct kobj_attribute *a, |
---|
| 444 | + char *buf) |
---|
| 445 | +{ |
---|
| 446 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 447 | + |
---|
| 448 | + return scnprintf(buf, PAGE_SIZE, "%u\n", |
---|
| 449 | + READ_ONCE(fs_info->discard_ctl.kbps_limit)); |
---|
| 450 | +} |
---|
| 451 | + |
---|
| 452 | +static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj, |
---|
| 453 | + struct kobj_attribute *a, |
---|
| 454 | + const char *buf, size_t len) |
---|
| 455 | +{ |
---|
| 456 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 457 | + struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; |
---|
| 458 | + u32 kbps_limit; |
---|
| 459 | + int ret; |
---|
| 460 | + |
---|
| 461 | + ret = kstrtou32(buf, 10, &kbps_limit); |
---|
| 462 | + if (ret) |
---|
| 463 | + return -EINVAL; |
---|
| 464 | + |
---|
| 465 | + WRITE_ONCE(discard_ctl->kbps_limit, kbps_limit); |
---|
| 466 | + |
---|
| 467 | + return len; |
---|
| 468 | +} |
---|
| 469 | +BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show, |
---|
| 470 | + btrfs_discard_kbps_limit_store); |
---|
| 471 | + |
---|
| 472 | +static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj, |
---|
| 473 | + struct kobj_attribute *a, |
---|
| 474 | + char *buf) |
---|
| 475 | +{ |
---|
| 476 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 477 | + |
---|
| 478 | + return scnprintf(buf, PAGE_SIZE, "%llu\n", |
---|
| 479 | + READ_ONCE(fs_info->discard_ctl.max_discard_size)); |
---|
| 480 | +} |
---|
| 481 | + |
---|
| 482 | +static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj, |
---|
| 483 | + struct kobj_attribute *a, |
---|
| 484 | + const char *buf, size_t len) |
---|
| 485 | +{ |
---|
| 486 | + struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); |
---|
| 487 | + struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl; |
---|
| 488 | + u64 max_discard_size; |
---|
| 489 | + int ret; |
---|
| 490 | + |
---|
| 491 | + ret = kstrtou64(buf, 10, &max_discard_size); |
---|
| 492 | + if (ret) |
---|
| 493 | + return -EINVAL; |
---|
| 494 | + |
---|
| 495 | + WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size); |
---|
| 496 | + |
---|
| 497 | + return len; |
---|
| 498 | +} |
---|
| 499 | +BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show, |
---|
| 500 | + btrfs_discard_max_discard_size_store); |
---|
| 501 | + |
---|
| 502 | +static const struct attribute *discard_debug_attrs[] = { |
---|
| 503 | + BTRFS_ATTR_PTR(discard, discardable_bytes), |
---|
| 504 | + BTRFS_ATTR_PTR(discard, discardable_extents), |
---|
| 505 | + BTRFS_ATTR_PTR(discard, discard_bitmap_bytes), |
---|
| 506 | + BTRFS_ATTR_PTR(discard, discard_bytes_saved), |
---|
| 507 | + BTRFS_ATTR_PTR(discard, discard_extent_bytes), |
---|
| 508 | + BTRFS_ATTR_PTR(discard, iops_limit), |
---|
| 509 | + BTRFS_ATTR_PTR(discard, kbps_limit), |
---|
| 510 | + BTRFS_ATTR_PTR(discard, max_discard_size), |
---|
| 511 | + NULL, |
---|
| 512 | +}; |
---|
| 513 | + |
---|
| 514 | +/* |
---|
| 515 | + * Runtime debugging exported via sysfs |
---|
| 516 | + * |
---|
| 517 | + * /sys/fs/btrfs/debug - applies to module or all filesystems |
---|
| 518 | + * /sys/fs/btrfs/UUID - applies only to the given filesystem |
---|
| 519 | + */ |
---|
| 520 | +static const struct attribute *btrfs_debug_mount_attrs[] = { |
---|
| 521 | + NULL, |
---|
| 522 | +}; |
---|
| 523 | + |
---|
| 524 | +static struct attribute *btrfs_debug_feature_attrs[] = { |
---|
| 525 | + NULL |
---|
| 526 | +}; |
---|
| 527 | + |
---|
| 528 | +static const struct attribute_group btrfs_debug_feature_attr_group = { |
---|
| 529 | + .name = "debug", |
---|
| 530 | + .attrs = btrfs_debug_feature_attrs, |
---|
| 531 | +}; |
---|
| 532 | + |
---|
| 533 | +#endif |
---|
| 534 | + |
---|
248 | 535 | static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) |
---|
249 | 536 | { |
---|
250 | 537 | u64 val; |
---|
.. | .. |
---|
253 | 540 | val = *value_ptr; |
---|
254 | 541 | if (lock) |
---|
255 | 542 | spin_unlock(lock); |
---|
256 | | - return snprintf(buf, PAGE_SIZE, "%llu\n", val); |
---|
| 543 | + return scnprintf(buf, PAGE_SIZE, "%llu\n", val); |
---|
257 | 544 | } |
---|
258 | 545 | |
---|
259 | 546 | static ssize_t global_rsv_size_show(struct kobject *kobj, |
---|
.. | .. |
---|
287 | 574 | |
---|
288 | 575 | { |
---|
289 | 576 | struct btrfs_space_info *sinfo = to_space_info(kobj->parent); |
---|
290 | | - struct btrfs_block_group_cache *block_group; |
---|
| 577 | + struct btrfs_block_group *block_group; |
---|
291 | 578 | int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags); |
---|
292 | 579 | u64 val = 0; |
---|
293 | 580 | |
---|
294 | 581 | down_read(&sinfo->groups_sem); |
---|
295 | 582 | list_for_each_entry(block_group, &sinfo->block_groups[index], list) { |
---|
296 | 583 | if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes)) |
---|
297 | | - val += block_group->key.offset; |
---|
| 584 | + val += block_group->length; |
---|
298 | 585 | else |
---|
299 | | - val += btrfs_block_group_used(&block_group->item); |
---|
| 586 | + val += block_group->used; |
---|
300 | 587 | } |
---|
301 | 588 | up_read(&sinfo->groups_sem); |
---|
302 | | - return snprintf(buf, PAGE_SIZE, "%llu\n", val); |
---|
| 589 | + return scnprintf(buf, PAGE_SIZE, "%llu\n", val); |
---|
303 | 590 | } |
---|
304 | 591 | |
---|
305 | | -static struct attribute *raid_attributes[] = { |
---|
| 592 | +static struct attribute *raid_attrs[] = { |
---|
306 | 593 | BTRFS_ATTR_PTR(raid, total_bytes), |
---|
307 | 594 | BTRFS_ATTR_PTR(raid, used_bytes), |
---|
308 | 595 | NULL |
---|
309 | 596 | }; |
---|
| 597 | +ATTRIBUTE_GROUPS(raid); |
---|
310 | 598 | |
---|
311 | 599 | static void release_raid_kobj(struct kobject *kobj) |
---|
312 | 600 | { |
---|
313 | 601 | kfree(to_raid_kobj(kobj)); |
---|
314 | 602 | } |
---|
315 | 603 | |
---|
316 | | -struct kobj_type btrfs_raid_ktype = { |
---|
| 604 | +static struct kobj_type btrfs_raid_ktype = { |
---|
317 | 605 | .sysfs_ops = &kobj_sysfs_ops, |
---|
318 | 606 | .release = release_raid_kobj, |
---|
319 | | - .default_attrs = raid_attributes, |
---|
| 607 | + .default_groups = raid_groups, |
---|
320 | 608 | }; |
---|
321 | 609 | |
---|
322 | 610 | #define SPACE_INFO_ATTR(field) \ |
---|
.. | .. |
---|
335 | 623 | { |
---|
336 | 624 | struct btrfs_space_info *sinfo = to_space_info(kobj); |
---|
337 | 625 | s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned); |
---|
338 | | - return snprintf(buf, PAGE_SIZE, "%lld\n", val); |
---|
| 626 | + return scnprintf(buf, PAGE_SIZE, "%lld\n", val); |
---|
339 | 627 | } |
---|
340 | 628 | |
---|
341 | 629 | SPACE_INFO_ATTR(flags); |
---|
.. | .. |
---|
363 | 651 | BTRFS_ATTR_PTR(space_info, total_bytes_pinned), |
---|
364 | 652 | NULL, |
---|
365 | 653 | }; |
---|
| 654 | +ATTRIBUTE_GROUPS(space_info); |
---|
366 | 655 | |
---|
367 | 656 | static void space_info_release(struct kobject *kobj) |
---|
368 | 657 | { |
---|
.. | .. |
---|
371 | 660 | kfree(sinfo); |
---|
372 | 661 | } |
---|
373 | 662 | |
---|
374 | | -struct kobj_type space_info_ktype = { |
---|
| 663 | +static struct kobj_type space_info_ktype = { |
---|
375 | 664 | .sysfs_ops = &kobj_sysfs_ops, |
---|
376 | 665 | .release = space_info_release, |
---|
377 | | - .default_attrs = space_info_attrs, |
---|
| 666 | + .default_groups = space_info_groups, |
---|
378 | 667 | }; |
---|
379 | 668 | |
---|
380 | 669 | static const struct attribute *allocation_attrs[] = { |
---|
.. | .. |
---|
391 | 680 | ssize_t ret; |
---|
392 | 681 | |
---|
393 | 682 | spin_lock(&fs_info->super_lock); |
---|
394 | | - ret = snprintf(buf, PAGE_SIZE, label[0] ? "%s\n" : "%s", label); |
---|
| 683 | + ret = scnprintf(buf, PAGE_SIZE, label[0] ? "%s\n" : "%s", label); |
---|
395 | 684 | spin_unlock(&fs_info->super_lock); |
---|
396 | 685 | |
---|
397 | 686 | return ret; |
---|
.. | .. |
---|
439 | 728 | { |
---|
440 | 729 | struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
---|
441 | 730 | |
---|
442 | | - return snprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize); |
---|
| 731 | + return scnprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->nodesize); |
---|
443 | 732 | } |
---|
444 | 733 | |
---|
445 | 734 | BTRFS_ATTR(, nodesize, btrfs_nodesize_show); |
---|
.. | .. |
---|
449 | 738 | { |
---|
450 | 739 | struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
---|
451 | 740 | |
---|
452 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
---|
453 | | - fs_info->super_copy->sectorsize); |
---|
| 741 | + return scnprintf(buf, PAGE_SIZE, "%u\n", |
---|
| 742 | + fs_info->super_copy->sectorsize); |
---|
454 | 743 | } |
---|
455 | 744 | |
---|
456 | 745 | BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show); |
---|
.. | .. |
---|
460 | 749 | { |
---|
461 | 750 | struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
---|
462 | 751 | |
---|
463 | | - return snprintf(buf, PAGE_SIZE, "%u\n", |
---|
464 | | - fs_info->super_copy->sectorsize); |
---|
| 752 | + return scnprintf(buf, PAGE_SIZE, "%u\n", fs_info->super_copy->sectorsize); |
---|
465 | 753 | } |
---|
466 | 754 | |
---|
467 | 755 | BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show); |
---|
.. | .. |
---|
473 | 761 | int quota_override; |
---|
474 | 762 | |
---|
475 | 763 | quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); |
---|
476 | | - return snprintf(buf, PAGE_SIZE, "%d\n", quota_override); |
---|
| 764 | + return scnprintf(buf, PAGE_SIZE, "%d\n", quota_override); |
---|
477 | 765 | } |
---|
478 | 766 | |
---|
479 | 767 | static ssize_t quota_override_store(struct kobject *kobj, |
---|
.. | .. |
---|
506 | 794 | |
---|
507 | 795 | BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store); |
---|
508 | 796 | |
---|
| 797 | +static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj, |
---|
| 798 | + struct kobj_attribute *a, char *buf) |
---|
| 799 | +{ |
---|
| 800 | + struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
---|
| 801 | + |
---|
| 802 | + return scnprintf(buf, PAGE_SIZE, "%pU\n", |
---|
| 803 | + fs_info->fs_devices->metadata_uuid); |
---|
| 804 | +} |
---|
| 805 | + |
---|
| 806 | +BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show); |
---|
| 807 | + |
---|
| 808 | +static ssize_t btrfs_checksum_show(struct kobject *kobj, |
---|
| 809 | + struct kobj_attribute *a, char *buf) |
---|
| 810 | +{ |
---|
| 811 | + struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
---|
| 812 | + u16 csum_type = btrfs_super_csum_type(fs_info->super_copy); |
---|
| 813 | + |
---|
| 814 | + return scnprintf(buf, PAGE_SIZE, "%s (%s)\n", |
---|
| 815 | + btrfs_super_csum_name(csum_type), |
---|
| 816 | + crypto_shash_driver_name(fs_info->csum_shash)); |
---|
| 817 | +} |
---|
| 818 | + |
---|
| 819 | +BTRFS_ATTR(, checksum, btrfs_checksum_show); |
---|
| 820 | + |
---|
| 821 | +static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj, |
---|
| 822 | + struct kobj_attribute *a, char *buf) |
---|
| 823 | +{ |
---|
| 824 | + struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
---|
| 825 | + const char *str; |
---|
| 826 | + |
---|
| 827 | + switch (READ_ONCE(fs_info->exclusive_operation)) { |
---|
| 828 | + case BTRFS_EXCLOP_NONE: |
---|
| 829 | + str = "none\n"; |
---|
| 830 | + break; |
---|
| 831 | + case BTRFS_EXCLOP_BALANCE: |
---|
| 832 | + str = "balance\n"; |
---|
| 833 | + break; |
---|
| 834 | + case BTRFS_EXCLOP_DEV_ADD: |
---|
| 835 | + str = "device add\n"; |
---|
| 836 | + break; |
---|
| 837 | + case BTRFS_EXCLOP_DEV_REMOVE: |
---|
| 838 | + str = "device remove\n"; |
---|
| 839 | + break; |
---|
| 840 | + case BTRFS_EXCLOP_DEV_REPLACE: |
---|
| 841 | + str = "device replace\n"; |
---|
| 842 | + break; |
---|
| 843 | + case BTRFS_EXCLOP_RESIZE: |
---|
| 844 | + str = "resize\n"; |
---|
| 845 | + break; |
---|
| 846 | + case BTRFS_EXCLOP_SWAP_ACTIVATE: |
---|
| 847 | + str = "swap activate\n"; |
---|
| 848 | + break; |
---|
| 849 | + default: |
---|
| 850 | + str = "UNKNOWN\n"; |
---|
| 851 | + break; |
---|
| 852 | + } |
---|
| 853 | + return scnprintf(buf, PAGE_SIZE, "%s", str); |
---|
| 854 | +} |
---|
| 855 | +BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show); |
---|
| 856 | + |
---|
509 | 857 | static const struct attribute *btrfs_attrs[] = { |
---|
510 | 858 | BTRFS_ATTR_PTR(, label), |
---|
511 | 859 | BTRFS_ATTR_PTR(, nodesize), |
---|
512 | 860 | BTRFS_ATTR_PTR(, sectorsize), |
---|
513 | 861 | BTRFS_ATTR_PTR(, clone_alignment), |
---|
514 | 862 | BTRFS_ATTR_PTR(, quota_override), |
---|
| 863 | + BTRFS_ATTR_PTR(, metadata_uuid), |
---|
| 864 | + BTRFS_ATTR_PTR(, checksum), |
---|
| 865 | + BTRFS_ATTR_PTR(, exclusive_operation), |
---|
515 | 866 | NULL, |
---|
516 | 867 | }; |
---|
517 | 868 | |
---|
.. | .. |
---|
596 | 947 | |
---|
597 | 948 | static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) |
---|
598 | 949 | { |
---|
599 | | - if (fs_devs->device_dir_kobj) { |
---|
600 | | - kobject_del(fs_devs->device_dir_kobj); |
---|
601 | | - kobject_put(fs_devs->device_dir_kobj); |
---|
602 | | - fs_devs->device_dir_kobj = NULL; |
---|
| 950 | + if (fs_devs->devinfo_kobj) { |
---|
| 951 | + kobject_del(fs_devs->devinfo_kobj); |
---|
| 952 | + kobject_put(fs_devs->devinfo_kobj); |
---|
| 953 | + fs_devs->devinfo_kobj = NULL; |
---|
| 954 | + } |
---|
| 955 | + |
---|
| 956 | + if (fs_devs->devices_kobj) { |
---|
| 957 | + kobject_del(fs_devs->devices_kobj); |
---|
| 958 | + kobject_put(fs_devs->devices_kobj); |
---|
| 959 | + fs_devs->devices_kobj = NULL; |
---|
603 | 960 | } |
---|
604 | 961 | |
---|
605 | 962 | if (fs_devs->fsid_kobj.state_initialized) { |
---|
.. | .. |
---|
624 | 981 | } |
---|
625 | 982 | } |
---|
626 | 983 | |
---|
| 984 | +static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices) |
---|
| 985 | +{ |
---|
| 986 | + struct btrfs_device *device; |
---|
| 987 | + struct btrfs_fs_devices *seed; |
---|
| 988 | + |
---|
| 989 | + list_for_each_entry(device, &fs_devices->devices, dev_list) |
---|
| 990 | + btrfs_sysfs_remove_device(device); |
---|
| 991 | + |
---|
| 992 | + list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { |
---|
| 993 | + list_for_each_entry(device, &seed->devices, dev_list) |
---|
| 994 | + btrfs_sysfs_remove_device(device); |
---|
| 995 | + } |
---|
| 996 | +} |
---|
| 997 | + |
---|
627 | 998 | void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) |
---|
628 | 999 | { |
---|
629 | | - btrfs_reset_fs_info_ptr(fs_info); |
---|
| 1000 | + struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; |
---|
| 1001 | + |
---|
| 1002 | + sysfs_remove_link(fsid_kobj, "bdi"); |
---|
630 | 1003 | |
---|
631 | 1004 | if (fs_info->space_info_kobj) { |
---|
632 | 1005 | sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); |
---|
633 | 1006 | kobject_del(fs_info->space_info_kobj); |
---|
634 | 1007 | kobject_put(fs_info->space_info_kobj); |
---|
635 | 1008 | } |
---|
| 1009 | +#ifdef CONFIG_BTRFS_DEBUG |
---|
| 1010 | + if (fs_info->discard_debug_kobj) { |
---|
| 1011 | + sysfs_remove_files(fs_info->discard_debug_kobj, |
---|
| 1012 | + discard_debug_attrs); |
---|
| 1013 | + kobject_del(fs_info->discard_debug_kobj); |
---|
| 1014 | + kobject_put(fs_info->discard_debug_kobj); |
---|
| 1015 | + } |
---|
| 1016 | + if (fs_info->debug_kobj) { |
---|
| 1017 | + sysfs_remove_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); |
---|
| 1018 | + kobject_del(fs_info->debug_kobj); |
---|
| 1019 | + kobject_put(fs_info->debug_kobj); |
---|
| 1020 | + } |
---|
| 1021 | +#endif |
---|
636 | 1022 | addrm_unknown_feature_attrs(fs_info, false); |
---|
637 | | - sysfs_remove_group(&fs_info->fs_devices->fsid_kobj, &btrfs_feature_attr_group); |
---|
638 | | - sysfs_remove_files(&fs_info->fs_devices->fsid_kobj, btrfs_attrs); |
---|
639 | | - btrfs_sysfs_rm_device_link(fs_info->fs_devices, NULL); |
---|
| 1023 | + sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); |
---|
| 1024 | + sysfs_remove_files(fsid_kobj, btrfs_attrs); |
---|
| 1025 | + btrfs_sysfs_remove_fs_devices(fs_info->fs_devices); |
---|
640 | 1026 | } |
---|
641 | 1027 | |
---|
642 | | -const char * const btrfs_feature_set_names[FEAT_MAX] = { |
---|
| 1028 | +static const char * const btrfs_feature_set_names[FEAT_MAX] = { |
---|
643 | 1029 | [FEAT_COMPAT] = "compat", |
---|
644 | 1030 | [FEAT_COMPAT_RO] = "compat_ro", |
---|
645 | 1031 | [FEAT_INCOMPAT] = "incompat", |
---|
646 | 1032 | }; |
---|
| 1033 | + |
---|
| 1034 | +const char *btrfs_feature_set_name(enum btrfs_feature_set set) |
---|
| 1035 | +{ |
---|
| 1036 | + return btrfs_feature_set_names[set]; |
---|
| 1037 | +} |
---|
647 | 1038 | |
---|
648 | 1039 | char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) |
---|
649 | 1040 | { |
---|
.. | .. |
---|
663 | 1054 | continue; |
---|
664 | 1055 | |
---|
665 | 1056 | name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; |
---|
666 | | - len += snprintf(str + len, bufsize - len, "%s%s", |
---|
| 1057 | + len += scnprintf(str + len, bufsize - len, "%s%s", |
---|
667 | 1058 | len ? "," : "", name); |
---|
668 | 1059 | } |
---|
669 | 1060 | |
---|
.. | .. |
---|
714 | 1105 | } |
---|
715 | 1106 | } |
---|
716 | 1107 | |
---|
717 | | -/* when one_device is NULL, it removes all device links */ |
---|
| 1108 | +/* |
---|
| 1109 | + * Create a sysfs entry for a given block group type at path |
---|
| 1110 | + * /sys/fs/btrfs/UUID/allocation/data/TYPE |
---|
| 1111 | + */ |
---|
| 1112 | +void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache) |
---|
| 1113 | +{ |
---|
| 1114 | + struct btrfs_fs_info *fs_info = cache->fs_info; |
---|
| 1115 | + struct btrfs_space_info *space_info = cache->space_info; |
---|
| 1116 | + struct raid_kobject *rkobj; |
---|
| 1117 | + const int index = btrfs_bg_flags_to_raid_index(cache->flags); |
---|
| 1118 | + unsigned int nofs_flag; |
---|
| 1119 | + int ret; |
---|
718 | 1120 | |
---|
719 | | -int btrfs_sysfs_rm_device_link(struct btrfs_fs_devices *fs_devices, |
---|
720 | | - struct btrfs_device *one_device) |
---|
| 1121 | + /* |
---|
| 1122 | + * Setup a NOFS context because kobject_add(), deep in its call chain, |
---|
| 1123 | + * does GFP_KERNEL allocations, and we are often called in a context |
---|
| 1124 | + * where if reclaim is triggered we can deadlock (we are either holding |
---|
| 1125 | + * a transaction handle or some lock required for a transaction |
---|
| 1126 | + * commit). |
---|
| 1127 | + */ |
---|
| 1128 | + nofs_flag = memalloc_nofs_save(); |
---|
| 1129 | + |
---|
| 1130 | + rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS); |
---|
| 1131 | + if (!rkobj) { |
---|
| 1132 | + memalloc_nofs_restore(nofs_flag); |
---|
| 1133 | + btrfs_warn(cache->fs_info, |
---|
| 1134 | + "couldn't alloc memory for raid level kobject"); |
---|
| 1135 | + return; |
---|
| 1136 | + } |
---|
| 1137 | + |
---|
| 1138 | + rkobj->flags = cache->flags; |
---|
| 1139 | + kobject_init(&rkobj->kobj, &btrfs_raid_ktype); |
---|
| 1140 | + |
---|
| 1141 | + /* |
---|
| 1142 | + * We call this either on mount, or if we've created a block group for a |
---|
| 1143 | + * new index type while running (i.e. when restriping). The running |
---|
| 1144 | + * case is tricky because we could race with other threads, so we need |
---|
| 1145 | + * to have this check to make sure we didn't already init the kobject. |
---|
| 1146 | + * |
---|
| 1147 | + * We don't have to protect on the free side because it only happens on |
---|
| 1148 | + * unmount. |
---|
| 1149 | + */ |
---|
| 1150 | + spin_lock(&space_info->lock); |
---|
| 1151 | + if (space_info->block_group_kobjs[index]) { |
---|
| 1152 | + spin_unlock(&space_info->lock); |
---|
| 1153 | + kobject_put(&rkobj->kobj); |
---|
| 1154 | + return; |
---|
| 1155 | + } else { |
---|
| 1156 | + space_info->block_group_kobjs[index] = &rkobj->kobj; |
---|
| 1157 | + } |
---|
| 1158 | + spin_unlock(&space_info->lock); |
---|
| 1159 | + |
---|
| 1160 | + ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s", |
---|
| 1161 | + btrfs_bg_type_to_raid_name(rkobj->flags)); |
---|
| 1162 | + memalloc_nofs_restore(nofs_flag); |
---|
| 1163 | + if (ret) { |
---|
| 1164 | + spin_lock(&space_info->lock); |
---|
| 1165 | + space_info->block_group_kobjs[index] = NULL; |
---|
| 1166 | + spin_unlock(&space_info->lock); |
---|
| 1167 | + kobject_put(&rkobj->kobj); |
---|
| 1168 | + btrfs_warn(fs_info, |
---|
| 1169 | + "failed to add kobject for block cache, ignoring"); |
---|
| 1170 | + return; |
---|
| 1171 | + } |
---|
| 1172 | +} |
---|
| 1173 | + |
---|
| 1174 | +/* |
---|
| 1175 | + * Remove sysfs directories for all block group types of a given space info and |
---|
| 1176 | + * the space info as well |
---|
| 1177 | + */ |
---|
| 1178 | +void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info) |
---|
| 1179 | +{ |
---|
| 1180 | + int i; |
---|
| 1181 | + |
---|
| 1182 | + for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) { |
---|
| 1183 | + struct kobject *kobj; |
---|
| 1184 | + |
---|
| 1185 | + kobj = space_info->block_group_kobjs[i]; |
---|
| 1186 | + space_info->block_group_kobjs[i] = NULL; |
---|
| 1187 | + if (kobj) { |
---|
| 1188 | + kobject_del(kobj); |
---|
| 1189 | + kobject_put(kobj); |
---|
| 1190 | + } |
---|
| 1191 | + } |
---|
| 1192 | + kobject_del(&space_info->kobj); |
---|
| 1193 | + kobject_put(&space_info->kobj); |
---|
| 1194 | +} |
---|
| 1195 | + |
---|
| 1196 | +static const char *alloc_name(u64 flags) |
---|
| 1197 | +{ |
---|
| 1198 | + switch (flags) { |
---|
| 1199 | + case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA: |
---|
| 1200 | + return "mixed"; |
---|
| 1201 | + case BTRFS_BLOCK_GROUP_METADATA: |
---|
| 1202 | + return "metadata"; |
---|
| 1203 | + case BTRFS_BLOCK_GROUP_DATA: |
---|
| 1204 | + return "data"; |
---|
| 1205 | + case BTRFS_BLOCK_GROUP_SYSTEM: |
---|
| 1206 | + return "system"; |
---|
| 1207 | + default: |
---|
| 1208 | + WARN_ON(1); |
---|
| 1209 | + return "invalid-combination"; |
---|
| 1210 | + }; |
---|
| 1211 | +} |
---|
| 1212 | + |
---|
| 1213 | +/* |
---|
| 1214 | + * Create a sysfs entry for a space info type at path |
---|
| 1215 | + * /sys/fs/btrfs/UUID/allocation/TYPE |
---|
| 1216 | + */ |
---|
| 1217 | +int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, |
---|
| 1218 | + struct btrfs_space_info *space_info) |
---|
| 1219 | +{ |
---|
| 1220 | + int ret; |
---|
| 1221 | + |
---|
| 1222 | + ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, |
---|
| 1223 | + fs_info->space_info_kobj, "%s", |
---|
| 1224 | + alloc_name(space_info->flags)); |
---|
| 1225 | + if (ret) { |
---|
| 1226 | + kobject_put(&space_info->kobj); |
---|
| 1227 | + return ret; |
---|
| 1228 | + } |
---|
| 1229 | + |
---|
| 1230 | + return 0; |
---|
| 1231 | +} |
---|
| 1232 | + |
---|
| 1233 | +void btrfs_sysfs_remove_device(struct btrfs_device *device) |
---|
721 | 1234 | { |
---|
722 | 1235 | struct hd_struct *disk; |
---|
723 | 1236 | struct kobject *disk_kobj; |
---|
| 1237 | + struct kobject *devices_kobj; |
---|
724 | 1238 | |
---|
725 | | - if (!fs_devices->device_dir_kobj) |
---|
726 | | - return -EINVAL; |
---|
| 1239 | + /* |
---|
| 1240 | + * Seed fs_devices devices_kobj aren't used, fetch kobject from the |
---|
| 1241 | + * fs_info::fs_devices. |
---|
| 1242 | + */ |
---|
| 1243 | + devices_kobj = device->fs_info->fs_devices->devices_kobj; |
---|
| 1244 | + ASSERT(devices_kobj); |
---|
727 | 1245 | |
---|
728 | | - if (one_device && one_device->bdev) { |
---|
729 | | - disk = one_device->bdev->bd_part; |
---|
| 1246 | + if (device->bdev) { |
---|
| 1247 | + disk = device->bdev->bd_part; |
---|
730 | 1248 | disk_kobj = &part_to_dev(disk)->kobj; |
---|
731 | | - |
---|
732 | | - sysfs_remove_link(fs_devices->device_dir_kobj, |
---|
733 | | - disk_kobj->name); |
---|
| 1249 | + sysfs_remove_link(devices_kobj, disk_kobj->name); |
---|
734 | 1250 | } |
---|
735 | 1251 | |
---|
736 | | - if (one_device) |
---|
737 | | - return 0; |
---|
738 | | - |
---|
739 | | - list_for_each_entry(one_device, |
---|
740 | | - &fs_devices->devices, dev_list) { |
---|
741 | | - if (!one_device->bdev) |
---|
742 | | - continue; |
---|
743 | | - disk = one_device->bdev->bd_part; |
---|
744 | | - disk_kobj = &part_to_dev(disk)->kobj; |
---|
745 | | - |
---|
746 | | - sysfs_remove_link(fs_devices->device_dir_kobj, |
---|
747 | | - disk_kobj->name); |
---|
| 1252 | + if (device->devid_kobj.state_initialized) { |
---|
| 1253 | + kobject_del(&device->devid_kobj); |
---|
| 1254 | + kobject_put(&device->devid_kobj); |
---|
| 1255 | + wait_for_completion(&device->kobj_unregister); |
---|
748 | 1256 | } |
---|
749 | | - |
---|
750 | | - return 0; |
---|
751 | 1257 | } |
---|
752 | 1258 | |
---|
753 | | -int btrfs_sysfs_add_device(struct btrfs_fs_devices *fs_devs) |
---|
| 1259 | +static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj, |
---|
| 1260 | + struct kobj_attribute *a, |
---|
| 1261 | + char *buf) |
---|
754 | 1262 | { |
---|
755 | | - if (!fs_devs->device_dir_kobj) |
---|
756 | | - fs_devs->device_dir_kobj = kobject_create_and_add("devices", |
---|
757 | | - &fs_devs->fsid_kobj); |
---|
| 1263 | + int val; |
---|
| 1264 | + struct btrfs_device *device = container_of(kobj, struct btrfs_device, |
---|
| 1265 | + devid_kobj); |
---|
758 | 1266 | |
---|
759 | | - if (!fs_devs->device_dir_kobj) |
---|
760 | | - return -ENOMEM; |
---|
| 1267 | + val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state); |
---|
761 | 1268 | |
---|
762 | | - return 0; |
---|
| 1269 | + return scnprintf(buf, PAGE_SIZE, "%d\n", val); |
---|
| 1270 | +} |
---|
| 1271 | +BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show); |
---|
| 1272 | + |
---|
| 1273 | +static ssize_t btrfs_devinfo_missing_show(struct kobject *kobj, |
---|
| 1274 | + struct kobj_attribute *a, char *buf) |
---|
| 1275 | +{ |
---|
| 1276 | + int val; |
---|
| 1277 | + struct btrfs_device *device = container_of(kobj, struct btrfs_device, |
---|
| 1278 | + devid_kobj); |
---|
| 1279 | + |
---|
| 1280 | + val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state); |
---|
| 1281 | + |
---|
| 1282 | + return scnprintf(buf, PAGE_SIZE, "%d\n", val); |
---|
| 1283 | +} |
---|
| 1284 | +BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show); |
---|
| 1285 | + |
---|
| 1286 | +static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj, |
---|
| 1287 | + struct kobj_attribute *a, |
---|
| 1288 | + char *buf) |
---|
| 1289 | +{ |
---|
| 1290 | + int val; |
---|
| 1291 | + struct btrfs_device *device = container_of(kobj, struct btrfs_device, |
---|
| 1292 | + devid_kobj); |
---|
| 1293 | + |
---|
| 1294 | + val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state); |
---|
| 1295 | + |
---|
| 1296 | + return scnprintf(buf, PAGE_SIZE, "%d\n", val); |
---|
| 1297 | +} |
---|
| 1298 | +BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show); |
---|
| 1299 | + |
---|
| 1300 | +static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj, |
---|
| 1301 | + struct kobj_attribute *a, char *buf) |
---|
| 1302 | +{ |
---|
| 1303 | + int val; |
---|
| 1304 | + struct btrfs_device *device = container_of(kobj, struct btrfs_device, |
---|
| 1305 | + devid_kobj); |
---|
| 1306 | + |
---|
| 1307 | + val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state); |
---|
| 1308 | + |
---|
| 1309 | + return scnprintf(buf, PAGE_SIZE, "%d\n", val); |
---|
| 1310 | +} |
---|
| 1311 | +BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show); |
---|
| 1312 | + |
---|
| 1313 | +static struct attribute *devid_attrs[] = { |
---|
| 1314 | + BTRFS_ATTR_PTR(devid, in_fs_metadata), |
---|
| 1315 | + BTRFS_ATTR_PTR(devid, missing), |
---|
| 1316 | + BTRFS_ATTR_PTR(devid, replace_target), |
---|
| 1317 | + BTRFS_ATTR_PTR(devid, writeable), |
---|
| 1318 | + NULL |
---|
| 1319 | +}; |
---|
| 1320 | +ATTRIBUTE_GROUPS(devid); |
---|
| 1321 | + |
---|
| 1322 | +static void btrfs_release_devid_kobj(struct kobject *kobj) |
---|
| 1323 | +{ |
---|
| 1324 | + struct btrfs_device *device = container_of(kobj, struct btrfs_device, |
---|
| 1325 | + devid_kobj); |
---|
| 1326 | + |
---|
| 1327 | + memset(&device->devid_kobj, 0, sizeof(struct kobject)); |
---|
| 1328 | + complete(&device->kobj_unregister); |
---|
763 | 1329 | } |
---|
764 | 1330 | |
---|
765 | | -int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices, |
---|
766 | | - struct btrfs_device *one_device) |
---|
| 1331 | +static struct kobj_type devid_ktype = { |
---|
| 1332 | + .sysfs_ops = &kobj_sysfs_ops, |
---|
| 1333 | + .default_groups = devid_groups, |
---|
| 1334 | + .release = btrfs_release_devid_kobj, |
---|
| 1335 | +}; |
---|
| 1336 | + |
---|
| 1337 | +int btrfs_sysfs_add_device(struct btrfs_device *device) |
---|
767 | 1338 | { |
---|
768 | | - int error = 0; |
---|
769 | | - struct btrfs_device *dev; |
---|
| 1339 | + int ret; |
---|
770 | 1340 | unsigned int nofs_flag; |
---|
| 1341 | + struct kobject *devices_kobj; |
---|
| 1342 | + struct kobject *devinfo_kobj; |
---|
| 1343 | + |
---|
| 1344 | + /* |
---|
| 1345 | + * Make sure we use the fs_info::fs_devices to fetch the kobjects even |
---|
| 1346 | + * for the seed fs_devices |
---|
| 1347 | + */ |
---|
| 1348 | + devices_kobj = device->fs_info->fs_devices->devices_kobj; |
---|
| 1349 | + devinfo_kobj = device->fs_info->fs_devices->devinfo_kobj; |
---|
| 1350 | + ASSERT(devices_kobj); |
---|
| 1351 | + ASSERT(devinfo_kobj); |
---|
771 | 1352 | |
---|
772 | 1353 | nofs_flag = memalloc_nofs_save(); |
---|
773 | | - list_for_each_entry(dev, &fs_devices->devices, dev_list) { |
---|
| 1354 | + |
---|
| 1355 | + if (device->bdev) { |
---|
774 | 1356 | struct hd_struct *disk; |
---|
775 | 1357 | struct kobject *disk_kobj; |
---|
776 | 1358 | |
---|
777 | | - if (!dev->bdev) |
---|
778 | | - continue; |
---|
779 | | - |
---|
780 | | - if (one_device && one_device != dev) |
---|
781 | | - continue; |
---|
782 | | - |
---|
783 | | - disk = dev->bdev->bd_part; |
---|
| 1359 | + disk = device->bdev->bd_part; |
---|
784 | 1360 | disk_kobj = &part_to_dev(disk)->kobj; |
---|
785 | 1361 | |
---|
786 | | - error = sysfs_create_link(fs_devices->device_dir_kobj, |
---|
787 | | - disk_kobj, disk_kobj->name); |
---|
788 | | - if (error) |
---|
789 | | - break; |
---|
| 1362 | + ret = sysfs_create_link(devices_kobj, disk_kobj, disk_kobj->name); |
---|
| 1363 | + if (ret) { |
---|
| 1364 | + btrfs_warn(device->fs_info, |
---|
| 1365 | + "creating sysfs device link for devid %llu failed: %d", |
---|
| 1366 | + device->devid, ret); |
---|
| 1367 | + goto out; |
---|
| 1368 | + } |
---|
790 | 1369 | } |
---|
791 | | - memalloc_nofs_restore(nofs_flag); |
---|
792 | 1370 | |
---|
793 | | - return error; |
---|
| 1371 | + init_completion(&device->kobj_unregister); |
---|
| 1372 | + ret = kobject_init_and_add(&device->devid_kobj, &devid_ktype, |
---|
| 1373 | + devinfo_kobj, "%llu", device->devid); |
---|
| 1374 | + if (ret) { |
---|
| 1375 | + kobject_put(&device->devid_kobj); |
---|
| 1376 | + btrfs_warn(device->fs_info, |
---|
| 1377 | + "devinfo init for devid %llu failed: %d", |
---|
| 1378 | + device->devid, ret); |
---|
| 1379 | + } |
---|
| 1380 | + |
---|
| 1381 | +out: |
---|
| 1382 | + memalloc_nofs_restore(nofs_flag); |
---|
| 1383 | + return ret; |
---|
| 1384 | +} |
---|
| 1385 | + |
---|
| 1386 | +static int btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices) |
---|
| 1387 | +{ |
---|
| 1388 | + int ret; |
---|
| 1389 | + struct btrfs_device *device; |
---|
| 1390 | + struct btrfs_fs_devices *seed; |
---|
| 1391 | + |
---|
| 1392 | + list_for_each_entry(device, &fs_devices->devices, dev_list) { |
---|
| 1393 | + ret = btrfs_sysfs_add_device(device); |
---|
| 1394 | + if (ret) |
---|
| 1395 | + goto fail; |
---|
| 1396 | + } |
---|
| 1397 | + |
---|
| 1398 | + list_for_each_entry(seed, &fs_devices->seed_list, seed_list) { |
---|
| 1399 | + list_for_each_entry(device, &seed->devices, dev_list) { |
---|
| 1400 | + ret = btrfs_sysfs_add_device(device); |
---|
| 1401 | + if (ret) |
---|
| 1402 | + goto fail; |
---|
| 1403 | + } |
---|
| 1404 | + } |
---|
| 1405 | + |
---|
| 1406 | + return 0; |
---|
| 1407 | + |
---|
| 1408 | +fail: |
---|
| 1409 | + btrfs_sysfs_remove_fs_devices(fs_devices); |
---|
| 1410 | + return ret; |
---|
| 1411 | +} |
---|
| 1412 | + |
---|
| 1413 | +void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action) |
---|
| 1414 | +{ |
---|
| 1415 | + int ret; |
---|
| 1416 | + |
---|
| 1417 | + ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action); |
---|
| 1418 | + if (ret) |
---|
| 1419 | + pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed\n", |
---|
| 1420 | + action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj), |
---|
| 1421 | + &disk_to_dev(bdev->bd_disk)->kobj); |
---|
| 1422 | +} |
---|
| 1423 | + |
---|
| 1424 | +void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices) |
---|
| 1425 | + |
---|
| 1426 | +{ |
---|
| 1427 | + char fsid_buf[BTRFS_UUID_UNPARSED_SIZE]; |
---|
| 1428 | + |
---|
| 1429 | + /* |
---|
| 1430 | + * Sprouting changes fsid of the mounted filesystem, rename the fsid |
---|
| 1431 | + * directory |
---|
| 1432 | + */ |
---|
| 1433 | + snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fs_devices->fsid); |
---|
| 1434 | + if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf)) |
---|
| 1435 | + btrfs_warn(fs_devices->fs_info, |
---|
| 1436 | + "sysfs: failed to create fsid for sprout"); |
---|
| 1437 | +} |
---|
| 1438 | + |
---|
| 1439 | +void btrfs_sysfs_update_devid(struct btrfs_device *device) |
---|
| 1440 | +{ |
---|
| 1441 | + char tmp[24]; |
---|
| 1442 | + |
---|
| 1443 | + snprintf(tmp, sizeof(tmp), "%llu", device->devid); |
---|
| 1444 | + |
---|
| 1445 | + if (kobject_rename(&device->devid_kobj, tmp)) |
---|
| 1446 | + btrfs_warn(device->fs_devices->fs_info, |
---|
| 1447 | + "sysfs: failed to update devid for %llu", |
---|
| 1448 | + device->devid); |
---|
794 | 1449 | } |
---|
795 | 1450 | |
---|
796 | 1451 | /* /sys/fs/btrfs/ entry */ |
---|
797 | 1452 | static struct kset *btrfs_kset; |
---|
798 | 1453 | |
---|
799 | | -/* /sys/kernel/debug/btrfs */ |
---|
800 | | -static struct dentry *btrfs_debugfs_root_dentry; |
---|
801 | | - |
---|
802 | | -/* Debugging tunables and exported data */ |
---|
803 | | -u64 btrfs_debugfs_test; |
---|
804 | | - |
---|
805 | 1454 | /* |
---|
| 1455 | + * Creates: |
---|
| 1456 | + * /sys/fs/btrfs/UUID |
---|
| 1457 | + * |
---|
806 | 1458 | * Can be called by the device discovery thread. |
---|
807 | | - * And parent can be specified for seed device |
---|
808 | 1459 | */ |
---|
809 | | -int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs, |
---|
810 | | - struct kobject *parent) |
---|
| 1460 | +int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs) |
---|
811 | 1461 | { |
---|
812 | 1462 | int error; |
---|
813 | 1463 | |
---|
814 | 1464 | init_completion(&fs_devs->kobj_unregister); |
---|
815 | 1465 | fs_devs->fsid_kobj.kset = btrfs_kset; |
---|
816 | | - error = kobject_init_and_add(&fs_devs->fsid_kobj, |
---|
817 | | - &btrfs_ktype, parent, "%pU", fs_devs->fsid); |
---|
| 1466 | + error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, NULL, |
---|
| 1467 | + "%pU", fs_devs->fsid); |
---|
818 | 1468 | if (error) { |
---|
819 | 1469 | kobject_put(&fs_devs->fsid_kobj); |
---|
820 | 1470 | return error; |
---|
| 1471 | + } |
---|
| 1472 | + |
---|
| 1473 | + fs_devs->devices_kobj = kobject_create_and_add("devices", |
---|
| 1474 | + &fs_devs->fsid_kobj); |
---|
| 1475 | + if (!fs_devs->devices_kobj) { |
---|
| 1476 | + btrfs_err(fs_devs->fs_info, |
---|
| 1477 | + "failed to init sysfs device interface"); |
---|
| 1478 | + btrfs_sysfs_remove_fsid(fs_devs); |
---|
| 1479 | + return -ENOMEM; |
---|
| 1480 | + } |
---|
| 1481 | + |
---|
| 1482 | + fs_devs->devinfo_kobj = kobject_create_and_add("devinfo", |
---|
| 1483 | + &fs_devs->fsid_kobj); |
---|
| 1484 | + if (!fs_devs->devinfo_kobj) { |
---|
| 1485 | + btrfs_err(fs_devs->fs_info, |
---|
| 1486 | + "failed to init sysfs devinfo kobject"); |
---|
| 1487 | + btrfs_sysfs_remove_fsid(fs_devs); |
---|
| 1488 | + return -ENOMEM; |
---|
821 | 1489 | } |
---|
822 | 1490 | |
---|
823 | 1491 | return 0; |
---|
.. | .. |
---|
829 | 1497 | struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; |
---|
830 | 1498 | struct kobject *fsid_kobj = &fs_devs->fsid_kobj; |
---|
831 | 1499 | |
---|
832 | | - btrfs_set_fs_info_ptr(fs_info); |
---|
833 | | - |
---|
834 | | - error = btrfs_sysfs_add_device_link(fs_devs, NULL); |
---|
| 1500 | + error = btrfs_sysfs_add_fs_devices(fs_devs); |
---|
835 | 1501 | if (error) |
---|
836 | 1502 | return error; |
---|
837 | 1503 | |
---|
838 | 1504 | error = sysfs_create_files(fsid_kobj, btrfs_attrs); |
---|
839 | 1505 | if (error) { |
---|
840 | | - btrfs_sysfs_rm_device_link(fs_devs, NULL); |
---|
| 1506 | + btrfs_sysfs_remove_fs_devices(fs_devs); |
---|
841 | 1507 | return error; |
---|
842 | 1508 | } |
---|
843 | 1509 | |
---|
.. | .. |
---|
846 | 1512 | if (error) |
---|
847 | 1513 | goto failure; |
---|
848 | 1514 | |
---|
| 1515 | +#ifdef CONFIG_BTRFS_DEBUG |
---|
| 1516 | + fs_info->debug_kobj = kobject_create_and_add("debug", fsid_kobj); |
---|
| 1517 | + if (!fs_info->debug_kobj) { |
---|
| 1518 | + error = -ENOMEM; |
---|
| 1519 | + goto failure; |
---|
| 1520 | + } |
---|
| 1521 | + |
---|
| 1522 | + error = sysfs_create_files(fs_info->debug_kobj, btrfs_debug_mount_attrs); |
---|
| 1523 | + if (error) |
---|
| 1524 | + goto failure; |
---|
| 1525 | + |
---|
| 1526 | + /* Discard directory */ |
---|
| 1527 | + fs_info->discard_debug_kobj = kobject_create_and_add("discard", |
---|
| 1528 | + fs_info->debug_kobj); |
---|
| 1529 | + if (!fs_info->discard_debug_kobj) { |
---|
| 1530 | + error = -ENOMEM; |
---|
| 1531 | + goto failure; |
---|
| 1532 | + } |
---|
| 1533 | + |
---|
| 1534 | + error = sysfs_create_files(fs_info->discard_debug_kobj, |
---|
| 1535 | + discard_debug_attrs); |
---|
| 1536 | + if (error) |
---|
| 1537 | + goto failure; |
---|
| 1538 | +#endif |
---|
| 1539 | + |
---|
849 | 1540 | error = addrm_unknown_feature_attrs(fs_info, true); |
---|
| 1541 | + if (error) |
---|
| 1542 | + goto failure; |
---|
| 1543 | + |
---|
| 1544 | + error = sysfs_create_link(fsid_kobj, &fs_info->sb->s_bdi->dev->kobj, "bdi"); |
---|
850 | 1545 | if (error) |
---|
851 | 1546 | goto failure; |
---|
852 | 1547 | |
---|
.. | .. |
---|
867 | 1562 | return error; |
---|
868 | 1563 | } |
---|
869 | 1564 | |
---|
| 1565 | +static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj) |
---|
| 1566 | +{ |
---|
| 1567 | + return to_fs_info(kobj->parent->parent); |
---|
| 1568 | +} |
---|
| 1569 | + |
---|
| 1570 | +#define QGROUP_ATTR(_member, _show_name) \ |
---|
| 1571 | +static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj, \ |
---|
| 1572 | + struct kobj_attribute *a, \ |
---|
| 1573 | + char *buf) \ |
---|
| 1574 | +{ \ |
---|
| 1575 | + struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ |
---|
| 1576 | + struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ |
---|
| 1577 | + struct btrfs_qgroup, kobj); \ |
---|
| 1578 | + return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf); \ |
---|
| 1579 | +} \ |
---|
| 1580 | +BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member) |
---|
| 1581 | + |
---|
| 1582 | +#define QGROUP_RSV_ATTR(_name, _type) \ |
---|
| 1583 | +static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj, \ |
---|
| 1584 | + struct kobj_attribute *a, \ |
---|
| 1585 | + char *buf) \ |
---|
| 1586 | +{ \ |
---|
| 1587 | + struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj); \ |
---|
| 1588 | + struct btrfs_qgroup *qgroup = container_of(qgroup_kobj, \ |
---|
| 1589 | + struct btrfs_qgroup, kobj); \ |
---|
| 1590 | + return btrfs_show_u64(&qgroup->rsv.values[_type], \ |
---|
| 1591 | + &fs_info->qgroup_lock, buf); \ |
---|
| 1592 | +} \ |
---|
| 1593 | +BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name) |
---|
| 1594 | + |
---|
| 1595 | +QGROUP_ATTR(rfer, referenced); |
---|
| 1596 | +QGROUP_ATTR(excl, exclusive); |
---|
| 1597 | +QGROUP_ATTR(max_rfer, max_referenced); |
---|
| 1598 | +QGROUP_ATTR(max_excl, max_exclusive); |
---|
| 1599 | +QGROUP_ATTR(lim_flags, limit_flags); |
---|
| 1600 | +QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA); |
---|
| 1601 | +QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS); |
---|
| 1602 | +QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC); |
---|
| 1603 | + |
---|
| 1604 | +static struct attribute *qgroup_attrs[] = { |
---|
| 1605 | + BTRFS_ATTR_PTR(qgroup, referenced), |
---|
| 1606 | + BTRFS_ATTR_PTR(qgroup, exclusive), |
---|
| 1607 | + BTRFS_ATTR_PTR(qgroup, max_referenced), |
---|
| 1608 | + BTRFS_ATTR_PTR(qgroup, max_exclusive), |
---|
| 1609 | + BTRFS_ATTR_PTR(qgroup, limit_flags), |
---|
| 1610 | + BTRFS_ATTR_PTR(qgroup, rsv_data), |
---|
| 1611 | + BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans), |
---|
| 1612 | + BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc), |
---|
| 1613 | + NULL |
---|
| 1614 | +}; |
---|
| 1615 | +ATTRIBUTE_GROUPS(qgroup); |
---|
| 1616 | + |
---|
| 1617 | +static void qgroup_release(struct kobject *kobj) |
---|
| 1618 | +{ |
---|
| 1619 | + struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj); |
---|
| 1620 | + |
---|
| 1621 | + memset(&qgroup->kobj, 0, sizeof(*kobj)); |
---|
| 1622 | +} |
---|
| 1623 | + |
---|
| 1624 | +static struct kobj_type qgroup_ktype = { |
---|
| 1625 | + .sysfs_ops = &kobj_sysfs_ops, |
---|
| 1626 | + .release = qgroup_release, |
---|
| 1627 | + .default_groups = qgroup_groups, |
---|
| 1628 | +}; |
---|
| 1629 | + |
---|
| 1630 | +int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info, |
---|
| 1631 | + struct btrfs_qgroup *qgroup) |
---|
| 1632 | +{ |
---|
| 1633 | + struct kobject *qgroups_kobj = fs_info->qgroups_kobj; |
---|
| 1634 | + int ret; |
---|
| 1635 | + |
---|
| 1636 | + if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) |
---|
| 1637 | + return 0; |
---|
| 1638 | + if (qgroup->kobj.state_initialized) |
---|
| 1639 | + return 0; |
---|
| 1640 | + if (!qgroups_kobj) |
---|
| 1641 | + return -EINVAL; |
---|
| 1642 | + |
---|
| 1643 | + ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj, |
---|
| 1644 | + "%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid), |
---|
| 1645 | + btrfs_qgroup_subvolid(qgroup->qgroupid)); |
---|
| 1646 | + if (ret < 0) |
---|
| 1647 | + kobject_put(&qgroup->kobj); |
---|
| 1648 | + |
---|
| 1649 | + return ret; |
---|
| 1650 | +} |
---|
| 1651 | + |
---|
| 1652 | +void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info) |
---|
| 1653 | +{ |
---|
| 1654 | + struct btrfs_qgroup *qgroup; |
---|
| 1655 | + struct btrfs_qgroup *next; |
---|
| 1656 | + |
---|
| 1657 | + if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) |
---|
| 1658 | + return; |
---|
| 1659 | + |
---|
| 1660 | + rbtree_postorder_for_each_entry_safe(qgroup, next, |
---|
| 1661 | + &fs_info->qgroup_tree, node) |
---|
| 1662 | + btrfs_sysfs_del_one_qgroup(fs_info, qgroup); |
---|
| 1663 | + if (fs_info->qgroups_kobj) { |
---|
| 1664 | + kobject_del(fs_info->qgroups_kobj); |
---|
| 1665 | + kobject_put(fs_info->qgroups_kobj); |
---|
| 1666 | + fs_info->qgroups_kobj = NULL; |
---|
| 1667 | + } |
---|
| 1668 | +} |
---|
| 1669 | + |
---|
| 1670 | +/* Called when qgroups get initialized, thus there is no need for locking */ |
---|
| 1671 | +int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info) |
---|
| 1672 | +{ |
---|
| 1673 | + struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj; |
---|
| 1674 | + struct btrfs_qgroup *qgroup; |
---|
| 1675 | + struct btrfs_qgroup *next; |
---|
| 1676 | + int ret = 0; |
---|
| 1677 | + |
---|
| 1678 | + if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) |
---|
| 1679 | + return 0; |
---|
| 1680 | + |
---|
| 1681 | + ASSERT(fsid_kobj); |
---|
| 1682 | + if (fs_info->qgroups_kobj) |
---|
| 1683 | + return 0; |
---|
| 1684 | + |
---|
| 1685 | + fs_info->qgroups_kobj = kobject_create_and_add("qgroups", fsid_kobj); |
---|
| 1686 | + if (!fs_info->qgroups_kobj) { |
---|
| 1687 | + ret = -ENOMEM; |
---|
| 1688 | + goto out; |
---|
| 1689 | + } |
---|
| 1690 | + rbtree_postorder_for_each_entry_safe(qgroup, next, |
---|
| 1691 | + &fs_info->qgroup_tree, node) { |
---|
| 1692 | + ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup); |
---|
| 1693 | + if (ret < 0) |
---|
| 1694 | + goto out; |
---|
| 1695 | + } |
---|
| 1696 | + |
---|
| 1697 | +out: |
---|
| 1698 | + if (ret < 0) |
---|
| 1699 | + btrfs_sysfs_del_qgroups(fs_info); |
---|
| 1700 | + return ret; |
---|
| 1701 | +} |
---|
| 1702 | + |
---|
| 1703 | +void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info, |
---|
| 1704 | + struct btrfs_qgroup *qgroup) |
---|
| 1705 | +{ |
---|
| 1706 | + if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state)) |
---|
| 1707 | + return; |
---|
| 1708 | + |
---|
| 1709 | + if (qgroup->kobj.state_initialized) { |
---|
| 1710 | + kobject_del(&qgroup->kobj); |
---|
| 1711 | + kobject_put(&qgroup->kobj); |
---|
| 1712 | + } |
---|
| 1713 | +} |
---|
870 | 1714 | |
---|
871 | 1715 | /* |
---|
872 | 1716 | * Change per-fs features in /sys/fs/btrfs/UUID/features to match current |
---|
.. | .. |
---|
877 | 1721 | { |
---|
878 | 1722 | struct btrfs_fs_devices *fs_devs; |
---|
879 | 1723 | struct kobject *fsid_kobj; |
---|
880 | | - u64 features; |
---|
881 | | - int ret; |
---|
| 1724 | + u64 __maybe_unused features; |
---|
| 1725 | + int __maybe_unused ret; |
---|
882 | 1726 | |
---|
883 | 1727 | if (!fs_info) |
---|
884 | 1728 | return; |
---|
885 | 1729 | |
---|
| 1730 | + /* |
---|
| 1731 | + * See 14e46e04958df74 and e410e34fad913dd, feature bit updates are not |
---|
| 1732 | + * safe when called from some contexts (eg. balance) |
---|
| 1733 | + */ |
---|
886 | 1734 | features = get_features(fs_info, set); |
---|
887 | 1735 | ASSERT(bit & supported_feature_masks[set]); |
---|
888 | 1736 | |
---|
.. | .. |
---|
900 | 1748 | ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); |
---|
901 | 1749 | } |
---|
902 | 1750 | |
---|
903 | | -static int btrfs_init_debugfs(void) |
---|
904 | | -{ |
---|
905 | | -#ifdef CONFIG_DEBUG_FS |
---|
906 | | - btrfs_debugfs_root_dentry = debugfs_create_dir("btrfs", NULL); |
---|
907 | | - if (!btrfs_debugfs_root_dentry) |
---|
908 | | - return -ENOMEM; |
---|
909 | | - |
---|
910 | | - /* |
---|
911 | | - * Example code, how to export data through debugfs. |
---|
912 | | - * |
---|
913 | | - * file: /sys/kernel/debug/btrfs/test |
---|
914 | | - * contents of: btrfs_debugfs_test |
---|
915 | | - */ |
---|
916 | | -#ifdef CONFIG_BTRFS_DEBUG |
---|
917 | | - debugfs_create_u64("test", S_IRUGO | S_IWUSR, btrfs_debugfs_root_dentry, |
---|
918 | | - &btrfs_debugfs_test); |
---|
919 | | -#endif |
---|
920 | | - |
---|
921 | | -#endif |
---|
922 | | - return 0; |
---|
923 | | -} |
---|
924 | | - |
---|
925 | 1751 | int __init btrfs_init_sysfs(void) |
---|
926 | 1752 | { |
---|
927 | 1753 | int ret; |
---|
.. | .. |
---|
929 | 1755 | btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); |
---|
930 | 1756 | if (!btrfs_kset) |
---|
931 | 1757 | return -ENOMEM; |
---|
932 | | - |
---|
933 | | - ret = btrfs_init_debugfs(); |
---|
934 | | - if (ret) |
---|
935 | | - goto out1; |
---|
936 | 1758 | |
---|
937 | 1759 | init_feature_attrs(); |
---|
938 | 1760 | ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); |
---|
.. | .. |
---|
943 | 1765 | if (ret) |
---|
944 | 1766 | goto out_remove_group; |
---|
945 | 1767 | |
---|
| 1768 | +#ifdef CONFIG_BTRFS_DEBUG |
---|
| 1769 | + ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); |
---|
| 1770 | + if (ret) { |
---|
| 1771 | + sysfs_unmerge_group(&btrfs_kset->kobj, |
---|
| 1772 | + &btrfs_static_feature_attr_group); |
---|
| 1773 | + goto out_remove_group; |
---|
| 1774 | + } |
---|
| 1775 | +#endif |
---|
| 1776 | + |
---|
946 | 1777 | return 0; |
---|
947 | 1778 | |
---|
948 | 1779 | out_remove_group: |
---|
949 | 1780 | sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); |
---|
950 | 1781 | out2: |
---|
951 | | - debugfs_remove_recursive(btrfs_debugfs_root_dentry); |
---|
952 | | -out1: |
---|
953 | 1782 | kset_unregister(btrfs_kset); |
---|
954 | 1783 | |
---|
955 | 1784 | return ret; |
---|
.. | .. |
---|
960 | 1789 | sysfs_unmerge_group(&btrfs_kset->kobj, |
---|
961 | 1790 | &btrfs_static_feature_attr_group); |
---|
962 | 1791 | sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); |
---|
| 1792 | +#ifdef CONFIG_BTRFS_DEBUG |
---|
| 1793 | + sysfs_remove_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group); |
---|
| 1794 | +#endif |
---|
963 | 1795 | kset_unregister(btrfs_kset); |
---|
964 | | - debugfs_remove_recursive(btrfs_debugfs_root_dentry); |
---|
965 | 1796 | } |
---|
966 | 1797 | |
---|