diff mbox series

[3/5] btrfs: change the device allocation_hint property via sysfs

Message ID 7c56077a080b9ab77d1a722cb3bdde50e83895c4.1646589622.git.kreijack@inwind.it (mailing list archive)
State New, archived
Headers show
Series btrfs: allocation_hint | expand

Commit Message

Goffredo Baroncelli March 6, 2022, 6:14 p.m. UTC
From: Goffredo Baroncelli <kreijack@inwind.it>

This patch allow to change the allocation_hint property writing
a numerical value in the file.

/sysfs/fs/btrfs/<UUID>/devinfo/<devid>/allocation_hint

To update this field it is added the property "allocation_hint" in
btrfs-prog too.

Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
---
 fs/btrfs/sysfs.c   | 76 +++++++++++++++++++++++++++++++++++++++++++++-
 fs/btrfs/volumes.c |  2 +-
 fs/btrfs/volumes.h |  2 ++
 3 files changed, 78 insertions(+), 2 deletions(-)

Comments

Josef Bacik March 22, 2022, 7:19 p.m. UTC | #1
On Sun, Mar 06, 2022 at 07:14:41PM +0100, Goffredo Baroncelli wrote:
> From: Goffredo Baroncelli <kreijack@inwind.it>
> 
> This patch allow to change the allocation_hint property writing
> a numerical value in the file.
> 
> /sysfs/fs/btrfs/<UUID>/devinfo/<devid>/allocation_hint
> 
> To update this field it is added the property "allocation_hint" in
> btrfs-prog too.
> 
> Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
> ---
>  fs/btrfs/sysfs.c   | 76 +++++++++++++++++++++++++++++++++++++++++++++-
>  fs/btrfs/volumes.c |  2 +-
>  fs/btrfs/volumes.h |  2 ++
>  3 files changed, 78 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
> index 59d92a385a96..c6723456c0e1 100644
> --- a/fs/btrfs/sysfs.c
> +++ b/fs/btrfs/sysfs.c
> @@ -1606,7 +1606,81 @@ static ssize_t btrfs_devinfo_allocation_hint_show(struct kobject *kobj,
>  	}
>  	return scnprintf(buf, PAGE_SIZE, "<UNKNOWN>\n");
>  }
> -BTRFS_ATTR(devid, allocation_hint, btrfs_devinfo_allocation_hint_show);
> +
> +static ssize_t btrfs_devinfo_allocation_hint_store(struct kobject *kobj,
> +				 struct kobj_attribute *a,
> +				 const char *buf, size_t len)

If you're using vim, use

