mirror of
				https://github.com/torvalds/linux.git
				synced 2025-10-31 16:48:26 +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; | ||||
| } | ||||
| 
 | ||||
| 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) | ||||
| { | ||||
| 	int ret = 0; | ||||
|  | @ -3434,6 +3456,10 @@ long btrfs_ioctl(struct file *file, unsigned int | |||
| 		return btrfs_ioctl_balance_ctl(root, arg); | ||||
| 	case BTRFS_IOC_BALANCE_PROGRESS: | ||||
| 		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; | ||||
|  |  | |||
|  | @ -285,6 +285,16 @@ enum btrfs_dev_stat_values { | |||
| 	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, \ | ||||
| 				   struct btrfs_ioctl_vol_args) | ||||
| #define BTRFS_IOC_DEFRAG _IOW(BTRFS_IOCTL_MAGIC, 2, \ | ||||
|  | @ -349,5 +359,9 @@ enum btrfs_dev_stat_values { | |||
| 					struct btrfs_ioctl_ino_path_args) | ||||
| #define BTRFS_IOC_LOGICAL_INO _IOWR(BTRFS_IOCTL_MAGIC, 36, \ | ||||
| 					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 | ||||
|  |  | |||
|  | @ -4673,3 +4673,37 @@ void btrfs_dev_stat_print_on_error(struct btrfs_device *dev) | |||
| 			   btrfs_dev_stat_read(dev, | ||||
| 					       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); | ||||
| void btrfs_dev_stat_print_on_error(struct btrfs_device *device); | ||||
| 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, | ||||
| 				      int index) | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Stefan Behrens
						Stefan Behrens