Blame view

fs/btrfs/sysfs.c 47.7 KB
c1d7c514f   David Sterba   btrfs: replace GP...
1
  // SPDX-License-Identifier: GPL-2.0
6cbd55707   Chris Mason   Btrfs: add GPLv2
2
3
  /*
   * Copyright (C) 2007 Oracle.  All rights reserved.
6cbd55707   Chris Mason   Btrfs: add GPLv2
4
   */
58176a960   Josef Bacik   Btrfs: Add per-ro...
5
  #include <linux/sched.h>
32a9991f1   David Sterba   btrfs: factor sys...
6
  #include <linux/sched/mm.h>
58176a960   Josef Bacik   Btrfs: Add per-ro...
7
8
9
  #include <linux/slab.h>
  #include <linux/spinlock.h>
  #include <linux/completion.h>
79da4fa4d   Jeff Mahoney   btrfs: publish un...
10
  #include <linux/bug.h>
41e6d2a80   Johannes Thumshirn   btrfs: sysfs: sho...
11
  #include <crypto/hash.h>
58176a960   Josef Bacik   Btrfs: Add per-ro...
12

bae45de03   Chris Mason   Btrfs: add dir in...
13
  #include "ctree.h"
dfb79ddb1   Dennis Zhou   btrfs: track disc...
14
  #include "discard.h"
bae45de03   Chris Mason   Btrfs: add dir in...
15
  #include "disk-io.h"
7573df554   Omar Sandoval   btrfs: sysfs: exp...
16
  #include "send.h"
bae45de03   Chris Mason   Btrfs: add dir in...
17
  #include "transaction.h"
079b72bca   Jeff Mahoney   btrfs: publish su...
18
  #include "sysfs.h"
29e5be240   Jeff Mahoney   btrfs: publish de...
19
  #include "volumes.h"
8719aaae8   Josef Bacik   btrfs: move space...
20
  #include "space-info.h"
aac0023c2   Josef Bacik   btrfs: move basic...
21
  #include "block-group.h"
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
22
  #include "qgroup.h"
079b72bca   Jeff Mahoney   btrfs: publish su...
23

9188db611   David Sterba   btrfs: sysfs: mov...
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
  struct btrfs_feature_attr {
  	struct kobj_attribute kobj_attr;
  	enum btrfs_feature_set feature_set;
  	u64 feature_bit;
  };
  
  /* For raid type sysfs entries */
  struct raid_kobject {
  	u64 flags;
  	struct kobject kobj;
  };
  
  #define __INIT_KOBJ_ATTR(_name, _mode, _show, _store)			\
  {									\
  	.attr	= { .name = __stringify(_name), .mode = _mode },	\
  	.show	= _show,						\
  	.store	= _store,						\
  }
  
  #define BTRFS_ATTR_RW(_prefix, _name, _show, _store)			\
  	static struct kobj_attribute btrfs_attr_##_prefix##_##_name =	\
  			__INIT_KOBJ_ATTR(_name, 0644, _show, _store)
  
  #define BTRFS_ATTR(_prefix, _name, _show)				\
  	static struct kobj_attribute btrfs_attr_##_prefix##_##_name =	\
  			__INIT_KOBJ_ATTR(_name, 0444, _show, NULL)
  
  #define BTRFS_ATTR_PTR(_prefix, _name)					\
  	(&btrfs_attr_##_prefix##_##_name.attr)
  
  #define BTRFS_FEAT_ATTR(_name, _feature_set, _feature_prefix, _feature_bit)  \
  static struct btrfs_feature_attr btrfs_attr_features_##_name = {	     \
  	.kobj_attr = __INIT_KOBJ_ATTR(_name, S_IRUGO,			     \
  				      btrfs_feature_attr_show,		     \
  				      btrfs_feature_attr_store),	     \
  	.feature_set	= _feature_set,					     \
  	.feature_bit	= _feature_prefix ##_## _feature_bit,		     \
  }
  #define BTRFS_FEAT_ATTR_PTR(_name)					     \
  	(&btrfs_attr_features_##_name.kobj_attr.attr)
  
  #define BTRFS_FEAT_ATTR_COMPAT(name, feature) \
  	BTRFS_FEAT_ATTR(name, FEAT_COMPAT, BTRFS_FEATURE_COMPAT, feature)
  #define BTRFS_FEAT_ATTR_COMPAT_RO(name, feature) \
  	BTRFS_FEAT_ATTR(name, FEAT_COMPAT_RO, BTRFS_FEATURE_COMPAT_RO, feature)
  #define BTRFS_FEAT_ATTR_INCOMPAT(name, feature) \
  	BTRFS_FEAT_ATTR(name, FEAT_INCOMPAT, BTRFS_FEATURE_INCOMPAT, feature)
510d73600   Jeff Mahoney   btrfs: publish pe...
71
  static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj);
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
72
  static inline struct btrfs_fs_devices *to_fs_devs(struct kobject *kobj);
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
73

8f52316c2   David Sterba   btrfs: sysfs: mov...
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
  static struct btrfs_feature_attr *to_btrfs_feature_attr(struct kobj_attribute *a)
  {
  	return container_of(a, struct btrfs_feature_attr, kobj_attr);
  }
  
  static struct kobj_attribute *attr_to_btrfs_attr(struct attribute *attr)
  {
  	return container_of(attr, struct kobj_attribute, attr);
  }
  
  static struct btrfs_feature_attr *attr_to_btrfs_feature_attr(
  		struct attribute *attr)
  {
  	return to_btrfs_feature_attr(attr_to_btrfs_attr(attr));
  }
510d73600   Jeff Mahoney   btrfs: publish pe...
89
90
  static u64 get_features(struct btrfs_fs_info *fs_info,
  			enum btrfs_feature_set set)
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
91
  {
510d73600   Jeff Mahoney   btrfs: publish pe...
92
93
94
95
96
97
98
  	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...
99
  }
ba631941e   Jeff Mahoney   btrfs: add abilit...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  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   Jeff Mahoney   btrfs: convert pr...
130
131
  		pr_warn("btrfs: sysfs: unknown feature set %d
  ",
cc37bb042   David Sterba   btrfs: replace BU...
132
133
  				fa->feature_set);
  		return 0;
ba631941e   Jeff Mahoney   btrfs: add abilit...
134
135
136
137
138
139
140
141
142
  	}
  
  	if (set & fa->feature_bit)
  		val |= 1;
  	if (clear & fa->feature_bit)
  		val |= 2;
  
  	return val;
  }
