Blame view

fs/btrfs/sysfs.c 22 KB
6cbd55707   Chris Mason   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   Josef Bacik   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   Josef Bacik   Btrfs: Add per-ro...
23
  #include <linux/kobject.h>
79da4fa4d   Jeff Mahoney   btrfs: publish un...
24
  #include <linux/bug.h>
29e5be240   Jeff Mahoney   btrfs: publish de...
25
  #include <linux/genhd.h>
1bae30982   David Sterba   btrfs: add simple...
26
  #include <linux/debugfs.h>
58176a960   Josef Bacik   Btrfs: Add per-ro...
27

bae45de03   Chris Mason   Btrfs: add dir in...
28
29
30
  #include "ctree.h"
  #include "disk-io.h"
  #include "transaction.h"
079b72bca   Jeff Mahoney   btrfs: publish su...
31
  #include "sysfs.h"
29e5be240   Jeff Mahoney   btrfs: publish de...
32
  #include "volumes.h"
079b72bca   Jeff Mahoney   btrfs: publish su...
33

510d73600   Jeff Mahoney   btrfs: publish pe...
34
  static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj);
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
35
  static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj);
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
36

510d73600   Jeff Mahoney   btrfs: publish pe...
37
38
  static u64 get_features(struct btrfs_fs_info *fs_info,
  			enum btrfs_feature_set set)
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
39
  {
510d73600   Jeff Mahoney   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   Jeff Mahoney   btrfs: publish pe...
47
  }
ba631941e   Jeff Mahoney   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:
cc37bb042   David Sterba   btrfs: replace BU...
78
79
80
81
  		printk(KERN_WARNING "btrfs: sysfs: unknown feature set %d
  ",
  				fa->feature_set);
  		return 0;
