[v2,1/2] ocfs2: add trimfs dlm lock resource
diff mbox

Message ID 1513228484-2084-1-git-send-email-ghe@suse.com
State New
Headers show

Commit Message

Gang He Dec. 14, 2017, 5:14 a.m. UTC
Introduce a new dlm lock resource, which will be used to
communicate during fstrim a ocfs2 device from cluster nodes.

Signed-off-by: Gang He <ghe@suse.com>
---
 fs/ocfs2/dlmglue.c      | 86 +++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ocfs2/dlmglue.h      | 29 +++++++++++++++++
 fs/ocfs2/ocfs2.h        |  1 +
 fs/ocfs2/ocfs2_lockid.h |  5 +++
 4 files changed, 121 insertions(+)

Comments

Changwei Ge Jan. 10, 2018, 6:40 a.m. UTC | #1
Hi Gang,

On 2017/12/14 13:16, Gang He wrote:
> Introduce a new dlm lock resource, which will be used to
> communicate during fstrim a ocfs2 device from cluster nodes.
> 
> Signed-off-by: Gang He <ghe@suse.com>
> ---
>   fs/ocfs2/dlmglue.c      | 86 +++++++++++++++++++++++++++++++++++++++++++++++++
>   fs/ocfs2/dlmglue.h      | 29 +++++++++++++++++
>   fs/ocfs2/ocfs2.h        |  1 +
>   fs/ocfs2/ocfs2_lockid.h |  5 +++
>   4 files changed, 121 insertions(+)
> 
> diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
> index 4689940..5615747 100644
> --- a/fs/ocfs2/dlmglue.c
> +++ b/fs/ocfs2/dlmglue.c
> @@ -259,6 +259,10 @@ struct ocfs2_lock_res_ops {
>   	.flags		= 0,
>   };
>   
> +static struct ocfs2_lock_res_ops ocfs2_trim_fs_lops = {
> +	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,

Um, I don't think it is proper to add flag LOCK_TYPE_REQUIRES_REFRESH.
Because it seems that trimfs procedure doesn't have to persist stuff into disk.

Thanks,
Changwei

> +};
> +
>   static struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = {
>   	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
>   };
> @@ -676,6 +680,24 @@ static void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res,
>   				   &ocfs2_nfs_sync_lops, osb);
>   }
>   
> +void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb)
> +{
> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
> +
> +	ocfs2_lock_res_init_once(lockres);
> +	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_TRIM_FS, 0, 0, lockres->l_name);
> +	ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_TRIM_FS,
> +				   &ocfs2_trim_fs_lops, osb);
> +}
> +
> +void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb)
> +{
> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
> +
> +	ocfs2_simple_drop_lockres(osb, lockres);
> +	ocfs2_lock_res_free(lockres);
> +}
> +
>   static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
>   					    struct ocfs2_super *osb)
>   {
> @@ -2745,6 +2767,70 @@ void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, int ex)
>   				     ex ? LKM_EXMODE : LKM_PRMODE);
>   }
>   
> +int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
> +		       struct ocfs2_trim_fs_info *info, int trylock)
> +{
> +	int status;
> +	struct ocfs2_trim_fs_lvb *lvb;
> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
> +
> +	if (info)
> +		info->tf_valid = 0;
> +
> +	if (ocfs2_is_hard_readonly(osb))
> +		return -EROFS;
> +
> +	if (ocfs2_mount_local(osb))
> +		return 0;
> +
> +	status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX,
> +				    trylock ? DLM_LKF_NOQUEUE : 0, 0);
> +	if (status < 0) {
> +		if (status != -EAGAIN)
> +			mlog_errno(status);
> +		return status;
> +	}
> +
> +	if (info) {
> +		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
> +		if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) &&
> +		    lvb->lvb_version == OCFS2_TRIMFS_LVB_VERSION) {
> +			info->tf_valid = 1;
> +			info->tf_success = lvb->lvb_success;
> +			info->tf_nodenum = be32_to_cpu(lvb->lvb_nodenum);
> +			info->tf_start = be64_to_cpu(lvb->lvb_start);
> +			info->tf_len = be64_to_cpu(lvb->lvb_len);
> +			info->tf_minlen = be64_to_cpu(lvb->lvb_minlen);
> +			info->tf_trimlen = be64_to_cpu(lvb->lvb_trimlen);
> +		}
> +	}
> +
> +	return status;
> +}
> +
> +void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
> +			  struct ocfs2_trim_fs_info *info)
> +{
> +	struct ocfs2_trim_fs_lvb *lvb;
> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
> +
> +	if (ocfs2_mount_local(osb))
> +		return;
> +
> +	if (info) {
> +		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
> +		lvb->lvb_version = OCFS2_TRIMFS_LVB_VERSION;
> +		lvb->lvb_success = info->tf_success;
> +		lvb->lvb_nodenum = cpu_to_be32(info->tf_nodenum);
> +		lvb->lvb_start = cpu_to_be64(info->tf_start);
> +		lvb->lvb_len = cpu_to_be64(info->tf_len);
> +		lvb->lvb_minlen = cpu_to_be64(info->tf_minlen);
> +		lvb->lvb_trimlen = cpu_to_be64(info->tf_trimlen);
> +	}
> +
> +	ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
> +}
> +
>   int ocfs2_dentry_lock(struct dentry *dentry, int ex)
>   {
>   	int ret;
> diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
> index a7fc18b..2253688 100644
> --- a/fs/ocfs2/dlmglue.h
> +++ b/fs/ocfs2/dlmglue.h
> @@ -70,6 +70,29 @@ struct ocfs2_orphan_scan_lvb {
>   	__be32	lvb_os_seqno;
>   };
>   
> +#define OCFS2_TRIMFS_LVB_VERSION 1
> +
> +struct ocfs2_trim_fs_lvb {
> +	__u8	lvb_version;
> +	__u8	lvb_success;
> +	__u8	lvb_reserved[2];
> +	__be32	lvb_nodenum;
> +	__be64	lvb_start;
> +	__be64	lvb_len;
> +	__be64	lvb_minlen;
> +	__be64	lvb_trimlen;
> +};
> +
> +struct ocfs2_trim_fs_info {
> +	u8	tf_valid;	/* lvb is valid, or not */
> +	u8	tf_success;	/* trim is successful, or not */
> +	u32	tf_nodenum;	/* osb node number */
> +	u64	tf_start;	/* trim start offset in clusters */
> +	u64	tf_len;		/* trim end offset in clusters */
> +	u64	tf_minlen;	/* trim minimum contiguous free clusters */
> +	u64	tf_trimlen;	/* trimmed length in bytes */
> +};
> +
>   struct ocfs2_lock_holder {
>   	struct list_head oh_list;
>   	struct pid *oh_owner_pid;
> @@ -153,6 +176,12 @@ void ocfs2_super_unlock(struct ocfs2_super *osb,
>   void ocfs2_rename_unlock(struct ocfs2_super *osb);
>   int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex);
>   void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, int ex);
> +void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb);
> +void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb);
> +int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
> +		       struct ocfs2_trim_fs_info *info, int trylock);
> +void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
> +			  struct ocfs2_trim_fs_info *info);
>   int ocfs2_dentry_lock(struct dentry *dentry, int ex);
>   void ocfs2_dentry_unlock(struct dentry *dentry, int ex);
>   int ocfs2_file_lock(struct file *file, int ex, int trylock);
> diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
> index 9a50f22..6867eef 100644
> --- a/fs/ocfs2/ocfs2.h
> +++ b/fs/ocfs2/ocfs2.h
> @@ -404,6 +404,7 @@ struct ocfs2_super
>   	struct ocfs2_lock_res osb_super_lockres;
>   	struct ocfs2_lock_res osb_rename_lockres;
>   	struct ocfs2_lock_res osb_nfs_sync_lockres;
> +	struct ocfs2_lock_res osb_trim_fs_lockres;
>   	struct ocfs2_dlm_debug *osb_dlm_debug;
>   
>   	struct dentry *osb_debug_root;
> diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
> index d277aab..7051b99 100644
> --- a/fs/ocfs2/ocfs2_lockid.h
> +++ b/fs/ocfs2/ocfs2_lockid.h
> @@ -50,6 +50,7 @@ enum ocfs2_lock_type {
>   	OCFS2_LOCK_TYPE_NFS_SYNC,
>   	OCFS2_LOCK_TYPE_ORPHAN_SCAN,
>   	OCFS2_LOCK_TYPE_REFCOUNT,
> +	OCFS2_LOCK_TYPE_TRIM_FS,
>   	OCFS2_NUM_LOCK_TYPES
>   };
>   
> @@ -93,6 +94,9 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
>   		case OCFS2_LOCK_TYPE_REFCOUNT:
>   			c = 'T';
>   			break;
> +		case OCFS2_LOCK_TYPE_TRIM_FS:
> +			c = 'I';
> +			break;
>   		default:
>   			c = '\0';
>   	}
> @@ -115,6 +119,7 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
>   	[OCFS2_LOCK_TYPE_NFS_SYNC] = "NFSSync",
>   	[OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan",
>   	[OCFS2_LOCK_TYPE_REFCOUNT] = "Refcount",
> +	[OCFS2_LOCK_TYPE_TRIM_FS] = "TrimFs",
>   };
>   
>   static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
>
Gang He Jan. 10, 2018, 8:40 a.m. UTC | #2
Hi Changwei,