510d73600   Jeff Mahoney   btrfs: publish pe...
143
144
  static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
  				       struct kobj_attribute *a, char *buf)
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
145
  {
510d73600   Jeff Mahoney   btrfs: publish pe...
146
  	int val = 0;
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
147
  	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
ba631941e   Jeff Mahoney   btrfs: add abilit...
148
  	struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
510d73600   Jeff Mahoney   btrfs: publish pe...
149
  	if (fs_info) {
510d73600   Jeff Mahoney   btrfs: publish pe...
150
151
152
  		u64 features = get_features(fs_info, fa->feature_set);
  		if (features & fa->feature_bit)
  			val = 1;
ba631941e   Jeff Mahoney   btrfs: add abilit...
153
154
  	} else
  		val = can_modify_feature(fa);
510d73600   Jeff Mahoney   btrfs: publish pe...
155

abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
156
157
  	return scnprintf(buf, PAGE_SIZE, "%d
  ", val);
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
158
  }
ba631941e   Jeff Mahoney   btrfs: add abilit...
159
160
161
162
163
164
  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...
165
166
167
168
169
170
171
  	u64 features, set, clear;
  	unsigned long val;
  	int ret;
  
  	fs_info = to_fs_info(kobj);
  	if (!fs_info)
  		return -EPERM;
bc98a42c1   David Howells   VFS: Convert sb->...
172
  	if (sb_rdonly(fs_info->sb))
ee6111386   David Sterba   btrfs: add read-o...
173
  		return -EROFS;
ba631941e   Jeff Mahoney   btrfs: add abilit...
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
  	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...
206
207
208
209
210
211
212
213
  	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...
214
215
216
217
218
  	/*
  	 * 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...
219
220
221
  
  	return count;
  }
510d73600   Jeff Mahoney   btrfs: publish pe...
222
223
  static umode_t btrfs_feature_visible(struct kobject *kobj,
  				     struct attribute *attr, int unused)
079b72bca   Jeff Mahoney   btrfs: publish su...
224
  {
510d73600   Jeff Mahoney   btrfs: publish pe...
225
226
227
228
229
230
231
232
233
  	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...
234
235
236
  		if (can_modify_feature(fa))
  			mode |= S_IWUSR;
  		else if (!(features & fa->feature_bit))
510d73600   Jeff Mahoney   btrfs: publish pe...
237
238
239
240
  			mode = 0;
  	}
  
  	return mode;
079b72bca   Jeff Mahoney   btrfs: publish su...
241
242
243
244
245
246
  }
  
  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   Nick Terrell   btrfs: Add zstd s...
247
  BTRFS_FEAT_ATTR_INCOMPAT(compress_zstd, COMPRESS_ZSTD);
079b72bca   Jeff Mahoney   btrfs: publish su...
248
249
250
251
  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...
252
  BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES);
56f20f400   Nikolay Borisov   btrfs: Add sysfs ...
253
  BTRFS_FEAT_ATTR_INCOMPAT(metadata_uuid, METADATA_UUID);
3b5bb73bd   David Sterba   btrfs: sysfs: add...
254
  BTRFS_FEAT_ATTR_COMPAT_RO(free_space_tree, FREE_SPACE_TREE);
cfbb825c7   David Sterba   btrfs: add incomp...
255
  BTRFS_FEAT_ATTR_INCOMPAT(raid1c34, RAID1C34);
079b72bca   Jeff Mahoney   btrfs: publish su...
256
257
258
259
260
261
  
  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   Nick Terrell   btrfs: Add zstd s...
262
  	BTRFS_FEAT_ATTR_PTR(compress_zstd),
079b72bca   Jeff Mahoney   btrfs: publish su...
263
264
265
266
  	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...
267
  	BTRFS_FEAT_ATTR_PTR(no_holes),
56f20f400   Nikolay Borisov   btrfs: Add sysfs ...
268
  	BTRFS_FEAT_ATTR_PTR(metadata_uuid),
3b5bb73bd   David Sterba   btrfs: sysfs: add...
269
  	BTRFS_FEAT_ATTR_PTR(free_space_tree),
cfbb825c7   David Sterba   btrfs: add incomp...
270
  	BTRFS_FEAT_ATTR_PTR(raid1c34),
079b72bca   Jeff Mahoney   btrfs: publish su...
271
272
  	NULL
  };
f902bd3a5   Misono Tomohiro   btrfs: sysfs: Add...
273
274
275
276
277
278
279
  /*
   * Features which depend on feature bits and may differ between each fs.
   *
   * /sys/fs/btrfs/features lists all available features of this kernel while
   * /sys/fs/btrfs/UUID/features shows features of the fs which are enabled or
   * can be changed online.
   */
079b72bca   Jeff Mahoney   btrfs: publish su...
280
281
  static const struct attribute_group btrfs_feature_attr_group = {
  	.name = "features",
510d73600   Jeff Mahoney   btrfs: publish pe...
282
  	.is_visible = btrfs_feature_visible,
079b72bca   Jeff Mahoney   btrfs: publish su...
283
284
  	.attrs = btrfs_supported_feature_attrs,
  };
58176a960   Josef Bacik   Btrfs: Add per-ro...
285

f902bd3a5   Misono Tomohiro   btrfs: sysfs: Add...
286
287
288
  static ssize_t rmdir_subvol_show(struct kobject *kobj,
  				 struct kobj_attribute *ka, char *buf)
  {
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
289
290
  	return scnprintf(buf, PAGE_SIZE, "0
  ");
f902bd3a5   Misono Tomohiro   btrfs: sysfs: Add...
291
292
  }
  BTRFS_ATTR(static_feature, rmdir_subvol, rmdir_subvol_show);
f7cea56c0   David Sterba   btrfs: sysfs: exp...
293
294
295
296
297
298
299
300
301
302
303
  static ssize_t supported_checksums_show(struct kobject *kobj,
  					struct kobj_attribute *a, char *buf)
  {
  	ssize_t ret = 0;
  	int i;
  
  	for (i = 0; i < btrfs_get_num_csums(); i++) {
  		/*
  		 * This "trick" only works as long as 'enum btrfs_csum_type' has
  		 * no holes in it
  		 */
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
304
  		ret += scnprintf(buf + ret, PAGE_SIZE - ret, "%s%s",
f7cea56c0   David Sterba   btrfs: sysfs: exp...
305
306
307
  				(i == 0 ? "" : " "), btrfs_super_csum_name(i));
  
  	}
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
308
309
  	ret += scnprintf(buf + ret, PAGE_SIZE - ret, "
  ");
f7cea56c0   David Sterba   btrfs: sysfs: exp...
310
311
312
  	return ret;
  }
  BTRFS_ATTR(static_feature, supported_checksums, supported_checksums_show);
7573df554   Omar Sandoval   btrfs: sysfs: exp...
313
314
315
316
317
318
319
  static ssize_t send_stream_version_show(struct kobject *kobj,
  					struct kobj_attribute *ka, char *buf)
  {
  	return snprintf(buf, PAGE_SIZE, "%d
  ", BTRFS_SEND_STREAM_VERSION);
  }
  BTRFS_ATTR(static_feature, send_stream_version, send_stream_version_show);
f902bd3a5   Misono Tomohiro   btrfs: sysfs: Add...
320
321
  static struct attribute *btrfs_supported_static_feature_attrs[] = {
  	BTRFS_ATTR_PTR(static_feature, rmdir_subvol),
f7cea56c0   David Sterba   btrfs: sysfs: exp...
322
  	BTRFS_ATTR_PTR(static_feature, supported_checksums),
7573df554   Omar Sandoval   btrfs: sysfs: exp...
323
  	BTRFS_ATTR_PTR(static_feature, send_stream_version),
f902bd3a5   Misono Tomohiro   btrfs: sysfs: Add...
324
325
326
327
328
329
330
331
332
333
334
335
336
  	NULL
  };
  
  /*
   * Features which only depend on kernel version.
   *
   * These are listed in /sys/fs/btrfs/features along with
   * btrfs_feature_attr_group
   */
  static const struct attribute_group btrfs_static_feature_attr_group = {
  	.name = "features",
  	.attrs = btrfs_supported_static_feature_attrs,
  };
6e369febb   David Sterba   btrfs: sysfs: add...
337
338
339
  #ifdef CONFIG_BTRFS_DEBUG
  
  /*
e4faab844   Dennis Zhou   btrfs: sysfs: add...
340
341
   * Discard statistics and tunables
   */
dfb79ddb1   Dennis Zhou   btrfs: track disc...
342
  #define discard_to_fs_info(_kobj)	to_fs_info((_kobj)->parent->parent)
5dc7c10b8   Dennis Zhou   btrfs: keep track...
343
344
345
346
347
  static ssize_t btrfs_discardable_bytes_show(struct kobject *kobj,
  					    struct kobj_attribute *a,
  					    char *buf)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
348
349
  	return scnprintf(buf, PAGE_SIZE, "%lld
  ",
5dc7c10b8   Dennis Zhou   btrfs: keep track...
350
351
352
  			atomic64_read(&fs_info->discard_ctl.discardable_bytes));
  }
  BTRFS_ATTR(discard, discardable_bytes, btrfs_discardable_bytes_show);
dfb79ddb1   Dennis Zhou   btrfs: track disc...
353
354
355
356
357
  static ssize_t btrfs_discardable_extents_show(struct kobject *kobj,
  					      struct kobj_attribute *a,
  					      char *buf)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
358
359
  	return scnprintf(buf, PAGE_SIZE, "%d
  ",
dfb79ddb1   Dennis Zhou   btrfs: track disc...
360
361
362
  			atomic_read(&fs_info->discard_ctl.discardable_extents));
  }
  BTRFS_ATTR(discard, discardable_extents, btrfs_discardable_extents_show);
9ddf648f9   Dennis Zhou   btrfs: keep track...
363
364
365
366
367
  static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj,
  					       struct kobj_attribute *a,
  					       char *buf)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
368
369
  	return scnprintf(buf, PAGE_SIZE, "%lld
  ",
9ddf648f9   Dennis Zhou   btrfs: keep track...
370
371
372
373
374
375
376
377
378
  			fs_info->discard_ctl.discard_bitmap_bytes);
  }
  BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show);
  
  static ssize_t btrfs_discard_bytes_saved_show(struct kobject *kobj,
  					      struct kobj_attribute *a,
  					      char *buf)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
379
380
  	return scnprintf(buf, PAGE_SIZE, "%lld
  ",
9ddf648f9   Dennis Zhou   btrfs: keep track...
381
382
383
384
385
386
387
388
389
  		atomic64_read(&fs_info->discard_ctl.discard_bytes_saved));
  }
  BTRFS_ATTR(discard, discard_bytes_saved, btrfs_discard_bytes_saved_show);
  
  static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj,
  					       struct kobj_attribute *a,
  					       char *buf)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
390
391
  	return scnprintf(buf, PAGE_SIZE, "%lld
  ",
9ddf648f9   Dennis Zhou   btrfs: keep track...
392
393
394
  			fs_info->discard_ctl.discard_extent_bytes);
  }
  BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show);
a23093008   Dennis Zhou   btrfs: calculate ...
395
396
397
398
399
  static ssize_t btrfs_discard_iops_limit_show(struct kobject *kobj,
  					     struct kobj_attribute *a,
  					     char *buf)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
400
401
  	return scnprintf(buf, PAGE_SIZE, "%u
  ",
a23093008   Dennis Zhou   btrfs: calculate ...
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
  			READ_ONCE(fs_info->discard_ctl.iops_limit));
  }
  
  static ssize_t btrfs_discard_iops_limit_store(struct kobject *kobj,
  					      struct kobj_attribute *a,
  					      const char *buf, size_t len)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
  	struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl;
  	u32 iops_limit;
  	int ret;
  
  	ret = kstrtou32(buf, 10, &iops_limit);
  	if (ret)
  		return -EINVAL;
  
  	WRITE_ONCE(discard_ctl->iops_limit, iops_limit);
  
  	return len;
  }
  BTRFS_ATTR_RW(discard, iops_limit, btrfs_discard_iops_limit_show,
  	      btrfs_discard_iops_limit_store);
e93591bb6   Dennis Zhou   btrfs: add kbps d...
424
425
426
427
428
  static ssize_t btrfs_discard_kbps_limit_show(struct kobject *kobj,
  					     struct kobj_attribute *a,
  					     char *buf)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
429
430
  	return scnprintf(buf, PAGE_SIZE, "%u
  ",
e93591bb6   Dennis Zhou   btrfs: add kbps d...
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
  			READ_ONCE(fs_info->discard_ctl.kbps_limit));
  }
  
  static ssize_t btrfs_discard_kbps_limit_store(struct kobject *kobj,
  					      struct kobj_attribute *a,
  					      const char *buf, size_t len)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
  	struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl;
  	u32 kbps_limit;
  	int ret;
  
  	ret = kstrtou32(buf, 10, &kbps_limit);
  	if (ret)
  		return -EINVAL;
  
  	WRITE_ONCE(discard_ctl->kbps_limit, kbps_limit);
  
  	return len;
  }
  BTRFS_ATTR_RW(discard, kbps_limit, btrfs_discard_kbps_limit_show,
  	      btrfs_discard_kbps_limit_store);
19b2a2c71   Dennis Zhou   btrfs: make max a...
453
454
455
456
457
  static ssize_t btrfs_discard_max_discard_size_show(struct kobject *kobj,
  						   struct kobj_attribute *a,
  						   char *buf)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