ba631941e   Jeff Mahoney   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   Jeff Mahoney   btrfs: publish pe...
91
92
  static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
  				       struct kobj_attribute *a, char *buf)
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
93
  {
510d73600   Jeff Mahoney   btrfs: publish pe...
94
  	int val = 0;
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
95
  	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
ba631941e   Jeff Mahoney   btrfs: add abilit...
96
  	struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
510d73600   Jeff Mahoney   btrfs: publish pe...
97
  	if (fs_info) {
510d73600   Jeff Mahoney   btrfs: publish pe...
98
99
100
  		u64 features = get_features(fs_info, fa->feature_set);
  		if (features & fa->feature_bit)
  			val = 1;
ba631941e   Jeff Mahoney   btrfs: add abilit...
101
102
  	} else
  		val = can_modify_feature(fa);
510d73600   Jeff Mahoney   btrfs: publish pe...
103
104
105
  
  	return snprintf(buf, PAGE_SIZE, "%d
  ", val);
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
106
  }
ba631941e   Jeff Mahoney   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   Jeff Mahoney   btrfs: add abilit...
113
114
115
116
117
118
119
120
121
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
  	u64 features, set, clear;
  	unsigned long val;
  	int ret;
  
  	fs_info = to_fs_info(kobj);
  	if (!fs_info)
  		return -EPERM;
  
  	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   Jeff Mahoney   btrfs: add abilit...
153
154
155
156
157
158
159
160
  	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   David Sterba   btrfs: move commi...
161
162
163
164
165
  	/*
  	 * 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   Jeff Mahoney   btrfs: add abilit...
166
167
168
  
  	return count;
  }
510d73600   Jeff Mahoney   btrfs: publish pe...
169
170
  static umode_t btrfs_feature_visible(struct kobject *kobj,
  				     struct attribute *attr, int unused)
079b72bca   Jeff Mahoney   btrfs: publish su...
171
  {
510d73600   Jeff Mahoney   btrfs: publish pe...
172
173
174
175
176
177
178
179
180
  	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   Jeff Mahoney   btrfs: add abilit...
181
182
183
  		if (can_modify_feature(fa))
  			mode |= S_IWUSR;
  		else if (!(features & fa->feature_bit))
510d73600   Jeff Mahoney   btrfs: publish pe...
184
185
186
187
  			mode = 0;
  	}
  
  	return mode;
079b72bca   Jeff Mahoney   btrfs: publish su...
188
189
190
191
192
193
  }
  
  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);
079b72bca   Jeff Mahoney   btrfs: publish su...
194
195
196
197
  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   David Sterba   btrfs: sysfs: lis...
198
  BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES);
3b5bb73bd   David Sterba   btrfs: sysfs: add...
199
  BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE);
079b72bca   Jeff Mahoney   btrfs: publish su...
200
201
202
203
204
205
  
  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),
079b72bca   Jeff Mahoney   btrfs: publish su...
206
207
208
209
  	BTRFS_FEAT_ATTR_PTR(big_metadata),
  	BTRFS_FEAT_ATTR_PTR(extended_iref),
  	BTRFS_FEAT_ATTR_PTR(raid56),
  	BTRFS_FEAT_ATTR_PTR(skinny_metadata),
c736c095d   David Sterba   btrfs: sysfs: lis...
210
  	BTRFS_FEAT_ATTR_PTR(no_holes),
3b5bb73bd   David Sterba   btrfs: sysfs: add...
211
  	BTRFS_FEAT_ATTR_PTR(free_space_tree),
079b72bca   Jeff Mahoney   btrfs: publish su...
212
213
214
215
216
  	NULL
  };
  
  static const struct attribute_group btrfs_feature_attr_group = {
  	.name = "features",
510d73600   Jeff Mahoney   btrfs: publish pe...
217
  	.is_visible = btrfs_feature_visible,
079b72bca   Jeff Mahoney   btrfs: publish su...
218
219
  	.attrs = btrfs_supported_feature_attrs,
  };
58176a960   Josef Bacik   Btrfs: Add per-ro...
220

6ab0a2029   Jeff Mahoney   btrfs: publish al...
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
  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   Anand Jain   btrfs: code optim...
240
  BTRFS_ATTR(global_rsv_size, global_rsv_size_show);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
241
242
243
244
245
246
247
248
  
  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   Anand Jain   btrfs: code optim...
249
  BTRFS_ATTR(global_rsv_reserved, global_rsv_reserved_show);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
250
251
  
  #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj)
c1895442b   Jeff Mahoney   btrfs: allocate r...
252
  #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj)
6ab0a2029   Jeff Mahoney   btrfs: publish al...
253
254
255
256
257
258
259
260
261
262
263
264
  
  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   Jeff Mahoney   btrfs: allocate r...
265
  	int index = to_raid_kobj(kobj)->raid_type;
6ab0a2029   Jeff Mahoney   btrfs: publish al...
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
  	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   Jeff Mahoney   btrfs: allocate r...
288
  	kfree(to_raid_kobj(kobj));
6ab0a2029   Jeff Mahoney   btrfs: publish al...
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
  }
  
  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   Anand Jain   btrfs: code optim...
305
  BTRFS_ATTR(field, btrfs_space_info_show_##field)
6ab0a2029   Jeff Mahoney   btrfs: publish al...
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
  
  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);
  SPACE_INFO_ATTR(disk_used);
  SPACE_INFO_ATTR(disk_total);
98b3d389e   Anand Jain   btrfs: code optim...
325
  BTRFS_ATTR(total_bytes_pinned, btrfs_space_info_show_total_bytes_pinned);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
  
  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),
  	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   Jeff Mahoney   btrfs: publish fs...
358
359
360
361
  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   Satoru Takeuchi   btrfs: label shou...
362
363
364
  	char *label = fs_info->super_copy->label;
  	return snprintf(buf, PAGE_SIZE, label[0] ? "%s
  " : "%s", label);
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
365
366
367
368
369
370
371
  }
  
  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   Satoru Takeuchi   btrfs: label shou...
372
  	size_t p_len;
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
373

79aec2b80   Anand Jain   btrfs: sysfs labe...
374
375
  	if (fs_info->sb->s_flags & MS_RDONLY)
  		return -EROFS;
48fcc3ff7   Satoru Takeuchi   btrfs: label shou...
376
377
378
379
380
381
382
383
384
  	/*
  	 * p_len is the len until the first occurrence of either
  	 * '
  ' or '\0'
  	 */
  	p_len = strcspn(buf, "
  ");
  
  	if (p_len >= BTRFS_LABEL_SIZE)
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
385
  		return -EINVAL;
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
386

a6f69dc80   David Sterba   btrfs: move commi...
387
  	spin_lock(&fs_info->super_lock);
48fcc3ff7   Satoru Takeuchi   btrfs: label shou...
388
389
  	memset(fs_info->super_copy->label, 0, BTRFS_LABEL_SIZE);
  	memcpy(fs_info->super_copy->label, buf, p_len);
a6f69dc80   David Sterba   btrfs: move commi...
390
  	spin_unlock(&fs_info->super_lock);
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
391

a6f69dc80   David Sterba   btrfs: move commi...
392
393
394
395
396
  	/*
  	 * 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   Jeff Mahoney   btrfs: publish fs...
397

a6f69dc80   David Sterba   btrfs: move commi...
398
  	return len;
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
399
  }
20ee0825e   Anand Jain   btrfs: code optim...
400
  BTRFS_ATTR_RW(label, btrfs_label_show, btrfs_label_store);
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
401

df93589a1   David Sterba   btrfs: export mor...
402
403
404
405
406
407
408
409
  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);
  
  	return snprintf(buf, PAGE_SIZE, "%u
  ", fs_info->super_copy->nodesize);
  }
98b3d389e   Anand Jain   btrfs: code optim...
410
  BTRFS_ATTR(nodesize, btrfs_nodesize_show);
df93589a1   David Sterba   btrfs: export mor...
411
412
413
414
415
416
417
418
419
  
  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);
  
  	return snprintf(buf, PAGE_SIZE, "%u
  ", fs_info->super_copy->sectorsize);
  }
98b3d389e   Anand Jain   btrfs: code optim...
420
  BTRFS_ATTR(sectorsize, btrfs_sectorsize_show);
df93589a1   David Sterba   btrfs: export mor...
421
422
423
424
425
426
427
428
429
  
  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);
  
  	return snprintf(buf, PAGE_SIZE, "%u
  ", fs_info->super_copy->sectorsize);
  }
98b3d389e   Anand Jain   btrfs: code optim...
430
  BTRFS_ATTR(clone_alignment, btrfs_clone_alignment_show);
df93589a1   David Sterba   btrfs: export mor...
431

0dd2906f7   Anand Jain   Btrfs: sysfs: let...
432
  static const struct attribute *btrfs_attrs[] = {
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
433
  	BTRFS_ATTR_PTR(label),
df93589a1   David Sterba   btrfs: export mor...
434
435
436
  	BTRFS_ATTR_PTR(nodesize),
  	BTRFS_ATTR_PTR(sectorsize),
  	BTRFS_ATTR_PTR(clone_alignment),
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
437
438
  	NULL,
  };
c1b7e4745   Anand Jain   Btrfs: rename sup...
439
  static void btrfs_release_fsid_kobj(struct kobject *kobj)
510d73600   Jeff Mahoney   btrfs: publish pe...
440
  {
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
441
  	struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj);
248d200df   Anand Jain   Btrfs: sysfs: fix...
442

c1b7e4745   Anand Jain   Btrfs: rename sup...
443
  	memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject));
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
444
  	complete(&fs_devs->kobj_unregister);
510d73600   Jeff Mahoney   btrfs: publish pe...
445
446
447
448
  }
  
  static struct kobj_type btrfs_ktype = {
  	.sysfs_ops	= &kobj_sysfs_ops,
c1b7e4745   Anand Jain   Btrfs: rename sup...
449
  	.release	= btrfs_release_fsid_kobj,
510d73600   Jeff Mahoney   btrfs: publish pe...
450
  };
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
451
452
453
454
  static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj)
  {
  	if (kobj->ktype != &btrfs_ktype)
  		return NULL;
c1b7e4745   Anand Jain   Btrfs: rename sup...
455
  	return container_of(kobj, struct btrfs_fs_devices, fsid_kobj);
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
456
  }
510d73600   Jeff Mahoney   btrfs: publish pe...
457
458
459
460
  static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
  {
  	if (kobj->ktype != &btrfs_ktype)
  		return NULL;
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
461
  	return to_fs_devs(kobj)->fs_info;
510d73600   Jeff Mahoney   btrfs: publish pe...
462
  }
58176a960   Josef Bacik   Btrfs: Add per-ro...
463

e453d989e   Jeff Mahoney   btrfs: fix leaks ...
464
465
466
  #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   David Sterba   btrfs: constify s...
467
  static const u64 supported_feature_masks[3] = {
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
  	[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   Anand Jain   Btrfs: rename sup...
501
  				ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj,
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
502
503
504
505
  							&agroup);
  				if (ret)
  					return ret;
  			} else
c1b7e4745   Anand Jain   Btrfs: rename sup...
506
  				sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj,
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
507
508
509
510
511
512
  						    &agroup);
  		}
  
  	}
  	return 0;
  }
2e3e12815   Anand Jain   Btrfs: sysfs: pro...
513
  static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
514
  {
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
515
516
517
518
  	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   Anand Jain   Btrfs: sysfs: reo...
519
  	}
c1b7e4745   Anand Jain   Btrfs: rename sup...
520
521
522
  	if (fs_devs->fsid_kobj.state_initialized) {
  		kobject_del(&fs_devs->fsid_kobj);
  		kobject_put(&fs_devs->fsid_kobj);
f90fc5472   Anand Jain   Btrfs: Check if k...
523
524
  		wait_for_completion(&fs_devs->kobj_unregister);
  	}
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
525
  }
2e3e12815   Anand Jain   Btrfs: sysfs: pro...
526
  /* when fs_devs is NULL it will remove all fsid kobject */
1d1c1be37   Anand Jain   Btrfs: sysfs: btr...
527
  void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
2e3e12815   Anand Jain   Btrfs: sysfs: pro...
528
529
530
531
532
533
534
535
536
537
538
539
  {
  	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   Anand Jain   Btrfs: rename btr...
540
  void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info)
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
541
  {
5a13f4308   Anand Jain   Btrfs: sysfs: add...
542
  	btrfs_reset_fs_info_ptr(fs_info);
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
543
544
545
546
547
  	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   Jeff Mahoney   btrfs: fix leaks ...
548
  	addrm_unknown_feature_attrs(fs_info, false);
c1b7e4745   Anand Jain   Btrfs: rename sup...
549
550
  	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   Anand Jain   Btrfs: rename btr...
551
  	btrfs_sysfs_rm_device_link(fs_info->fs_devices, NULL);
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
552
  }
79da4fa4d   Jeff Mahoney   btrfs: publish un...
553
554
555
556
557
  const char * const btrfs_feature_set_names[3] = {
  	[FEAT_COMPAT]	 = "compat",
  	[FEAT_COMPAT_RO] = "compat_ro",
  	[FEAT_INCOMPAT]	 = "incompat",
  };
3b02a68a6   Jeff Mahoney   btrfs: use featur...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
  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   Jeff Mahoney   btrfs: publish un...
582
583
584
585
586
587
588
589
590
  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   Jeff Mahoney   btrfs: use featur...
591
592
593
  	memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs));
  	memset(btrfs_unknown_feature_names, 0,
  	       sizeof(btrfs_unknown_feature_names));