set cindent
set cino=(0

This will give you the proper formatting we expect, this should be something
like

statice ssize_t btrfs_devinfo_allocation_hint_store(struct kobject *kobj,
						    struct kobj_attribute *a,
						    const char *buf, size_t len)


> +{
> +	struct btrfs_fs_info *fs_info;
> +	struct btrfs_root *root;
> +	struct btrfs_device *device;
> +	int ret;
> +	struct btrfs_trans_handle *trans;
> +	int i, l;
> +	u64 type, prev_type;
> +
> +	if (len < 1)
> +		return -EINVAL;
> +
> +	/* remove trailing newline */
> +	l = len;
> +	if (buf[len-1] == '\n')
> +		l--;
> +

This is unnecessary, because lower you can do...

> +	for (i = 0 ; i < ARRAY_SIZE(allocation_hint_name) ; i++) {
> +		if (l != strlen(allocation_hint_name[i].name))
> +			continue;
> +
> +		if (strncasecmp(allocation_hint_name[i].name, buf, l))
> +			continue;
> +

strmatch(buf, allocation_hint_name[i].name)

I would make a separate patch to change strmatch to do strncasecmp instead, but
then you can just use that helper.

> +		type = allocation_hint_name[i].value;
> +		break;
> +	}
> +
> +	if (i >= ARRAY_SIZE(allocation_hint_name))
> +		return -EINVAL;
> +
> +	device = container_of(kobj, struct btrfs_device, devid_kobj);
> +	fs_info = device->fs_info;
> +	if (!fs_info)
> +		return -EPERM;
> +
> +	root = fs_info->chunk_root;
> +	if (sb_rdonly(fs_info->sb))
> +		return -EROFS;
> +
> +	/* check if a change is really needed */
> +	if ((device->type & BTRFS_DEV_ALLOCATION_HINT_MASK) == type)
> +		return len;
> +
> +	trans = btrfs_start_transaction(root, 1);
> +	if (IS_ERR(trans))
> +		return PTR_ERR(trans);
> +
> +	prev_type = device->type;
> +	device->type = (device->type & ~BTRFS_DEV_ALLOCATION_HINT_MASK) | type;
> +
> +	ret = btrfs_update_device(trans, device);
> +
> +	if (ret < 0) {
> +		btrfs_abort_transaction(trans, ret);
> +		btrfs_end_transaction(trans);
> +		goto abort;
> +	}
> +
> +	ret = btrfs_commit_transaction(trans);
> +	if (ret < 0)
> +		goto abort;
> +
> +	return len;
> +abort:
> +	device->type = prev_type;
> +	return  ret;

Extra whitespace here.

> +}
> +BTRFS_ATTR_RW(devid, allocation_hint, btrfs_devinfo_allocation_hint_show,
> +				      btrfs_devinfo_allocation_hint_store);
> +
>  
>  /*
>   * Information about one device.
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 5e3e13d4940b..d4ac90f5c949 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -2846,7 +2846,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
>  	return ret;
>  }
>  
> -static noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
> +noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
>  					struct btrfs_device *device)
>  {
>  	int ret;

You can drop the noinline thing here as well, and make sure to fix the
indentation.

> diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
> index bd297f23d19e..93ac27d8097c 100644
> --- a/fs/btrfs/volumes.h
> +++ b/fs/btrfs/volumes.h
> @@ -636,5 +636,7 @@ int btrfs_bg_type_to_factor(u64 flags);
>  const char *btrfs_bg_type_to_raid_name(u64 flags);
>  int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info);
>  bool btrfs_repair_one_zone(struct btrfs_fs_info *fs_info, u64 logical);
> +int btrfs_update_device(struct btrfs_trans_handle *trans,
> +			struct btrfs_device *device);

Make the indentation correct.  Thanks,

Josef
Goffredo Baroncelli March 22, 2022, 7:52 p.m. UTC | #2
On 22/03/2022 20.19, Josef Bacik wrote:
> On Sun, Mar 06, 2022 at 07:14:41PM +0100, Goffredo Baroncelli wrote:
>> From: Goffredo Baroncelli <kreijack@inwind.it>
>>
>> This patch allow to change the allocation_hint property writing
>> a numerical value in the file.
>>
>> /sysfs/fs/btrfs/<UUID>/devinfo/<devid>/allocation_hint
>>
>> To update this field it is added the property "allocation_hint" in
>> btrfs-prog too.
>>
>> Signed-off-by: Goffredo Baroncelli <kreijack@inwind.it>
>> ---
>>   fs/btrfs/sysfs.c   | 76 +++++++++++++++++++++++++++++++++++++++++++++-
>>   fs/btrfs/volumes.c |  2 +-
>>   fs/btrfs/volumes.h |  2 ++
>>   3 files changed, 78 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
>> index 59d92a385a96..c6723456c0e1 100644
>> --- a/fs/btrfs/sysfs.c
>> +++ b/fs/btrfs/sysfs.c
>> @@ -1606,7 +1606,81 @@ static ssize_t btrfs_devinfo_allocation_hint_show(struct kobject *kobj,
>>   	}
>>   	return scnprintf(buf, PAGE_SIZE, "<UNKNOWN>\n");
>>   }
>> -BTRFS_ATTR(devid, allocation_hint, btrfs_devinfo_allocation_hint_show);
>> +
>> +static ssize_t btrfs_devinfo_allocation_hint_store(struct kobject *kobj,
>> +				 struct kobj_attribute *a,
>> +				 const char *buf, size_t len)
> 
> If you're using vim, use
> 
> set cindent
> set cino=(0
> 
> This will give you the proper formatting we expect, this should be something
> like
> 
> statice ssize_t btrfs_devinfo_allocation_hint_store(struct kobject *kobj,
> 						    struct kobj_attribute *a,
> 						    const char *buf, size_t len)
> 
> 
>> +{
>> +	struct btrfs_fs_info *fs_info;
>> +	struct btrfs_root *root;
>> +	struct btrfs_device *device;
>> +	int ret;
>> +	struct btrfs_trans_handle *trans;
>> +	int i, l;
>> +	u64 type, prev_type;
>> +
>> +	if (len < 1)
>> +		return -EINVAL;
>> +
>> +	/* remove trailing newline */
>> +	l = len;
>> +	if (buf[len-1] == '\n')
>> +		l--;
>> +
> 
> This is unnecessary, because lower you can do...
> 
>> +	for (i = 0 ; i < ARRAY_SIZE(allocation_hint_name) ; i++) {
>> +		if (l != strlen(allocation_hint_name[i].name))
>> +			continue;
>> +
>> +		if (strncasecmp(allocation_hint_name[i].name, buf, l))
>> +			continue;
>> +
> 
> strmatch(buf, allocation_hint_name[i].name)
> 
> I would make a separate patch to change strmatch to do strncasecmp instead, but
> then you can just use that helper.

Looking at the code of strmatch()

   /*
    * Look for an exact string @string in @buffer with possible leading or
    * trailing whitespace
    */
   static bool strmatch(const char *buffer, const char *string)
   {
           const size_t len = strlen(string);
   
           /* Skip leading whitespace */
           buffer = skip_spaces(buffer);
   
           /* Match entire string, check if the rest is whitespace or empty */
           if (strncmp(string, buffer, len) == 0 &&
               strlen(skip_spaces(buffer + len)) == 0)
                   return true;
   
           return false;
   }

Is buf always zero terminated ?


> 
>> +		type = allocation_hint_name[i].value;
>> +		break;
>> +	}
>> +
>> +	if (i >= ARRAY_SIZE(allocation_hint_name))
>> +		return -EINVAL;
>> +
>> +	device = container_of(kobj, struct btrfs_device, devid_kobj);
>> +	fs_info = device->fs_info;
>> +	if (!fs_info)
>> +		return -EPERM;
>> +
>> +	root = fs_info->chunk_root;
>> +	if (sb_rdonly(fs_info->sb))
>> +		return -EROFS;
>> +
>> +	/* check if a change is really needed */
>> +	if ((device->type & BTRFS_DEV_ALLOCATION_HINT_MASK) == type)
>> +		return len;
>> +
>> +	trans = btrfs_start_transaction(root, 1);
>> +	if (IS_ERR(trans))
>> +		return PTR_ERR(trans);
>> +
>> +	prev_type = device->type;
>> +	device->type = (device->type & ~BTRFS_DEV_ALLOCATION_HINT_MASK) | type;
>> +
>> +	ret = btrfs_update_device(trans, device);
>> +
>> +	if (ret < 0) {
>> +		btrfs_abort_transaction(trans, ret);
>> +		btrfs_end_transaction(trans);
>> +		goto abort;
>> +	}
>> +
>> +	ret = btrfs_commit_transaction(trans);
>> +	if (ret < 0)
>> +		goto abort;
>> +
>> +	return len;
>> +abort:
>> +	device->type = prev_type;
>> +	return  ret;
> 
> Extra whitespace here.
Ok
> 
>> +}
>> +BTRFS_ATTR_RW(devid, allocation_hint, btrfs_devinfo_allocation_hint_show,
>> +				      btrfs_devinfo_allocation_hint_store);
>> +
>>   
>>   /*
>>    * Information about one device.
>> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
>> index 5e3e13d4940b..d4ac90f5c949 100644
>> --- a/fs/btrfs/volumes.c
>> +++ b/fs/btrfs/volumes.c
>> @@ -2846,7 +2846,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
>>   	return ret;
>>   }
>>   
>> -static noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
>> +noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
>>   					struct btrfs_device *device)
>>   {
>>   	int ret;
> 
> You can drop the noinline thing here as well, and make sure to fix the
> indentation.
Ok
> 
>> diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
>> index bd297f23d19e..93ac27d8097c 100644
>> --- a/fs/btrfs/volumes.h
>> +++ b/fs/btrfs/volumes.h
>> @@ -636,5 +636,7 @@ int btrfs_bg_type_to_factor(u64 flags);
>>   const char *btrfs_bg_type_to_raid_name(u64 flags);
>>   int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info);
>>   bool btrfs_repair_one_zone(struct btrfs_fs_info *fs_info, u64 logical);
>> +int btrfs_update_device(struct btrfs_trans_handle *trans,
>> +			struct btrfs_device *device);
> 
> Make the indentation correct.  Thanks,

It is correct. Are the '+' and the tab that misaligned the patch.

> 
> Josef
diff mbox series

Patch

diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index 59d92a385a96..c6723456c0e1 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -1606,7 +1606,81 @@  static ssize_t btrfs_devinfo_allocation_hint_show(struct kobject *kobj,
 	}
 	return scnprintf(buf, PAGE_SIZE, "<UNKNOWN>\n");
 }
-BTRFS_ATTR(devid, allocation_hint, btrfs_devinfo_allocation_hint_show);
+
+static ssize_t btrfs_devinfo_allocation_hint_store(struct kobject *kobj,
+				 struct kobj_attribute *a,
+				 const char *buf, size_t len)
+{
+	struct btrfs_fs_info *fs_info;
+	struct btrfs_root *root;
+	struct btrfs_device *device;
+	int ret;
+	struct btrfs_trans_handle *trans;
+	int i, l;
+	u64 type, prev_type;
+
+	if (len < 1)
+		return -EINVAL;
+
+	/* remove trailing newline */
+	l = len;
+	if (buf[len-1] == '\n')
+		l--;
+
+	for (i = 0 ; i < ARRAY_SIZE(allocation_hint_name) ; i++) {
+		if (l != strlen(allocation_hint_name[i].name))
+			continue;
+
+		if (strncasecmp(allocation_hint_name[i].name, buf, l))
+			continue;
+
+		type = allocation_hint_name[i].value;
+		break;
+	}
+
+	if (i >= ARRAY_SIZE(allocation_hint_name))
+		return -EINVAL;
+
+	device = container_of(kobj, struct btrfs_device, devid_kobj);
+	fs_info = device->fs_info;
+	if (!fs_info)
+		return -EPERM;
+
+	root = fs_info->chunk_root;
+	if (sb_rdonly(fs_info->sb))
+		return -EROFS;
+
+	/* check if a change is really needed */
+	if ((device->type & BTRFS_DEV_ALLOCATION_HINT_MASK) == type)
+		return len;
+
+	trans = btrfs_start_transaction(root, 1);
+	if (IS_ERR(trans))
+		return PTR_ERR(trans);
+
+	prev_type = device->type;
+	device->type = (device->type & ~BTRFS_DEV_ALLOCATION_HINT_MASK) | type;
+
+	ret = btrfs_update_device(trans, device);
+
+	if (ret < 0) {
+		btrfs_abort_transaction(trans, ret);
+		btrfs_end_transaction(trans);
+		goto abort;
+	}
+
+	ret = btrfs_commit_transaction(trans);
+	if (ret < 0)
+		goto abort;
+
+	return len;
+abort:
+	device->type = prev_type;
+	return  ret;
+}
+BTRFS_ATTR_RW(devid, allocation_hint, btrfs_devinfo_allocation_hint_show,
+				      btrfs_devinfo_allocation_hint_store);
+
 
 /*
  * Information about one device.
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 5e3e13d4940b..d4ac90f5c949 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -2846,7 +2846,7 @@  int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
 	return ret;
 }
 
-static noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
+noinline int btrfs_update_device(struct btrfs_trans_handle *trans,
 					struct btrfs_device *device)
 {
 	int ret;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index bd297f23d19e..93ac27d8097c 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -636,5 +636,7 @@  int btrfs_bg_type_to_factor(u64 flags);
 const char *btrfs_bg_type_to_raid_name(u64 flags);
 int btrfs_verify_dev_extents(struct btrfs_fs_info *fs_info);
 bool btrfs_repair_one_zone(struct btrfs_fs_info *fs_info, u64 logical);
+int btrfs_update_device(struct btrfs_trans_handle *trans,
+			struct btrfs_device *device);
 
 #endif