458
459
  	return scnprintf(buf, PAGE_SIZE, "%llu
  ",
19b2a2c71   Dennis Zhou   btrfs: make max a...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
  			READ_ONCE(fs_info->discard_ctl.max_discard_size));
  }
  
  static ssize_t btrfs_discard_max_discard_size_store(struct kobject *kobj,
  						    struct kobj_attribute *a,
  						    const char *buf, size_t len)
  {
  	struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj);
  	struct btrfs_discard_ctl *discard_ctl = &fs_info->discard_ctl;
  	u64 max_discard_size;
  	int ret;
  
  	ret = kstrtou64(buf, 10, &max_discard_size);
  	if (ret)
  		return -EINVAL;
  
  	WRITE_ONCE(discard_ctl->max_discard_size, max_discard_size);
  
  	return len;
  }
  BTRFS_ATTR_RW(discard, max_discard_size, btrfs_discard_max_discard_size_show,
  	      btrfs_discard_max_discard_size_store);
e4faab844   Dennis Zhou   btrfs: sysfs: add...
482
  static const struct attribute *discard_debug_attrs[] = {
5dc7c10b8   Dennis Zhou   btrfs: keep track...
483
  	BTRFS_ATTR_PTR(discard, discardable_bytes),
dfb79ddb1   Dennis Zhou   btrfs: track disc...
484
  	BTRFS_ATTR_PTR(discard, discardable_extents),
9ddf648f9   Dennis Zhou   btrfs: keep track...
485
486
487
  	BTRFS_ATTR_PTR(discard, discard_bitmap_bytes),
  	BTRFS_ATTR_PTR(discard, discard_bytes_saved),
  	BTRFS_ATTR_PTR(discard, discard_extent_bytes),
a23093008   Dennis Zhou   btrfs: calculate ...
488
  	BTRFS_ATTR_PTR(discard, iops_limit),
e93591bb6   Dennis Zhou   btrfs: add kbps d...
489
  	BTRFS_ATTR_PTR(discard, kbps_limit),
19b2a2c71   Dennis Zhou   btrfs: make max a...
490
  	BTRFS_ATTR_PTR(discard, max_discard_size),
e4faab844   Dennis Zhou   btrfs: sysfs: add...
491
492
493
494
  	NULL,
  };
  
  /*
6e369febb   David Sterba   btrfs: sysfs: add...
495
496
497
498
499
   * Runtime debugging exported via sysfs
   *
   * /sys/fs/btrfs/debug - applies to module or all filesystems
   * /sys/fs/btrfs/UUID  - applies only to the given filesystem
   */
93945cb43   Dennis Zhou   btrfs: sysfs: mak...
500
501
502
  static const struct attribute *btrfs_debug_mount_attrs[] = {
  	NULL,
  };
6e369febb   David Sterba   btrfs: sysfs: add...
503
504
505
506
507
508
509
510
511
512
  static struct attribute *btrfs_debug_feature_attrs[] = {
  	NULL
  };
  
  static const struct attribute_group btrfs_debug_feature_attr_group = {
  	.name = "debug",
  	.attrs = btrfs_debug_feature_attrs,
  };
  
  #endif
6ab0a2029   Jeff Mahoney   btrfs: publish al...
513
514
515
516
517
518
519
520
  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);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
521
522
  	return scnprintf(buf, PAGE_SIZE, "%llu
  ", val);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
523
524
525
526
527
528
529
530
531
  }
  
  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);
  }
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
532
  BTRFS_ATTR(allocation, global_rsv_size, global_rsv_size_show);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
533
534
535
536
537
538
539
540
  
  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);
  }
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
541
  BTRFS_ATTR(allocation, global_rsv_reserved, global_rsv_reserved_show);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
542
543
  
  #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj)
c1895442b   Jeff Mahoney   btrfs: allocate r...
544
  #define to_raid_kobj(_kobj) container_of(_kobj, struct raid_kobject, kobj)
6ab0a2029   Jeff Mahoney   btrfs: publish al...
545
546
547
  
  static ssize_t raid_bytes_show(struct kobject *kobj,
  			       struct kobj_attribute *attr, char *buf);
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
548
549
  BTRFS_ATTR(raid, total_bytes, raid_bytes_show);
  BTRFS_ATTR(raid, used_bytes, raid_bytes_show);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
550
551
552
553
554
555
  
  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);
32da5386d   David Sterba   btrfs: rename btr...
556
  	struct btrfs_block_group *block_group;
75cb379d2   Jeff Mahoney   btrfs: defer addi...
557
  	int index = btrfs_bg_flags_to_raid_index(to_raid_kobj(kobj)->flags);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
558
559
560
561
  	u64 val = 0;
  
  	down_read(&sinfo->groups_sem);
  	list_for_each_entry(block_group, &sinfo->block_groups[index], list) {
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
562
  		if (&attr->attr == BTRFS_ATTR_PTR(raid, total_bytes))
b3470b5db   David Sterba   btrfs: add dedica...
563
  			val += block_group->length;
6ab0a2029   Jeff Mahoney   btrfs: publish al...
564
  		else
bf38be65f   David Sterba   btrfs: move block...
565
  			val += block_group->used;
6ab0a2029   Jeff Mahoney   btrfs: publish al...
566
567
  	}
  	up_read(&sinfo->groups_sem);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
568
569
  	return scnprintf(buf, PAGE_SIZE, "%llu
  ", val);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
570
  }
7c7e30140   Kimberly Brown   btrfs: sysfs: Rep...
571
  static struct attribute *raid_attrs[] = {
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
572
573
  	BTRFS_ATTR_PTR(raid, total_bytes),
  	BTRFS_ATTR_PTR(raid, used_bytes),
6ab0a2029   Jeff Mahoney   btrfs: publish al...
574
575
  	NULL
  };
7c7e30140   Kimberly Brown   btrfs: sysfs: Rep...
576
  ATTRIBUTE_GROUPS(raid);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
577
578
579
  
  static void release_raid_kobj(struct kobject *kobj)
  {
c1895442b   Jeff Mahoney   btrfs: allocate r...
580
  	kfree(to_raid_kobj(kobj));
6ab0a2029   Jeff Mahoney   btrfs: publish al...
581
  }
536ea45cb   David Sterba   btrfs: sysfs: une...
582
  static struct kobj_type btrfs_raid_ktype = {
6ab0a2029   Jeff Mahoney   btrfs: publish al...
583
584
  	.sysfs_ops = &kobj_sysfs_ops,
  	.release = release_raid_kobj,
7c7e30140   Kimberly Brown   btrfs: sysfs: Rep...
585
  	.default_groups = raid_groups,
6ab0a2029   Jeff Mahoney   btrfs: publish al...
586
587
588
589
590
591
592
593
594
595
  };
  
  #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);	\
  }									\
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
596
  BTRFS_ATTR(space_info, field, btrfs_space_info_show_##field)
6ab0a2029   Jeff Mahoney   btrfs: publish al...
597
598
599
600
601
602
603
  
  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);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
604
605
  	return scnprintf(buf, PAGE_SIZE, "%lld
  ", val);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
606
607
608
609
610
611
612
613
  }
  
  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   Wang Xiaoguang   btrfs: add missin...
614
  SPACE_INFO_ATTR(bytes_readonly);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
615
616
  SPACE_INFO_ATTR(disk_used);
  SPACE_INFO_ATTR(disk_total);
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
617
618
  BTRFS_ATTR(space_info, total_bytes_pinned,
  	   btrfs_space_info_show_total_bytes_pinned);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
619
620
  
  static struct attribute *space_info_attrs[] = {
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
621
622
623
624
625
626
627
628
629
630
  	BTRFS_ATTR_PTR(space_info, flags),
  	BTRFS_ATTR_PTR(space_info, total_bytes),
  	BTRFS_ATTR_PTR(space_info, bytes_used),
  	BTRFS_ATTR_PTR(space_info, bytes_pinned),
  	BTRFS_ATTR_PTR(space_info, bytes_reserved),
  	BTRFS_ATTR_PTR(space_info, bytes_may_use),
  	BTRFS_ATTR_PTR(space_info, bytes_readonly),
  	BTRFS_ATTR_PTR(space_info, disk_used),
  	BTRFS_ATTR_PTR(space_info, disk_total),
  	BTRFS_ATTR_PTR(space_info, total_bytes_pinned),
6ab0a2029   Jeff Mahoney   btrfs: publish al...
631
632
  	NULL,
  };
7c7e30140   Kimberly Brown   btrfs: sysfs: Rep...
633
  ATTRIBUTE_GROUPS(space_info);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
634
635
636
637
638
639
640
  
  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);
  }
27992d014   David Sterba   btrfs: sysfs: une...
641
  static struct kobj_type space_info_ktype = {
6ab0a2029   Jeff Mahoney   btrfs: publish al...
642
643
  	.sysfs_ops = &kobj_sysfs_ops,
  	.release = space_info_release,
7c7e30140   Kimberly Brown   btrfs: sysfs: Rep...
644
  	.default_groups = space_info_groups,
6ab0a2029   Jeff Mahoney   btrfs: publish al...
645
646
647
  };
  
  static const struct attribute *allocation_attrs[] = {
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
648
649
  	BTRFS_ATTR_PTR(allocation, global_rsv_reserved),
  	BTRFS_ATTR_PTR(allocation, global_rsv_size),
6ab0a2029   Jeff Mahoney   btrfs: publish al...
650
651
  	NULL,
  };
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
652
653
654
655
  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...
656
  	char *label = fs_info->super_copy->label;
ee17fc800   David Sterba   btrfs: sysfs: pro...
657
658
659
  	ssize_t ret;
  
  	spin_lock(&fs_info->super_lock);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
660
661
  	ret = scnprintf(buf, PAGE_SIZE, label[0] ? "%s
  " : "%s", label);
ee17fc800   David Sterba   btrfs: sysfs: pro...
662
663
664
  	spin_unlock(&fs_info->super_lock);
  
  	return ret;
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
665
666
667
668
669
670
671
  }
  
  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...
672
  	size_t p_len;
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
673

66ac9fe7b   David Sterba   btrfs: add check ...
674
675
  	if (!fs_info)
  		return -EPERM;
bc98a42c1   David Howells   VFS: Convert sb->...
676
  	if (sb_rdonly(fs_info->sb))
79aec2b80   Anand Jain   btrfs: sysfs labe...
677
  		return -EROFS;
