mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 18:20:25 +02:00 
			
		
		
		
	Btrfs: add ioctl to get and reset the device stats
An ioctl interface is added to get the device statistic counters. A second ioctl is added to atomically get and reset these counters. Signed-off-by: Stefan Behrens <sbehrens@giantdisaster.de>
This commit is contained in:
		
							parent
							
								
									442a4f6308
								
							
						
					
					
						commit
						c11d2c236c
					
				
					 4 changed files with 77 additions and 0 deletions
				
			
		| 
						 | 
					@ -3046,6 +3046,28 @@ static long btrfs_ioctl_scrub_progress(struct btrfs_root *root,
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static long btrfs_ioctl_get_dev_stats(struct btrfs_root *root,
 | 
				
			||||||
 | 
									      void __user *arg, int reset_after_read)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct btrfs_ioctl_get_dev_stats *sa;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (reset_after_read && !capable(CAP_SYS_ADMIN))
 | 
				
			||||||
 | 
							return -EPERM;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sa = memdup_user(arg, sizeof(*sa));
 | 
				
			||||||
 | 
						if (IS_ERR(sa))
 | 
				
			||||||
 | 
							return PTR_ERR(sa);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = btrfs_get_dev_stats(root, sa, reset_after_read);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (copy_to_user(arg, sa, sizeof(*sa)))
 | 
				
			||||||
 | 
							ret = -EFAULT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						kfree(sa);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
 | 
					static long btrfs_ioctl_ino_to_path(struct btrfs_root *root, void __user *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int ret = 0;
 | 
						int ret = 0;
 | 
				
			||||||
| 
						 | 
					@ -3434,6 +3456,10 @@ long btrfs_ioctl(struct file *file, unsigned int
 | 
				
			||||||
		return btrfs_ioctl_balance_ctl(root, arg);
 | 
							return btrfs_ioctl_balance_ctl(root, arg);
 | 
				
			||||||
	case BTRFS_IOC_BALANCE_PROGRESS:
 | 
						case BTRFS_IOC_BALANCE_PROGRESS:
 | 
				
			||||||
		return btrfs_ioctl_balance_progress(root, argp);
 | 
							return btrfs_ioctl_balance_progress(root, argp);
 | 
				
			||||||
 | 
						case BTRFS_IOC_GET_DEV_STATS:
 | 
				
			||||||
 | 
							return btrfs_ioctl_get_dev_stats(root, argp, 0);
 | 
				
			||||||
 | 
						case BTRFS_IOC_GET_AND_RESET_DEV_STATS:
 | 
				
			||||||
 | 
							return btrfs_ioctl_get_dev_stats(root, argp, 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return -ENOTTY;
 | 
						return -ENOTTY;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -285,6 +285,16 @@ enum btrfs_dev_stat_values {
 | 
				
			||||||
	BTRFS_DEV_STAT_VALUES_MAX
 | 
						BTRFS_DEV_STAT_VALUES_MAX
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct btrfs_ioctl_get_dev_stats {
 | 
				
			||||||
 | 
						__u64 devid;				/* in */
 | 
				
			||||||
 | 
						__u64 nr_items;				/* in/out */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* out values: */
 | 
				
			||||||
 | 
						__u64 values[BTRFS_DEV_STAT_VALUES_MAX];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						__u64 unused[128 - 2 - BTRFS_DEV_STAT_VALUES_MAX]; /* pad to 1k */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
 | 
					#define BTRFS_IOC_SNAP_CREATE _IOW(BTRFS_IOCTL_MAGIC, 1, \
 | 
				
			||||||
				   struct btrfs_ioctl_vol_args)
 | 
									   struct btrfs_ioctl_vol_args)
 | 
				
			||||||
#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
 | 
					#define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \
 | 
				
			||||||
| 
						 | 
					@ -349,5 +359,9 @@ enum btrfs_dev_stat_values {
 | 
				
			||||||
					struct btrfs_ioctl_ino_path_args)
 | 
										struct btrfs_ioctl_ino_path_args)
 | 
				
			||||||
#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
 | 
					#define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \
 | 
				
			||||||
					struct btrfs_ioctl_ino_path_args)
 | 
										struct btrfs_ioctl_ino_path_args)
 | 
				
			||||||
 | 
					#define BTRFS_IOC_GET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 52, \
 | 
				
			||||||
 | 
									      struct btrfs_ioctl_get_dev_stats)
 | 
				
			||||||
 | 
					#define BTRFS_IOC_GET_AND_RESET_DEV_STATS _IOWR(BTRFS_IOCTL_MAGIC, 53, \
 | 
				
			||||||
 | 
										struct btrfs_ioctl_get_dev_stats)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4673,3 +4673,37 @@ void btrfs_dev_stat_print_on_error(struct btrfs_device *dev)
 | 
				
			||||||
			   btrfs_dev_stat_read(dev,
 | 
								   btrfs_dev_stat_read(dev,
 | 
				
			||||||
					       BTRFS_DEV_STAT_GENERATION_ERRS));
 | 
										       BTRFS_DEV_STAT_GENERATION_ERRS));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int btrfs_get_dev_stats(struct btrfs_root *root,
 | 
				
			||||||
 | 
								struct btrfs_ioctl_get_dev_stats *stats,
 | 
				
			||||||
 | 
								int reset_after_read)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct btrfs_device *dev;
 | 
				
			||||||
 | 
						struct btrfs_fs_devices *fs_devices = root->fs_info->fs_devices;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_lock(&fs_devices->device_list_mutex);
 | 
				
			||||||
 | 
						dev = btrfs_find_device(root, stats->devid, NULL, NULL);
 | 
				
			||||||
 | 
						mutex_unlock(&fs_devices->device_list_mutex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!dev) {
 | 
				
			||||||
 | 
							printk(KERN_WARNING
 | 
				
			||||||
 | 
							       "btrfs: get dev_stats failed, device not found\n");
 | 
				
			||||||
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
						} else if (reset_after_read) {
 | 
				
			||||||
 | 
							for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++) {
 | 
				
			||||||
 | 
								if (stats->nr_items > i)
 | 
				
			||||||
 | 
									stats->values[i] =
 | 
				
			||||||
 | 
										btrfs_dev_stat_read_and_reset(dev, i);
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									btrfs_dev_stat_reset(dev, i);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							for (i = 0; i < BTRFS_DEV_STAT_VALUES_MAX; i++)
 | 
				
			||||||
 | 
								if (stats->nr_items > i)
 | 
				
			||||||
 | 
									stats->values[i] = btrfs_dev_stat_read(dev, i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (stats->nr_items > BTRFS_DEV_STAT_VALUES_MAX)
 | 
				
			||||||
 | 
							stats->nr_items = BTRFS_DEV_STAT_VALUES_MAX;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -290,6 +290,9 @@ struct btrfs_device *btrfs_find_device_for_logical(struct btrfs_root *root,
 | 
				
			||||||
						   u64 logical, int mirror_num);
 | 
											   u64 logical, int mirror_num);
 | 
				
			||||||
void btrfs_dev_stat_print_on_error(struct btrfs_device *device);
 | 
					void btrfs_dev_stat_print_on_error(struct btrfs_device *device);
 | 
				
			||||||
void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index);
 | 
					void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index);
 | 
				
			||||||
 | 
					int btrfs_get_dev_stats(struct btrfs_root *root,
 | 
				
			||||||
 | 
								struct btrfs_ioctl_get_dev_stats *stats,
 | 
				
			||||||
 | 
								int reset_after_read);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline void btrfs_dev_stat_inc(struct btrfs_device *dev,
 | 
					static inline void btrfs_dev_stat_inc(struct btrfs_device *dev,
 | 
				
			||||||
				      int index)
 | 
									      int index)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue