LCOV - code coverage report
Current view: top level - fs/btrfs - sysfs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 213 0.0 %
Date: 2014-04-16 Functions: 0 31 0.0 %
Branches: 0 287 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2007 Oracle.  All rights reserved.
       3                 :            :  *
       4                 :            :  * This program is free software; you can redistribute it and/or
       5                 :            :  * modify it under the terms of the GNU General Public
       6                 :            :  * License v2 as published by the Free Software Foundation.
       7                 :            :  *
       8                 :            :  * This program is distributed in the hope that it will be useful,
       9                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      10                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      11                 :            :  * General Public License for more details.
      12                 :            :  *
      13                 :            :  * You should have received a copy of the GNU General Public
      14                 :            :  * License along with this program; if not, write to the
      15                 :            :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      16                 :            :  * Boston, MA 021110-1307, USA.
      17                 :            :  */
      18                 :            : 
      19                 :            : #include <linux/sched.h>
      20                 :            : #include <linux/slab.h>
      21                 :            : #include <linux/spinlock.h>
      22                 :            : #include <linux/completion.h>
      23                 :            : #include <linux/buffer_head.h>
      24                 :            : #include <linux/kobject.h>
      25                 :            : #include <linux/bug.h>
      26                 :            : #include <linux/genhd.h>
      27                 :            : 
      28                 :            : #include "ctree.h"
      29                 :            : #include "disk-io.h"
      30                 :            : #include "transaction.h"
      31                 :            : #include "sysfs.h"
      32                 :            : #include "volumes.h"
      33                 :            : 
      34                 :            : static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj);
      35                 :            : 
      36                 :            : static u64 get_features(struct btrfs_fs_info *fs_info,
      37                 :            :                         enum btrfs_feature_set set)
      38                 :            : {
      39                 :            :         struct btrfs_super_block *disk_super = fs_info->super_copy;
      40 [ #  # ][ #  # ]:          0 :         if (set == FEAT_COMPAT)
           [ #  #  #  # ]
                 [ #  # ]
      41                 :            :                 return btrfs_super_compat_flags(disk_super);
      42 [ #  # ][ #  # ]:          0 :         else if (set == FEAT_COMPAT_RO)
         [ #  # ][ #  # ]
                 [ #  # ]
      43                 :            :                 return btrfs_super_compat_ro_flags(disk_super);
      44                 :            :         else
      45                 :            :                 return btrfs_super_incompat_flags(disk_super);
      46                 :            : }
      47                 :            : 
      48                 :            : static void set_features(struct btrfs_fs_info *fs_info,
      49                 :            :                          enum btrfs_feature_set set, u64 features)
      50                 :            : {
      51                 :            :         struct btrfs_super_block *disk_super = fs_info->super_copy;
      52         [ #  # ]:          0 :         if (set == FEAT_COMPAT)
      53                 :            :                 btrfs_set_super_compat_flags(disk_super, features);
      54         [ #  # ]:          0 :         else if (set == FEAT_COMPAT_RO)
      55                 :            :                 btrfs_set_super_compat_ro_flags(disk_super, features);
      56                 :            :         else
      57                 :            :                 btrfs_set_super_incompat_flags(disk_super, features);
      58                 :            : }
      59                 :            : 
      60                 :          0 : static int can_modify_feature(struct btrfs_feature_attr *fa)
      61                 :            : {
      62                 :            :         int val = 0;
      63                 :            :         u64 set, clear;
      64      [ #  #  # ]:          0 :         switch (fa->feature_set) {
      65                 :            :         case FEAT_COMPAT:
      66                 :            :                 set = BTRFS_FEATURE_COMPAT_SAFE_SET;
      67                 :            :                 clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR;
      68                 :            :                 break;
      69                 :            :         case FEAT_COMPAT_RO:
      70                 :            :                 set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET;
      71                 :            :                 clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR;
      72                 :            :                 break;
      73                 :            :         case FEAT_INCOMPAT:
      74                 :            :                 set = BTRFS_FEATURE_INCOMPAT_SAFE_SET;
      75                 :            :                 clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
      76                 :            :                 break;
      77                 :            :         default:
      78                 :          0 :                 printk(KERN_WARNING "btrfs: sysfs: unknown feature set %d\n",
      79                 :            :                                 fa->feature_set);
      80                 :            :                 return 0;
      81                 :            :         }
      82                 :            : 
      83         [ #  # ]:          0 :         if (set & fa->feature_bit)
      84                 :            :                 val |= 1;
      85                 :            :         if (clear & fa->feature_bit)
      86                 :            :                 val |= 2;
      87                 :            : 
      88                 :            :         return val;
      89                 :            : }
      90                 :            : 
      91                 :          0 : static ssize_t btrfs_feature_attr_show(struct kobject *kobj,
      92                 :            :                                        struct kobj_attribute *a, char *buf)
      93                 :            : {
      94                 :            :         int val = 0;
      95                 :          0 :         struct btrfs_fs_info *fs_info = to_fs_info(kobj);
      96                 :          0 :         struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
      97         [ #  # ]:          0 :         if (fs_info) {
      98                 :          0 :                 u64 features = get_features(fs_info, fa->feature_set);
      99         [ #  # ]:          0 :                 if (features & fa->feature_bit)
     100                 :            :                         val = 1;
     101                 :            :         } else
     102                 :          0 :                 val = can_modify_feature(fa);
     103                 :            : 
     104                 :          0 :         return snprintf(buf, PAGE_SIZE, "%d\n", val);
     105                 :            : }
     106                 :            : 
     107                 :          0 : static ssize_t btrfs_feature_attr_store(struct kobject *kobj,
     108                 :            :                                         struct kobj_attribute *a,
     109                 :            :                                         const char *buf, size_t count)
     110                 :            : {
     111                 :          0 :         struct btrfs_fs_info *fs_info;
     112                 :            :         struct btrfs_feature_attr *fa = to_btrfs_feature_attr(a);
     113                 :            :         struct btrfs_trans_handle *trans;
     114                 :            :         u64 features, set, clear;
     115                 :            :         unsigned long val;
     116                 :            :         int ret;
     117                 :            : 
     118                 :            :         fs_info = to_fs_info(kobj);
     119         [ #  # ]:          0 :         if (!fs_info)
     120                 :            :                 return -EPERM;
     121                 :            : 
     122                 :          0 :         ret = kstrtoul(skip_spaces(buf), 0, &val);
     123         [ #  # ]:          0 :         if (ret)
     124                 :            :                 return ret;
     125                 :            : 
     126         [ #  # ]:          0 :         if (fa->feature_set == FEAT_COMPAT) {
     127                 :            :                 set = BTRFS_FEATURE_COMPAT_SAFE_SET;
     128                 :            :                 clear = BTRFS_FEATURE_COMPAT_SAFE_CLEAR;
     129         [ #  # ]:          0 :         } else if (fa->feature_set == FEAT_COMPAT_RO) {
     130                 :            :                 set = BTRFS_FEATURE_COMPAT_RO_SAFE_SET;
     131                 :            :                 clear = BTRFS_FEATURE_COMPAT_RO_SAFE_CLEAR;
     132                 :            :         } else {
     133                 :            :                 set = BTRFS_FEATURE_INCOMPAT_SAFE_SET;
     134                 :            :                 clear = BTRFS_FEATURE_INCOMPAT_SAFE_CLEAR;
     135                 :            :         }
     136                 :            : 
     137                 :            :         features = get_features(fs_info, fa->feature_set);
     138                 :            : 
     139                 :            :         /* Nothing to do */
     140 [ #  # ][ #  # ]:          0 :         if ((val && (features & fa->feature_bit)) ||
                 [ #  # ]
     141         [ #  # ]:          0 :             (!val && !(features & fa->feature_bit)))
     142                 :          0 :                 return count;
     143                 :            : 
     144 [ #  # ][ #  # ]:          0 :         if ((val && !(set & fa->feature_bit)) ||
                 [ #  # ]
     145                 :            :             (!val && !(clear & fa->feature_bit))) {
     146         [ #  # ]:          0 :                 btrfs_info(fs_info,
     147                 :            :                         "%sabling feature %s on mounted fs is not supported.",
     148                 :            :                         val ? "En" : "Dis", fa->kobj_attr.attr.name);
     149                 :          0 :                 return -EPERM;
     150                 :            :         }
     151                 :            : 
     152         [ #  # ]:          0 :         btrfs_info(fs_info, "%s %s feature flag",
     153                 :            :                    val ? "Setting" : "Clearing", fa->kobj_attr.attr.name);
     154                 :            : 
     155                 :          0 :         trans = btrfs_start_transaction(fs_info->fs_root, 0);
     156         [ #  # ]:          0 :         if (IS_ERR(trans))
     157                 :          0 :                 return PTR_ERR(trans);
     158                 :            : 
     159                 :            :         spin_lock(&fs_info->super_lock);
     160                 :          0 :         features = get_features(fs_info, fa->feature_set);
     161         [ #  # ]:          0 :         if (val)
     162                 :          0 :                 features |= fa->feature_bit;
     163                 :            :         else
     164                 :          0 :                 features &= ~fa->feature_bit;
     165                 :            :         set_features(fs_info, fa->feature_set, features);
     166                 :            :         spin_unlock(&fs_info->super_lock);
     167                 :            : 
     168                 :          0 :         ret = btrfs_commit_transaction(trans, fs_info->fs_root);
     169         [ #  # ]:          0 :         if (ret)
     170                 :            :                 return ret;
     171                 :            : 
     172                 :          0 :         return count;
     173                 :            : }
     174                 :            : 
     175                 :          0 : static umode_t btrfs_feature_visible(struct kobject *kobj,
     176                 :            :                                      struct attribute *attr, int unused)
     177                 :            : {
     178                 :          0 :         struct btrfs_fs_info *fs_info = to_fs_info(kobj);
     179                 :          0 :         umode_t mode = attr->mode;
     180                 :            : 
     181         [ #  # ]:          0 :         if (fs_info) {
     182                 :            :                 struct btrfs_feature_attr *fa;
     183                 :            :                 u64 features;
     184                 :            : 
     185                 :            :                 fa = attr_to_btrfs_feature_attr(attr);
     186                 :          0 :                 features = get_features(fs_info, fa->feature_set);
     187                 :            : 
     188         [ #  # ]:          0 :                 if (can_modify_feature(fa))
     189                 :          0 :                         mode |= S_IWUSR;
     190         [ #  # ]:          0 :                 else if (!(features & fa->feature_bit))
     191                 :            :                         mode = 0;
     192                 :            :         }
     193                 :            : 
     194                 :          0 :         return mode;
     195                 :            : }
     196                 :            : 
     197                 :            : BTRFS_FEAT_ATTR_INCOMPAT(mixed_backref, MIXED_BACKREF);
     198                 :            : BTRFS_FEAT_ATTR_INCOMPAT(default_subvol, DEFAULT_SUBVOL);
     199                 :            : BTRFS_FEAT_ATTR_INCOMPAT(mixed_groups, MIXED_GROUPS);
     200                 :            : BTRFS_FEAT_ATTR_INCOMPAT(compress_lzo, COMPRESS_LZO);
     201                 :            : BTRFS_FEAT_ATTR_INCOMPAT(big_metadata, BIG_METADATA);
     202                 :            : BTRFS_FEAT_ATTR_INCOMPAT(extended_iref, EXTENDED_IREF);
     203                 :            : BTRFS_FEAT_ATTR_INCOMPAT(raid56, RAID56);
     204                 :            : BTRFS_FEAT_ATTR_INCOMPAT(skinny_metadata, SKINNY_METADATA);
     205                 :            : BTRFS_FEAT_ATTR_INCOMPAT(no_holes, NO_HOLES);
     206                 :            : 
     207                 :            : static struct attribute *btrfs_supported_feature_attrs[] = {
     208                 :            :         BTRFS_FEAT_ATTR_PTR(mixed_backref),
     209                 :            :         BTRFS_FEAT_ATTR_PTR(default_subvol),
     210                 :            :         BTRFS_FEAT_ATTR_PTR(mixed_groups),
     211                 :            :         BTRFS_FEAT_ATTR_PTR(compress_lzo),
     212                 :            :         BTRFS_FEAT_ATTR_PTR(big_metadata),
     213                 :            :         BTRFS_FEAT_ATTR_PTR(extended_iref),
     214                 :            :         BTRFS_FEAT_ATTR_PTR(raid56),
     215                 :            :         BTRFS_FEAT_ATTR_PTR(skinny_metadata),
     216                 :            :         BTRFS_FEAT_ATTR_PTR(no_holes),
     217                 :            :         NULL
     218                 :            : };
     219                 :            : 
     220                 :            : static const struct attribute_group btrfs_feature_attr_group = {
     221                 :            :         .name = "features",
     222                 :            :         .is_visible = btrfs_feature_visible,
     223                 :            :         .attrs = btrfs_supported_feature_attrs,
     224                 :            : };
     225                 :            : 
     226                 :          0 : static ssize_t btrfs_show_u64(u64 *value_ptr, spinlock_t *lock, char *buf)
     227                 :            : {
     228                 :            :         u64 val;
     229         [ #  # ]:          0 :         if (lock)
     230                 :            :                 spin_lock(lock);
     231                 :          0 :         val = *value_ptr;
     232         [ #  # ]:          0 :         if (lock)
     233                 :            :                 spin_unlock(lock);
     234                 :          0 :         return snprintf(buf, PAGE_SIZE, "%llu\n", val);
     235                 :            : }
     236                 :            : 
     237                 :          0 : static ssize_t global_rsv_size_show(struct kobject *kobj,
     238                 :            :                                     struct kobj_attribute *ka, char *buf)
     239                 :            : {
     240                 :          0 :         struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
     241                 :            :         struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
     242                 :          0 :         return btrfs_show_u64(&block_rsv->size, &block_rsv->lock, buf);
     243                 :            : }
     244                 :            : BTRFS_ATTR(global_rsv_size, 0444, global_rsv_size_show);
     245                 :            : 
     246                 :          0 : static ssize_t global_rsv_reserved_show(struct kobject *kobj,
     247                 :            :                                         struct kobj_attribute *a, char *buf)
     248                 :            : {
     249                 :          0 :         struct btrfs_fs_info *fs_info = to_fs_info(kobj->parent);
     250                 :            :         struct btrfs_block_rsv *block_rsv = &fs_info->global_block_rsv;
     251                 :          0 :         return btrfs_show_u64(&block_rsv->reserved, &block_rsv->lock, buf);
     252                 :            : }
     253                 :            : BTRFS_ATTR(global_rsv_reserved, 0444, global_rsv_reserved_show);
     254                 :            : 
     255                 :            : #define to_space_info(_kobj) container_of(_kobj, struct btrfs_space_info, kobj)
     256                 :            : 
     257                 :            : static ssize_t raid_bytes_show(struct kobject *kobj,
     258                 :            :                                struct kobj_attribute *attr, char *buf);
     259                 :            : BTRFS_RAID_ATTR(total_bytes, raid_bytes_show);
     260                 :            : BTRFS_RAID_ATTR(used_bytes, raid_bytes_show);
     261                 :            : 
     262                 :          0 : static ssize_t raid_bytes_show(struct kobject *kobj,
     263                 :            :                                struct kobj_attribute *attr, char *buf)
     264                 :            : 
     265                 :            : {
     266                 :          0 :         struct btrfs_space_info *sinfo = to_space_info(kobj->parent);
     267                 :            :         struct btrfs_block_group_cache *block_group;
     268                 :          0 :         int index = kobj - sinfo->block_group_kobjs;
     269                 :            :         u64 val = 0;
     270                 :            : 
     271                 :          0 :         down_read(&sinfo->groups_sem);
     272         [ #  # ]:          0 :         list_for_each_entry(block_group, &sinfo->block_groups[index], list) {
     273         [ #  # ]:          0 :                 if (&attr->attr == BTRFS_RAID_ATTR_PTR(total_bytes))
     274                 :          0 :                         val += block_group->key.offset;
     275                 :            :                 else
     276                 :          0 :                         val += btrfs_block_group_used(&block_group->item);
     277                 :            :         }
     278                 :          0 :         up_read(&sinfo->groups_sem);
     279                 :          0 :         return snprintf(buf, PAGE_SIZE, "%llu\n", val);
     280                 :            : }
     281                 :            : 
     282                 :            : static struct attribute *raid_attributes[] = {
     283                 :            :         BTRFS_RAID_ATTR_PTR(total_bytes),
     284                 :            :         BTRFS_RAID_ATTR_PTR(used_bytes),
     285                 :            :         NULL
     286                 :            : };
     287                 :            : 
     288                 :          0 : static void release_raid_kobj(struct kobject *kobj)
     289                 :            : {
     290                 :          0 :         kobject_put(kobj->parent);
     291                 :          0 : }
     292                 :            : 
     293                 :            : struct kobj_type btrfs_raid_ktype = {
     294                 :            :         .sysfs_ops = &kobj_sysfs_ops,
     295                 :            :         .release = release_raid_kobj,
     296                 :            :         .default_attrs = raid_attributes,
     297                 :            : };
     298                 :            : 
     299                 :            : #define SPACE_INFO_ATTR(field)                                          \
     300                 :            : static ssize_t btrfs_space_info_show_##field(struct kobject *kobj,      \
     301                 :            :                                              struct kobj_attribute *a,  \
     302                 :            :                                              char *buf)                 \
     303                 :            : {                                                                       \
     304                 :            :         struct btrfs_space_info *sinfo = to_space_info(kobj);           \
     305                 :            :         return btrfs_show_u64(&sinfo->field, &sinfo->lock, buf);  \
     306                 :            : }                                                                       \
     307                 :            : BTRFS_ATTR(field, 0444, btrfs_space_info_show_##field)
     308                 :            : 
     309                 :          0 : static ssize_t btrfs_space_info_show_total_bytes_pinned(struct kobject *kobj,
     310                 :            :                                                        struct kobj_attribute *a,
     311                 :            :                                                        char *buf)
     312                 :            : {
     313                 :            :         struct btrfs_space_info *sinfo = to_space_info(kobj);
     314                 :          0 :         s64 val = percpu_counter_sum(&sinfo->total_bytes_pinned);
     315                 :          0 :         return snprintf(buf, PAGE_SIZE, "%lld\n", val);
     316                 :            : }
     317                 :            : 
     318                 :          0 : SPACE_INFO_ATTR(flags);
     319                 :          0 : SPACE_INFO_ATTR(total_bytes);
     320                 :          0 : SPACE_INFO_ATTR(bytes_used);
     321                 :          0 : SPACE_INFO_ATTR(bytes_pinned);
     322                 :          0 : SPACE_INFO_ATTR(bytes_reserved);
     323                 :          0 : SPACE_INFO_ATTR(bytes_may_use);
     324                 :          0 : SPACE_INFO_ATTR(disk_used);
     325                 :          0 : SPACE_INFO_ATTR(disk_total);
     326                 :            : BTRFS_ATTR(total_bytes_pinned, 0444, btrfs_space_info_show_total_bytes_pinned);
     327                 :            : 
     328                 :            : static struct attribute *space_info_attrs[] = {
     329                 :            :         BTRFS_ATTR_PTR(flags),
     330                 :            :         BTRFS_ATTR_PTR(total_bytes),
     331                 :            :         BTRFS_ATTR_PTR(bytes_used),
     332                 :            :         BTRFS_ATTR_PTR(bytes_pinned),
     333                 :            :         BTRFS_ATTR_PTR(bytes_reserved),
     334                 :            :         BTRFS_ATTR_PTR(bytes_may_use),
     335                 :            :         BTRFS_ATTR_PTR(disk_used),
     336                 :            :         BTRFS_ATTR_PTR(disk_total),
     337                 :            :         BTRFS_ATTR_PTR(total_bytes_pinned),
     338                 :            :         NULL,
     339                 :            : };
     340                 :            : 
     341                 :          0 : static void space_info_release(struct kobject *kobj)
     342                 :            : {
     343                 :          0 :         struct btrfs_space_info *sinfo = to_space_info(kobj);
     344                 :          0 :         percpu_counter_destroy(&sinfo->total_bytes_pinned);
     345                 :          0 :         kfree(sinfo);
     346                 :          0 : }
     347                 :            : 
     348                 :            : struct kobj_type space_info_ktype = {
     349                 :            :         .sysfs_ops = &kobj_sysfs_ops,
     350                 :            :         .release = space_info_release,
     351                 :            :         .default_attrs = space_info_attrs,
     352                 :            : };
     353                 :            : 
     354                 :            : static const struct attribute *allocation_attrs[] = {
     355                 :            :         BTRFS_ATTR_PTR(global_rsv_reserved),
     356                 :            :         BTRFS_ATTR_PTR(global_rsv_size),
     357                 :            :         NULL,
     358                 :            : };
     359                 :            : 
     360                 :          0 : static ssize_t btrfs_label_show(struct kobject *kobj,
     361                 :            :                                 struct kobj_attribute *a, char *buf)
     362                 :            : {
     363                 :            :         struct btrfs_fs_info *fs_info = to_fs_info(kobj);
     364                 :          0 :         return snprintf(buf, PAGE_SIZE, "%s\n", fs_info->super_copy->label);
     365                 :            : }
     366                 :            : 
     367                 :          0 : static ssize_t btrfs_label_store(struct kobject *kobj,
     368                 :            :                                  struct kobj_attribute *a,
     369                 :            :                                  const char *buf, size_t len)
     370                 :            : {
     371                 :            :         struct btrfs_fs_info *fs_info = to_fs_info(kobj);
     372                 :            :         struct btrfs_trans_handle *trans;
     373                 :          0 :         struct btrfs_root *root = fs_info->fs_root;
     374                 :            :         int ret;
     375                 :            : 
     376         [ #  # ]:          0 :         if (len >= BTRFS_LABEL_SIZE) {
     377                 :          0 :                 pr_err("BTRFS: unable to set label with more than %d bytes\n",
     378                 :            :                        BTRFS_LABEL_SIZE - 1);
     379                 :          0 :                 return -EINVAL;
     380                 :            :         }
     381                 :            : 
     382                 :          0 :         trans = btrfs_start_transaction(root, 0);
     383         [ #  # ]:          0 :         if (IS_ERR(trans))
     384                 :          0 :                 return PTR_ERR(trans);
     385                 :            : 
     386                 :          0 :         spin_lock(&root->fs_info->super_lock);
     387                 :          0 :         strcpy(fs_info->super_copy->label, buf);
     388                 :          0 :         spin_unlock(&root->fs_info->super_lock);
     389                 :          0 :         ret = btrfs_commit_transaction(trans, root);
     390                 :            : 
     391         [ #  # ]:          0 :         if (!ret)
     392                 :          0 :                 return len;
     393                 :            : 
     394                 :            :         return ret;
     395                 :            : }
     396                 :            : BTRFS_ATTR_RW(label, 0644, btrfs_label_show, btrfs_label_store);
     397                 :            : 
     398                 :            : static struct attribute *btrfs_attrs[] = {
     399                 :            :         BTRFS_ATTR_PTR(label),
     400                 :            :         NULL,
     401                 :            : };
     402                 :            : 
     403                 :          0 : static void btrfs_release_super_kobj(struct kobject *kobj)
     404                 :            : {
     405                 :            :         struct btrfs_fs_info *fs_info = to_fs_info(kobj);
     406                 :          0 :         complete(&fs_info->kobj_unregister);
     407                 :          0 : }
     408                 :            : 
     409                 :            : static struct kobj_type btrfs_ktype = {
     410                 :            :         .sysfs_ops      = &kobj_sysfs_ops,
     411                 :            :         .release        = btrfs_release_super_kobj,
     412                 :            :         .default_attrs  = btrfs_attrs,
     413                 :            : };
     414                 :            : 
     415                 :            : static inline struct btrfs_fs_info *to_fs_info(struct kobject *kobj)
     416                 :            : {
     417 [ #  # ][ #  # ]:          0 :         if (kobj->ktype != &btrfs_ktype)
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     418                 :            :                 return NULL;
     419                 :          0 :         return container_of(kobj, struct btrfs_fs_info, super_kobj);
     420                 :            : }
     421                 :            : 
     422                 :            : #define NUM_FEATURE_BITS 64
     423                 :            : static char btrfs_unknown_feature_names[3][NUM_FEATURE_BITS][13];
     424                 :            : static struct btrfs_feature_attr btrfs_feature_attrs[3][NUM_FEATURE_BITS];
     425                 :            : 
     426                 :            : static u64 supported_feature_masks[3] = {
     427                 :            :         [FEAT_COMPAT]    = BTRFS_FEATURE_COMPAT_SUPP,
     428                 :            :         [FEAT_COMPAT_RO] = BTRFS_FEATURE_COMPAT_RO_SUPP,
     429                 :            :         [FEAT_INCOMPAT]  = BTRFS_FEATURE_INCOMPAT_SUPP,
     430                 :            : };
     431                 :            : 
     432                 :          0 : static int addrm_unknown_feature_attrs(struct btrfs_fs_info *fs_info, bool add)
     433                 :            : {
     434                 :            :         int set;
     435                 :            : 
     436         [ #  # ]:          0 :         for (set = 0; set < FEAT_MAX; set++) {
     437                 :            :                 int i;
     438                 :            :                 struct attribute *attrs[2];
     439                 :          0 :                 struct attribute_group agroup = {
     440                 :            :                         .name = "features",
     441                 :            :                         .attrs = attrs,
     442                 :            :                 };
     443                 :          0 :                 u64 features = get_features(fs_info, set);
     444                 :          0 :                 features &= ~supported_feature_masks[set];
     445                 :            : 
     446         [ #  # ]:          0 :                 if (!features)
     447                 :          0 :                         continue;
     448                 :            : 
     449                 :          0 :                 attrs[1] = NULL;
     450         [ #  # ]:          0 :                 for (i = 0; i < NUM_FEATURE_BITS; i++) {
     451                 :            :                         struct btrfs_feature_attr *fa;
     452                 :            : 
     453         [ #  # ]:          0 :                         if (!(features & (1ULL << i)))
     454                 :          0 :                                 continue;
     455                 :            : 
     456                 :          0 :                         fa = &btrfs_feature_attrs[set][i];
     457                 :          0 :                         attrs[0] = &fa->kobj_attr.attr;
     458         [ #  # ]:          0 :                         if (add) {
     459                 :            :                                 int ret;
     460                 :          0 :                                 ret = sysfs_merge_group(&fs_info->super_kobj,
     461                 :            :                                                         &agroup);
     462         [ #  # ]:          0 :                                 if (ret)
     463                 :          0 :                                         return ret;
     464                 :            :                         } else
     465                 :          0 :                                 sysfs_unmerge_group(&fs_info->super_kobj,
     466                 :            :                                                     &agroup);
     467                 :            :                 }
     468                 :            : 
     469                 :            :         }
     470                 :            :         return 0;
     471                 :            : }
     472                 :            : 
     473                 :          0 : static void __btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
     474                 :            : {
     475                 :          0 :         kobject_del(&fs_info->super_kobj);
     476                 :          0 :         kobject_put(&fs_info->super_kobj);
     477                 :          0 :         wait_for_completion(&fs_info->kobj_unregister);
     478                 :          0 : }
     479                 :            : 
     480                 :          0 : void btrfs_sysfs_remove_one(struct btrfs_fs_info *fs_info)
     481                 :            : {
     482         [ #  # ]:          0 :         if (fs_info->space_info_kobj) {
     483                 :          0 :                 sysfs_remove_files(fs_info->space_info_kobj, allocation_attrs);
     484                 :          0 :                 kobject_del(fs_info->space_info_kobj);
     485                 :          0 :                 kobject_put(fs_info->space_info_kobj);
     486                 :            :         }
     487                 :          0 :         kobject_del(fs_info->device_dir_kobj);
     488                 :          0 :         kobject_put(fs_info->device_dir_kobj);
     489                 :          0 :         addrm_unknown_feature_attrs(fs_info, false);
     490                 :          0 :         sysfs_remove_group(&fs_info->super_kobj, &btrfs_feature_attr_group);
     491                 :          0 :         __btrfs_sysfs_remove_one(fs_info);
     492                 :          0 : }
     493                 :            : 
     494                 :            : const char * const btrfs_feature_set_names[3] = {
     495                 :            :         [FEAT_COMPAT]    = "compat",
     496                 :            :         [FEAT_COMPAT_RO] = "compat_ro",
     497                 :            :         [FEAT_INCOMPAT]  = "incompat",
     498                 :            : };
     499                 :            : 
     500                 :          0 : char *btrfs_printable_features(enum btrfs_feature_set set, u64 flags)
     501                 :            : {
     502                 :            :         size_t bufsize = 4096; /* safe max, 64 names * 64 bytes */
     503                 :            :         int len = 0;
     504                 :            :         int i;
     505                 :            :         char *str;
     506                 :            : 
     507                 :            :         str = kmalloc(bufsize, GFP_KERNEL);
     508         [ #  # ]:          0 :         if (!str)
     509                 :            :                 return str;
     510                 :            : 
     511         [ #  # ]:          0 :         for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) {
     512                 :            :                 const char *name;
     513                 :            : 
     514         [ #  # ]:          0 :                 if (!(flags & (1ULL << i)))
     515                 :          0 :                         continue;
     516                 :            : 
     517                 :          0 :                 name = btrfs_feature_attrs[set][i].kobj_attr.attr.name;
     518         [ #  # ]:          0 :                 len += snprintf(str + len, bufsize - len, "%s%s",
     519                 :            :                                 len ? "," : "", name);
     520                 :            :         }
     521                 :            : 
     522                 :            :         return str;
     523                 :            : }
     524                 :            : 
     525                 :          0 : static void init_feature_attrs(void)
     526                 :            : {
     527                 :            :         struct btrfs_feature_attr *fa;
     528                 :            :         int set, i;
     529                 :            : 
     530                 :            :         BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names) !=
     531                 :            :                      ARRAY_SIZE(btrfs_feature_attrs));
     532                 :            :         BUILD_BUG_ON(ARRAY_SIZE(btrfs_unknown_feature_names[0]) !=
     533                 :            :                      ARRAY_SIZE(btrfs_feature_attrs[0]));
     534                 :            : 
     535                 :          0 :         memset(btrfs_feature_attrs, 0, sizeof(btrfs_feature_attrs));
     536                 :          0 :         memset(btrfs_unknown_feature_names, 0,
     537                 :            :                sizeof(btrfs_unknown_feature_names));
     538                 :            : 
     539         [ #  # ]:          0 :         for (i = 0; btrfs_supported_feature_attrs[i]; i++) {
     540                 :            :                 struct btrfs_feature_attr *sfa;
     541                 :            :                 struct attribute *a = btrfs_supported_feature_attrs[i];
     542                 :            :                 int bit;
     543                 :            :                 sfa = attr_to_btrfs_feature_attr(a);
     544 [ #  # ][ #  # ]:          0 :                 bit = ilog2(sfa->feature_bit);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     545                 :          0 :                 fa = &btrfs_feature_attrs[sfa->feature_set][bit];
     546                 :            : 
     547                 :          0 :                 fa->kobj_attr.attr.name = sfa->kobj_attr.attr.name;
     548                 :            :         }
     549                 :            : 
     550         [ #  # ]:          0 :         for (set = 0; set < FEAT_MAX; set++) {
     551         [ #  # ]:          0 :                 for (i = 0; i < ARRAY_SIZE(btrfs_feature_attrs[set]); i++) {
     552                 :          0 :                         char *name = btrfs_unknown_feature_names[set][i];
     553                 :          0 :                         fa = &btrfs_feature_attrs[set][i];
     554                 :            : 
     555         [ #  # ]:          0 :                         if (fa->kobj_attr.attr.name)
     556                 :          0 :                                 continue;
     557                 :            : 
     558                 :          0 :                         snprintf(name, 13, "%s:%u",
     559                 :            :                                  btrfs_feature_set_names[set], i);
     560                 :            : 
     561                 :          0 :                         fa->kobj_attr.attr.name = name;
     562                 :          0 :                         fa->kobj_attr.attr.mode = S_IRUGO;
     563                 :          0 :                         fa->feature_set = set;
     564                 :          0 :                         fa->feature_bit = 1ULL << i;
     565                 :            :                 }
     566                 :            :         }
     567                 :          0 : }
     568                 :            : 
     569                 :          0 : static int add_device_membership(struct btrfs_fs_info *fs_info)
     570                 :            : {
     571                 :            :         int error = 0;
     572                 :          0 :         struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
     573                 :            :         struct btrfs_device *dev;
     574                 :            : 
     575                 :          0 :         fs_info->device_dir_kobj = kobject_create_and_add("devices",
     576                 :            :                                                 &fs_info->super_kobj);
     577         [ #  # ]:          0 :         if (!fs_info->device_dir_kobj)
     578                 :            :                 return -ENOMEM;
     579                 :            : 
     580         [ #  # ]:          0 :         list_for_each_entry(dev, &fs_devices->devices, dev_list) {
     581                 :            :                 struct hd_struct *disk;
     582                 :            :                 struct kobject *disk_kobj;
     583                 :            : 
     584         [ #  # ]:          0 :                 if (!dev->bdev)
     585                 :          0 :                         continue;
     586                 :            : 
     587                 :          0 :                 disk = dev->bdev->bd_part;
     588                 :          0 :                 disk_kobj = &part_to_dev(disk)->kobj;
     589                 :            : 
     590                 :          0 :                 error = sysfs_create_link(fs_info->device_dir_kobj,
     591                 :            :                                           disk_kobj, disk_kobj->name);
     592         [ #  # ]:          0 :                 if (error)
     593                 :            :                         break;
     594                 :            :         }
     595                 :            : 
     596                 :          0 :         return error;
     597                 :            : }
     598                 :            : 
     599                 :            : /* /sys/fs/btrfs/ entry */
     600                 :            : static struct kset *btrfs_kset;
     601                 :            : 
     602                 :          0 : int btrfs_sysfs_add_one(struct btrfs_fs_info *fs_info)
     603                 :            : {
     604                 :            :         int error;
     605                 :            : 
     606                 :            :         init_completion(&fs_info->kobj_unregister);
     607                 :          0 :         fs_info->super_kobj.kset = btrfs_kset;
     608                 :          0 :         error = kobject_init_and_add(&fs_info->super_kobj, &btrfs_ktype, NULL,
     609                 :          0 :                                      "%pU", fs_info->fsid);
     610         [ #  # ]:          0 :         if (error)
     611                 :            :                 return error;
     612                 :            : 
     613                 :          0 :         error = sysfs_create_group(&fs_info->super_kobj,
     614                 :            :                                    &btrfs_feature_attr_group);
     615         [ #  # ]:          0 :         if (error) {
     616                 :          0 :                 __btrfs_sysfs_remove_one(fs_info);
     617                 :          0 :                 return error;
     618                 :            :         }
     619                 :            : 
     620                 :          0 :         error = addrm_unknown_feature_attrs(fs_info, true);
     621         [ #  # ]:          0 :         if (error)
     622                 :            :                 goto failure;
     623                 :            : 
     624                 :          0 :         error = add_device_membership(fs_info);
     625         [ #  # ]:          0 :         if (error)
     626                 :            :                 goto failure;
     627                 :            : 
     628                 :          0 :         fs_info->space_info_kobj = kobject_create_and_add("allocation",
     629                 :            :                                                   &fs_info->super_kobj);
     630         [ #  # ]:          0 :         if (!fs_info->space_info_kobj) {
     631                 :            :                 error = -ENOMEM;
     632                 :            :                 goto failure;
     633                 :            :         }
     634                 :            : 
     635                 :          0 :         error = sysfs_create_files(fs_info->space_info_kobj, allocation_attrs);
     636         [ #  # ]:          0 :         if (error)
     637                 :            :                 goto failure;
     638                 :            : 
     639                 :            :         return 0;
     640                 :            : failure:
     641                 :          0 :         btrfs_sysfs_remove_one(fs_info);
     642                 :          0 :         return error;
     643                 :            : }
     644                 :            : 
     645                 :          0 : int btrfs_init_sysfs(void)
     646                 :            : {
     647                 :            :         int ret;
     648                 :          0 :         btrfs_kset = kset_create_and_add("btrfs", NULL, fs_kobj);
     649         [ #  # ]:          0 :         if (!btrfs_kset)
     650                 :            :                 return -ENOMEM;
     651                 :            : 
     652                 :          0 :         init_feature_attrs();
     653                 :            : 
     654                 :          0 :         ret = sysfs_create_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
     655         [ #  # ]:          0 :         if (ret) {
     656                 :          0 :                 kset_unregister(btrfs_kset);
     657                 :          0 :                 return ret;
     658                 :            :         }
     659                 :            : 
     660                 :            :         return 0;
     661                 :            : }
     662                 :            : 
     663                 :          0 : void btrfs_exit_sysfs(void)
     664                 :            : {
     665                 :          0 :         sysfs_remove_group(&btrfs_kset->kobj, &btrfs_feature_attr_group);
     666                 :          0 :         kset_unregister(btrfs_kset);
     667                 :          0 : }
     668                 :            : 

Generated by: LCOV version 1.9