48fcc3ff7   Satoru Takeuchi   btrfs: label shou...
678
679
680
681
682
683
684
685
686
  	/*
  	 * 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...
687
  		return -EINVAL;
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
688

a6f69dc80   David Sterba   btrfs: move commi...
689
  	spin_lock(&fs_info->super_lock);
48fcc3ff7   Satoru Takeuchi   btrfs: label shou...
690
691
  	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...
692
  	spin_unlock(&fs_info->super_lock);
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
693

a6f69dc80   David Sterba   btrfs: move commi...
694
695
696
697
698
  	/*
  	 * 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...
699

a6f69dc80   David Sterba   btrfs: move commi...
700
  	return len;
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
701
  }
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
702
  BTRFS_ATTR_RW(, label, btrfs_label_show, btrfs_label_store);
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
703

df93589a1   David Sterba   btrfs: export mor...
704
705
706
707
  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);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
708
709
  	return scnprintf(buf, PAGE_SIZE, "%u
  ", fs_info->super_copy->nodesize);
df93589a1   David Sterba   btrfs: export mor...
710
  }
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
711
  BTRFS_ATTR(, nodesize, btrfs_nodesize_show);
df93589a1   David Sterba   btrfs: export mor...
712
713
714
715
716
  
  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);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
717
718
719
  	return scnprintf(buf, PAGE_SIZE, "%u
  ",
  			 fs_info->super_copy->sectorsize);
df93589a1   David Sterba   btrfs: export mor...
720
  }
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
721
  BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show);
df93589a1   David Sterba   btrfs: export mor...
722
723
724
725
726
  
  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);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
727
728
  	return scnprintf(buf, PAGE_SIZE, "%u
  ", fs_info->super_copy->sectorsize);
df93589a1   David Sterba   btrfs: export mor...
729
  }
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
730
  BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show);
df93589a1   David Sterba   btrfs: export mor...
731

2723480a0   Sargun Dhillon   btrfs: Add quota_...
732
733
734
735
736
737
738
  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);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
739
740
  	return scnprintf(buf, PAGE_SIZE, "%d
  ", quota_override);
2723480a0   Sargun Dhillon   btrfs: Add quota_...
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
  }
  
  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;
  }
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
770
  BTRFS_ATTR_RW(, quota_override, quota_override_show, quota_override_store);
2723480a0   Sargun Dhillon   btrfs: Add quota_...
771

56f20f400   Nikolay Borisov   btrfs: Add sysfs ...
772
773
774
775
  static ssize_t btrfs_metadata_uuid_show(struct kobject *kobj,
  				struct kobj_attribute *a, char *buf)
  {
  	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
776
777
  	return scnprintf(buf, PAGE_SIZE, "%pU
  ",
56f20f400   Nikolay Borisov   btrfs: Add sysfs ...
778
779
780
781
  			fs_info->fs_devices->metadata_uuid);
  }
  
  BTRFS_ATTR(, metadata_uuid, btrfs_metadata_uuid_show);
41e6d2a80   Johannes Thumshirn   btrfs: sysfs: sho...
782
783
784
785
786
  static ssize_t btrfs_checksum_show(struct kobject *kobj,
  				   struct kobj_attribute *a, char *buf)
  {
  	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
  	u16 csum_type = btrfs_super_csum_type(fs_info->super_copy);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
787
788
  	return scnprintf(buf, PAGE_SIZE, "%s (%s)
  ",
41e6d2a80   Johannes Thumshirn   btrfs: sysfs: sho...
789
790
791
792
793
  			btrfs_super_csum_name(csum_type),
  			crypto_shash_driver_name(fs_info->csum_shash));
  }
  
  BTRFS_ATTR(, checksum, btrfs_checksum_show);
66a2823c5   Goldwyn Rodrigues   btrfs: sysfs: exp...
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
  static ssize_t btrfs_exclusive_operation_show(struct kobject *kobj,
  		struct kobj_attribute *a, char *buf)
  {
  	struct btrfs_fs_info *fs_info = to_fs_info(kobj);
  	const char *str;
  
  	switch (READ_ONCE(fs_info->exclusive_operation)) {
  		case  BTRFS_EXCLOP_NONE:
  			str = "none
  ";
  			break;
  		case BTRFS_EXCLOP_BALANCE:
  			str = "balance
  ";
  			break;
  		case BTRFS_EXCLOP_DEV_ADD:
  			str = "device add
  ";
  			break;
  		case BTRFS_EXCLOP_DEV_REMOVE:
  			str = "device remove
  ";
  			break;
  		case BTRFS_EXCLOP_DEV_REPLACE:
  			str = "device replace
  ";
  			break;
  		case BTRFS_EXCLOP_RESIZE:
  			str = "resize
  ";
  			break;
  		case BTRFS_EXCLOP_SWAP_ACTIVATE:
  			str = "swap activate
  ";
  			break;
  		default:
  			str = "UNKNOWN
  ";
  			break;
  	}
  	return scnprintf(buf, PAGE_SIZE, "%s", str);
  }
  BTRFS_ATTR(, exclusive_operation, btrfs_exclusive_operation_show);
0dd2906f7   Anand Jain   Btrfs: sysfs: let...
837
  static const struct attribute *btrfs_attrs[] = {
a969f4cc1   Hans van Kranenburg   btrfs: prefix sys...
838
839
840
841
842
  	BTRFS_ATTR_PTR(, label),
  	BTRFS_ATTR_PTR(, nodesize),
  	BTRFS_ATTR_PTR(, sectorsize),
  	BTRFS_ATTR_PTR(, clone_alignment),
  	BTRFS_ATTR_PTR(, quota_override),
56f20f400   Nikolay Borisov   btrfs: Add sysfs ...
843
  	BTRFS_ATTR_PTR(, metadata_uuid),
41e6d2a80   Johannes Thumshirn   btrfs: sysfs: sho...
844
  	BTRFS_ATTR_PTR(, checksum),
66a2823c5   Goldwyn Rodrigues   btrfs: sysfs: exp...
845
  	BTRFS_ATTR_PTR(, exclusive_operation),
f8ba9c11f   Jeff Mahoney   btrfs: publish fs...
846
847
  	NULL,
  };
c1b7e4745   Anand Jain   Btrfs: rename sup...
848
  static void btrfs_release_fsid_kobj(struct kobject *kobj)
510d73600   Jeff Mahoney   btrfs: publish pe...
849
  {
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
850
  	struct btrfs_fs_devices *fs_devs = to_fs_devs(kobj);
248d200df   Anand Jain   Btrfs: sysfs: fix...
851

c1b7e4745   Anand Jain   Btrfs: rename sup...
852
  	memset(&fs_devs->fsid_kobj, 0, sizeof(struct kobject));
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
853
  	complete(&fs_devs->kobj_unregister);
510d73600   Jeff Mahoney   btrfs: publish pe...
854
855
856
857
  }
  
  static struct kobj_type btrfs_ktype = {
  	.sysfs_ops	= &kobj_sysfs_ops,
c1b7e4745   Anand Jain   Btrfs: rename sup...
858
  	.release	= btrfs_release_fsid_kobj,
510d73600   Jeff Mahoney   btrfs: publish pe...
859
  };
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
860
861
862
863
  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...
864
  	return container_of(kobj, struct btrfs_fs_devices, fsid_kobj);
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
865
  }
510d73600   Jeff Mahoney   btrfs: publish pe...
866
867
868
869
  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...
870
  	return to_fs_devs(kobj)->fs_info;
510d73600   Jeff Mahoney   btrfs: publish pe...
871
  }
58176a960   Josef Bacik   Btrfs: Add per-ro...
872

e453d989e   Jeff Mahoney   btrfs: fix leaks ...
873
  #define NUM_FEATURE_BITS 64
6c52157fa   Tomohiro Misono   btrfs: sysfs: Use...
874
875
876
  #define BTRFS_FEATURE_NAME_MAX 13
  static char btrfs_unknown_feature_names[FEAT_MAX][NUM_FEATURE_BITS][BTRFS_FEATURE_NAME_MAX];
  static struct btrfs_feature_attr btrfs_feature_attrs[FEAT_MAX][NUM_FEATURE_BITS];
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
877

6c52157fa   Tomohiro Misono   btrfs: sysfs: Use...
878
  static const u64 supported_feature_masks[FEAT_MAX] = {
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
  	[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...
912
  				ret = sysfs_merge_group(&fs_info->fs_devices->fsid_kobj,
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
913
914
915
916
  							&agroup);
  				if (ret)
  					return ret;
  			} else
c1b7e4745   Anand Jain   Btrfs: rename sup...
917
  				sysfs_unmerge_group(&fs_info->fs_devices->fsid_kobj,
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
918
919
920
921
922
923
  						    &agroup);
  		}
  
  	}
  	return 0;
  }
2e3e12815   Anand Jain   Btrfs: sysfs: pro...
924
  static void __btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
925
  {
a013d141e   Anand Jain   btrfs: sysfs, add...
926
927
928
929
930
  	if (fs_devs->devinfo_kobj) {
  		kobject_del(fs_devs->devinfo_kobj);
  		kobject_put(fs_devs->devinfo_kobj);
  		fs_devs->devinfo_kobj = NULL;
  	}
b5501504c   Anand Jain   btrfs: sysfs, ren...
931
932
933
934
  	if (fs_devs->devices_kobj) {
  		kobject_del(fs_devs->devices_kobj);
  		kobject_put(fs_devs->devices_kobj);
  		fs_devs->devices_kobj = NULL;
aaf133051   Anand Jain   Btrfs: sysfs: reo...
935
  	}
c1b7e4745   Anand Jain   Btrfs: rename sup...
936
937
938
  	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...
939
940
  		wait_for_completion(&fs_devs->kobj_unregister);
  	}
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
941
  }
2e3e12815   Anand Jain   Btrfs: sysfs: pro...
942
  /* when fs_devs is NULL it will remove all fsid kobject */
1d1c1be37   Anand Jain   Btrfs: sysfs: btr...
943
  void btrfs_sysfs_remove_fsid(struct btrfs_fs_devices *fs_devs)