79da4fa4d   Jeff Mahoney   btrfs: publish un...
594
595
596
  	for (i = 0; btrfs_supported_feature_attrs[i]; i++) {
  		struct btrfs_feature_attr *sfa;
  		struct attribute *a = btrfs_supported_feature_attrs[i];
3b02a68a6   Jeff Mahoney   btrfs: use featur...
597
  		int bit;
79da4fa4d   Jeff Mahoney   btrfs: publish un...
598
  		sfa = attr_to_btrfs_feature_attr(a);
3b02a68a6   Jeff Mahoney   btrfs: use featur...
599
600
  		bit = ilog2(sfa->feature_bit);
  		fa = &btrfs_feature_attrs[sfa->feature_set][bit];
79da4fa4d   Jeff Mahoney   btrfs: publish un...
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
  
  		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   Anand Jain   Btrfs: sysfs: fix...
623
  /* when one_device is NULL, it removes all device links */
325760404   Anand Jain   Btrfs: rename btr...
624
  int btrfs_sysfs_rm_device_link(struct btrfs_fs_devices *fs_devices,
99994cde9   Anand Jain   btrfs: dev delete...
625
626
627
628
  		struct btrfs_device *one_device)
  {
  	struct hd_struct *disk;
  	struct kobject *disk_kobj;
6c14a1641   Anand Jain   Btrfs: sysfs btrf...
629
  	if (!fs_devices->device_dir_kobj)
99994cde9   Anand Jain   btrfs: dev delete...
630
  		return -EINVAL;
87fa3bb07   Liu Bo   Btrfs: fix regres...
631
  	if (one_device && one_device->bdev) {
99994cde9   Anand Jain   btrfs: dev delete...
632
633
  		disk = one_device->bdev->bd_part;
  		disk_kobj = &part_to_dev(disk)->kobj;
6c14a1641   Anand Jain   Btrfs: sysfs btrf...
634
  		sysfs_remove_link(fs_devices->device_dir_kobj,
99994cde9   Anand Jain   btrfs: dev delete...
635
636
  						disk_kobj->name);
  	}
e7e1aa9c9   Anand Jain   Btrfs: sysfs: fix...
637
638
639
640
  	if (one_device)
  		return 0;
  
  	list_for_each_entry(one_device,
6c14a1641   Anand Jain   Btrfs: sysfs btrf...
641
  			&fs_devices->devices, dev_list) {
e7e1aa9c9   Anand Jain   Btrfs: sysfs: fix...
642
643
644
645
  		if (!one_device->bdev)
  			continue;
  		disk = one_device->bdev->bd_part;
  		disk_kobj = &part_to_dev(disk)->kobj;
6c14a1641   Anand Jain   Btrfs: sysfs btrf...
646
  		sysfs_remove_link(fs_devices->device_dir_kobj,
e7e1aa9c9   Anand Jain   Btrfs: sysfs: fix...
647
648
  						disk_kobj->name);
  	}
99994cde9   Anand Jain   btrfs: dev delete...
649
650
  	return 0;
  }
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
651
  int btrfs_sysfs_add_device(struct btrfs_fs_devices *fs_devs)
29e5be240   Jeff Mahoney   btrfs: publish de...
652
  {
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
653
654
  	if (!fs_devs->device_dir_kobj)
  		fs_devs->device_dir_kobj = kobject_create_and_add("devices",
c1b7e4745   Anand Jain   Btrfs: rename sup...
655
  						&fs_devs->fsid_kobj);
0d39376aa   Anand Jain   btrfs: dev add sh...
656

2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
657
  	if (!fs_devs->device_dir_kobj)
29e5be240   Jeff Mahoney   btrfs: publish de...
658
  		return -ENOMEM;
00c921c23   Anand Jain   Btrfs: sysfs: sep...
659
660
  	return 0;
  }
e3bd6973b   Anand Jain   Btrfs: rename btr...
661
  int btrfs_sysfs_add_device_link(struct btrfs_fs_devices *fs_devices,
1ba43816a   Anand Jain   Btrfs: sysfs btrf...
662
  				struct btrfs_device *one_device)
00c921c23   Anand Jain   Btrfs: sysfs: sep...
663
664
  {
  	int error = 0;
00c921c23   Anand Jain   Btrfs: sysfs: sep...
665
  	struct btrfs_device *dev;
29e5be240   Jeff Mahoney   btrfs: publish de...
666
  	list_for_each_entry(dev, &fs_devices->devices, dev_list) {
f085381e6   Anand Jain   btrfs: fix null p...
667
668
669
670
671
  		struct hd_struct *disk;
  		struct kobject *disk_kobj;
  
  		if (!dev->bdev)
  			continue;
0d39376aa   Anand Jain   btrfs: dev add sh...
672
673
  		if (one_device && one_device != dev)
  			continue;
f085381e6   Anand Jain   btrfs: fix null p...
674
675
  		disk = dev->bdev->bd_part;
  		disk_kobj = &part_to_dev(disk)->kobj;
29e5be240   Jeff Mahoney   btrfs: publish de...
676

2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
677
  		error = sysfs_create_link(fs_devices->device_dir_kobj,
29e5be240   Jeff Mahoney   btrfs: publish de...
678
679
680
681
682
683
684
  					  disk_kobj, disk_kobj->name);
  		if (error)
  			break;
  	}
  
  	return error;
  }
510d73600   Jeff Mahoney   btrfs: publish pe...
685
686
  /* /sys/fs/btrfs/ entry */
  static struct kset *btrfs_kset;
1bae30982   David Sterba   btrfs: add simple...
687
688
689
690
691
  /* /sys/kernel/debug/btrfs */
  static struct dentry *btrfs_debugfs_root_dentry;
  
  /* Debugging tunables and exported data */
  u64 btrfs_debugfs_test;
720592157   Anand Jain   Btrfs: sysfs: int...
692
693
694
695
  /*
   * Can be called by the device discovery thread.
   * And parent can be specified for seed device
   */
0c10e2d48   Anand Jain   Btrfs: sysfs: mak...
696
  int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs,
720592157   Anand Jain   Btrfs: sysfs: int...
697
  				struct kobject *parent)
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
698
699
  {
  	int error;
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
700
  	init_completion(&fs_devs->kobj_unregister);
c1b7e4745   Anand Jain   Btrfs: rename sup...
701
702
  	fs_devs->fsid_kobj.kset = btrfs_kset;
  	error = kobject_init_and_add(&fs_devs->fsid_kobj,
24bd69cb0   Anand Jain   Btrfs: sysfs: add...
703
  				&btrfs_ktype, parent, "%pU", fs_devs->fsid);
720592157   Anand Jain   Btrfs: sysfs: int...
704
705
  	return error;
  }