>>> 
> Hi Gang,
> 
> On 2017/12/14 13:16, Gang He wrote:
>> Introduce a new dlm lock resource, which will be used to
>> communicate during fstrim a ocfs2 device from cluster nodes.
>> 
>> Signed-off-by: Gang He <ghe@suse.com>
>> ---
>>   fs/ocfs2/dlmglue.c      | 86 
> +++++++++++++++++++++++++++++++++++++++++++++++++
>>   fs/ocfs2/dlmglue.h      | 29 +++++++++++++++++
>>   fs/ocfs2/ocfs2.h        |  1 +
>>   fs/ocfs2/ocfs2_lockid.h |  5 +++
>>   4 files changed, 121 insertions(+)
>> 
>> diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
>> index 4689940..5615747 100644
>> --- a/fs/ocfs2/dlmglue.c
>> +++ b/fs/ocfs2/dlmglue.c
>> @@ -259,6 +259,10 @@ struct ocfs2_lock_res_ops {
>>   	.flags		= 0,
>>   };
>>   
>> +static struct ocfs2_lock_res_ops ocfs2_trim_fs_lops = {
>> +	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
> 
> Um, I don't think it is proper to add flag LOCK_TYPE_REQUIRES_REFRESH.
> Because it seems that trimfs procedure doesn't have to persist stuff into 
> disk.
I just copy for the ocfs2_orphan_scan_lops code, maybe the flag is not necessary,
I will look at the related code, then give a feedback.

Thanks
Gang 

> 
> Thanks,
> Changwei
> 
>> +};
>> +
>>   static struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = {
>>   	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
>>   };
>> @@ -676,6 +680,24 @@ static void ocfs2_nfs_sync_lock_res_init(struct 
> ocfs2_lock_res *res,
>>   				   &ocfs2_nfs_sync_lops, osb);
>>   }
>>   
>> +void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb)
>> +{
>> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
>> +
>> +	ocfs2_lock_res_init_once(lockres);
>> +	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_TRIM_FS, 0, 0, lockres->l_name);
>> +	ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_TRIM_FS,
>> +				   &ocfs2_trim_fs_lops, osb);
>> +}
>> +
>> +void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb)
>> +{
>> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
>> +
>> +	ocfs2_simple_drop_lockres(osb, lockres);
>> +	ocfs2_lock_res_free(lockres);
>> +}
>> +
>>   static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
>>   					    struct ocfs2_super *osb)
>>   {
>> @@ -2745,6 +2767,70 @@ void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, 
> int ex)
>>   				     ex ? LKM_EXMODE : LKM_PRMODE);
>>   }
>>   
>> +int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
>> +		       struct ocfs2_trim_fs_info *info, int trylock)
>> +{
>> +	int status;
>> +	struct ocfs2_trim_fs_lvb *lvb;
>> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
>> +
>> +	if (info)
>> +		info->tf_valid = 0;
>> +
>> +	if (ocfs2_is_hard_readonly(osb))
>> +		return -EROFS;
>> +
>> +	if (ocfs2_mount_local(osb))
>> +		return 0;
>> +
>> +	status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX,
>> +				    trylock ? DLM_LKF_NOQUEUE : 0, 0);
>> +	if (status < 0) {
>> +		if (status != -EAGAIN)
>> +			mlog_errno(status);
>> +		return status;
>> +	}
>> +
>> +	if (info) {
>> +		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
>> +		if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) &&
>> +		    lvb->lvb_version == OCFS2_TRIMFS_LVB_VERSION) {
>> +			info->tf_valid = 1;
>> +			info->tf_success = lvb->lvb_success;
>> +			info->tf_nodenum = be32_to_cpu(lvb->lvb_nodenum);
>> +			info->tf_start = be64_to_cpu(lvb->lvb_start);
>> +			info->tf_len = be64_to_cpu(lvb->lvb_len);
>> +			info->tf_minlen = be64_to_cpu(lvb->lvb_minlen);
>> +			info->tf_trimlen = be64_to_cpu(lvb->lvb_trimlen);
>> +		}
>> +	}
>> +
>> +	return status;
>> +}
>> +
>> +void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
>> +			  struct ocfs2_trim_fs_info *info)
>> +{
>> +	struct ocfs2_trim_fs_lvb *lvb;
>> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
>> +
>> +	if (ocfs2_mount_local(osb))
>> +		return;
>> +
>> +	if (info) {
>> +		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
>> +		lvb->lvb_version = OCFS2_TRIMFS_LVB_VERSION;
>> +		lvb->lvb_success = info->tf_success;
>> +		lvb->lvb_nodenum = cpu_to_be32(info->tf_nodenum);
>> +		lvb->lvb_start = cpu_to_be64(info->tf_start);
>> +		lvb->lvb_len = cpu_to_be64(info->tf_len);
>> +		lvb->lvb_minlen = cpu_to_be64(info->tf_minlen);
>> +		lvb->lvb_trimlen = cpu_to_be64(info->tf_trimlen);
>> +	}
>> +
>> +	ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
>> +}
>> +
>>   int ocfs2_dentry_lock(struct dentry *dentry, int ex)
>>   {
>>   	int ret;
>> diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
>> index a7fc18b..2253688 100644
>> --- a/fs/ocfs2/dlmglue.h
>> +++ b/fs/ocfs2/dlmglue.h
>> @@ -70,6 +70,29 @@ struct ocfs2_orphan_scan_lvb {
>>   	__be32	lvb_os_seqno;
>>   };
>>   
>> +#define OCFS2_TRIMFS_LVB_VERSION 1
>> +
>> +struct ocfs2_trim_fs_lvb {
>> +	__u8	lvb_version;
>> +	__u8	lvb_success;
>> +	__u8	lvb_reserved[2];
>> +	__be32	lvb_nodenum;
>> +	__be64	lvb_start;
>> +	__be64	lvb_len;
>> +	__be64	lvb_minlen;
>> +	__be64	lvb_trimlen;
>> +};
>> +
>> +struct ocfs2_trim_fs_info {
>> +	u8	tf_valid;	/* lvb is valid, or not */
>> +	u8	tf_success;	/* trim is successful, or not */
>> +	u32	tf_nodenum;	/* osb node number */
>> +	u64	tf_start;	/* trim start offset in clusters */
>> +	u64	tf_len;		/* trim end offset in clusters */
>> +	u64	tf_minlen;	/* trim minimum contiguous free clusters */
>> +	u64	tf_trimlen;	/* trimmed length in bytes */
>> +};
>> +
>>   struct ocfs2_lock_holder {
>>   	struct list_head oh_list;
>>   	struct pid *oh_owner_pid;
>> @@ -153,6 +176,12 @@ void ocfs2_super_unlock(struct ocfs2_super *osb,
>>   void ocfs2_rename_unlock(struct ocfs2_super *osb);
>>   int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex);
>>   void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, int ex);
>> +void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb);
>> +void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb);
>> +int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
>> +		       struct ocfs2_trim_fs_info *info, int trylock);
>> +void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
>> +			  struct ocfs2_trim_fs_info *info);
>>   int ocfs2_dentry_lock(struct dentry *dentry, int ex);
>>   void ocfs2_dentry_unlock(struct dentry *dentry, int ex);
>>   int ocfs2_file_lock(struct file *file, int ex, int trylock);
>> diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
>> index 9a50f22..6867eef 100644
>> --- a/fs/ocfs2/ocfs2.h
>> +++ b/fs/ocfs2/ocfs2.h
>> @@ -404,6 +404,7 @@ struct ocfs2_super
>>   	struct ocfs2_lock_res osb_super_lockres;
>>   	struct ocfs2_lock_res osb_rename_lockres;
>>   	struct ocfs2_lock_res osb_nfs_sync_lockres;
>> +	struct ocfs2_lock_res osb_trim_fs_lockres;
>>   	struct ocfs2_dlm_debug *osb_dlm_debug;
>>   
>>   	struct dentry *osb_debug_root;
>> diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
>> index d277aab..7051b99 100644
>> --- a/fs/ocfs2/ocfs2_lockid.h
>> +++ b/fs/ocfs2/ocfs2_lockid.h
>> @@ -50,6 +50,7 @@ enum ocfs2_lock_type {
>>   	OCFS2_LOCK_TYPE_NFS_SYNC,
>>   	OCFS2_LOCK_TYPE_ORPHAN_SCAN,
>>   	OCFS2_LOCK_TYPE_REFCOUNT,
>> +	OCFS2_LOCK_TYPE_TRIM_FS,
>>   	OCFS2_NUM_LOCK_TYPES
>>   };
>>   
>> @@ -93,6 +94,9 @@ static inline char ocfs2_lock_type_char(enum 
> ocfs2_lock_type type)
>>   		case OCFS2_LOCK_TYPE_REFCOUNT:
>>   			c = 'T';
>>   			break;
>> +		case OCFS2_LOCK_TYPE_TRIM_FS:
>> +			c = 'I';
>> +			break;
>>   		default:
>>   			c = '\0';
>>   	}
>> @@ -115,6 +119,7 @@ static inline char ocfs2_lock_type_char(enum 
> ocfs2_lock_type type)
>>   	[OCFS2_LOCK_TYPE_NFS_SYNC] = "NFSSync",
>>   	[OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan",
>>   	[OCFS2_LOCK_TYPE_REFCOUNT] = "Refcount",
>> +	[OCFS2_LOCK_TYPE_TRIM_FS] = "TrimFs",
>>   };
>>   
>>   static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type 
> type)
>>
Changwei Ge Jan. 17, 2018, 7:39 a.m. UTC | #3
It looks good to me.