2e3e12815   Anand Jain   Btrfs: sysfs: pro...
944
945
946
947
948
949
950
  {
  	struct list_head *fs_uuids = btrfs_get_fs_uuids();
  
  	if (fs_devs) {
  		__btrfs_sysfs_remove_fsid(fs_devs);
  		return;
  	}
c4babc5e3   Anand Jain   btrfs: rename str...
951
  	list_for_each_entry(fs_devs, fs_uuids, fs_list) {
2e3e12815   Anand Jain   Btrfs: sysfs: pro...
952
953
954
  		__btrfs_sysfs_remove_fsid(fs_devs);
  	}
  }
53f8a74cb   Anand Jain   btrfs: split and ...
955
956
957
  static void btrfs_sysfs_remove_fs_devices(struct btrfs_fs_devices *fs_devices)
  {
  	struct btrfs_device *device;
30b0e4e0e   Anand Jain   btrfs: initialize...
958
  	struct btrfs_fs_devices *seed;
53f8a74cb   Anand Jain   btrfs: split and ...
959
960
961
  
  	list_for_each_entry(device, &fs_devices->devices, dev_list)
  		btrfs_sysfs_remove_device(device);
30b0e4e0e   Anand Jain   btrfs: initialize...
962
963
964
965
966
  
  	list_for_each_entry(seed, &fs_devices->seed_list, seed_list) {
  		list_for_each_entry(device, &seed->devices, dev_list)
  			btrfs_sysfs_remove_device(device);
  	}
53f8a74cb   Anand Jain   btrfs: split and ...
967
  }
6618a59bf   Anand Jain   Btrfs: rename btr...
968
  void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info)
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
969
  {
3092c68fc   Nikolay Borisov   btrfs: sysfs: add...
970
  	struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj;
3092c68fc   Nikolay Borisov   btrfs: sysfs: add...
971
  	sysfs_remove_link(fsid_kobj, "bdi");
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
972
973
974
975
976
  	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);
  	}
71e8978eb   Dennis Zhou   btrfs: sysfs: add...
977
  #ifdef CONFIG_BTRFS_DEBUG
e4faab844   Dennis Zhou   btrfs: sysfs: add...
978
979
980
981
982
983
  	if (fs_info->discard_debug_kobj) {
  		sysfs_remove_files(fs_info->discard_debug_kobj,
  				   discard_debug_attrs);
  		kobject_del(fs_info->discard_debug_kobj);
  		kobject_put(fs_info->discard_debug_kobj);
  	}
93945cb43   Dennis Zhou   btrfs: sysfs: mak...
984
985
986
987
988
  	if (fs_info->debug_kobj) {
  		sysfs_remove_files(fs_info->debug_kobj, btrfs_debug_mount_attrs);
  		kobject_del(fs_info->debug_kobj);
  		kobject_put(fs_info->debug_kobj);
  	}
71e8978eb   Dennis Zhou   btrfs: sysfs: add...
989
  #endif
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
990
  	addrm_unknown_feature_attrs(fs_info, false);
3092c68fc   Nikolay Borisov   btrfs: sysfs: add...
991
992
  	sysfs_remove_group(fsid_kobj, &btrfs_feature_attr_group);
  	sysfs_remove_files(fsid_kobj, btrfs_attrs);
53f8a74cb   Anand Jain   btrfs: split and ...
993
  	btrfs_sysfs_remove_fs_devices(fs_info->fs_devices);
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
994
  }
f10152bcc   David Sterba   btrfs: sysfs: rep...
995
  static const char * const btrfs_feature_set_names[FEAT_MAX] = {
79da4fa4d   Jeff Mahoney   btrfs: publish un...
996
997
998
999
  	[FEAT_COMPAT]	 = "compat",
  	[FEAT_COMPAT_RO] = "compat_ro",
  	[FEAT_INCOMPAT]	 = "incompat",
  };
9e6df7ced   David Sterba   btrfs: remove con...
1000
  const char *btrfs_feature_set_name(enum btrfs_feature_set set)
f10152bcc   David Sterba   btrfs: sysfs: rep...
1001
1002
1003
  {
  	return btrfs_feature_set_names[set];
  }
3b02a68a6   Jeff Mahoney   btrfs: use featur...
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
  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;
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
1022
  		len += scnprintf(str + len, bufsize - len, "%s%s",
3b02a68a6   Jeff Mahoney   btrfs: use featur...
1023
1024
1025
1026
1027
  				len ? "," : "", name);
  	}
  
  	return str;
  }
79da4fa4d   Jeff Mahoney   btrfs: publish un...
1028
1029
1030
1031
1032
1033
1034
1035
1036
  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...
1037
1038
1039
  	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...
1040
1041
1042
  	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...
1043
  		int bit;
79da4fa4d   Jeff Mahoney   btrfs: publish un...
1044
  		sfa = attr_to_btrfs_feature_attr(a);
3b02a68a6   Jeff Mahoney   btrfs: use featur...
1045
1046
  		bit = ilog2(sfa->feature_bit);
  		fa = &btrfs_feature_attrs[sfa->feature_set][bit];
79da4fa4d   Jeff Mahoney   btrfs: publish un...
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
  
  		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;
6c52157fa   Tomohiro Misono   btrfs: sysfs: Use...
1058
  			snprintf(name, BTRFS_FEATURE_NAME_MAX, "%s:%u",
79da4fa4d   Jeff Mahoney   btrfs: publish un...
1059
1060
1061
1062
1063
1064
1065
1066
1067
  				 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;
  		}
  	}
  }
32a9991f1   David Sterba   btrfs: factor sys...
1068
1069
1070
1071
  /*
   * Create a sysfs entry for a given block group type at path
   * /sys/fs/btrfs/UUID/allocation/data/TYPE
   */
32da5386d   David Sterba   btrfs: rename btr...
1072
  void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache)
32a9991f1   David Sterba   btrfs: factor sys...
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
  {
  	struct btrfs_fs_info *fs_info = cache->fs_info;
  	struct btrfs_space_info *space_info = cache->space_info;
  	struct raid_kobject *rkobj;
  	const int index = btrfs_bg_flags_to_raid_index(cache->flags);
  	unsigned int nofs_flag;
  	int ret;
  
  	/*
  	 * Setup a NOFS context because kobject_add(), deep in its call chain,
  	 * does GFP_KERNEL allocations, and we are often called in a context
  	 * where if reclaim is triggered we can deadlock (we are either holding
  	 * a transaction handle or some lock required for a transaction
  	 * commit).
  	 */
  	nofs_flag = memalloc_nofs_save();
  
  	rkobj = kzalloc(sizeof(*rkobj), GFP_NOFS);
  	if (!rkobj) {
  		memalloc_nofs_restore(nofs_flag);
  		btrfs_warn(cache->fs_info,
  				"couldn't alloc memory for raid level kobject");
  		return;
  	}
  
  	rkobj->flags = cache->flags;
  	kobject_init(&rkobj->kobj, &btrfs_raid_ktype);
49ea112da   Josef Bacik   btrfs: do not cre...
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
  
  	/*
  	 * We call this either on mount, or if we've created a block group for a
  	 * new index type while running (i.e. when restriping).  The running
  	 * case is tricky because we could race with other threads, so we need
  	 * to have this check to make sure we didn't already init the kobject.
  	 *
  	 * We don't have to protect on the free side because it only happens on
  	 * unmount.
  	 */
  	spin_lock(&space_info->lock);
  	if (space_info->block_group_kobjs[index]) {
  		spin_unlock(&space_info->lock);
  		kobject_put(&rkobj->kobj);
  		return;
  	} else {
  		space_info->block_group_kobjs[index] = &rkobj->kobj;
  	}
  	spin_unlock(&space_info->lock);
32a9991f1   David Sterba   btrfs: factor sys...
1119
1120
1121
1122
  	ret = kobject_add(&rkobj->kobj, &space_info->kobj, "%s",
  			  btrfs_bg_type_to_raid_name(rkobj->flags));
  	memalloc_nofs_restore(nofs_flag);
  	if (ret) {
49ea112da   Josef Bacik   btrfs: do not cre...
1123
1124
1125
  		spin_lock(&space_info->lock);
  		space_info->block_group_kobjs[index] = NULL;
  		spin_unlock(&space_info->lock);
32a9991f1   David Sterba   btrfs: factor sys...
1126
1127
1128
1129
1130
  		kobject_put(&rkobj->kobj);
  		btrfs_warn(fs_info,
  			"failed to add kobject for block cache, ignoring");
  		return;
  	}
32a9991f1   David Sterba   btrfs: factor sys...
1131
  }
b5865babb   David Sterba   btrfs: factor out...
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
  /*
   * Remove sysfs directories for all block group types of a given space info and
   * the space info as well
   */
  void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info)
  {
  	int i;
  
  	for (i = 0; i < BTRFS_NR_RAID_TYPES; i++) {
  		struct kobject *kobj;
  
  		kobj = space_info->block_group_kobjs[i];
  		space_info->block_group_kobjs[i] = NULL;
  		if (kobj) {
  			kobject_del(kobj);
  			kobject_put(kobj);
  		}
  	}
  	kobject_del(&space_info->kobj);
  	kobject_put(&space_info->kobj);
  }
b882327a7   David Sterba   btrfs: factor out...
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
  static const char *alloc_name(u64 flags)
  {
  	switch (flags) {
  	case BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA:
  		return "mixed";
  	case BTRFS_BLOCK_GROUP_METADATA:
  		return "metadata";
  	case BTRFS_BLOCK_GROUP_DATA:
  		return "data";
  	case BTRFS_BLOCK_GROUP_SYSTEM:
  		return "system";
  	default:
  		WARN_ON(1);
  		return "invalid-combination";
  	};
  }
  
  /*
   * Create a sysfs entry for a space info type at path
   * /sys/fs/btrfs/UUID/allocation/TYPE
   */
  int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info,
  				    struct btrfs_space_info *space_info)
  {
  	int ret;
  
  	ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype,
  				   fs_info->space_info_kobj, "%s",
  				   alloc_name(space_info->flags));
  	if (ret) {
  		kobject_put(&space_info->kobj);
  		return ret;
  	}
  
  	return 0;
  }
