Btrfs: fix wrong device bytes_used in the super block
[linux-2.6-block.git] / fs / btrfs / volumes.h
index 2aaa00c4781637f508302829ed51e3ae05402c84..f79d532fedb059801a8f96043bb96b1a300cd7e6 100644 (file)
@@ -36,37 +36,38 @@ struct btrfs_device {
        struct list_head dev_list;
        struct list_head dev_alloc_list;
        struct btrfs_fs_devices *fs_devices;
+
        struct btrfs_root *dev_root;
 
+       struct rcu_string *name;
+
+       u64 generation;
+
+       spinlock_t io_lock ____cacheline_aligned;
+       int running_pending;
        /* regular prio bios */
        struct btrfs_pending_bios pending_bios;
        /* WRITE_SYNC bios */
        struct btrfs_pending_bios pending_sync_bios;
 
-       u64 generation;
-       int running_pending;
+       struct block_device *bdev;
+
+       /* the mode sent to blkdev_get */
+       fmode_t mode;
+
        int writeable;
        int in_fs_metadata;
        int missing;
        int can_discard;
        int is_tgtdev_for_dev_replace;
 
-       spinlock_t io_lock;
-       /* the mode sent to blkdev_get */
-       fmode_t mode;
-
-       struct block_device *bdev;
-
-
-       struct rcu_string *name;
-
        /* the internal btrfs device id */
        u64 devid;
 
-       /* size of the device */
+       /* size of the device in memory */
        u64 total_bytes;
 
-       /* size of the disk */
+       /* size of the device on disk */
        u64 disk_total_bytes;
 
        /* bytes used */
@@ -83,10 +84,26 @@ struct btrfs_device {
        /* minimal io size for this device */
        u32 sector_size;
 
-
        /* physical drive uuid (or lvm uuid) */
        u8 uuid[BTRFS_UUID_SIZE];
 
+       /*
+        * size of the device on the current transaction
+        *
+        * This variant is update when committing the transaction,
+        * and protected by device_list_mutex
+        */
+       u64 commit_total_bytes;
+
+       /* bytes used on the current transaction */
+       u64 commit_bytes_used;
+       /*
+        * used to manage the device which is resized
+        *
+        * It is protected by chunk_lock.
+        */
+       struct list_head resized_list;
+
        /* for sending down flush barriers */
        int nobarriers;
        struct bio *flush_bio;
@@ -107,26 +124,23 @@ struct btrfs_device {
        struct radix_tree_root reada_zones;
        struct radix_tree_root reada_extents;
 
-
        /* disk I/O failure stats. For detailed description refer to
         * enum btrfs_dev_stat_values in ioctl.h */
        int dev_stats_valid;
-       int dev_stats_dirty; /* counters need to be written to disk */
+
+       /* Counter to record the change of device stats */
+       atomic_t dev_stats_ccnt;
        atomic_t dev_stat_values[BTRFS_DEV_STAT_VALUES_MAX];
 };
 
 struct btrfs_fs_devices {
        u8 fsid[BTRFS_FSID_SIZE]; /* FS specific uuid */
 
-       /* the device with this id has the most recent copy of the super */
-       u64 latest_devid;
-       u64 latest_trans;
        u64 num_devices;
        u64 open_devices;
        u64 rw_devices;
        u64 missing_devices;
        u64 total_rw_bytes;
-       u64 num_can_discard;
        u64 total_devices;
        struct block_device *latest_bdev;
 
@@ -139,6 +153,7 @@ struct btrfs_fs_devices {
        struct mutex device_list_mutex;
        struct list_head devices;
 
+       struct list_head resized_devices;
        /* devices not currently being allocated */
        struct list_head alloc_list;
        struct list_head list;
@@ -325,6 +340,7 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_info *fs_info, u64 devid,
 int btrfs_shrink_device(struct btrfs_device *device, u64 new_size);
 int btrfs_init_new_device(struct btrfs_root *root, char *path);
 int btrfs_init_dev_replace_tgtdev(struct btrfs_root *root, char *device_path,
+                                 struct btrfs_device *srcdev,
                                  struct btrfs_device **device_out);
 int btrfs_balance(struct btrfs_balance_control *bctl,
                  struct btrfs_ioctl_balance_args *bargs);
@@ -360,11 +376,18 @@ unsigned long btrfs_full_stripe_len(struct btrfs_root *root,
 int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
                                struct btrfs_root *extent_root,
                                u64 chunk_offset, u64 chunk_size);
+
+static inline int btrfs_dev_stats_dirty(struct btrfs_device *dev)
+{
+       return atomic_read(&dev->dev_stats_ccnt);
+}
+
 static inline void btrfs_dev_stat_inc(struct btrfs_device *dev,
                                      int index)
 {
        atomic_inc(dev->dev_stat_values + index);
-       dev->dev_stats_dirty = 1;
+       smp_mb__before_atomic();
+       atomic_inc(&dev->dev_stats_ccnt);
 }
 
 static inline int btrfs_dev_stat_read(struct btrfs_device *dev,
@@ -379,7 +402,8 @@ static inline int btrfs_dev_stat_read_and_reset(struct btrfs_device *dev,
        int ret;
 
        ret = atomic_xchg(dev->dev_stat_values + index, 0);
-       dev->dev_stats_dirty = 1;
+       smp_mb__before_atomic();
+       atomic_inc(&dev->dev_stats_ccnt);
        return ret;
 }
 
@@ -387,7 +411,8 @@ static inline void btrfs_dev_stat_set(struct btrfs_device *dev,
                                      int index, unsigned long val)
 {
        atomic_set(dev->dev_stat_values + index, val);
-       dev->dev_stats_dirty = 1;
+       smp_mb__before_atomic();
+       atomic_inc(&dev->dev_stats_ccnt);
 }
 
 static inline void btrfs_dev_stat_reset(struct btrfs_device *dev,
@@ -395,4 +420,8 @@ static inline void btrfs_dev_stat_reset(struct btrfs_device *dev,
 {
        btrfs_dev_stat_set(dev, index, 0);
 }
+
+void btrfs_update_commit_device_size(struct btrfs_fs_info *fs_info);
+void btrfs_update_commit_device_bytes_used(struct btrfs_root *root,
+                                       struct btrfs_transaction *transaction);
 #endif