96f3136e5   Anand Jain   Btrfs: rename btr...
706
  int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info)
720592157   Anand Jain   Btrfs: sysfs: int...
707
708
  {
  	int error;
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
709
  	struct btrfs_fs_devices *fs_devs = fs_info->fs_devices;
c1b7e4745   Anand Jain   Btrfs: rename sup...
710
  	struct kobject *fsid_kobj = &fs_devs->fsid_kobj;
720592157   Anand Jain   Btrfs: sysfs: int...
711

5a13f4308   Anand Jain   Btrfs: sysfs: add...
712
  	btrfs_set_fs_info_ptr(fs_info);
e3bd6973b   Anand Jain   Btrfs: rename btr...
713
  	error = btrfs_sysfs_add_device_link(fs_devs, NULL);
b7c35e81a   Anand Jain   Btrfs: sysfs: sep...
714
  	if (error)
aaf133051   Anand Jain   Btrfs: sysfs: reo...
715
  		return error;
aaf133051   Anand Jain   Btrfs: sysfs: reo...
716

c1b7e4745   Anand Jain   Btrfs: rename sup...
717
  	error = sysfs_create_files(fsid_kobj, btrfs_attrs);
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
718
  	if (error) {
325760404   Anand Jain   Btrfs: rename btr...
719
  		btrfs_sysfs_rm_device_link(fs_devs, NULL);
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
720
721
  		return error;
  	}
79da4fa4d   Jeff Mahoney   btrfs: publish un...
722

c1b7e4745   Anand Jain   Btrfs: rename sup...
723
  	error = sysfs_create_group(fsid_kobj,
0dd2906f7   Anand Jain   Btrfs: sysfs: let...
724
725
726
  				   &btrfs_feature_attr_group);
  	if (error)
  		goto failure;
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
727
  	error = addrm_unknown_feature_attrs(fs_info, true);
79da4fa4d   Jeff Mahoney   btrfs: publish un...
728
729
  	if (error)
  		goto failure;
6ab0a2029   Jeff Mahoney   btrfs: publish al...
730
  	fs_info->space_info_kobj = kobject_create_and_add("allocation",
c1b7e4745   Anand Jain   Btrfs: rename sup...
731
  						  fsid_kobj);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
732
733
734
735
736
737
738
739
  	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   Jeff Mahoney   btrfs: publish un...
740
741
  	return 0;
  failure:
6618a59bf   Anand Jain   Btrfs: rename btr...
742
  	btrfs_sysfs_remove_mounted(fs_info);
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
743
744
  	return error;
  }