53f8a74cb   Anand Jain   btrfs: split and ...
1189
  void btrfs_sysfs_remove_device(struct btrfs_device *device)
99994cde9   Anand Jain   btrfs: dev delete...
1190
1191
1192
  {
  	struct hd_struct *disk;
  	struct kobject *disk_kobj;
985e233e9   Anand Jain   btrfs: add btrfs_...
1193
  	struct kobject *devices_kobj;
99994cde9   Anand Jain   btrfs: dev delete...
1194

985e233e9   Anand Jain   btrfs: add btrfs_...
1195
1196
1197
1198
1199
1200
  	/*
  	 * Seed fs_devices devices_kobj aren't used, fetch kobject from the
  	 * fs_info::fs_devices.
  	 */
  	devices_kobj = device->fs_info->fs_devices->devices_kobj;
  	ASSERT(devices_kobj);
99994cde9   Anand Jain   btrfs: dev delete...
1201

985e233e9   Anand Jain   btrfs: add btrfs_...
1202
1203
1204
1205
1206
  	if (device->bdev) {
  		disk = device->bdev->bd_part;
  		disk_kobj = &part_to_dev(disk)->kobj;
  		sysfs_remove_link(devices_kobj, disk_kobj->name);
  	}
668e48af7   Anand Jain   btrfs: sysfs, add...
1207

985e233e9   Anand Jain   btrfs: add btrfs_...
1208
1209
1210
1211
1212
1213
  	if (device->devid_kobj.state_initialized) {
  		kobject_del(&device->devid_kobj);
  		kobject_put(&device->devid_kobj);
  		wait_for_completion(&device->kobj_unregister);
  	}
  }
99994cde9   Anand Jain   btrfs: dev delete...
1214

668e48af7   Anand Jain   btrfs: sysfs, add...
1215
1216
1217
1218
1219
1220
1221
1222
1223
  static ssize_t btrfs_devinfo_in_fs_metadata_show(struct kobject *kobj,
  					         struct kobj_attribute *a,
  					         char *buf)
  {
  	int val;
  	struct btrfs_device *device = container_of(kobj, struct btrfs_device,
  						   devid_kobj);
  
  	val = !!test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
1224
1225
  	return scnprintf(buf, PAGE_SIZE, "%d
  ", val);
668e48af7   Anand Jain   btrfs: sysfs, add...
1226
1227
  }
  BTRFS_ATTR(devid, in_fs_metadata, btrfs_devinfo_in_fs_metadata_show);
25864778b   Anand Jain   btrfs: sysfs, uni...
1228
  static ssize_t btrfs_devinfo_missing_show(struct kobject *kobj,
668e48af7   Anand Jain   btrfs: sysfs, add...
1229
1230
1231
1232
1233
1234
1235
  					struct kobj_attribute *a, char *buf)
  {
  	int val;
  	struct btrfs_device *device = container_of(kobj, struct btrfs_device,
  						   devid_kobj);
  
  	val = !!test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
1236
1237
  	return scnprintf(buf, PAGE_SIZE, "%d
  ", val);
668e48af7   Anand Jain   btrfs: sysfs, add...
1238
  }
25864778b   Anand Jain   btrfs: sysfs, uni...
1239
  BTRFS_ATTR(devid, missing, btrfs_devinfo_missing_show);
668e48af7   Anand Jain   btrfs: sysfs, add...
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
  
  static ssize_t btrfs_devinfo_replace_target_show(struct kobject *kobj,
  					         struct kobj_attribute *a,
  					         char *buf)
  {
  	int val;
  	struct btrfs_device *device = container_of(kobj, struct btrfs_device,
  						   devid_kobj);
  
  	val = !!test_bit(BTRFS_DEV_STATE_REPLACE_TGT, &device->dev_state);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
1250
1251
  	return scnprintf(buf, PAGE_SIZE, "%d
  ", val);
668e48af7   Anand Jain   btrfs: sysfs, add...
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
  }
  BTRFS_ATTR(devid, replace_target, btrfs_devinfo_replace_target_show);
  
  static ssize_t btrfs_devinfo_writeable_show(struct kobject *kobj,
  					    struct kobj_attribute *a, char *buf)
  {
  	int val;
  	struct btrfs_device *device = container_of(kobj, struct btrfs_device,
  						   devid_kobj);
  
  	val = !!test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state);
abdd9feb4   Takashi Iwai   btrfs: sysfs: Use...
1263
1264
  	return scnprintf(buf, PAGE_SIZE, "%d
  ", val);
668e48af7   Anand Jain   btrfs: sysfs, add...
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
  }
  BTRFS_ATTR(devid, writeable, btrfs_devinfo_writeable_show);
  
  static struct attribute *devid_attrs[] = {
  	BTRFS_ATTR_PTR(devid, in_fs_metadata),
  	BTRFS_ATTR_PTR(devid, missing),
  	BTRFS_ATTR_PTR(devid, replace_target),
  	BTRFS_ATTR_PTR(devid, writeable),
  	NULL
  };
  ATTRIBUTE_GROUPS(devid);
  
  static void btrfs_release_devid_kobj(struct kobject *kobj)
  {
  	struct btrfs_device *device = container_of(kobj, struct btrfs_device,
  						   devid_kobj);
  
  	memset(&device->devid_kobj, 0, sizeof(struct kobject));
  	complete(&device->kobj_unregister);
  }
  
  static struct kobj_type devid_ktype = {
  	.sysfs_ops	= &kobj_sysfs_ops,
  	.default_groups = devid_groups,
  	.release	= btrfs_release_devid_kobj,
  };
cd36da2e7   Anand Jain   btrfs: simplify p...
1291
  int btrfs_sysfs_add_device(struct btrfs_device *device)
00c921c23   Anand Jain   Btrfs: sysfs: sep...
1292
  {
178a16c94   Anand Jain   btrfs: add btrfs_...
1293
  	int ret;
a47bd78d0   Josef Bacik   btrfs: sysfs: use...
1294
  	unsigned int nofs_flag;
178a16c94   Anand Jain   btrfs: add btrfs_...
1295
1296
  	struct kobject *devices_kobj;
  	struct kobject *devinfo_kobj;
00c921c23   Anand Jain   Btrfs: sysfs: sep...
1297

178a16c94   Anand Jain   btrfs: add btrfs_...
1298
1299
1300
1301
1302
1303
1304
1305
  	/*
  	 * Make sure we use the fs_info::fs_devices to fetch the kobjects even
  	 * for the seed fs_devices
  	 */
  	devices_kobj = device->fs_info->fs_devices->devices_kobj;
  	devinfo_kobj = device->fs_info->fs_devices->devinfo_kobj;
  	ASSERT(devices_kobj);
  	ASSERT(devinfo_kobj);
f085381e6   Anand Jain   btrfs: fix null p...
1306

178a16c94   Anand Jain   btrfs: add btrfs_...
1307
  	nofs_flag = memalloc_nofs_save();
0d39376aa   Anand Jain   btrfs: dev add sh...
1308

178a16c94   Anand Jain   btrfs: add btrfs_...
1309
1310
1311
  	if (device->bdev) {
  		struct hd_struct *disk;
  		struct kobject *disk_kobj;
668e48af7   Anand Jain   btrfs: sysfs, add...
1312

178a16c94   Anand Jain   btrfs: add btrfs_...
1313
1314
  		disk = device->bdev->bd_part;
  		disk_kobj = &part_to_dev(disk)->kobj;
668e48af7   Anand Jain   btrfs: sysfs, add...
1315

178a16c94   Anand Jain   btrfs: add btrfs_...
1316
1317
1318
1319
1320
1321
  		ret = sysfs_create_link(devices_kobj, disk_kobj, disk_kobj->name);
  		if (ret) {
  			btrfs_warn(device->fs_info,
  				"creating sysfs device link for devid %llu failed: %d",
  				device->devid, ret);
  			goto out;
668e48af7   Anand Jain   btrfs: sysfs, add...
1322
  		}
178a16c94   Anand Jain   btrfs: add btrfs_...
1323
  	}
29e5be240   Jeff Mahoney   btrfs: publish de...
1324

178a16c94   Anand Jain   btrfs: add btrfs_...
1325
1326
1327
1328
1329
1330
1331
1332
  	init_completion(&device->kobj_unregister);
  	ret = kobject_init_and_add(&device->devid_kobj, &devid_ktype,
  				   devinfo_kobj, "%llu", device->devid);
  	if (ret) {
  		kobject_put(&device->devid_kobj);
  		btrfs_warn(device->fs_info,
  			   "devinfo init for devid %llu failed: %d",
  			   device->devid, ret);
29e5be240   Jeff Mahoney   btrfs: publish de...
1333
  	}
178a16c94   Anand Jain   btrfs: add btrfs_...
1334
1335
  
  out:
a47bd78d0   Josef Bacik   btrfs: sysfs: use...
1336
  	memalloc_nofs_restore(nofs_flag);
178a16c94   Anand Jain   btrfs: add btrfs_...
1337
1338
  	return ret;
  }
29e5be240   Jeff Mahoney   btrfs: publish de...
1339

cd36da2e7   Anand Jain   btrfs: simplify p...
1340
  static int btrfs_sysfs_add_fs_devices(struct btrfs_fs_devices *fs_devices)
178a16c94   Anand Jain   btrfs: add btrfs_...
1341
1342
  {
  	int ret;
cd36da2e7   Anand Jain   btrfs: simplify p...
1343
  	struct btrfs_device *device;
30b0e4e0e   Anand Jain   btrfs: initialize...
1344
  	struct btrfs_fs_devices *seed;
178a16c94   Anand Jain   btrfs: add btrfs_...
1345
1346
1347
1348
  
  	list_for_each_entry(device, &fs_devices->devices, dev_list) {
  		ret = btrfs_sysfs_add_device(device);
  		if (ret)
7ad3912a7   Anand Jain   btrfs: handle err...
1349
  			goto fail;
178a16c94   Anand Jain   btrfs: add btrfs_...
1350
  	}
30b0e4e0e   Anand Jain   btrfs: initialize...
1351
1352
1353
1354
  	list_for_each_entry(seed, &fs_devices->seed_list, seed_list) {
  		list_for_each_entry(device, &seed->devices, dev_list) {
  			ret = btrfs_sysfs_add_device(device);
  			if (ret)
7ad3912a7   Anand Jain   btrfs: handle err...
1355
  				goto fail;
30b0e4e0e   Anand Jain   btrfs: initialize...
1356
1357
  		}
  	}
178a16c94   Anand Jain   btrfs: add btrfs_...
1358
  	return 0;
7ad3912a7   Anand Jain   btrfs: handle err...
1359
1360
1361
1362
  
  fail:
  	btrfs_sysfs_remove_fs_devices(fs_devices);
  	return ret;
29e5be240   Jeff Mahoney   btrfs: publish de...
1363
  }
5b28692e0   David Sterba   btrfs: factor out...
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
  void btrfs_kobject_uevent(struct block_device *bdev, enum kobject_action action)
  {
  	int ret;
  
  	ret = kobject_uevent(&disk_to_dev(bdev->bd_disk)->kobj, action);
  	if (ret)
  		pr_warn("BTRFS: Sending event '%d' to kobject: '%s' (%p): failed
  ",
  			action, kobject_name(&disk_to_dev(bdev->bd_disk)->kobj),
  			&disk_to_dev(bdev->bd_disk)->kobj);
  }
8e5600818   Nikolay Borisov   btrfs: remove fsi...
1375
  void btrfs_sysfs_update_sprout_fsid(struct btrfs_fs_devices *fs_devices)
f93c39970   David Sterba   btrfs: factor out...
1376
1377
1378
1379
1380
1381
1382
  {
  	char fsid_buf[BTRFS_UUID_UNPARSED_SIZE];
  
  	/*
  	 * Sprouting changes fsid of the mounted filesystem, rename the fsid
  	 * directory
  	 */
8e5600818   Nikolay Borisov   btrfs: remove fsi...
1383
  	snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU", fs_devices->fsid);
f93c39970   David Sterba   btrfs: factor out...
1384
1385
1386
1387
  	if (kobject_rename(&fs_devices->fsid_kobj, fsid_buf))
  		btrfs_warn(fs_devices->fs_info,
  				"sysfs: failed to create fsid for sprout");
  }
668e48af7   Anand Jain   btrfs: sysfs, add...
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
  void btrfs_sysfs_update_devid(struct btrfs_device *device)
  {
  	char tmp[24];
  
  	snprintf(tmp, sizeof(tmp), "%llu", device->devid);
  
  	if (kobject_rename(&device->devid_kobj, tmp))
  		btrfs_warn(device->fs_devices->fs_info,
  			   "sysfs: failed to update devid for %llu",
  			   device->devid);
  }
510d73600   Jeff Mahoney   btrfs: publish pe...
1399
1400
  /* /sys/fs/btrfs/ entry */
  static struct kset *btrfs_kset;
720592157   Anand Jain   Btrfs: sysfs: int...
1401
  /*
c6761a9ed   Anand Jain   btrfs: sysfs, btr...
1402
1403
1404
   * Creates:
   *		/sys/fs/btrfs/UUID
   *
720592157   Anand Jain   Btrfs: sysfs: int...
1405
   * Can be called by the device discovery thread.
720592157   Anand Jain   Btrfs: sysfs: int...
1406
   */
c6761a9ed   Anand Jain   btrfs: sysfs, btr...
1407
  int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs)
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
1408
1409
  {
  	int error;
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
1410
  	init_completion(&fs_devs->kobj_unregister);
c1b7e4745   Anand Jain   Btrfs: rename sup...
1411
  	fs_devs->fsid_kobj.kset = btrfs_kset;
c6761a9ed   Anand Jain   btrfs: sysfs, btr...
1412
1413
  	error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, NULL,
  				     "%pU", fs_devs->fsid);
e32773357   Tobin C. Harding   btrfs: sysfs: don...
1414
1415
1416
1417
  	if (error) {
  		kobject_put(&fs_devs->fsid_kobj);
  		return error;
  	}
bc036bb33   Anand Jain   btrfs: sysfs, mer...
1418
1419
1420
1421
1422
  	fs_devs->devices_kobj = kobject_create_and_add("devices",
  						       &fs_devs->fsid_kobj);
  	if (!fs_devs->devices_kobj) {
  		btrfs_err(fs_devs->fs_info,
  			  "failed to init sysfs device interface");
1f6087e69   Anand Jain   btrfs: sysfs, use...
1423
  		btrfs_sysfs_remove_fsid(fs_devs);
bc036bb33   Anand Jain   btrfs: sysfs, mer...
1424
1425
  		return -ENOMEM;
  	}
a013d141e   Anand Jain   btrfs: sysfs, add...
1426
1427
1428
1429
1430
1431
1432
1433
  	fs_devs->devinfo_kobj = kobject_create_and_add("devinfo",
  						       &fs_devs->fsid_kobj);
  	if (!fs_devs->devinfo_kobj) {
  		btrfs_err(fs_devs->fs_info,
  			  "failed to init sysfs devinfo kobject");
  		btrfs_sysfs_remove_fsid(fs_devs);
  		return -ENOMEM;
  	}
e32773357   Tobin C. Harding   btrfs: sysfs: don...
1434
  	return 0;
720592157   Anand Jain   Btrfs: sysfs: int...
1435
  }
96f3136e5   Anand Jain   Btrfs: rename btr...
1436
  int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info)