Reviewed-by: Changwei Ge <ge.changwei@h3c.com>

On 2017/12/14 13:16, Gang He wrote:
> Introduce a new dlm lock resource, which will be used to
> communicate during fstrim a ocfs2 device from cluster nodes.
> 
> Signed-off-by: Gang He <ghe@suse.com>
> ---
>   fs/ocfs2/dlmglue.c      | 86 +++++++++++++++++++++++++++++++++++++++++++++++++
>   fs/ocfs2/dlmglue.h      | 29 +++++++++++++++++
>   fs/ocfs2/ocfs2.h        |  1 +
>   fs/ocfs2/ocfs2_lockid.h |  5 +++
>   4 files changed, 121 insertions(+)
> 
> diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
> index 4689940..5615747 100644
> --- a/fs/ocfs2/dlmglue.c
> +++ b/fs/ocfs2/dlmglue.c
> @@ -259,6 +259,10 @@ struct ocfs2_lock_res_ops {
>   	.flags		= 0,
>   };
>   
> +static struct ocfs2_lock_res_ops ocfs2_trim_fs_lops = {
> +	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
> +};
> +
>   static struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = {
>   	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
>   };
> @@ -676,6 +680,24 @@ static void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res,
>   				   &ocfs2_nfs_sync_lops, osb);
>   }
>   
> +void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb)
> +{
> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
> +
> +	ocfs2_lock_res_init_once(lockres);
> +	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_TRIM_FS, 0, 0, lockres->l_name);
> +	ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_TRIM_FS,
> +				   &ocfs2_trim_fs_lops, osb);
> +}
> +
> +void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb)
> +{
> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
> +
> +	ocfs2_simple_drop_lockres(osb, lockres);
> +	ocfs2_lock_res_free(lockres);
> +}
> +
>   static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
>   					    struct ocfs2_super *osb)
>   {
> @@ -2745,6 +2767,70 @@ void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, int ex)
>   				     ex ? LKM_EXMODE : LKM_PRMODE);
>   }
>   
> +int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
> +		       struct ocfs2_trim_fs_info *info, int trylock)
> +{
> +	int status;
> +	struct ocfs2_trim_fs_lvb *lvb;
> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
> +
> +	if (info)
> +		info->tf_valid = 0;
> +
> +	if (ocfs2_is_hard_readonly(osb))
> +		return -EROFS;
> +
> +	if (ocfs2_mount_local(osb))
> +		return 0;
> +
> +	status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX,
> +				    trylock ? DLM_LKF_NOQUEUE : 0, 0);
> +	if (status < 0) {
> +		if (status != -EAGAIN)
> +			mlog_errno(status);
> +		return status;
> +	}
> +
> +	if (info) {
> +		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
> +		if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) &&
> +		    lvb->lvb_version == OCFS2_TRIMFS_LVB_VERSION) {
> +			info->tf_valid = 1;
> +			info->tf_success = lvb->lvb_success;
> +			info->tf_nodenum = be32_to_cpu(lvb->lvb_nodenum);
> +			info->tf_start = be64_to_cpu(lvb->lvb_start);
> +			info->tf_len = be64_to_cpu(lvb->lvb_len);
> +			info->tf_minlen = be64_to_cpu(lvb->lvb_minlen);
> +			info->tf_trimlen = be64_to_cpu(lvb->lvb_trimlen);
> +		}
> +	}
> +
> +	return status;
> +}
> +
> +void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
> +			  struct ocfs2_trim_fs_info *info)
> +{
> +	struct ocfs2_trim_fs_lvb *lvb;
> +	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
> +
> +	if (ocfs2_mount_local(osb))
> +		return;
> +
> +	if (info) {
> +		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
> +		lvb->lvb_version = OCFS2_TRIMFS_LVB_VERSION;
> +		lvb->lvb_success = info->tf_success;
> +		lvb->lvb_nodenum = cpu_to_be32(info->tf_nodenum);
> +		lvb->lvb_start = cpu_to_be64(info->tf_start);
> +		lvb->lvb_len = cpu_to_be64(info->tf_len);
> +		lvb->lvb_minlen = cpu_to_be64(info->tf_minlen);
> +		lvb->lvb_trimlen = cpu_to_be64(info->tf_trimlen);
> +	}
> +
> +	ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
> +}
> +
>   int ocfs2_dentry_lock(struct dentry *dentry, int ex)
>   {
>   	int ret;
> diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
> index a7fc18b..2253688 100644
> --- a/fs/ocfs2/dlmglue.h
> +++ b/fs/ocfs2/dlmglue.h
> @@ -70,6 +70,29 @@ struct ocfs2_orphan_scan_lvb {
>   	__be32	lvb_os_seqno;
>   };
>   
> +#define OCFS2_TRIMFS_LVB_VERSION 1
> +
> +struct ocfs2_trim_fs_lvb {
> +	__u8	lvb_version;
> +	__u8	lvb_success;
> +	__u8	lvb_reserved[2];
> +	__be32	lvb_nodenum;
> +	__be64	lvb_start;
> +	__be64	lvb_len;
> +	__be64	lvb_minlen;
> +	__be64	lvb_trimlen;
> +};
> +
> +struct ocfs2_trim_fs_info {
> +	u8	tf_valid;	/* lvb is valid, or not */
> +	u8	tf_success;	/* trim is successful, or not */
> +	u32	tf_nodenum;	/* osb node number */
> +	u64	tf_start;	/* trim start offset in clusters */
> +	u64	tf_len;		/* trim end offset in clusters */
> +	u64	tf_minlen;	/* trim minimum contiguous free clusters */
> +	u64	tf_trimlen;	/* trimmed length in bytes */
> +};
> +
>   struct ocfs2_lock_holder {
>   	struct list_head oh_list;
>   	struct pid *oh_owner_pid;
> @@ -153,6 +176,12 @@ void ocfs2_super_unlock(struct ocfs2_super *osb,
>   void ocfs2_rename_unlock(struct ocfs2_super *osb);
>   int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex);
>   void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, int ex);
> +void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb);
> +void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb);
> +int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
> +		       struct ocfs2_trim_fs_info *info, int trylock);
> +void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
> +			  struct ocfs2_trim_fs_info *info);
>   int ocfs2_dentry_lock(struct dentry *dentry, int ex);
>   void ocfs2_dentry_unlock(struct dentry *dentry, int ex);
>   int ocfs2_file_lock(struct file *file, int ex, int trylock);
> diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
> index 9a50f22..6867eef 100644
> --- a/fs/ocfs2/ocfs2.h
> +++ b/fs/ocfs2/ocfs2.h
> @@ -404,6 +404,7 @@ struct ocfs2_super
>   	struct ocfs2_lock_res osb_super_lockres;
>   	struct ocfs2_lock_res osb_rename_lockres;
>   	struct ocfs2_lock_res osb_nfs_sync_lockres;
> +	struct ocfs2_lock_res osb_trim_fs_lockres;
>   	struct ocfs2_dlm_debug *osb_dlm_debug;
>   
>   	struct dentry *osb_debug_root;
> diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
> index d277aab..7051b99 100644
> --- a/fs/ocfs2/ocfs2_lockid.h
> +++ b/fs/ocfs2/ocfs2_lockid.h
> @@ -50,6 +50,7 @@ enum ocfs2_lock_type {
>   	OCFS2_LOCK_TYPE_NFS_SYNC,
>   	OCFS2_LOCK_TYPE_ORPHAN_SCAN,
>   	OCFS2_LOCK_TYPE_REFCOUNT,
> +	OCFS2_LOCK_TYPE_TRIM_FS,
>   	OCFS2_NUM_LOCK_TYPES
>   };
>   
> @@ -93,6 +94,9 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
>   		case OCFS2_LOCK_TYPE_REFCOUNT:
>   			c = 'T';
>   			break;
> +		case OCFS2_LOCK_TYPE_TRIM_FS:
> +			c = 'I';
> +			break;
>   		default:
>   			c = '\0';
>   	}
> @@ -115,6 +119,7 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
>   	[OCFS2_LOCK_TYPE_NFS_SYNC] = "NFSSync",
>   	[OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan",
>   	[OCFS2_LOCK_TYPE_REFCOUNT] = "Refcount",
> +	[OCFS2_LOCK_TYPE_TRIM_FS] = "TrimFs",
>   };
>   
>   static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
>

