Blame view
fs/btrfs/sysfs.c
23.4 KB
6cbd55707 Btrfs: add GPLv2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
/* * Copyright (C) 2007 Oracle. All rights reserved. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public * License v2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 021110-1307, USA. */ |
58176a960 Btrfs: Add per-ro... |
18 19 20 21 22 |
#include <linux/sched.h> #include <linux/slab.h> #include <linux/spinlock.h> #include <linux/completion.h> #include <linux/buffer_head.h> |
58176a960 Btrfs: Add per-ro... |
23 |
#include <linux/kobject.h> |
79da4fa4d btrfs: publish un... |
24 |
#include <linux/bug.h> |
29e5be240 btrfs: publish de... |
25 |
#include <linux/genhd.h> |
1bae30982 btrfs: add simple... |
26 |
#include <linux/debugfs.h> |
58176a960 Btrfs: Add per-ro... |
27 |
|
bae45de03 Btrfs: add dir in... |
28 29 30 |
#include "ctree.h" #include "disk-io.h" #include "transaction.h" |
079b72bca btrfs: publish su... |
31 |
#include "sysfs.h" |
29e5be240 btrfs: publish de... |
32 |
#include "volumes.h" |
079b72bca btrfs: publish su... |
33 |
|
510d73600 btrfs: publish pe... |
34 |
static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj); |
2e7910d6c Btrfs: sysfs: mov... |
35 |
static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj); |
5ac1d209f btrfs: publish pe... |
36 |
|
510d73600 btrfs: publish pe... |
37 38 |
static u64 get_features(struct btrfs_fs_info *fs_info, enum btrfs_feature_set set) |
5ac1d209f btrfs: publish pe... |
39 |
{ |
510d73600 btrfs: publish pe... |
40 41 42 43 44 45 46 |
struct btrfs_super_block *disk_super = fs_info->super_copy; if (set == FEAT_COMPAT) return btrfs_super_compat_flags(disk_super); else if (set == FEAT_COMPAT_RO) return btrfs_super_compat_ro_flags(disk_super); else return btrfs_super_incompat_flags(disk_super); |
5ac1d209f btrfs: publish pe... |
47 |
} |
ba631941e btrfs: add abilit... |
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
static void set_features(struct btrfs_fs_info *fs_info, enum btrfs_feature_set set, u64 features) { struct btrfs_super_block *disk_super = fs_info->super_copy; if (set == FEAT_COMPAT) btrfs_set_super_compat_flags(disk_super, features); else if (set == FEAT_COMPAT_RO) btrfs_set_super_compat_ro_flags(disk_super, features); else btrfs_set_super_incompat_flags(disk_super, features); } static int can_modify_feature(struct btrfs_feature_attr *fa) { int val = 0; u64 set, clear; switch (fa->feature_set) { case FEAT_COMPAT: set = BTRFS_FEATURE_COMPAT_SAFE_SET; clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; break; case FEAT_COMPAT_RO: set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; break; case FEAT_INCOMPAT: set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; break; default: |
62e855771 btrfs: convert pr... |
78 79 |
pr_warn("btrfs: sysfs: unknown feature set %d ", |
cc37bb042 btrfs: replace BU... |
80 81 |
fa->feature_set); return 0; |
ba631941e btrfs: add abilit... |
82 83 84 85 86 87 88 89 90 |
} if (set & fa->feature_bit) val |= 1; if (clear & fa->feature_bit) val |= 2; return val; } |
510d73600 btrfs: publish pe... |
91 92 |
static ssize_t btrfs_feature_attr_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) |
5ac1d209f btrfs: publish pe... |
93 |
{ |
510d73600 btrfs: publish pe... |
94 |
int val = 0; |
5ac1d209f btrfs: publish pe... |
95 |
struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
ba631941e btrfs: add abilit... |
96 |
struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); |
510d73600 btrfs: publish pe... |
97 |
if (fs_info) { |
510d73600 btrfs: publish pe... |
98 99 100 |
u64 features = get_features(fs_info, fa->feature_set); if (features & fa->feature_bit) val = 1; |
ba631941e btrfs: add abilit... |
101 102 |
} else val = can_modify_feature(fa); |
510d73600 btrfs: publish pe... |
103 104 105 |
return snprintf(buf, PAGE_SIZE, "%d ", val); |
5ac1d209f btrfs: publish pe... |
106 |
} |
ba631941e btrfs: add abilit... |
107 108 109 110 111 112 |
static ssize_t btrfs_feature_attr_store(struct kobject *kobj, struct kobj_attribute *a, const char *buf, size_t count) { struct btrfs_fs_info *fs_info; struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a); |
ba631941e btrfs: add abilit... |
113 114 115 116 117 118 119 |
u64 features, set, clear; unsigned long val; int ret; fs_info = to_fs_info(kobj); if (!fs_info) return -EPERM; |
bc98a42c1 VFS: Convert sb->... |
120 |
if (sb_rdonly(fs_info->sb)) |
ee6111386 btrfs: add read-o... |
121 |
return -EROFS; |
ba631941e btrfs: add abilit... |
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
ret = kstrtoul(skip_spaces(buf), 0, &val); if (ret) return ret; if (fa->feature_set == FEAT_COMPAT) { set = BTRFS_FEATURE_COMPAT_SAFE_SET; clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR; } else if (fa->feature_set == FEAT_COMPAT_RO) { set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET; clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR; } else { set = BTRFS_FEATURE_INCOMPAT_SAFE_SET; clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR; } features = get_features(fs_info, fa->feature_set); /* Nothing to do */ if ((val && (features & fa->feature_bit)) || (!val && !(features & fa->feature_bit))) return count; if ((val && !(set & fa->feature_bit)) || (!val && !(clear & fa->feature_bit))) { btrfs_info(fs_info, "%sabling feature %s on mounted fs is not supported.", val ? "En" : "Dis", fa->kobj_attr.attr.name); return -EPERM; } btrfs_info(fs_info, "%s %s feature flag", val ? "Setting" : "Clearing", fa->kobj_attr.attr.name); |
ba631941e btrfs: add abilit... |
154 155 156 157 158 159 160 161 |
spin_lock(&fs_info->super_lock); features = get_features(fs_info, fa->feature_set); if (val) features |= fa->feature_bit; else features &= ~fa->feature_bit; set_features(fs_info, fa->feature_set, features); spin_unlock(&fs_info->super_lock); |
0eae2747e btrfs: move commi... |
162 163 164 165 166 |
/* * We don't want to do full transaction commit from inside sysfs */ btrfs_set_pending(fs_info, COMMIT); wake_up_process(fs_info->transaction_kthread); |
ba631941e btrfs: add abilit... |
167 168 169 |
return count; } |
510d73600 btrfs: publish pe... |
170 171 |
static umode_t btrfs_feature_visible(struct kobject *kobj, struct attribute *attr, int unused) |
079b72bca btrfs: publish su... |
172 |
{ |
510d73600 btrfs: publish pe... |
173 174 175 176 177 178 179 180 181 |
struct btrfs_fs_info *fs_info = to_fs_info(kobj); umode_t mode = attr->mode; if (fs_info) { struct btrfs_feature_attr *fa; u64 features; fa = attr_to_btrfs_feature_attr(attr); features = get_features(fs_info, fa->feature_set); |
ba631941e btrfs: add abilit... |
182 183 184 |
if (can_modify_feature(fa)) mode |= S_IWUSR; else if (!(features & fa->feature_bit)) |
510d73600 btrfs: publish pe... |
185 186 187 188 |
mode = 0; } return mode; |
079b72bca btrfs: publish su... |
189 190 191 192 193 194 |
} BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF); BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL); BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS); BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO); |
5c1aab1dd btrfs: Add zstd s... |
195 |
BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD); |
079b72bca btrfs: publish su... |
196 197 198 199 |
BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA); BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF); BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56); BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA); |
c736c095d btrfs: sysfs: lis... |
200 |
BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES); |
3b5bb73bd btrfs: sysfs: add... |
201 |
BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE); |
079b72bca btrfs: publish su... |
202 203 204 205 206 207 |
static struct attribute *btrfs_supported_feature_attrs[] = { BTRFS_FEAT_ATTR_PTR(mixed_backref), BTRFS_FEAT_ATTR_PTR(default_subvol), BTRFS_FEAT_ATTR_PTR(mixed_groups), BTRFS_FEAT_ATTR_PTR(compress_lzo), |
5c1aab1dd btrfs: Add zstd s... |
208 |
BTRFS_FEAT_ATTR_PTR(compress_zstd), |
079b72bca btrfs: publish su... |
209 210 211 212 |
BTRFS_FEAT_ATTR_PTR(big_metadata), BTRFS_FEAT_ATTR_PTR(extended_iref), BTRFS_FEAT_ATTR_PTR(raid56), BTRFS_FEAT_ATTR_PTR(skinny_metadata), |
c736c095d btrfs: sysfs: lis... |
213 |
BTRFS_FEAT_ATTR_PTR(no_holes), |
3b5bb73bd btrfs: sysfs: add... |
214 |
BTRFS_FEAT_ATTR_PTR(free_space_tree), |
079b72bca btrfs: publish su... |
215 216 217 218 219 |
NULL }; static const struct attribute_group btrfs_feature_attr_group = { .name = "features", |
510d73600 btrfs: publish pe... |
220 |
.is_visible = btrfs_feature_visible, |
079b72bca btrfs: publish su... |
221 222 |
.attrs = btrfs_supported_feature_attrs, }; |
58176a960 Btrfs: Add per-ro... |
223 |
|
6ab0a2029 btrfs: publish al... |
224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf) { u64 val; if (lock) spin_lock(lock); val = *value_ptr; if (lock) spin_unlock(lock); return snprintf(buf, PAGE_SIZE, "%llu ", val); } static ssize_t global_rsv_size_show(struct kobject *kobj, struct kobj_attribute *ka, char *buf) { struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf); } |
98b3d389e btrfs: code optim... |
243 |
BTRFS_ATTR(global_rsv_size, global_rsv_size_show); |
6ab0a2029 btrfs: publish al... |
244 245 246 247 248 249 250 251 |
static ssize_t global_rsv_reserved_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) { struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent); struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv; return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf); } |
98b3d389e btrfs: code optim... |
252 |
BTRFS_ATTR(global_rsv_reserved, global_rsv_reserved_show); |
6ab0a2029 btrfs: publish al... |
253 254 |
#define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj) |
c1895442b btrfs: allocate r... |
255 |
#define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj) |
6ab0a2029 btrfs: publish al... |
256 257 258 259 260 261 262 263 264 265 266 267 |
static ssize_t raid_bytes_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf); BTRFS_RAID_ATTR(total_bytes, raid_bytes_show); BTRFS_RAID_ATTR(used_bytes, raid_bytes_show); static ssize_t raid_bytes_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { struct btrfs_space_info *sinfo = to_space_info(kobj->parent); struct btrfs_block_group_cache *block_group; |
c1895442b btrfs: allocate r... |
268 |
int index = to_raid_kobj(kobj)->raid_type; |
6ab0a2029 btrfs: publish al... |
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
u64 val = 0; down_read(&sinfo->groups_sem); list_for_each_entry(block_group, &sinfo->block_groups[index], list) { if (&attr->attr == BTRFS_RAID_ATTR_PTR(total_bytes)) val += block_group->key.offset; else val += btrfs_block_group_used(&block_group->item); } up_read(&sinfo->groups_sem); return snprintf(buf, PAGE_SIZE, "%llu ", val); } static struct attribute *raid_attributes[] = { BTRFS_RAID_ATTR_PTR(total_bytes), BTRFS_RAID_ATTR_PTR(used_bytes), NULL }; static void release_raid_kobj(struct kobject *kobj) { |
c1895442b btrfs: allocate r... |
291 |
kfree(to_raid_kobj(kobj)); |
6ab0a2029 btrfs: publish al... |
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 |
} struct kobj_type btrfs_raid_ktype = { .sysfs_ops = &kobj_sysfs_ops, .release = release_raid_kobj, .default_attrs = raid_attributes, }; #define SPACE_INFO_ATTR(field) \ static ssize_t btrfs_space_info_show_##field(struct kobject *kobj, \ struct kobj_attribute *a, \ char *buf) \ { \ struct btrfs_space_info *sinfo = to_space_info(kobj); \ return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf); \ } \ |
98b3d389e btrfs: code optim... |
308 |
BTRFS_ATTR(field, btrfs_space_info_show_##field) |
6ab0a2029 btrfs: publish al... |
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 |
static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj, struct kobj_attribute *a, char *buf) { struct btrfs_space_info *sinfo = to_space_info(kobj); s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned); return snprintf(buf, PAGE_SIZE, "%lld ", val); } SPACE_INFO_ATTR(flags); SPACE_INFO_ATTR(total_bytes); SPACE_INFO_ATTR(bytes_used); SPACE_INFO_ATTR(bytes_pinned); SPACE_INFO_ATTR(bytes_reserved); SPACE_INFO_ATTR(bytes_may_use); |
c1fd5c30d btrfs: add missin... |
326 |
SPACE_INFO_ATTR(bytes_readonly); |
6ab0a2029 btrfs: publish al... |
327 328 |
SPACE_INFO_ATTR(disk_used); SPACE_INFO_ATTR(disk_total); |
98b3d389e btrfs: code optim... |
329 |
BTRFS_ATTR(total_bytes_pinned, btrfs_space_info_show_total_bytes_pinned); |
6ab0a2029 btrfs: publish al... |
330 331 332 333 334 335 336 337 |
static struct attribute *space_info_attrs[] = { BTRFS_ATTR_PTR(flags), BTRFS_ATTR_PTR(total_bytes), BTRFS_ATTR_PTR(bytes_used), BTRFS_ATTR_PTR(bytes_pinned), BTRFS_ATTR_PTR(bytes_reserved), BTRFS_ATTR_PTR(bytes_may_use), |
c1fd5c30d btrfs: add missin... |
338 |
BTRFS_ATTR_PTR(bytes_readonly), |
6ab0a2029 btrfs: publish al... |
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 |
BTRFS_ATTR_PTR(disk_used), BTRFS_ATTR_PTR(disk_total), BTRFS_ATTR_PTR(total_bytes_pinned), NULL, }; static void space_info_release(struct kobject *kobj) { struct btrfs_space_info *sinfo = to_space_info(kobj); percpu_counter_destroy(&sinfo->total_bytes_pinned); kfree(sinfo); } struct kobj_type space_info_ktype = { .sysfs_ops = &kobj_sysfs_ops, .release = space_info_release, .default_attrs = space_info_attrs, }; static const struct attribute *allocation_attrs[] = { BTRFS_ATTR_PTR(global_rsv_reserved), BTRFS_ATTR_PTR(global_rsv_size), NULL, }; |
f8ba9c11f btrfs: publish fs... |
363 364 365 366 |
static ssize_t btrfs_label_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) { struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
48fcc3ff7 btrfs: label shou... |
367 |
char *label = fs_info->super_copy->label; |
ee17fc800 btrfs: sysfs: pro... |
368 369 370 371 372 373 374 375 |
ssize_t ret; spin_lock(&fs_info->super_lock); ret = snprintf(buf, PAGE_SIZE, label[0] ? "%s " : "%s", label); spin_unlock(&fs_info->super_lock); return ret; |
f8ba9c11f btrfs: publish fs... |
376 377 378 379 380 381 382 |
} static ssize_t btrfs_label_store(struct kobject *kobj, struct kobj_attribute *a, const char *buf, size_t len) { struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
48fcc3ff7 btrfs: label shou... |
383 |
size_t p_len; |
f8ba9c11f btrfs: publish fs... |
384 |
|
66ac9fe7b btrfs: add check ... |
385 386 |
if (!fs_info) return -EPERM; |
bc98a42c1 VFS: Convert sb->... |
387 |
if (sb_rdonly(fs_info->sb)) |
79aec2b80 btrfs: sysfs labe... |
388 |
return -EROFS; |
48fcc3ff7 btrfs: label shou... |
389 390 391 392 393 394 395 396 397 |
/* * p_len is the len until the first occurrence of either * ' ' or '\0' */ p_len = strcspn(buf, " "); if (p_len >= BTRFS_LABEL_SIZE) |
f8ba9c11f btrfs: publish fs... |
398 |
return -EINVAL; |
f8ba9c11f btrfs: publish fs... |
399 |
|
a6f69dc80 btrfs: move commi... |
400 |
spin_lock(&fs_info->super_lock); |
48fcc3ff7 btrfs: label shou... |
401 402 |
memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE); memcpy(fs_info->super_copy->label, buf, p_len); |
a6f69dc80 btrfs: move commi... |
403 |
spin_unlock(&fs_info->super_lock); |
f8ba9c11f btrfs: publish fs... |
404 |
|
a6f69dc80 btrfs: move commi... |
405 406 407 408 409 |
/* * We don't want to do full transaction commit from inside sysfs */ btrfs_set_pending(fs_info, COMMIT); wake_up_process(fs_info->transaction_kthread); |
f8ba9c11f btrfs: publish fs... |
410 |
|
a6f69dc80 btrfs: move commi... |
411 |
return len; |
f8ba9c11f btrfs: publish fs... |
412 |
} |
20ee0825e btrfs: code optim... |
413 |
BTRFS_ATTR_RW(label, btrfs_label_show, btrfs_label_store); |
f8ba9c11f btrfs: publish fs... |
414 |
|
df93589a1 btrfs: export mor... |
415 416 417 418 |
static ssize_t btrfs_nodesize_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) { struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
2b0509fa4 Revert "btrfs: us... |
419 420 |
return snprintf(buf, PAGE_SIZE, "%u ", fs_info->super_copy->nodesize); |
df93589a1 btrfs: export mor... |
421 |
} |
98b3d389e btrfs: code optim... |
422 |
BTRFS_ATTR(nodesize, btrfs_nodesize_show); |
df93589a1 btrfs: export mor... |
423 424 425 426 427 |
static ssize_t btrfs_sectorsize_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) { struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
2b0509fa4 Revert "btrfs: us... |
428 429 430 |
return snprintf(buf, PAGE_SIZE, "%u ", fs_info->super_copy->sectorsize); |
df93589a1 btrfs: export mor... |
431 |
} |
98b3d389e btrfs: code optim... |
432 |
BTRFS_ATTR(sectorsize, btrfs_sectorsize_show); |
df93589a1 btrfs: export mor... |
433 434 435 436 437 |
static ssize_t btrfs_clone_alignment_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) { struct btrfs_fs_info *fs_info = to_fs_info(kobj); |
2b0509fa4 Revert "btrfs: us... |
438 439 440 |
return snprintf(buf, PAGE_SIZE, "%u ", fs_info->super_copy->sectorsize); |
df93589a1 btrfs: export mor... |
441 |
} |
98b3d389e btrfs: code optim... |
442 |
BTRFS_ATTR(clone_alignment, btrfs_clone_alignment_show); |
df93589a1 btrfs: export mor... |
443 |
|
2723480a0 btrfs: Add quota_... |
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
static ssize_t quota_override_show(struct kobject *kobj, struct kobj_attribute *a, char *buf) { struct btrfs_fs_info *fs_info = to_fs_info(kobj); int quota_override; quota_override = test_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); return snprintf(buf, PAGE_SIZE, "%d ", quota_override); } static ssize_t quota_override_store(struct kobject *kobj, struct kobj_attribute *a, const char *buf, size_t len) { struct btrfs_fs_info *fs_info = to_fs_info(kobj); unsigned long knob; int err; if (!fs_info) return -EPERM; if (!capable(CAP_SYS_RESOURCE)) return -EPERM; err = kstrtoul(buf, 10, &knob); if (err) return err; if (knob > 1) return -EINVAL; if (knob) set_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); else clear_bit(BTRFS_FS_QUOTA_OVERRIDE, &fs_info->flags); return len; } BTRFS_ATTR_RW(quota_override, quota_override_show, quota_override_store); |
0dd2906f7 Btrfs: sysfs: let... |
484 |
static const struct attribute *btrfs_attrs[] = { |
f8ba9c11f btrfs: publish fs... |
485 |
BTRFS_ATTR_PTR(label), |
df93589a1 btrfs: export mor... |
486 487 488 |
BTRFS_ATTR_PTR(nodesize), BTRFS_ATTR_PTR(sectorsize), BTRFS_ATTR_PTR(clone_alignment), |
2723480a0 btrfs: Add quota_... |
489 |
BTRFS_ATTR_PTR(quota_override), |
f8ba9c11f btrfs: publish fs... |
490 491 |
NULL, }; |
c1b7e4745 Btrfs: rename sup... |
492 |
static void btrfs_release_fsid_kobj(struct kobject *kobj) |
510d73600 btrfs: publish pe... |
493 |
{ |
2e7910d6c Btrfs: sysfs: mov... |
494 |
struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj); |
248d200df Btrfs: sysfs: fix... |
495 |
|
c1b7e4745 Btrfs: rename sup... |
496 |
memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject)); |
2e7910d6c Btrfs: sysfs: mov... |
497 |
complete(&fs_devs->kobj_unregister); |
510d73600 btrfs: publish pe... |
498 499 500 501 |
} static struct kobj_type btrfs_ktype = { .sysfs_ops = &kobj_sysfs_ops, |
c1b7e4745 Btrfs: rename sup... |
502 |
.release = btrfs_release_fsid_kobj, |
510d73600 btrfs: publish pe... |
503 |
}; |
2e7910d6c Btrfs: sysfs: mov... |
504 505 506 507 |
static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj) { if (kobj->ktype != &btrfs_ktype) return NULL; |
c1b7e4745 Btrfs: rename sup... |
508 |
return container_of(kobj, struct btrfs_fs_devices, fsid_kobj); |
2e7910d6c Btrfs: sysfs: mov... |
509 |
} |
510d73600 btrfs: publish pe... |
510 511 512 513 |
static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj) { if (kobj->ktype != &btrfs_ktype) return NULL; |
2e7910d6c Btrfs: sysfs: mov... |
514 |
return to_fs_devs(kobj)->fs_info; |
510d73600 btrfs: publish pe... |
515 |
} |
58176a960 Btrfs: Add per-ro... |
516 |
|
e453d989e btrfs: fix leaks ... |
517 518 519 |
#define NUM_FEATURE_BITS 64 static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13]; static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS]; |
e8c9f1860 btrfs: constify s... |
520 |
static const u64 supported_feature_masks[3] = { |
e453d989e btrfs: fix leaks ... |
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
[FEAT_COMPAT] = BTRFS_FEATURE_COMPAT_SUPP, [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP, [FEAT_INCOMPAT] = BTRFS_FEATURE_INCOMPAT_SUPP, }; static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add) { int set; for (set = 0; set < FEAT_MAX; set++) { int i; struct attribute *attrs[2]; struct attribute_group agroup = { .name = "features", .attrs = attrs, }; u64 features = get_features(fs_info, set); features &= ~supported_feature_masks[set]; if (!features) continue; attrs[1] = NULL; for (i = 0; i < NUM_FEATURE_BITS; i++) { struct btrfs_feature_attr *fa; if (!(features & (1ULL << i))) continue; fa = &btrfs_feature_attrs[set][i]; attrs[0] = &fa->kobj_attr.attr; if (add) { int ret; |
c1b7e4745 Btrfs: rename sup... |
554 |
ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj, |
e453d989e btrfs: fix leaks ... |
555 556 557 558 |
&agroup); if (ret) return ret; } else |
c1b7e4745 Btrfs: rename sup... |
559 |
sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj, |
e453d989e btrfs: fix leaks ... |
560 561 562 563 564 565 |
&agroup); } } return 0; } |
2e3e12815 Btrfs: sysfs: pro... |
566 |
static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) |
5ac1d209f btrfs: publish pe... |
567 |
{ |
2e7910d6c Btrfs: sysfs: mov... |
568 569 570 571 |
if (fs_devs->device_dir_kobj) { kobject_del(fs_devs->device_dir_kobj); kobject_put(fs_devs->device_dir_kobj); fs_devs->device_dir_kobj = NULL; |
aaf133051 Btrfs: sysfs: reo... |
572 |
} |
c1b7e4745 Btrfs: rename sup... |
573 574 575 |
if (fs_devs->fsid_kobj.state_initialized) { kobject_del(&fs_devs->fsid_kobj); kobject_put(&fs_devs->fsid_kobj); |
f90fc5472 Btrfs: Check if k... |
576 577 |
wait_for_completion(&fs_devs->kobj_unregister); } |
5ac1d209f btrfs: publish pe... |
578 |
} |
2e3e12815 Btrfs: sysfs: pro... |
579 |
/* when fs_devs is NULL it will remove all fsid kobject */ |
1d1c1be37 Btrfs: sysfs: btr... |
580 |
void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs) |
2e3e12815 Btrfs: sysfs: pro... |
581 582 583 584 585 586 587 588 589 590 591 592 |
{ struct list_head *fs_uuids = btrfs_get_fs_uuids(); if (fs_devs) { __btrfs_sysfs_remove_fsid(fs_devs); return; } list_for_each_entry(fs_devs, fs_uuids, list) { __btrfs_sysfs_remove_fsid(fs_devs); } } |
6618a59bf Btrfs: rename btr... |
593 |
void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info) |
e453d989e btrfs: fix leaks ... |
594 |
{ |
5a13f4308 Btrfs: sysfs: add... |
595 |
btrfs_reset_fs_info_ptr(fs_info); |
e453d989e btrfs: fix leaks ... |
596 597 598 599 600 |
if (fs_info->space_info_kobj) { sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs); kobject_del(fs_info->space_info_kobj); kobject_put(fs_info->space_info_kobj); } |
e453d989e btrfs: fix leaks ... |
601 |
addrm_unknown_feature_attrs(fs_info, false); |
c1b7e4745 Btrfs: rename sup... |
602 603 |
sysfs_remove_group(&fs_info->fs_devices->fsid_kobj, &btrfs_feature_attr_group); sysfs_remove_files(&fs_info->fs_devices->fsid_kobj, btrfs_attrs); |
325760404 Btrfs: rename btr... |
604 |
btrfs_sysfs_rm_device_link(fs_info->fs_devices, NULL); |
e453d989e btrfs: fix leaks ... |
605 |
} |
79da4fa4d btrfs: publish un... |
606 607 608 609 610 |
const char * const btrfs_feature_set_names[3] = { [FEAT_COMPAT] = "compat", [FEAT_COMPAT_RO] = "compat_ro", [FEAT_INCOMPAT] = "incompat", }; |
3b02a68a6 btrfs: use featur... |
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags) { size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */ int len = 0; int i; char *str; str = kmalloc(bufsize, GFP_KERNEL); if (!str) return str; for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { const char *name; if (!(flags & (1ULL << i))) continue; name = btrfs_feature_attrs[set][i].kobj_attr.attr.name; len += snprintf(str + len, bufsize - len, "%s%s", len ? "," : "", name); } return str; } |
79da4fa4d btrfs: publish un... |
635 636 637 638 639 640 641 642 643 |
static void init_feature_attrs(void) { struct btrfs_feature_attr *fa; int set, i; BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names) != ARRAY_SIZE(btrfs_feature_attrs)); BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) != ARRAY_SIZE(btrfs_feature_attrs[0])); |
3b02a68a6 btrfs: use featur... |
644 645 646 |
memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs)); memset(btrfs_unknown_feature_names, 0, sizeof(btrfs_unknown_feature_names)); |
79da4fa4d btrfs: publish un... |
647 648 649 |
for (i = 0; btrfs_supported_feature_attrs[i]; i++) { struct btrfs_feature_attr *sfa; struct attribute *a = btrfs_supported_feature_attrs[i]; |
3b02a68a6 btrfs: use featur... |
650 |
int bit; |
79da4fa4d btrfs: publish un... |
651 |
sfa = attr_to_btrfs_feature_attr(a); |
3b02a68a6 btrfs: use featur... |
652 653 |
bit = ilog2(sfa->feature_bit); fa = &btrfs_feature_attrs[sfa->feature_set][bit]; |
79da4fa4d btrfs: publish un... |
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 |
fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name; } for (set = 0; set < FEAT_MAX; set++) { for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) { char *name = btrfs_unknown_feature_names[set][i]; fa = &btrfs_feature_attrs[set][i]; if (fa->kobj_attr.attr.name) continue; snprintf(name, 13, "%s:%u", btrfs_feature_set_names[set], i); fa->kobj_attr.attr.name = name; fa->kobj_attr.attr.mode = S_IRUGO; fa->feature_set = set; fa->feature_bit = 1ULL << i; } } } |
e7e1aa9c9 Btrfs: sysfs: fix... |
676 |
/* when one_device is NULL, it removes all device links */ |
325760404 Btrfs: rename btr... |
677 |
int btrfs_sysfs_rm_device_link(struct btrfs_fs_devices *fs_devices, |
99994cde9 btrfs: dev delete... |
678 679 680 681 |
struct btrfs_device *one_device) { struct hd_struct *disk; struct kobject *disk_kobj; |
6c14a1641 Btrfs: sysfs btrf... |
682 |
if (!fs_devices->device_dir_kobj) |
99994cde9 btrfs: dev delete... |
683 |
return -EINVAL; |
87fa3bb07 Btrfs: fix regres... |
684 |
if (one_device && one_device->bdev) { |
99994cde9 btrfs: dev delete... |
685 686 |
disk = one_device->bdev->bd_part; disk_kobj = &part_to_dev(disk)->kobj; |
6c14a1641 Btrfs: sysfs btrf... |
687 |
sysfs_remove_link(fs_devices->device_dir_kobj, |
99994cde9 btrfs: dev delete... |
688 689 |
disk_kobj->name); } |
e7e1aa9c9 Btrfs: sysfs: fix... |
690 691 692 693 |
if (one_device) return 0; list_for_each_entry(one_device, |
6c14a1641 Btrfs: sysfs btrf... |
694 |
&fs_devices->devices, dev_list) { |
e7e1aa9c9 Btrfs: sysfs: fix... |
695 696 697 698 |
if (!one_device->bdev) continue; disk = one_device->bdev->bd_part; disk_kobj = &part_to_dev(disk)->kobj; |
6c14a1641 Btrfs: sysfs btrf... |
699 |
sysfs_remove_link(fs_devices->device_dir_kobj, |
e7e1aa9c9 Btrfs: sysfs: fix... |
700 701 |
disk_kobj->name); } |
99994cde9 btrfs: dev delete... |
702 703 |
return 0; } |
2e7910d6c Btrfs: sysfs: mov... |
704 |
int btrfs_sysfs_add_device(struct btrfs_fs_devices *fs_devs) |
29e5be240 btrfs: publish de... |
705 |
{ |
2e7910d6c Btrfs: sysfs: mov... |
706 707 |
if (!fs_devs->device_dir_kobj) fs_devs->device_dir_kobj = kobject_create_and_add("devices", |
c1b7e4745 Btrfs: rename sup... |
708 |
&fs_devs->fsid_kobj); |
0d39376aa btrfs: dev add sh... |
709 |
|
2e7910d6c Btrfs: sysfs: mov... |
710 |
if (!fs_devs->device_dir_kobj) |
29e5be240 btrfs: publish de... |
711 |
return -ENOMEM; |
00c921c23 Btrfs: sysfs: sep... |
712 713 |
return 0; } |
e3bd6973b Btrfs: rename btr... |
714 |
int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices, |
1ba43816a Btrfs: sysfs btrf... |
715 |
struct btrfs_device *one_device) |
00c921c23 Btrfs: sysfs: sep... |
716 717 |
{ int error = 0; |
00c921c23 Btrfs: sysfs: sep... |
718 |
struct btrfs_device *dev; |
29e5be240 btrfs: publish de... |
719 |
list_for_each_entry(dev, &fs_devices->devices, dev_list) { |
f085381e6 btrfs: fix null p... |
720 721 722 723 724 |
struct hd_struct *disk; struct kobject *disk_kobj; if (!dev->bdev) continue; |
0d39376aa btrfs: dev add sh... |
725 726 |
if (one_device && one_device != dev) continue; |
f085381e6 btrfs: fix null p... |
727 728 |
disk = dev->bdev->bd_part; disk_kobj = &part_to_dev(disk)->kobj; |
29e5be240 btrfs: publish de... |
729 |
|
2e7910d6c Btrfs: sysfs: mov... |
730 |
error = sysfs_create_link(fs_devices->device_dir_kobj, |
29e5be240 btrfs: publish de... |
731 732 733 734 735 736 737 |
disk_kobj, disk_kobj->name); if (error) break; } return error; } |
510d73600 btrfs: publish pe... |
738 739 |
/* /sys/fs/btrfs/ entry */ static struct kset *btrfs_kset; |
1bae30982 btrfs: add simple... |
740 741 742 743 744 |
/* /sys/kernel/debug/btrfs */ static struct dentry *btrfs_debugfs_root_dentry; /* Debugging tunables and exported data */ u64 btrfs_debugfs_test; |
720592157 Btrfs: sysfs: int... |
745 746 747 748 |
/* * Can be called by the device discovery thread. * And parent can be specified for seed device */ |
0c10e2d48 Btrfs: sysfs: mak... |
749 |
int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs, |
720592157 Btrfs: sysfs: int... |
750 |
struct kobject *parent) |
5ac1d209f btrfs: publish pe... |
751 752 |
{ int error; |
2e7910d6c Btrfs: sysfs: mov... |
753 |
init_completion(&fs_devs->kobj_unregister); |
c1b7e4745 Btrfs: rename sup... |
754 755 |
fs_devs->fsid_kobj.kset = btrfs_kset; error = kobject_init_and_add(&fs_devs->fsid_kobj, |
24bd69cb0 Btrfs: sysfs: add... |
756 |
&btrfs_ktype, parent, "%pU", fs_devs->fsid); |
720592157 Btrfs: sysfs: int... |
757 758 |
return error; } |
96f3136e5 Btrfs: rename btr... |
759 |
int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) |
720592157 Btrfs: sysfs: int... |
760 761 |
{ int error; |
2e7910d6c Btrfs: sysfs: mov... |
762 |
struct btrfs_fs_devices *fs_devs = fs_info->fs_devices; |
c1b7e4745 Btrfs: rename sup... |
763 |
struct kobject *fsid_kobj = &fs_devs->fsid_kobj; |
720592157 Btrfs: sysfs: int... |
764 |
|
5a13f4308 Btrfs: sysfs: add... |
765 |
btrfs_set_fs_info_ptr(fs_info); |
e3bd6973b Btrfs: rename btr... |
766 |
error = btrfs_sysfs_add_device_link(fs_devs, NULL); |
b7c35e81a Btrfs: sysfs: sep... |
767 |
if (error) |
aaf133051 Btrfs: sysfs: reo... |
768 |
return error; |
aaf133051 Btrfs: sysfs: reo... |
769 |
|
c1b7e4745 Btrfs: rename sup... |
770 |
error = sysfs_create_files(fsid_kobj, btrfs_attrs); |
e453d989e btrfs: fix leaks ... |
771 |
if (error) { |
325760404 Btrfs: rename btr... |
772 |
btrfs_sysfs_rm_device_link(fs_devs, NULL); |
e453d989e btrfs: fix leaks ... |
773 774 |
return error; } |
79da4fa4d btrfs: publish un... |
775 |
|
c1b7e4745 Btrfs: rename sup... |
776 |
error = sysfs_create_group(fsid_kobj, |
0dd2906f7 Btrfs: sysfs: let... |
777 778 779 |
&btrfs_feature_attr_group); if (error) goto failure; |
e453d989e btrfs: fix leaks ... |
780 |
error = addrm_unknown_feature_attrs(fs_info, true); |
79da4fa4d btrfs: publish un... |
781 782 |
if (error) goto failure; |
6ab0a2029 btrfs: publish al... |
783 |
fs_info->space_info_kobj = kobject_create_and_add("allocation", |
c1b7e4745 Btrfs: rename sup... |
784 |
fsid_kobj); |
6ab0a2029 btrfs: publish al... |
785 786 787 788 789 790 791 792 |
if (!fs_info->space_info_kobj) { error = -ENOMEM; goto failure; } error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs); if (error) goto failure; |
79da4fa4d btrfs: publish un... |
793 794 |
return 0; failure: |
6618a59bf Btrfs: rename btr... |
795 |
btrfs_sysfs_remove_mounted(fs_info); |
5ac1d209f btrfs: publish pe... |
796 797 |
return error; } |
444e75169 btrfs: sysfs: int... |
798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 |
/* * Change per-fs features in /sys/fs/btrfs/UUID/features to match current * values in superblock. Call after any changes to incompat/compat_ro flags */ void btrfs_sysfs_feature_update(struct btrfs_fs_info *fs_info, u64 bit, enum btrfs_feature_set set) { struct btrfs_fs_devices *fs_devs; struct kobject *fsid_kobj; u64 features; int ret; if (!fs_info) return; features = get_features(fs_info, set); ASSERT(bit & supported_feature_masks[set]); fs_devs = fs_info->fs_devices; fsid_kobj = &fs_devs->fsid_kobj; |
bf6092066 btrfs: sysfs: che... |
819 820 |
if (!fsid_kobj->state_initialized) return; |
444e75169 btrfs: sysfs: int... |
821 822 823 824 825 826 827 |
/* * FIXME: this is too heavy to update just one value, ideally we'd like * to use sysfs_update_group but some refactoring is needed first. */ sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group); ret = sysfs_create_group(fsid_kobj, &btrfs_feature_attr_group); } |
1bae30982 btrfs: add simple... |
828 829 830 831 832 833 |
static int btrfs_init_debugfs(void) { #ifdef CONFIG_DEBUG_FS btrfs_debugfs_root_dentry = debugfs_create_dir("btrfs", NULL); if (!btrfs_debugfs_root_dentry) return -ENOMEM; |
b0de6c4c8 btrfs: create exa... |
834 835 836 837 838 839 840 |
/* * Example code, how to export data through debugfs. * * file: /sys/kernel/debug/btrfs/test * contents of: btrfs_debugfs_test */ #ifdef CONFIG_BTRFS_DEBUG |
07f6a4804 btrfs: fix perms ... |
841 |
debugfs_create_u64("test", S_IRUGO | S_IWUSR, btrfs_debugfs_root_dentry, |
1bae30982 btrfs: add simple... |
842 843 |
&btrfs_debugfs_test); #endif |
b0de6c4c8 btrfs: create exa... |
844 845 |
#endif |
1bae30982 btrfs: add simple... |
846 847 |
return 0; } |
b214107ed Btrfs: trivial sp... |
848 |
int btrfs_init_sysfs(void) |
58176a960 Btrfs: Add per-ro... |
849 |
{ |
079b72bca btrfs: publish su... |
850 |
int ret; |
1bae30982 btrfs: add simple... |
851 |
|
e3fe4e712 btrfs: fixes for ... |
852 853 854 |
btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj); if (!btrfs_kset) return -ENOMEM; |
079b72bca btrfs: publish su... |
855 |
|
1bae30982 btrfs: add simple... |
856 857 |
ret = btrfs_init_debugfs(); if (ret) |
001a648df Btrfs: add missin... |
858 |
goto out1; |
79da4fa4d btrfs: publish un... |
859 |
|
1bae30982 btrfs: add simple... |
860 |
init_feature_attrs(); |
079b72bca btrfs: publish su... |
861 |
ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); |
001a648df Btrfs: add missin... |
862 863 864 865 866 867 868 869 |
if (ret) goto out2; return 0; out2: debugfs_remove_recursive(btrfs_debugfs_root_dentry); out1: kset_unregister(btrfs_kset); |
079b72bca btrfs: publish su... |
870 |
|
1bae30982 btrfs: add simple... |
871 |
return ret; |
58176a960 Btrfs: Add per-ro... |
872 |
} |
b214107ed Btrfs: trivial sp... |
873 |
void btrfs_exit_sysfs(void) |
58176a960 Btrfs: Add per-ro... |
874 |
{ |
079b72bca btrfs: publish su... |
875 |
sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group); |
e3fe4e712 btrfs: fixes for ... |
876 |
kset_unregister(btrfs_kset); |
1bae30982 btrfs: add simple... |
877 |
debugfs_remove_recursive(btrfs_debugfs_root_dentry); |
58176a960 Btrfs: Add per-ro... |
878 |
} |
55d474148 Btrfs: Disable sy... |
879 |