720592157   Anand Jain   Btrfs: sysfs: int...
1437
1438
  {
  	int error;
2e7910d6c   Anand Jain   Btrfs: sysfs: mov...
1439
  	struct btrfs_fs_devices *fs_devs = fs_info->fs_devices;
c1b7e4745   Anand Jain   Btrfs: rename sup...
1440
  	struct kobject *fsid_kobj = &fs_devs->fsid_kobj;
720592157   Anand Jain   Btrfs: sysfs: int...
1441

cd36da2e7   Anand Jain   btrfs: simplify p...
1442
  	error = btrfs_sysfs_add_fs_devices(fs_devs);
b7c35e81a   Anand Jain   Btrfs: sysfs: sep...
1443
  	if (error)
aaf133051   Anand Jain   Btrfs: sysfs: reo...
1444
  		return error;
aaf133051   Anand Jain   Btrfs: sysfs: reo...
1445

c1b7e4745   Anand Jain   Btrfs: rename sup...
1446
  	error = sysfs_create_files(fsid_kobj, btrfs_attrs);
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
1447
  	if (error) {
53f8a74cb   Anand Jain   btrfs: split and ...
1448
  		btrfs_sysfs_remove_fs_devices(fs_devs);
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
1449
1450
  		return error;
  	}
79da4fa4d   Jeff Mahoney   btrfs: publish un...
1451

c1b7e4745   Anand Jain   Btrfs: rename sup...
1452
  	error = sysfs_create_group(fsid_kobj,
0dd2906f7   Anand Jain   Btrfs: sysfs: let...
1453
1454
1455
  				   &btrfs_feature_attr_group);
  	if (error)
  		goto failure;
6e369febb   David Sterba   btrfs: sysfs: add...
1456
  #ifdef CONFIG_BTRFS_DEBUG
93945cb43   Dennis Zhou   btrfs: sysfs: mak...
1457
1458
1459
1460
1461
1462
1463
  	fs_info->debug_kobj = kobject_create_and_add("debug", fsid_kobj);
  	if (!fs_info->debug_kobj) {
  		error = -ENOMEM;
  		goto failure;
  	}
  
  	error = sysfs_create_files(fs_info->debug_kobj, btrfs_debug_mount_attrs);
6e369febb   David Sterba   btrfs: sysfs: add...
1464
1465
  	if (error)
  		goto failure;
e4faab844   Dennis Zhou   btrfs: sysfs: add...
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
  
  	/* Discard directory */
  	fs_info->discard_debug_kobj = kobject_create_and_add("discard",
  						     fs_info->debug_kobj);
  	if (!fs_info->discard_debug_kobj) {
  		error = -ENOMEM;
  		goto failure;
  	}
  
  	error = sysfs_create_files(fs_info->discard_debug_kobj,
  				   discard_debug_attrs);
  	if (error)
  		goto failure;
6e369febb   David Sterba   btrfs: sysfs: add...
1479
  #endif
e453d989e   Jeff Mahoney   btrfs: fix leaks ...
1480
  	error = addrm_unknown_feature_attrs(fs_info, true);
79da4fa4d   Jeff Mahoney   btrfs: publish un...
1481
1482
  	if (error)
  		goto failure;
3092c68fc   Nikolay Borisov   btrfs: sysfs: add...
1483
1484
1485
  	error = sysfs_create_link(fsid_kobj, &fs_info->sb->s_bdi->dev->kobj, "bdi");
  	if (error)
  		goto failure;
6ab0a2029   Jeff Mahoney   btrfs: publish al...
1486
  	fs_info->space_info_kobj = kobject_create_and_add("allocation",
c1b7e4745   Anand Jain   Btrfs: rename sup...
1487
  						  fsid_kobj);
6ab0a2029   Jeff Mahoney   btrfs: publish al...
1488
1489
1490
1491
1492
1493
1494
1495
  	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...
1496
1497
  	return 0;
  failure:
6618a59bf   Anand Jain   Btrfs: rename btr...
1498
  	btrfs_sysfs_remove_mounted(fs_info);
5ac1d209f   Jeff Mahoney   btrfs: publish pe...
1499
1500
  	return error;
  }
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
  static inline struct btrfs_fs_info *qgroup_kobj_to_fs_info(struct kobject *kobj)
  {
  	return to_fs_info(kobj->parent->parent);
  }
  
  #define QGROUP_ATTR(_member, _show_name)					\
  static ssize_t btrfs_qgroup_show_##_member(struct kobject *qgroup_kobj,		\
  					   struct kobj_attribute *a,		\
  					   char *buf)				\
  {										\
  	struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj);	\
  	struct btrfs_qgroup *qgroup = container_of(qgroup_kobj,			\
  			struct btrfs_qgroup, kobj);				\
  	return btrfs_show_u64(&qgroup->_member, &fs_info->qgroup_lock, buf);	\
  }										\
  BTRFS_ATTR(qgroup, _show_name, btrfs_qgroup_show_##_member)
  
  #define QGROUP_RSV_ATTR(_name, _type)						\
  static ssize_t btrfs_qgroup_rsv_show_##_name(struct kobject *qgroup_kobj,	\
  					     struct kobj_attribute *a,		\
  					     char *buf)				\
  {										\
  	struct btrfs_fs_info *fs_info = qgroup_kobj_to_fs_info(qgroup_kobj);	\
  	struct btrfs_qgroup *qgroup = container_of(qgroup_kobj,			\
  			struct btrfs_qgroup, kobj);				\
  	return btrfs_show_u64(&qgroup->rsv.values[_type],			\
  			&fs_info->qgroup_lock, buf);				\
  }										\
  BTRFS_ATTR(qgroup, rsv_##_name, btrfs_qgroup_rsv_show_##_name)
  
  QGROUP_ATTR(rfer, referenced);
  QGROUP_ATTR(excl, exclusive);
  QGROUP_ATTR(max_rfer, max_referenced);
  QGROUP_ATTR(max_excl, max_exclusive);
  QGROUP_ATTR(lim_flags, limit_flags);
  QGROUP_RSV_ATTR(data, BTRFS_QGROUP_RSV_DATA);
  QGROUP_RSV_ATTR(meta_pertrans, BTRFS_QGROUP_RSV_META_PERTRANS);
  QGROUP_RSV_ATTR(meta_prealloc, BTRFS_QGROUP_RSV_META_PREALLOC);
  
  static struct attribute *qgroup_attrs[] = {
  	BTRFS_ATTR_PTR(qgroup, referenced),
  	BTRFS_ATTR_PTR(qgroup, exclusive),
  	BTRFS_ATTR_PTR(qgroup, max_referenced),
  	BTRFS_ATTR_PTR(qgroup, max_exclusive),
  	BTRFS_ATTR_PTR(qgroup, limit_flags),
  	BTRFS_ATTR_PTR(qgroup, rsv_data),
  	BTRFS_ATTR_PTR(qgroup, rsv_meta_pertrans),
  	BTRFS_ATTR_PTR(qgroup, rsv_meta_prealloc),
  	NULL
  };
  ATTRIBUTE_GROUPS(qgroup);
  
  static void qgroup_release(struct kobject *kobj)
  {
  	struct btrfs_qgroup *qgroup = container_of(kobj, struct btrfs_qgroup, kobj);
  
  	memset(&qgroup->kobj, 0, sizeof(*kobj));
  }
  
  static struct kobj_type qgroup_ktype = {
  	.sysfs_ops = &kobj_sysfs_ops,
  	.release = qgroup_release,
  	.default_groups = qgroup_groups,
  };
  
  int btrfs_sysfs_add_one_qgroup(struct btrfs_fs_info *fs_info,
  				struct btrfs_qgroup *qgroup)
  {
  	struct kobject *qgroups_kobj = fs_info->qgroups_kobj;
  	int ret;
  
  	if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state))
  		return 0;
  	if (qgroup->kobj.state_initialized)
  		return 0;
  	if (!qgroups_kobj)
  		return -EINVAL;
  
  	ret = kobject_init_and_add(&qgroup->kobj, &qgroup_ktype, qgroups_kobj,
  			"%hu_%llu", btrfs_qgroup_level(qgroup->qgroupid),
  			btrfs_qgroup_subvolid(qgroup->qgroupid));
  	if (ret < 0)
  		kobject_put(&qgroup->kobj);
  
  	return ret;
  }
  
  void btrfs_sysfs_del_qgroups(struct btrfs_fs_info *fs_info)
  {
  	struct btrfs_qgroup *qgroup;
  	struct btrfs_qgroup *next;
  
  	if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state))
  		return;
  
  	rbtree_postorder_for_each_entry_safe(qgroup, next,
  					     &fs_info->qgroup_tree, node)
  		btrfs_sysfs_del_one_qgroup(fs_info, qgroup);
