diff options
Diffstat (limited to 'fs/btrfs/super.c')
-rw-r--r-- | fs/btrfs/super.c | 125 |
1 files changed, 71 insertions, 54 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index f267718cbd1..96eb9fef7bd 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -188,7 +188,8 @@ void btrfs_printk(struct btrfs_fs_info *fs_info, const char *fmt, ...) | |||
188 | va_start(args, fmt); | 188 | va_start(args, fmt); |
189 | 189 | ||
190 | if (fmt[0] == '<' && isdigit(fmt[1]) && fmt[2] == '>') { | 190 | if (fmt[0] == '<' && isdigit(fmt[1]) && fmt[2] == '>') { |
191 | strncpy(lvl, fmt, 3); | 191 | memcpy(lvl, fmt, 3); |
192 | lvl[3] = '\0'; | ||
192 | fmt += 3; | 193 | fmt += 3; |
193 | type = logtypes[fmt[1] - '0']; | 194 | type = logtypes[fmt[1] - '0']; |
194 | } else | 195 | } else |
@@ -435,11 +436,8 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
435 | case Opt_thread_pool: | 436 | case Opt_thread_pool: |
436 | intarg = 0; | 437 | intarg = 0; |
437 | match_int(&args[0], &intarg); | 438 | match_int(&args[0], &intarg); |
438 | if (intarg) { | 439 | if (intarg) |
439 | info->thread_pool_size = intarg; | 440 | info->thread_pool_size = intarg; |
440 | printk(KERN_INFO "btrfs: thread pool %d\n", | ||
441 | info->thread_pool_size); | ||
442 | } | ||
443 | break; | 441 | break; |
444 | case Opt_max_inline: | 442 | case Opt_max_inline: |
445 | num = match_strdup(&args[0]); | 443 | num = match_strdup(&args[0]); |
@@ -755,7 +753,6 @@ static int btrfs_fill_super(struct super_block *sb, | |||
755 | void *data, int silent) | 753 | void *data, int silent) |
756 | { | 754 | { |
757 | struct inode *inode; | 755 | struct inode *inode; |
758 | struct dentry *root_dentry; | ||
759 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); | 756 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
760 | struct btrfs_key key; | 757 | struct btrfs_key key; |
761 | int err; | 758 | int err; |
@@ -770,7 +767,7 @@ static int btrfs_fill_super(struct super_block *sb, | |||
770 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL | 767 | #ifdef CONFIG_BTRFS_FS_POSIX_ACL |
771 | sb->s_flags |= MS_POSIXACL; | 768 | sb->s_flags |= MS_POSIXACL; |
772 | #endif | 769 | #endif |
773 | 770 | sb->s_flags |= MS_I_VERSION; | |
774 | err = open_ctree(sb, fs_devices, (char *)data); | 771 | err = open_ctree(sb, fs_devices, (char *)data); |
775 | if (err) { | 772 | if (err) { |
776 | printk("btrfs: open_ctree failed\n"); | 773 | printk("btrfs: open_ctree failed\n"); |
@@ -786,15 +783,12 @@ static int btrfs_fill_super(struct super_block *sb, | |||
786 | goto fail_close; | 783 | goto fail_close; |
787 | } | 784 | } |
788 | 785 | ||
789 | root_dentry = d_alloc_root(inode); | 786 | sb->s_root = d_make_root(inode); |
790 | if (!root_dentry) { | 787 | if (!sb->s_root) { |
791 | iput(inode); | ||
792 | err = -ENOMEM; | 788 | err = -ENOMEM; |
793 | goto fail_close; | 789 | goto fail_close; |
794 | } | 790 | } |
795 | 791 | ||
796 | sb->s_root = root_dentry; | ||
797 | |||
798 | save_mount_options(sb, data); | 792 | save_mount_options(sb, data); |
799 | cleancache_init_fs(sb); | 793 | cleancache_init_fs(sb); |
800 | sb->s_flags |= MS_ACTIVE; | 794 | sb->s_flags |= MS_ACTIVE; |
@@ -929,63 +923,48 @@ static inline int is_subvolume_inode(struct inode *inode) | |||
929 | */ | 923 | */ |
930 | static char *setup_root_args(char *args) | 924 | static char *setup_root_args(char *args) |
931 | { | 925 | { |
932 | unsigned copied = 0; | 926 | unsigned len = strlen(args) + 2 + 1; |
933 | unsigned len = strlen(args) + 2; | 927 | char *src, *dst, *buf; |
934 | char *pos; | ||
935 | char *ret; | ||
936 | 928 | ||
937 | /* | 929 | /* |
938 | * We need the same args as before, but minus | 930 | * We need the same args as before, but with this substitution: |
939 | * | 931 | * s!subvol=[^,]+!subvolid=0! |
940 | * subvol=a | ||
941 | * | ||
942 | * and add | ||
943 | * | 932 | * |
944 | * subvolid=0 | 933 | * Since the replacement string is up to 2 bytes longer than the |
945 | * | 934 | * original, allocate strlen(args) + 2 + 1 bytes. |
946 | * which is a difference of 2 characters, so we allocate strlen(args) + | ||
947 | * 2 characters. | ||
948 | */ | 935 | */ |
949 | ret = kzalloc(len * sizeof(char), GFP_NOFS); | ||
950 | if (!ret) | ||
951 | return NULL; | ||
952 | pos = strstr(args, "subvol="); | ||
953 | 936 | ||
937 | src = strstr(args, "subvol="); | ||
954 | /* This shouldn't happen, but just in case.. */ | 938 | /* This shouldn't happen, but just in case.. */ |
955 | if (!pos) { | 939 | if (!src) |
956 | kfree(ret); | 940 | return NULL; |
941 | |||
942 | buf = dst = kmalloc(len, GFP_NOFS); | ||
943 | if (!buf) | ||
957 | return NULL; | 944 | return NULL; |
958 | } | ||
959 | 945 | ||
960 | /* | 946 | /* |
961 | * The subvol=<> arg is not at the front of the string, copy everybody | 947 | * If the subvol= arg is not at the start of the string, |
962 | * up to that into ret. | 948 | * copy whatever precedes it into buf. |
963 | */ | 949 | */ |
964 | if (pos != args) { | 950 | if (src != args) { |
965 | *pos = '\0'; | 951 | *src++ = '\0'; |
966 | strcpy(ret, args); | 952 | strcpy(buf, args); |
967 | copied += strlen(args); | 953 | dst += strlen(args); |
968 | pos++; | ||
969 | } | 954 | } |
970 | 955 | ||
971 | strncpy(ret + copied, "subvolid=0", len - copied); | 956 | strcpy(dst, "subvolid=0"); |
972 | 957 | dst += strlen("subvolid=0"); | |
973 | /* Length of subvolid=0 */ | ||
974 | copied += 10; | ||
975 | 958 | ||
976 | /* | 959 | /* |
977 | * If there is no , after the subvol= option then we know there's no | 960 | * If there is a "," after the original subvol=... string, |
978 | * other options and we can just return. | 961 | * copy that suffix into our buffer. Otherwise, we're done. |
979 | */ | 962 | */ |
980 | pos = strchr(pos, ','); | 963 | src = strchr(src, ','); |
981 | if (!pos) | 964 | if (src) |
982 | return ret; | 965 | strcpy(dst, src); |
983 | |||
984 | /* Copy the rest of the arguments into our buffer */ | ||
985 | strncpy(ret + copied, pos, len - copied); | ||
986 | copied += strlen(pos); | ||
987 | 966 | ||
988 | return ret; | 967 | return buf; |
989 | } | 968 | } |
990 | 969 | ||
991 | static struct dentry *mount_subvol(const char *subvol_name, int flags, | 970 | static struct dentry *mount_subvol(const char *subvol_name, int flags, |
@@ -1122,6 +1101,40 @@ error_fs_info: | |||
1122 | return ERR_PTR(error); | 1101 | return ERR_PTR(error); |
1123 | } | 1102 | } |
1124 | 1103 | ||
1104 | static void btrfs_set_max_workers(struct btrfs_workers *workers, int new_limit) | ||
1105 | { | ||
1106 | spin_lock_irq(&workers->lock); | ||
1107 | workers->max_workers = new_limit; | ||
1108 | spin_unlock_irq(&workers->lock); | ||
1109 | } | ||
1110 | |||
1111 | static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info, | ||
1112 | int new_pool_size, int old_pool_size) | ||
1113 | { | ||
1114 | if (new_pool_size == old_pool_size) | ||
1115 | return; | ||
1116 | |||
1117 | fs_info->thread_pool_size = new_pool_size; | ||
1118 | |||
1119 | printk(KERN_INFO "btrfs: resize thread pool %d -> %d\n", | ||
1120 | old_pool_size, new_pool_size); | ||
1121 | |||
1122 | btrfs_set_max_workers(&fs_info->generic_worker, new_pool_size); | ||
1123 | btrfs_set_max_workers(&fs_info->workers, new_pool_size); | ||
1124 | btrfs_set_max_workers(&fs_info->delalloc_workers, new_pool_size); | ||
1125 | btrfs_set_max_workers(&fs_info->submit_workers, new_pool_size); | ||
1126 | btrfs_set_max_workers(&fs_info->caching_workers, new_pool_size); | ||
1127 | btrfs_set_max_workers(&fs_info->fixup_workers, new_pool_size); | ||
1128 | btrfs_set_max_workers(&fs_info->endio_workers, new_pool_size); | ||
1129 | btrfs_set_max_workers(&fs_info->endio_meta_workers, new_pool_size); | ||
1130 | btrfs_set_max_workers(&fs_info->endio_meta_write_workers, new_pool_size); | ||
1131 | btrfs_set_max_workers(&fs_info->endio_write_workers, new_pool_size); | ||
1132 | btrfs_set_max_workers(&fs_info->endio_freespace_worker, new_pool_size); | ||
1133 | btrfs_set_max_workers(&fs_info->delayed_workers, new_pool_size); | ||
1134 | btrfs_set_max_workers(&fs_info->readahead_workers, new_pool_size); | ||
1135 | btrfs_set_max_workers(&fs_info->scrub_workers, new_pool_size); | ||
1136 | } | ||
1137 | |||
1125 | static int btrfs_remount(struct super_block *sb, int *flags, char *data) | 1138 | static int btrfs_remount(struct super_block *sb, int *flags, char *data) |
1126 | { | 1139 | { |
1127 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); | 1140 | struct btrfs_fs_info *fs_info = btrfs_sb(sb); |
@@ -1141,6 +1154,9 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
1141 | goto restore; | 1154 | goto restore; |
1142 | } | 1155 | } |
1143 | 1156 | ||
1157 | btrfs_resize_thread_pool(fs_info, | ||
1158 | fs_info->thread_pool_size, old_thread_pool_size); | ||
1159 | |||
1144 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | 1160 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) |
1145 | return 0; | 1161 | return 0; |
1146 | 1162 | ||
@@ -1184,7 +1200,8 @@ restore: | |||
1184 | fs_info->compress_type = old_compress_type; | 1200 | fs_info->compress_type = old_compress_type; |
1185 | fs_info->max_inline = old_max_inline; | 1201 | fs_info->max_inline = old_max_inline; |
1186 | fs_info->alloc_start = old_alloc_start; | 1202 | fs_info->alloc_start = old_alloc_start; |
1187 | fs_info->thread_pool_size = old_thread_pool_size; | 1203 | btrfs_resize_thread_pool(fs_info, |
1204 | old_thread_pool_size, fs_info->thread_pool_size); | ||
1188 | fs_info->metadata_ratio = old_metadata_ratio; | 1205 | fs_info->metadata_ratio = old_metadata_ratio; |
1189 | return ret; | 1206 | return ret; |
1190 | } | 1207 | } |