Patch
diff mbox

diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 4689940..5615747 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -259,6 +259,10 @@  struct ocfs2_lock_res_ops {
 	.flags		= 0,
 };
 
+static struct ocfs2_lock_res_ops ocfs2_trim_fs_lops = {
+	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
+};
+
 static struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = {
 	.flags		= LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
 };
@@ -676,6 +680,24 @@  static void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res,
 				   &ocfs2_nfs_sync_lops, osb);
 }
 
+void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb)
+{
+	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
+
+	ocfs2_lock_res_init_once(lockres);
+	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_TRIM_FS, 0, 0, lockres->l_name);
+	ocfs2_lock_res_init_common(osb, lockres, OCFS2_LOCK_TYPE_TRIM_FS,
+				   &ocfs2_trim_fs_lops, osb);
+}
+
+void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb)
+{
+	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
+
+	ocfs2_simple_drop_lockres(osb, lockres);
+	ocfs2_lock_res_free(lockres);
+}
+
 static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
 					    struct ocfs2_super *osb)
 {
@@ -2745,6 +2767,70 @@  void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, int ex)
 				     ex ? LKM_EXMODE : LKM_PRMODE);
 }
 
+int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
+		       struct ocfs2_trim_fs_info *info, int trylock)
+{
+	int status;
+	struct ocfs2_trim_fs_lvb *lvb;
+	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
+
+	if (info)
+		info->tf_valid = 0;
+
+	if (ocfs2_is_hard_readonly(osb))
+		return -EROFS;
+
+	if (ocfs2_mount_local(osb))
+		return 0;
+
+	status = ocfs2_cluster_lock(osb, lockres, DLM_LOCK_EX,
+				    trylock ? DLM_LKF_NOQUEUE : 0, 0);
+	if (status < 0) {
+		if (status != -EAGAIN)
+			mlog_errno(status);
+		return status;
+	}
+
+	if (info) {
+		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
+		if (ocfs2_dlm_lvb_valid(&lockres->l_lksb) &&
+		    lvb->lvb_version == OCFS2_TRIMFS_LVB_VERSION) {
+			info->tf_valid = 1;
+			info->tf_success = lvb->lvb_success;
+			info->tf_nodenum = be32_to_cpu(lvb->lvb_nodenum);
+			info->tf_start = be64_to_cpu(lvb->lvb_start);
+			info->tf_len = be64_to_cpu(lvb->lvb_len);
+			info->tf_minlen = be64_to_cpu(lvb->lvb_minlen);
+			info->tf_trimlen = be64_to_cpu(lvb->lvb_trimlen);
+		}
+	}
+
+	return status;
+}
+
+void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
+			  struct ocfs2_trim_fs_info *info)
+{
+	struct ocfs2_trim_fs_lvb *lvb;
+	struct ocfs2_lock_res *lockres = &osb->osb_trim_fs_lockres;
+
+	if (ocfs2_mount_local(osb))
+		return;
+
+	if (info) {
+		lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
+		lvb->lvb_version = OCFS2_TRIMFS_LVB_VERSION;
+		lvb->lvb_success = info->tf_success;
+		lvb->lvb_nodenum = cpu_to_be32(info->tf_nodenum);
+		lvb->lvb_start = cpu_to_be64(info->tf_start);
+		lvb->lvb_len = cpu_to_be64(info->tf_len);
+		lvb->lvb_minlen = cpu_to_be64(info->tf_minlen);
+		lvb->lvb_trimlen = cpu_to_be64(info->tf_trimlen);
+	}
+
+	ocfs2_cluster_unlock(osb, lockres, DLM_LOCK_EX);
+}
+
 int ocfs2_dentry_lock(struct dentry *dentry, int ex)
 {
 	int ret;
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index a7fc18b..2253688 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -70,6 +70,29 @@  struct ocfs2_orphan_scan_lvb {
 	__be32	lvb_os_seqno;
 };
 
+#define OCFS2_TRIMFS_LVB_VERSION 1
+
+struct ocfs2_trim_fs_lvb {
+	__u8	lvb_version;
+	__u8	lvb_success;
+	__u8	lvb_reserved[2];
+	__be32	lvb_nodenum;
+	__be64	lvb_start;
+	__be64	lvb_len;
+	__be64	lvb_minlen;
+	__be64	lvb_trimlen;
+};
+
+struct ocfs2_trim_fs_info {
+	u8	tf_valid;	/* lvb is valid, or not */
+	u8	tf_success;	/* trim is successful, or not */
+	u32	tf_nodenum;	/* osb node number */
+	u64	tf_start;	/* trim start offset in clusters */
+	u64	tf_len;		/* trim end offset in clusters */
+	u64	tf_minlen;	/* trim minimum contiguous free clusters */
+	u64	tf_trimlen;	/* trimmed length in bytes */
+};
+
 struct ocfs2_lock_holder {
 	struct list_head oh_list;
 	struct pid *oh_owner_pid;
@@ -153,6 +176,12 @@  void ocfs2_super_unlock(struct ocfs2_super *osb,
 void ocfs2_rename_unlock(struct ocfs2_super *osb);
 int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex);
 void ocfs2_nfs_sync_unlock(struct ocfs2_super *osb, int ex);
+void ocfs2_trim_fs_lock_res_init(struct ocfs2_super *osb);
+void ocfs2_trim_fs_lock_res_uninit(struct ocfs2_super *osb);
+int ocfs2_trim_fs_lock(struct ocfs2_super *osb,
+		       struct ocfs2_trim_fs_info *info, int trylock);
+void ocfs2_trim_fs_unlock(struct ocfs2_super *osb,
+			  struct ocfs2_trim_fs_info *info);
 int ocfs2_dentry_lock(struct dentry *dentry, int ex);
 void ocfs2_dentry_unlock(struct dentry *dentry, int ex);
 int ocfs2_file_lock(struct file *file, int ex, int trylock);
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 9a50f22..6867eef 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -404,6 +404,7 @@  struct ocfs2_super
 	struct ocfs2_lock_res osb_super_lockres;
 	struct ocfs2_lock_res osb_rename_lockres;
 	struct ocfs2_lock_res osb_nfs_sync_lockres;
+	struct ocfs2_lock_res osb_trim_fs_lockres;
 	struct ocfs2_dlm_debug *osb_dlm_debug;
 
 	struct dentry *osb_debug_root;
diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
index d277aab..7051b99 100644
--- a/fs/ocfs2/ocfs2_lockid.h
+++ b/fs/ocfs2/ocfs2_lockid.h
@@ -50,6 +50,7 @@  enum ocfs2_lock_type {
 	OCFS2_LOCK_TYPE_NFS_SYNC,
 	OCFS2_LOCK_TYPE_ORPHAN_SCAN,
 	OCFS2_LOCK_TYPE_REFCOUNT,
+	OCFS2_LOCK_TYPE_TRIM_FS,
 	OCFS2_NUM_LOCK_TYPES
 };
 
@@ -93,6 +94,9 @@  static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
 		case OCFS2_LOCK_TYPE_REFCOUNT:
 			c = 'T';
 			break;
+		case OCFS2_LOCK_TYPE_TRIM_FS:
+			c = 'I';
+			break;
 		default:
 			c = '\0';
 	}
@@ -115,6 +119,7 @@  static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
 	[OCFS2_LOCK_TYPE_NFS_SYNC] = "NFSSync",
 	[OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan",
 	[OCFS2_LOCK_TYPE_REFCOUNT] = "Refcount",
+	[OCFS2_LOCK_TYPE_TRIM_FS] = "TrimFs",
 };
 
 static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)