aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs
diff options
context:
space:
mode:
authorJosef Bacik <josef@redhat.com>2012-06-04 14:03:51 -0400
committerChris Mason <chris.mason@oracle.com>2012-06-14 21:29:16 -0400
commit606686eeac4550d2212bf3d621a810407ef5e9bf (patch)
tree50adade3a750137b68304dc280d7a75436417b12 /fs/btrfs
parent17ca04aff7e6171df684b7b65804df8830eb8c15 (diff)
Btrfs: use rcu to protect device->name
Al pointed out that we can just toss out the old name on a device and add a new one arbitrarily, so anybody who uses device->name in printk could possibly use free'd memory. Instead of adding locking around all of this he suggested doing it with RCU, so I've introduced a struct rcu_string that does just that and have gone through and protected all accesses to device->name that aren't under the uuid_mutex with rcu_read_lock(). This protects us and I will use it for dealing with removing the device that we used to mount the file system in a later patch. Thanks, Reviewed-by: David Sterba <dsterba@suse.cz> Signed-off-by: Josef Bacik <josef@redhat.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r--fs/btrfs/check-integrity.c16
-rw-r--r--fs/btrfs/disk-io.c10
-rw-r--r--fs/btrfs/extent_io.c7
-rw-r--r--fs/btrfs/ioctl.c13
-rw-r--r--fs/btrfs/rcu-string.h56
-rw-r--r--fs/btrfs/scrub.c30
-rw-r--r--fs/btrfs/volumes.c92
-rw-r--r--fs/btrfs/volumes.h2
8 files changed, 162 insertions, 64 deletions
diff --git a/fs/btrfs/check-integrity.c b/fs/btrfs/check-integrity.c
index 9cebb1fd6a3c..da6e9364a5e3 100644
--- a/fs/btrfs/check-integrity.c
+++ b/fs/btrfs/check-integrity.c
@@ -93,6 +93,7 @@
93#include "print-tree.h" 93#include "print-tree.h"
94#include "locking.h" 94#include "locking.h"
95#include "check-integrity.h" 95#include "check-integrity.h"
96#include "rcu-string.h"
96 97
97#define BTRFSIC_BLOCK_HASHTABLE_SIZE 0x10000 98#define BTRFSIC_BLOCK_HASHTABLE_SIZE 0x10000
98#define BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE 0x10000 99#define BTRFSIC_BLOCK_LINK_HASHTABLE_SIZE 0x10000
@@ -843,13 +844,14 @@ static int btrfsic_process_superblock_dev_mirror(
843 superblock_tmp->never_written = 0; 844 superblock_tmp->never_written = 0;
844 superblock_tmp->mirror_num = 1 + superblock_mirror_num; 845 superblock_tmp->mirror_num = 1 + superblock_mirror_num;
845 if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE) 846 if (state->print_mask & BTRFSIC_PRINT_MASK_SUPERBLOCK_WRITE)
846 printk(KERN_INFO "New initial S-block (bdev %p, %s)" 847 printk_in_rcu(KERN_INFO "New initial S-block (bdev %p, %s)"
847 " @%llu (%s/%llu/%d)\n", 848 " @%llu (%s/%llu/%d)\n",
848 superblock_bdev, device->name, 849 superblock_bdev,
849 (unsigned long long)dev_bytenr, 850 rcu_str_deref(device->name),
850 dev_state->name, 851 (unsigned long long)dev_bytenr,
851 (unsigned long long)dev_bytenr, 852 dev_state->name,
852 superblock_mirror_num); 853 (unsigned long long)dev_bytenr,
854 superblock_mirror_num);
853 list_add(&superblock_tmp->all_blocks_node, 855 list_add(&superblock_tmp->all_blocks_node,
854 &state->all_blocks_list); 856 &state->all_blocks_list);
855 btrfsic_block_hashtable_add(superblock_tmp, 857 btrfsic_block_hashtable_add(superblock_tmp,
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 5a3bf323e2bd..1c9664b16cd1 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -44,6 +44,7 @@
44#include "free-space-cache.h" 44#include "free-space-cache.h"
45#include "inode-map.h" 45#include "inode-map.h"
46#include "check-integrity.h" 46#include "check-integrity.h"
47#include "rcu-string.h"
47 48
48static struct extent_io_ops btree_extent_io_ops; 49static struct extent_io_ops btree_extent_io_ops;
49static void end_workqueue_fn(struct btrfs_work *work); 50static void end_workqueue_fn(struct btrfs_work *work);
@@ -2575,8 +2576,9 @@ static void btrfs_end_buffer_write_sync(struct buffer_head *bh, int uptodate)
2575 struct btrfs_device *device = (struct btrfs_device *) 2576 struct btrfs_device *device = (struct btrfs_device *)
2576 bh->b_private; 2577 bh->b_private;
2577 2578
2578 printk_ratelimited(KERN_WARNING "lost page write due to " 2579 printk_ratelimited_in_rcu(KERN_WARNING "lost page write due to "
2579 "I/O error on %s\n", device->name); 2580 "I/O error on %s\n",
2581 rcu_str_deref(device->name));
2580 /* note, we dont' set_buffer_write_io_error because we have 2582 /* note, we dont' set_buffer_write_io_error because we have
2581 * our own ways of dealing with the IO errors 2583 * our own ways of dealing with the IO errors
2582 */ 2584 */
@@ -2749,8 +2751,8 @@ static int write_dev_flush(struct btrfs_device *device, int wait)
2749 wait_for_completion(&device->flush_wait); 2751 wait_for_completion(&device->flush_wait);
2750 2752
2751 if (bio_flagged(bio, BIO_EOPNOTSUPP)) { 2753 if (bio_flagged(bio, BIO_EOPNOTSUPP)) {
2752 printk("btrfs: disabling barriers on dev %s\n", 2754 printk_in_rcu("btrfs: disabling barriers on dev %s\n",
2753 device->name); 2755 rcu_str_deref(device->name));
2754 device->nobarriers = 1; 2756 device->nobarriers = 1;
2755 } 2757 }
2756 if (!bio_flagged(bio, BIO_UPTODATE)) { 2758 if (!bio_flagged(bio, BIO_UPTODATE)) {
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index 2c8f7b204617..aaa12c1eb348 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -20,6 +20,7 @@
20#include "volumes.h" 20#include "volumes.h"
21#include "check-integrity.h" 21#include "check-integrity.h"
22#include "locking.h" 22#include "locking.h"
23#include "rcu-string.h"
23 24
24static struct kmem_cache *extent_state_cache; 25static struct kmem_cache *extent_state_cache;
25static struct kmem_cache *extent_buffer_cache; 26static struct kmem_cache *extent_buffer_cache;
@@ -1917,9 +1918,9 @@ int repair_io_failure(struct btrfs_mapping_tree *map_tree, u64 start,
1917 return -EIO; 1918 return -EIO;
1918 } 1919 }
1919 1920
1920 printk(KERN_INFO "btrfs read error corrected: ino %lu off %llu (dev %s " 1921 printk_in_rcu(KERN_INFO "btrfs read error corrected: ino %lu off %llu "
1921 "sector %llu)\n", page->mapping->host->i_ino, start, 1922 "(dev %s sector %llu)\n", page->mapping->host->i_ino,
1922 dev->name, sector); 1923 start, rcu_str_deref(dev->name), sector);
1923 1924
1924 bio_put(bio); 1925 bio_put(bio);
1925 return 0; 1926 return 0;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 24b776c08d99..c5254dde1f0f 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -52,6 +52,7 @@
52#include "locking.h" 52#include "locking.h"
53#include "inode-map.h" 53#include "inode-map.h"
54#include "backref.h" 54#include "backref.h"
55#include "rcu-string.h"
55 56
56/* Mask out flags that are inappropriate for the given type of inode. */ 57/* Mask out flags that are inappropriate for the given type of inode. */
57static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags) 58static inline __u32 btrfs_mask_flags(umode_t mode, __u32 flags)
@@ -1345,8 +1346,9 @@ static noinline int btrfs_ioctl_resize(struct btrfs_root *root,
1345 do_div(new_size, root->sectorsize); 1346 do_div(new_size, root->sectorsize);
1346 new_size *= root->sectorsize; 1347 new_size *= root->sectorsize;
1347 1348
1348 printk(KERN_INFO "btrfs: new size for %s is %llu\n", 1349 printk_in_rcu(KERN_INFO "btrfs: new size for %s is %llu\n",
1349 device->name, (unsigned long long)new_size); 1350 rcu_str_deref(device->name),
1351 (unsigned long long)new_size);
1350 1352
1351 if (new_size > old_size) { 1353 if (new_size > old_size) {
1352 trans = btrfs_start_transaction(root, 0); 1354 trans = btrfs_start_transaction(root, 0);
@@ -2264,7 +2266,12 @@ static long btrfs_ioctl_dev_info(struct btrfs_root *root, void __user *arg)
2264 di_args->total_bytes = dev->total_bytes; 2266 di_args->total_bytes = dev->total_bytes;
2265 memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid)); 2267 memcpy(di_args->uuid, dev->uuid, sizeof(di_args->uuid));
2266 if (dev->name) { 2268 if (dev->name) {
2267 strncpy(di_args->path, dev->name, sizeof(di_args->path)); 2269 struct rcu_string *name;
2270
2271 rcu_read_lock();
2272 name = rcu_dereference(dev->name);
2273 strncpy(di_args->path, name->str, sizeof(di_args->path));
2274 rcu_read_unlock();
2268 di_args->path[sizeof(di_args->path) - 1] = 0; 2275 di_args->path[sizeof(di_args->path) - 1] = 0;
2269 } else { 2276 } else {
2270 di_args->path[0] = '\0'; 2277 di_args->path[0] = '\0';
diff --git a/fs/btrfs/rcu-string.h b/fs/btrfs/rcu-string.h
new file mode 100644
index 000000000000..9e111e4576d4
--- /dev/null
+++ b/fs/btrfs/rcu-string.h
@@ -0,0 +1,56 @@
1/*
2 * Copyright (C) 2012 Red Hat. 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
19struct rcu_string {
20 struct rcu_head rcu;
21 char str[0];
22};
23
24static inline struct rcu_string *rcu_string_strdup(const char *src, gfp_t mask)
25{
26 size_t len = strlen(src) + 1;
27 struct rcu_string *ret = kzalloc(sizeof(struct rcu_string) +
28 (len * sizeof(char)), mask);
29 if (!ret)
30 return ret;
31 strncpy(ret->str, src, len);
32 return ret;
33}
34
35static inline void rcu_string_free(struct rcu_string *str)
36{
37 if (str)
38 kfree_rcu(str, rcu);
39}
40
41#define printk_in_rcu(fmt, ...) do { \
42 rcu_read_lock(); \
43 printk(fmt, __VA_ARGS__); \
44 rcu_read_unlock(); \
45} while (0)
46
47#define printk_ratelimited_in_rcu(fmt, ...) do { \
48 rcu_read_lock(); \
49 printk_ratelimited(fmt, __VA_ARGS__); \
50 rcu_read_unlock(); \
51} while (0)
52
53#define rcu_str_deref(rcu_str) ({ \
54 struct rcu_string *__str = rcu_dereference(rcu_str); \
55 __str->str; \
56})
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index a38cfa4f251e..b223620cd5a6 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -26,6 +26,7 @@
26#include "backref.h" 26#include "backref.h"
27#include "extent_io.h" 27#include "extent_io.h"
28#include "check-integrity.h" 28#include "check-integrity.h"
29#include "rcu-string.h"
29 30
30/* 31/*
31 * This is only the first step towards a full-features scrub. It reads all 32 * This is only the first step towards a full-features scrub. It reads all
@@ -320,10 +321,10 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx)
320 * hold all of the paths here 321 * hold all of the paths here
321 */ 322 */
322 for (i = 0; i < ipath->fspath->elem_cnt; ++i) 323 for (i = 0; i < ipath->fspath->elem_cnt; ++i)
323 printk(KERN_WARNING "btrfs: %s at logical %llu on dev " 324 printk_in_rcu(KERN_WARNING "btrfs: %s at logical %llu on dev "
324 "%s, sector %llu, root %llu, inode %llu, offset %llu, " 325 "%s, sector %llu, root %llu, inode %llu, offset %llu, "
325 "length %llu, links %u (path: %s)\n", swarn->errstr, 326 "length %llu, links %u (path: %s)\n", swarn->errstr,
326 swarn->logical, swarn->dev->name, 327 swarn->logical, rcu_str_deref(swarn->dev->name),
327 (unsigned long long)swarn->sector, root, inum, offset, 328 (unsigned long long)swarn->sector, root, inum, offset,
328 min(isize - offset, (u64)PAGE_SIZE), nlink, 329 min(isize - offset, (u64)PAGE_SIZE), nlink,
329 (char *)(unsigned long)ipath->fspath->val[i]); 330 (char *)(unsigned long)ipath->fspath->val[i]);
@@ -332,10 +333,10 @@ static int scrub_print_warning_inode(u64 inum, u64 offset, u64 root, void *ctx)
332 return 0; 333 return 0;
333 334
334err: 335err:
335 printk(KERN_WARNING "btrfs: %s at logical %llu on dev " 336 printk_in_rcu(KERN_WARNING "btrfs: %s at logical %llu on dev "
336 "%s, sector %llu, root %llu, inode %llu, offset %llu: path " 337 "%s, sector %llu, root %llu, inode %llu, offset %llu: path "
337 "resolving failed with ret=%d\n", swarn->errstr, 338 "resolving failed with ret=%d\n", swarn->errstr,
338 swarn->logical, swarn->dev->name, 339 swarn->logical, rcu_str_deref(swarn->dev->name),
339 (unsigned long long)swarn->sector, root, inum, offset, ret); 340 (unsigned long long)swarn->sector, root, inum, offset, ret);
340 341
341 free_ipath(ipath); 342 free_ipath(ipath);
@@ -390,10 +391,11 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
390 do { 391 do {
391 ret = tree_backref_for_extent(&ptr, eb, ei, item_size, 392 ret = tree_backref_for_extent(&ptr, eb, ei, item_size,
392 &ref_root, &ref_level); 393 &ref_root, &ref_level);
393 printk(KERN_WARNING 394 printk_in_rcu(KERN_WARNING
394 "btrfs: %s at logical %llu on dev %s, " 395 "btrfs: %s at logical %llu on dev %s, "
395 "sector %llu: metadata %s (level %d) in tree " 396 "sector %llu: metadata %s (level %d) in tree "
396 "%llu\n", errstr, swarn.logical, dev->name, 397 "%llu\n", errstr, swarn.logical,
398 rcu_str_deref(dev->name),
397 (unsigned long long)swarn.sector, 399 (unsigned long long)swarn.sector,
398 ref_level ? "node" : "leaf", 400 ref_level ? "node" : "leaf",
399 ret < 0 ? -1 : ref_level, 401 ret < 0 ? -1 : ref_level,
@@ -580,9 +582,11 @@ out:
580 spin_lock(&sdev->stat_lock); 582 spin_lock(&sdev->stat_lock);
581 ++sdev->stat.uncorrectable_errors; 583 ++sdev->stat.uncorrectable_errors;
582 spin_unlock(&sdev->stat_lock); 584 spin_unlock(&sdev->stat_lock);
583 printk_ratelimited(KERN_ERR 585
586 printk_ratelimited_in_rcu(KERN_ERR
584 "btrfs: unable to fixup (nodatasum) error at logical %llu on dev %s\n", 587 "btrfs: unable to fixup (nodatasum) error at logical %llu on dev %s\n",
585 (unsigned long long)fixup->logical, sdev->dev->name); 588 (unsigned long long)fixup->logical,
589 rcu_str_deref(sdev->dev->name));
586 } 590 }
587 591
588 btrfs_free_path(path); 592 btrfs_free_path(path);
@@ -936,18 +940,20 @@ corrected_error:
936 spin_lock(&sdev->stat_lock); 940 spin_lock(&sdev->stat_lock);
937 sdev->stat.corrected_errors++; 941 sdev->stat.corrected_errors++;
938 spin_unlock(&sdev->stat_lock); 942 spin_unlock(&sdev->stat_lock);
939 printk_ratelimited(KERN_ERR 943 printk_ratelimited_in_rcu(KERN_ERR
940 "btrfs: fixed up error at logical %llu on dev %s\n", 944 "btrfs: fixed up error at logical %llu on dev %s\n",
941 (unsigned long long)logical, sdev->dev->name); 945 (unsigned long long)logical,
946 rcu_str_deref(sdev->dev->name));
942 } 947 }
943 } else { 948 } else {
944did_not_correct_error: 949did_not_correct_error:
945 spin_lock(&sdev->stat_lock); 950 spin_lock(&sdev->stat_lock);
946 sdev->stat.uncorrectable_errors++; 951 sdev->stat.uncorrectable_errors++;
947 spin_unlock(&sdev->stat_lock); 952 spin_unlock(&sdev->stat_lock);
948 printk_ratelimited(KERN_ERR 953 printk_ratelimited_in_rcu(KERN_ERR
949 "btrfs: unable to fixup (regular) error at logical %llu on dev %s\n", 954 "btrfs: unable to fixup (regular) error at logical %llu on dev %s\n",
950 (unsigned long long)logical, sdev->dev->name); 955 (unsigned long long)logical,
956 rcu_str_deref(sdev->dev->name));
951 } 957 }
952 958
953out: 959out:
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 7782020996fe..8a3d2594b807 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -35,6 +35,7 @@
35#include "volumes.h" 35#include "volumes.h"
36#include "async-thread.h" 36#include "async-thread.h"
37#include "check-integrity.h" 37#include "check-integrity.h"
38#include "rcu-string.h"
38 39
39static int init_first_rw_device(struct btrfs_trans_handle *trans, 40static int init_first_rw_device(struct btrfs_trans_handle *trans,
40 struct btrfs_root *root, 41 struct btrfs_root *root,
@@ -64,7 +65,7 @@ static void free_fs_devices(struct btrfs_fs_devices *fs_devices)
64 device = list_entry(fs_devices->devices.next, 65 device = list_entry(fs_devices->devices.next,
65 struct btrfs_device, dev_list); 66 struct btrfs_device, dev_list);
66 list_del(&device->dev_list); 67 list_del(&device->dev_list);
67 kfree(device->name); 68 rcu_string_free(device->name);
68 kfree(device); 69 kfree(device);
69 } 70 }
70 kfree(fs_devices); 71 kfree(fs_devices);
@@ -334,8 +335,8 @@ static noinline int device_list_add(const char *path,
334{ 335{
335 struct btrfs_device *device; 336 struct btrfs_device *device;
336 struct btrfs_fs_devices *fs_devices; 337 struct btrfs_fs_devices *fs_devices;
338 struct rcu_string *name;
337 u64 found_transid = btrfs_super_generation(disk_super); 339 u64 found_transid = btrfs_super_generation(disk_super);
338 char *name;
339 340
340 fs_devices = find_fsid(disk_super->fsid); 341 fs_devices = find_fsid(disk_super->fsid);
341 if (!fs_devices) { 342 if (!fs_devices) {
@@ -369,11 +370,13 @@ static noinline int device_list_add(const char *path,
369 memcpy(device->uuid, disk_super->dev_item.uuid, 370 memcpy(device->uuid, disk_super->dev_item.uuid,
370 BTRFS_UUID_SIZE); 371 BTRFS_UUID_SIZE);
371 spin_lock_init(&device->io_lock); 372 spin_lock_init(&device->io_lock);
372 device->name = kstrdup(path, GFP_NOFS); 373
373 if (!device->name) { 374 name = rcu_string_strdup(path, GFP_NOFS);
375 if (!name) {
374 kfree(device); 376 kfree(device);
375 return -ENOMEM; 377 return -ENOMEM;
376 } 378 }
379 rcu_assign_pointer(device->name, name);
377 INIT_LIST_HEAD(&device->dev_alloc_list); 380 INIT_LIST_HEAD(&device->dev_alloc_list);
378 381
379 /* init readahead state */ 382 /* init readahead state */
@@ -390,12 +393,12 @@ static noinline int device_list_add(const char *path,
390 393
391 device->fs_devices = fs_devices; 394 device->fs_devices = fs_devices;
392 fs_devices->num_devices++; 395 fs_devices->num_devices++;
393 } else if (!device->name || strcmp(device->name, path)) { 396 } else if (!device->name || strcmp(device->name->str, path)) {
394 name = kstrdup(path, GFP_NOFS); 397 name = rcu_string_strdup(path, GFP_NOFS);
395 if (!name) 398 if (!name)
396 return -ENOMEM; 399 return -ENOMEM;
397 kfree(device->name); 400 rcu_string_free(device->name);
398 device->name = name; 401 rcu_assign_pointer(device->name, name);
399 if (device->missing) { 402 if (device->missing) {
400 fs_devices->missing_devices--; 403 fs_devices->missing_devices--;
401 device->missing = 0; 404 device->missing = 0;
@@ -430,15 +433,22 @@ static struct btrfs_fs_devices *clone_fs_devices(struct btrfs_fs_devices *orig)
430 433
431 /* We have held the volume lock, it is safe to get the devices. */ 434 /* We have held the volume lock, it is safe to get the devices. */
432 list_for_each_entry(orig_dev, &orig->devices, dev_list) { 435 list_for_each_entry(orig_dev, &orig->devices, dev_list) {
436 struct rcu_string *name;
437
433 device = kzalloc(sizeof(*device), GFP_NOFS); 438 device = kzalloc(sizeof(*device), GFP_NOFS);
434 if (!device) 439 if (!device)
435 goto error; 440 goto error;
436 441
437 device->name = kstrdup(orig_dev->name, GFP_NOFS); 442 /*
438 if (!device->name) { 443 * This is ok to do without rcu read locked because we hold the
444 * uuid mutex so nothing we touch in here is going to disappear.
445 */
446 name = rcu_string_strdup(orig_dev->name->str, GFP_NOFS);
447 if (!name) {
439 kfree(device); 448 kfree(device);
440 goto error; 449 goto error;
441 } 450 }
451 rcu_assign_pointer(device->name, name);
442 452
443 device->devid = orig_dev->devid; 453 device->devid = orig_dev->devid;
444 device->work.func = pending_bios_fn; 454 device->work.func = pending_bios_fn;
@@ -491,7 +501,7 @@ again:
491 } 501 }
492 list_del_init(&device->dev_list); 502 list_del_init(&device->dev_list);
493 fs_devices->num_devices--; 503 fs_devices->num_devices--;
494 kfree(device->name); 504 rcu_string_free(device->name);
495 kfree(device); 505 kfree(device);
496 } 506 }
497 507
@@ -516,7 +526,7 @@ static void __free_device(struct work_struct *work)
516 if (device->bdev) 526 if (device->bdev)
517 blkdev_put(device->bdev, device->mode); 527 blkdev_put(device->bdev, device->mode);
518 528
519 kfree(device->name); 529 rcu_string_free(device->name);
520 kfree(device); 530 kfree(device);
521} 531}
522 532
@@ -540,6 +550,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
540 mutex_lock(&fs_devices->device_list_mutex); 550 mutex_lock(&fs_devices->device_list_mutex);
541 list_for_each_entry(device, &fs_devices->devices, dev_list) { 551 list_for_each_entry(device, &fs_devices->devices, dev_list) {
542 struct btrfs_device *new_device; 552 struct btrfs_device *new_device;
553 struct rcu_string *name;
543 554
544 if (device->bdev) 555 if (device->bdev)
545 fs_devices->open_devices--; 556 fs_devices->open_devices--;
@@ -555,8 +566,11 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
555 new_device = kmalloc(sizeof(*new_device), GFP_NOFS); 566 new_device = kmalloc(sizeof(*new_device), GFP_NOFS);
556 BUG_ON(!new_device); /* -ENOMEM */ 567 BUG_ON(!new_device); /* -ENOMEM */
557 memcpy(new_device, device, sizeof(*new_device)); 568 memcpy(new_device, device, sizeof(*new_device));
558 new_device->name = kstrdup(device->name, GFP_NOFS); 569
559 BUG_ON(device->name && !new_device->name); /* -ENOMEM */ 570 /* Safe because we are under uuid_mutex */
571 name = rcu_string_strdup(device->name->str, GFP_NOFS);
572 BUG_ON(device->name && !name); /* -ENOMEM */
573 rcu_assign_pointer(new_device->name, name);
560 new_device->bdev = NULL; 574 new_device->bdev = NULL;
561 new_device->writeable = 0; 575 new_device->writeable = 0;
562 new_device->in_fs_metadata = 0; 576 new_device->in_fs_metadata = 0;
@@ -621,9 +635,9 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
621 if (!device->name) 635 if (!device->name)
622 continue; 636 continue;
623 637
624 bdev = blkdev_get_by_path(device->name, flags, holder); 638 bdev = blkdev_get_by_path(device->name->str, flags, holder);
625 if (IS_ERR(bdev)) { 639 if (IS_ERR(bdev)) {
626 printk(KERN_INFO "open %s failed\n", device->name); 640 printk(KERN_INFO "open %s failed\n", device->name->str);
627 goto error; 641 goto error;
628 } 642 }
629 filemap_write_and_wait(bdev->bd_inode->i_mapping); 643 filemap_write_and_wait(bdev->bd_inode->i_mapping);
@@ -1632,6 +1646,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1632 struct block_device *bdev; 1646 struct block_device *bdev;
1633 struct list_head *devices; 1647 struct list_head *devices;
1634 struct super_block *sb = root->fs_info->sb; 1648 struct super_block *sb = root->fs_info->sb;
1649 struct rcu_string *name;
1635 u64 total_bytes; 1650 u64 total_bytes;
1636 int seeding_dev = 0; 1651 int seeding_dev = 0;
1637 int ret = 0; 1652 int ret = 0;
@@ -1671,23 +1686,24 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
1671 goto error; 1686 goto error;
1672 } 1687 }
1673 1688
1674 device->name = kstrdup(device_path, GFP_NOFS); 1689 name = rcu_string_strdup(device_path, GFP_NOFS);
1675 if (!device->name) { 1690 if (!name) {
1676 kfree(device); 1691 kfree(device);
1677 ret = -ENOMEM; 1692 ret = -ENOMEM;
1678 goto error; 1693 goto error;
1679 } 1694 }
1695 rcu_assign_pointer(device->name, name);
1680 1696
1681 ret = find_next_devid(root, &device->devid); 1697 ret = find_next_devid(root, &device->devid);
1682 if (ret) { 1698 if (ret) {
1683 kfree(device->name); 1699 rcu_string_free(device->name);
1684 kfree(device); 1700 kfree(device);
1685 goto error; 1701 goto error;
1686 } 1702 }
1687 1703
1688 trans = btrfs_start_transaction(root, 0); 1704 trans = btrfs_start_transaction(root, 0);
1689 if (IS_ERR(trans)) { 1705 if (IS_ERR(trans)) {
1690 kfree(device->name); 1706 rcu_string_free(device->name);
1691 kfree(device); 1707 kfree(device);
1692 ret = PTR_ERR(trans); 1708 ret = PTR_ERR(trans);
1693 goto error; 1709 goto error;
@@ -1796,7 +1812,7 @@ error_trans:
1796 unlock_chunks(root); 1812 unlock_chunks(root);
1797 btrfs_abort_transaction(trans, root, ret); 1813 btrfs_abort_transaction(trans, root, ret);
1798 btrfs_end_transaction(trans, root); 1814 btrfs_end_transaction(trans, root);
1799 kfree(device->name); 1815 rcu_string_free(device->name);
1800 kfree(device); 1816 kfree(device);
1801error: 1817error:
1802 blkdev_put(bdev, FMODE_EXCL); 1818 blkdev_put(bdev, FMODE_EXCL);
@@ -4204,10 +4220,17 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
4204 bio->bi_sector = bbio->stripes[dev_nr].physical >> 9; 4220 bio->bi_sector = bbio->stripes[dev_nr].physical >> 9;
4205 dev = bbio->stripes[dev_nr].dev; 4221 dev = bbio->stripes[dev_nr].dev;
4206 if (dev && dev->bdev && (rw != WRITE || dev->writeable)) { 4222 if (dev && dev->bdev && (rw != WRITE || dev->writeable)) {
4223#ifdef DEBUG
4224 struct rcu_string *name;
4225
4226 rcu_read_lock();
4227 name = rcu_dereference(dev->name);
4207 pr_debug("btrfs_map_bio: rw %d, secor=%llu, dev=%lu " 4228 pr_debug("btrfs_map_bio: rw %d, secor=%llu, dev=%lu "
4208 "(%s id %llu), size=%u\n", rw, 4229 "(%s id %llu), size=%u\n", rw,
4209 (u64)bio->bi_sector, (u_long)dev->bdev->bd_dev, 4230 (u64)bio->bi_sector, (u_long)dev->bdev->bd_dev,
4210 dev->name, dev->devid, bio->bi_size); 4231 name->str, dev->devid, bio->bi_size);
4232 rcu_read_unlock();
4233#endif
4211 bio->bi_bdev = dev->bdev; 4234 bio->bi_bdev = dev->bdev;
4212 if (async_submit) 4235 if (async_submit)
4213 schedule_bio(root, dev, rw, bio); 4236 schedule_bio(root, dev, rw, bio);
@@ -4694,8 +4717,9 @@ int btrfs_init_dev_stats(struct btrfs_fs_info *fs_info)
4694 key.offset = device->devid; 4717 key.offset = device->devid;
4695 ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0); 4718 ret = btrfs_search_slot(NULL, dev_root, &key, path, 0, 0);
4696 if (ret) { 4719 if (ret) {
4697 printk(KERN_WARNING "btrfs: no dev_stats entry found for device %s (devid %llu) (OK on first mount after mkfs)\n", 4720 printk_in_rcu(KERN_WARNING "btrfs: no dev_stats entry found for device %s (devid %llu) (OK on first mount after mkfs)\n",
4698 device->name, (unsigned long long)device->devid); 4721 rcu_str_deref(device->name),
4722 (unsigned long long)device->devid);
4699 __btrfs_reset_dev_stats(device); 4723 __btrfs_reset_dev_stats(device);
4700 device->dev_stats_valid = 1; 4724 device->dev_stats_valid = 1;
4701 btrfs_release_path(path); 4725 btrfs_release_path(path);
@@ -4747,8 +4771,8 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans,
4747 BUG_ON(!path); 4771 BUG_ON(!path);
4748 ret = btrfs_search_slot(trans, dev_root, &key, path, -1, 1); 4772 ret = btrfs_search_slot(trans, dev_root, &key, path, -1, 1);
4749 if (ret < 0) { 4773 if (ret < 0) {
4750 printk(KERN_WARNING "btrfs: error %d while searching for dev_stats item for device %s!\n", 4774 printk_in_rcu(KERN_WARNING "btrfs: error %d while searching for dev_stats item for device %s!\n",
4751 ret, device->name); 4775 ret, rcu_str_deref(device->name));
4752 goto out; 4776 goto out;
4753 } 4777 }
4754 4778
@@ -4757,8 +4781,8 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans,
4757 /* need to delete old one and insert a new one */ 4781 /* need to delete old one and insert a new one */
4758 ret = btrfs_del_item(trans, dev_root, path); 4782 ret = btrfs_del_item(trans, dev_root, path);
4759 if (ret != 0) { 4783 if (ret != 0) {
4760 printk(KERN_WARNING "btrfs: delete too small dev_stats item for device %s failed %d!\n", 4784 printk_in_rcu(KERN_WARNING "btrfs: delete too small dev_stats item for device %s failed %d!\n",
4761 device->name, ret); 4785 rcu_str_deref(device->name), ret);
4762 goto out; 4786 goto out;
4763 } 4787 }
4764 ret = 1; 4788 ret = 1;
@@ -4770,8 +4794,8 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans,
4770 ret = btrfs_insert_empty_item(trans, dev_root, path, 4794 ret = btrfs_insert_empty_item(trans, dev_root, path,
4771 &key, sizeof(*ptr)); 4795 &key, sizeof(*ptr));
4772 if (ret < 0) { 4796 if (ret < 0) {
4773 printk(KERN_WARNING "btrfs: insert dev_stats item for device %s failed %d!\n", 4797 printk_in_rcu(KERN_WARNING "btrfs: insert dev_stats item for device %s failed %d!\n",
4774 device->name, ret); 4798 rcu_str_deref(device->name), ret);
4775 goto out; 4799 goto out;
4776 } 4800 }
4777 } 4801 }
@@ -4823,9 +4847,9 @@ void btrfs_dev_stat_print_on_error(struct btrfs_device *dev)
4823{ 4847{
4824 if (!dev->dev_stats_valid) 4848 if (!dev->dev_stats_valid)
4825 return; 4849 return;
4826 printk_ratelimited(KERN_ERR 4850 printk_ratelimited_in_rcu(KERN_ERR
4827 "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n", 4851 "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n",
4828 dev->name, 4852 rcu_str_deref(dev->name),
4829 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS), 4853 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS),
4830 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS), 4854 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS),
4831 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_FLUSH_ERRS), 4855 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_FLUSH_ERRS),
@@ -4837,8 +4861,8 @@ void btrfs_dev_stat_print_on_error(struct btrfs_device *dev)
4837 4861
4838static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev) 4862static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev)
4839{ 4863{
4840 printk(KERN_INFO "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n", 4864 printk_in_rcu(KERN_INFO "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n",
4841 dev->name, 4865 rcu_str_deref(dev->name),
4842 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS), 4866 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS),
4843 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS), 4867 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS),
4844 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_FLUSH_ERRS), 4868 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_FLUSH_ERRS),
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 3406a88ca83e..74366f27a76b 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -58,7 +58,7 @@ struct btrfs_device {
58 /* the mode sent to blkdev_get */ 58 /* the mode sent to blkdev_get */
59 fmode_t mode; 59 fmode_t mode;
60 60
61 char *name; 61 struct rcu_string *name;
62 62
63 /* the internal btrfs device id */ 63 /* the internal btrfs device id */
64 u64 devid; 64 u64 devid;