444e75169   David Sterba   btrfs: sysfs: int...
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
  
  /*
   * 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   David Sterba   btrfs: sysfs: che...
766
767
  	if (!fsid_kobj->state_initialized)
  		return;
444e75169   David Sterba   btrfs: sysfs: int...
768
769
770
771
772
773
774
  	/*
  	 * 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   David Sterba   btrfs: add simple...
775
776
777
778
779
780
781
782
783
784
785
786
  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;
  
  	debugfs_create_u64("test", S_IRUGO | S_IWUGO, btrfs_debugfs_root_dentry,
  			&btrfs_debugfs_test);
  #endif
  	return 0;
  }
b214107ed   Christoph Hellwig   Btrfs: trivial sp...
787
  int btrfs_init_sysfs(void)
58176a960   Josef Bacik   Btrfs: Add per-ro...
788
  {
079b72bca   Jeff Mahoney   btrfs: publish su...
789
  	int ret;
1bae30982   David Sterba   btrfs: add simple...
790

e3fe4e712   Greg Kroah-Hartman   btrfs: fixes for ...
791
792
793
  	btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
  	if (!btrfs_kset)
  		return -ENOMEM;
079b72bca   Jeff Mahoney   btrfs: publish su...
794

1bae30982   David Sterba   btrfs: add simple...
795
796
  	ret = btrfs_init_debugfs();
  	if (ret)
001a648df   Filipe Manana   Btrfs: add missin...
797
  		goto out1;
79da4fa4d   Jeff Mahoney   btrfs: publish un...
798

1bae30982   David Sterba   btrfs: add simple...
799
  	init_feature_attrs();
079b72bca   Jeff Mahoney   btrfs: publish su...
800
  	ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
001a648df   Filipe Manana   Btrfs: add missin...
801
802
803
804
805
806
807
808
  	if (ret)
  		goto out2;
  
  	return 0;
  out2:
  	debugfs_remove_recursive(btrfs_debugfs_root_dentry);
  out1:
  	kset_unregister(btrfs_kset);
079b72bca   Jeff Mahoney   btrfs: publish su...
809

1bae30982   David Sterba   btrfs: add simple...
810
  	return ret;
58176a960   Josef Bacik   Btrfs: Add per-ro...
811
  }
b214107ed   Christoph Hellwig   Btrfs: trivial sp...
812
  void btrfs_exit_sysfs(void)
58176a960   Josef Bacik   Btrfs: Add per-ro...
813
  {
079b72bca   Jeff Mahoney   btrfs: publish su...
814
  	sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
e3fe4e712   Greg Kroah-Hartman   btrfs: fixes for ...
815
  	kset_unregister(btrfs_kset);
1bae30982   David Sterba   btrfs: add simple...
816
  	debugfs_remove_recursive(btrfs_debugfs_root_dentry);
58176a960   Josef Bacik   Btrfs: Add per-ro...
817
  }
55d474148   Chris Mason   Btrfs: Disable sy...
818