62ab2cc04   Qu Wenruo   btrfs: sysfs: fix...
1599
1600
1601
1602
1603
  	if (fs_info->qgroups_kobj) {
  		kobject_del(fs_info->qgroups_kobj);
  		kobject_put(fs_info->qgroups_kobj);
  		fs_info->qgroups_kobj = NULL;
  	}
49e5fb462   Qu Wenruo   btrfs: qgroup: ex...
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
  }
  
  /* Called when qgroups get initialized, thus there is no need for locking */
  int btrfs_sysfs_add_qgroups(struct btrfs_fs_info *fs_info)
  {
  	struct kobject *fsid_kobj = &fs_info->fs_devices->fsid_kobj;
  	struct btrfs_qgroup *qgroup;
  	struct btrfs_qgroup *next;
  	int ret = 0;
  
  	if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state))
  		return 0;
  
  	ASSERT(fsid_kobj);
  	if (fs_info->qgroups_kobj)
  		return 0;
  
  	fs_info->qgroups_kobj = kobject_create_and_add("qgroups", fsid_kobj);
  	if (!fs_info->qgroups_kobj) {
  		ret = -ENOMEM;
  		goto out;
  	}
  	rbtree_postorder_for_each_entry_safe(qgroup, next,
  					     &fs_info->qgroup_tree, node) {
  		ret = btrfs_sysfs_add_one_qgroup(fs_info, qgroup);
  		if (ret < 0)
  			goto out;
  	}
  
  out:
  	if (ret < 0)
  		btrfs_sysfs_del_qgroups(fs_info);
  	return ret;
  }
  
  void btrfs_sysfs_del_one_qgroup(struct btrfs_fs_info *fs_info,
  				struct btrfs_qgroup *qgroup)
  {
  	if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &fs_info->fs_state))
  		return;
  
  	if (qgroup->kobj.state_initialized) {
  		kobject_del(&qgroup->kobj);
  		kobject_put(&qgroup->kobj);
  	}
  }
444e75169   David Sterba   btrfs: sysfs: int...
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
  
  /*
   * 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;
24646481f   Leon Romanovsky   btrfs: sysfs: fix...
1660
1661
  	u64 __maybe_unused features;
  	int __maybe_unused ret;
444e75169   David Sterba   btrfs: sysfs: int...
1662
1663
1664
  
  	if (!fs_info)
  		return;
24646481f   Leon Romanovsky   btrfs: sysfs: fix...
1665
1666
1667
1668
  	/*
  	 * See 14e46e04958df74 and e410e34fad913dd, feature bit updates are not
  	 * safe when called from some contexts (eg. balance)
  	 */
444e75169   David Sterba   btrfs: sysfs: int...
1669
1670
1671
1672
1673
  	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...
1674
1675
  	if (!fsid_kobj->state_initialized)
  		return;
444e75169   David Sterba   btrfs: sysfs: int...
1676
1677
1678
1679
1680
1681
1682
  	/*
  	 * 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);
  }
f5c29bd9d   Liu Bo   Btrfs: add __init...
1683
  int __init btrfs_init_sysfs(void)
58176a960   Josef Bacik   Btrfs: Add per-ro...
1684
  {
079b72bca   Jeff Mahoney   btrfs: publish su...
1685
  	int ret;
1bae30982   David Sterba   btrfs: add simple...
1686

e3fe4e712   Greg Kroah-Hartman   btrfs: fixes for ...
1687
1688
1689
  	btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
  	if (!btrfs_kset)
  		return -ENOMEM;
079b72bca   Jeff Mahoney   btrfs: publish su...
1690

1bae30982   David Sterba   btrfs: add simple...
1691
  	init_feature_attrs();
079b72bca   Jeff Mahoney   btrfs: publish su...
1692
  	ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
001a648df   Filipe Manana   Btrfs: add missin...
1693
1694
  	if (ret)
  		goto out2;
f902bd3a5   Misono Tomohiro   btrfs: sysfs: Add...
1695
1696
1697
1698
  	ret = sysfs_merge_group(&btrfs_kset->kobj,
  				&btrfs_static_feature_attr_group);
  	if (ret)
  		goto out_remove_group;
001a648df   Filipe Manana   Btrfs: add missin...
1699

6e369febb   David Sterba   btrfs: sysfs: add...
1700
1701
1702
1703
1704
  #ifdef CONFIG_BTRFS_DEBUG
  	ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group);
  	if (ret)
  		goto out2;
  #endif
001a648df   Filipe Manana   Btrfs: add missin...
1705
  	return 0;
f902bd3a5   Misono Tomohiro   btrfs: sysfs: Add...
1706
1707
1708
  
  out_remove_group:
  	sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
001a648df   Filipe Manana   Btrfs: add missin...
1709
  out2:
001a648df   Filipe Manana   Btrfs: add missin...
1710
  	kset_unregister(btrfs_kset);
079b72bca   Jeff Mahoney   btrfs: publish su...
1711

1bae30982   David Sterba   btrfs: add simple...
1712
  	return ret;
58176a960   Josef Bacik   Btrfs: Add per-ro...
1713
  }
e67c718b5   David Sterba   btrfs: add more _...
1714
  void __cold btrfs_exit_sysfs(void)
58176a960   Josef Bacik   Btrfs: Add per-ro...
1715
  {
f902bd3a5   Misono Tomohiro   btrfs: sysfs: Add...
1716
1717
  	sysfs_unmerge_group(&btrfs_kset->kobj,
  			    &btrfs_static_feature_attr_group);
079b72bca   Jeff Mahoney   btrfs: publish su...
1718
  	sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
71e8978eb   Dennis Zhou   btrfs: sysfs: add...
1719
1720
1721
  #ifdef CONFIG_BTRFS_DEBUG
  	sysfs_remove_group(&btrfs_kset->kobj, &btrfs_debug_feature_attr_group);
  #endif
e3fe4e712   Greg Kroah-Hartman   btrfs: fixes for ...
1722
  	kset_unregister(btrfs_kset);
58176a960   Josef Bacik   Btrfs: Add per-ro...
1723
  }
55d474148   Chris Mason   Btrfs: Disable sy...
1724