diff mbox series

[RFC,v2,07/16] fs: split off need_file_update_time and do_file_update_time

Message ID 20220516164718.2419891-8-shr@fb.com (mailing list archive)
State New, archived
Headers show
Series io-uring/xfs: support async buffered writes | expand

Commit Message

Stefan Roesch May 16, 2022, 4:47 p.m. UTC
This splits off the functions need_file_update_time() and
do_file_update_time() from the function file_update_time().

This is required to support async buffered writes.
No intended functional changes in this patch.

Signed-off-by: Stefan Roesch <shr@fb.com>
---
 fs/inode.c | 71 ++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 47 insertions(+), 24 deletions(-)

Comments

Jan Kara May 17, 2022, 11:20 a.m. UTC | #1
On Mon 16-05-22 09:47:09, Stefan Roesch wrote:
> This splits off the functions need_file_update_time() and
> do_file_update_time() from the function file_update_time().
> 
> This is required to support async buffered writes.
> No intended functional changes in this patch.
> 
> Signed-off-by: Stefan Roesch <shr@fb.com>

...
> +int file_update_time(struct file *file)
> +{
> +	int err;
> +	struct inode *inode = file_inode(file);
> +	struct timespec64 now = current_time(inode);
> +
> +	err = need_file_update_time(inode, file, &now);
> +	if (err < 0)
> +		return err;
> +
> +	return do_file_update_time(inode, file, &now, err);
> +}
>  EXPORT_SYMBOL(file_update_time);

I guess 'ret' would be a more appropriate variable name than 'err'.
Otherwise the patch looks good.

								Honza
Christian Brauner May 17, 2022, 1:40 p.m. UTC | #2
On Mon, May 16, 2022 at 09:47:09AM -0700, Stefan Roesch wrote:
> This splits off the functions need_file_update_time() and
> do_file_update_time() from the function file_update_time().
> 
> This is required to support async buffered writes.
> No intended functional changes in this patch.
> 
> Signed-off-by: Stefan Roesch <shr@fb.com>
> ---
>  fs/inode.c | 71 ++++++++++++++++++++++++++++++++++++------------------
>  1 file changed, 47 insertions(+), 24 deletions(-)
> 
> diff --git a/fs/inode.c b/fs/inode.c
> index a6d70a1983f8..1d0b02763e98 100644
> --- a/fs/inode.c
> +++ b/fs/inode.c
> @@ -2054,35 +2054,22 @@ int file_remove_privs(struct file *file)
>  }
>  EXPORT_SYMBOL(file_remove_privs);
>  
> -/**
> - *	file_update_time	-	update mtime and ctime time
> - *	@file: file accessed
> - *
> - *	Update the mtime and ctime members of an inode and mark the inode
> - *	for writeback.  Note that this function is meant exclusively for
> - *	usage in the file write path of filesystems, and filesystems may
> - *	choose to explicitly ignore update via this function with the
> - *	S_NOCMTIME inode flag, e.g. for network filesystem where these
> - *	timestamps are handled by the server.  This can return an error for
> - *	file systems who need to allocate space in order to update an inode.
> - */
> -
> -int file_update_time(struct file *file)
> +static int need_file_update_time(struct inode *inode, struct file *file,
> +				struct timespec64 *now)

I think file_need_update_time() is easier to understand.

>  {
> -	struct inode *inode = file_inode(file);
> -	struct timespec64 now;
>  	int sync_it = 0;
> -	int ret;
> +
> +	if (unlikely(file->f_mode & FMODE_NOCMTIME))
> +		return 0;

Moving this into this generic helper and using the generic helper
directly in file_update_atime() leads to a change in behavior for
file_update_time() callers. Currently they'd get time settings updated
even if FMODE_NOCMTIME is set but with this change they'd not get it
updated anymore if FMODE_NOCMTIME is set. Am I reading this right?

Is this a bugfix? And if so it should be split into a separate commit...

>  
>  	/* First try to exhaust all avenues to not sync */
>  	if (IS_NOCMTIME(inode))
>  		return 0;
>  
> -	now = current_time(inode);
> -	if (!timespec64_equal(&inode->i_mtime, &now))
> +	if (!timespec64_equal(&inode->i_mtime, now))
>  		sync_it = S_MTIME;
>  
> -	if (!timespec64_equal(&inode->i_ctime, &now))
> +	if (!timespec64_equal(&inode->i_ctime, now))
>  		sync_it |= S_CTIME;
>  
>  	if (IS_I_VERSION(inode) && inode_iversion_need_inc(inode))
> @@ -2091,15 +2078,49 @@ int file_update_time(struct file *file)
>  	if (!sync_it)
>  		return 0;
>  
> +	return sync_it;
> +}
> +
> +static int do_file_update_time(struct inode *inode, struct file *file,
> +			struct timespec64 *now, int sync_mode)
> +{
> +	int ret;
> +
>  	/* Finally allowed to write? Takes lock. */
>  	if (__mnt_want_write_file(file))
>  		return 0;
>  
> -	ret = inode_update_time(inode, &now, sync_it);
> +	ret = inode_update_time(inode, now, sync_mode);
>  	__mnt_drop_write_file(file);
>  
>  	return ret;
>  }

Maybe

static int __file_update_time(struct inode *inode, struct file *file,
			      struct timespec64 *now, int sync_mode)
{
	int ret = 0;

	/* try to update time settings */
	if (!__mnt_want_write_file(file)) {
		ret = inode_update_time(inode, now, sync_mode);
		__mnt_drop_write_file(file);
	}

	return ret;
}

reads a little easier and the old comment is a bit confusing imho. I'd
just say we keep it short. 

> +
> +/**
> + *	file_update_time	-	update mtime and ctime time
> + *	@file: file accessed
> + *
> + *	Update the mtime and ctime members of an inode and mark the inode
> + *	for writeback.  Note that this function is meant exclusively for
> + *	usage in the file write path of filesystems, and filesystems may
> + *	choose to explicitly ignore update via this function with the
> + *	S_NOCMTIME inode flag, e.g. for network filesystem where these
> + *	timestamps are handled by the server.  This can return an error for
> + *	file systems who need to allocate space in order to update an inode.
> + */
> +
> +int file_update_time(struct file *file)

My same lame complaint as before to make this kernel-doc. :)

/**
 * file_update_time - update mtime and ctime time
 * @file: file accessed
 *
 * Update the mtime and ctime members of an inode and mark the inode or
 * writeback. Note that this function is meant exclusively for sage in
 * the file write path of filesystems, and filesystems may hoose to
 * explicitly ignore update via this function with the _NOCMTIME inode
 * flag, e.g. for network filesystem where these imestamps are handled
 * by the server. This can return an error for ile systems who need to
 * allocate space in order to update an inode.
 *
 * Return: 0 on success, negative errno on failure.
 */
int file_update_time(struct file *file)

> +{
> +	int err;
> +	struct inode *inode = file_inode(file);
> +	struct timespec64 now = current_time(inode);
> +
> +	err = need_file_update_time(inode, file, &now);
> +	if (err < 0)
> +		return err;

I may misread this but shouldn't this be err <= 0, i.e., if it returns 0
then we don't need to update time?

> +
> +	return do_file_update_time(inode, file, &now, err);
> +}
>  EXPORT_SYMBOL(file_update_time);
>  
>  /* Caller must hold the file's inode lock */
> @@ -2108,6 +2129,7 @@ int file_modified(struct file *file)
>  	int ret;
>  	struct dentry *dentry = file_dentry(file);
>  	struct inode *inode = file_inode(file);
> +	struct timespec64 now = current_time(inode);
>  
>  	/*
>  	 * Clear the security bits if the process is not being run by root.
> @@ -2122,10 +2144,11 @@ int file_modified(struct file *file)
>  			return ret;
>  	}
>  
> -	if (unlikely(file->f_mode & FMODE_NOCMTIME))
> -		return 0;
> +	ret = need_file_update_time(inode, file, &now);
> +	if (ret <= 0)
> +		return ret;
>  
> -	return file_update_time(file);
> +	return do_file_update_time(inode, file, &now, ret);
>  }
>  EXPORT_SYMBOL(file_modified);
>  
> -- 
> 2.30.2
>
Stefan Roesch May 18, 2022, 11:21 p.m. UTC | #3
On 5/17/22 4:20 AM, Jan Kara wrote:
> On Mon 16-05-22 09:47:09, Stefan Roesch wrote:
>> This splits off the functions need_file_update_time() and
>> do_file_update_time() from the function file_update_time().
>>
>> This is required to support async buffered writes.
>> No intended functional changes in this patch.
>>
>> Signed-off-by: Stefan Roesch <shr@fb.com>
> 
> ...
>> +int file_update_time(struct file *file)
>> +{
>> +	int err;
>> +	struct inode *inode = file_inode(file);
>> +	struct timespec64 now = current_time(inode);
>> +
>> +	err = need_file_update_time(inode, file, &now);
>> +	if (err < 0)
>> +		return err;
>> +
>> +	return do_file_update_time(inode, file, &now, err);
>> +}
>>  EXPORT_SYMBOL(file_update_time);
> 
> I guess 'ret' would be a more appropriate variable name than 'err'.
> Otherwise the patch looks good.
> 

I renamed it to ret in the next version of the patch series.
> 								Honza
Stefan Roesch May 18, 2022, 11:28 p.m. UTC | #4
On 5/17/22 6:40 AM, Christian Brauner wrote:
> On Mon, May 16, 2022 at 09:47:09AM -0700, Stefan Roesch wrote:
>> This splits off the functions need_file_update_time() and
>> do_file_update_time() from the function file_update_time().
>>
>> This is required to support async buffered writes.
>> No intended functional changes in this patch.
>>
>> Signed-off-by: Stefan Roesch <shr@fb.com>
>> ---
>>  fs/inode.c | 71 ++++++++++++++++++++++++++++++++++++------------------
>>  1 file changed, 47 insertions(+), 24 deletions(-)
>>
>> diff --git a/fs/inode.c b/fs/inode.c
>> index a6d70a1983f8..1d0b02763e98 100644
>> --- a/fs/inode.c
>> +++ b/fs/inode.c
>> @@ -2054,35 +2054,22 @@ int file_remove_privs(struct file *file)
>>  }
>>  EXPORT_SYMBOL(file_remove_privs);
>>  
>> -/**
>> - *	file_update_time	-	update mtime and ctime time
>> - *	@file: file accessed
>> - *
>> - *	Update the mtime and ctime members of an inode and mark the inode
>> - *	for writeback.  Note that this function is meant exclusively for
>> - *	usage in the file write path of filesystems, and filesystems may
>> - *	choose to explicitly ignore update via this function with the
>> - *	S_NOCMTIME inode flag, e.g. for network filesystem where these
>> - *	timestamps are handled by the server.  This can return an error for
>> - *	file systems who need to allocate space in order to update an inode.
>> - */
>> -
>> -int file_update_time(struct file *file)
>> +static int need_file_update_time(struct inode *inode, struct file *file,
>> +				struct timespec64 *now)
> 
> I think file_need_update_time() is easier to understand.
> 

I renamed the function to file_needs_update_time().

>>  {
>> -	struct inode *inode = file_inode(file);
>> -	struct timespec64 now;
>>  	int sync_it = 0;
>> -	int ret;
>> +
>> +	if (unlikely(file->f_mode & FMODE_NOCMTIME))
>> +		return 0;
> 
> Moving this into this generic helper and using the generic helper
> directly in file_update_atime() leads to a change in behavior for
> file_update_time() callers. Currently they'd get time settings updated
> even if FMODE_NOCMTIME is set but with this change they'd not get it
> updated anymore if FMODE_NOCMTIME is set. Am I reading this right?
> 

Correct, this was not intended and will be addressed with the next version of the patch.

> Is this a bugfix? And if so it should be split into a separate commit...
> 
>>  
>>  	/* First try to exhaust all avenues to not sync */
>>  	if (IS_NOCMTIME(inode))
>>  		return 0;
>>  
>> -	now = current_time(inode);
>> -	if (!timespec64_equal(&inode->i_mtime, &now))
>> +	if (!timespec64_equal(&inode->i_mtime, now))
>>  		sync_it = S_MTIME;
>>  
>> -	if (!timespec64_equal(&inode->i_ctime, &now))
>> +	if (!timespec64_equal(&inode->i_ctime, now))
>>  		sync_it |= S_CTIME;
>>  
>>  	if (IS_I_VERSION(inode) && inode_iversion_need_inc(inode))
>> @@ -2091,15 +2078,49 @@ int file_update_time(struct file *file)
>>  	if (!sync_it)
>>  		return 0;
>>  
>> +	return sync_it;
>> +}
>> +
>> +static int do_file_update_time(struct inode *inode, struct file *file,
>> +			struct timespec64 *now, int sync_mode)
>> +{
>> +	int ret;
>> +
>>  	/* Finally allowed to write? Takes lock. */
>>  	if (__mnt_want_write_file(file))
>>  		return 0;
>>  
>> -	ret = inode_update_time(inode, &now, sync_it);
>> +	ret = inode_update_time(inode, now, sync_mode);
>>  	__mnt_drop_write_file(file);
>>  
>>  	return ret;
>>  }
> 
> Maybe
> 
> static int __file_update_time(struct inode *inode, struct file *file,
> 			      struct timespec64 *now, int sync_mode)
> {
> 	int ret = 0;
> 
> 	/* try to update time settings */
> 	if (!__mnt_want_write_file(file)) {
> 		ret = inode_update_time(inode, now, sync_mode);
> 		__mnt_drop_write_file(file);
> 	}
> 
> 	return ret;
> }
> 
> reads a little easier and the old comment is a bit confusing imho. I'd
> just say we keep it short. 
> 

I made the change.

>> +
>> +/**
>> + *	file_update_time	-	update mtime and ctime time
>> + *	@file: file accessed
>> + *
>> + *	Update the mtime and ctime members of an inode and mark the inode
>> + *	for writeback.  Note that this function is meant exclusively for
>> + *	usage in the file write path of filesystems, and filesystems may
>> + *	choose to explicitly ignore update via this function with the
>> + *	S_NOCMTIME inode flag, e.g. for network filesystem where these
>> + *	timestamps are handled by the server.  This can return an error for
>> + *	file systems who need to allocate space in order to update an inode.
>> + */
>> +
>> +int file_update_time(struct file *file)
> 
> My same lame complaint as before to make this kernel-doc. :)
> 
> /**
>  * file_update_time - update mtime and ctime time
>  * @file: file accessed
>  *
>  * Update the mtime and ctime members of an inode and mark the inode or
>  * writeback. Note that this function is meant exclusively for sage in
>  * the file write path of filesystems, and filesystems may hoose to
>  * explicitly ignore update via this function with the _NOCMTIME inode
>  * flag, e.g. for network filesystem where these imestamps are handled
>  * by the server. This can return an error for ile systems who need to
>  * allocate space in order to update an inode.
>  *
>  * Return: 0 on success, negative errno on failure.
>  */
> int file_update_time(struct file *file)
> 

I added the above kernel documentation, I only fixed a couple of typos.

>> +{
>> +	int err;
>> +	struct inode *inode = file_inode(file);
>> +	struct timespec64 now = current_time(inode);
>> +
>> +	err = need_file_update_time(inode, file, &now);
>> +	if (err < 0)
>> +		return err;
> 
> I may misread this but shouldn't this be err <= 0, i.e., if it returns 0
> then we don't need to update time?
> 

Good catch. Fixed.

>> +
>> +	return do_file_update_time(inode, file, &now, err);
>> +}
>>  EXPORT_SYMBOL(file_update_time);
>>  
>>  /* Caller must hold the file's inode lock */
>> @@ -2108,6 +2129,7 @@ int file_modified(struct file *file)
>>  	int ret;
>>  	struct dentry *dentry = file_dentry(file);
>>  	struct inode *inode = file_inode(file);
>> +	struct timespec64 now = current_time(inode);
>>  
>>  	/*
>>  	 * Clear the security bits if the process is not being run by root.
>> @@ -2122,10 +2144,11 @@ int file_modified(struct file *file)
>>  			return ret;
>>  	}
>>  
>> -	if (unlikely(file->f_mode & FMODE_NOCMTIME))
>> -		return 0;
>> +	ret = need_file_update_time(inode, file, &now);
>> +	if (ret <= 0)
>> +		return ret;
>>  
>> -	return file_update_time(file);
>> +	return do_file_update_time(inode, file, &now, ret);
>>  }
>>  EXPORT_SYMBOL(file_modified);
>>  
>> -- 
>> 2.30.2
>>
diff mbox series

Patch

diff --git a/fs/inode.c b/fs/inode.c
index a6d70a1983f8..1d0b02763e98 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -2054,35 +2054,22 @@  int file_remove_privs(struct file *file)
 }
 EXPORT_SYMBOL(file_remove_privs);
 
-/**
- *	file_update_time	-	update mtime and ctime time
- *	@file: file accessed
- *
- *	Update the mtime and ctime members of an inode and mark the inode
- *	for writeback.  Note that this function is meant exclusively for
- *	usage in the file write path of filesystems, and filesystems may
- *	choose to explicitly ignore update via this function with the
- *	S_NOCMTIME inode flag, e.g. for network filesystem where these
- *	timestamps are handled by the server.  This can return an error for
- *	file systems who need to allocate space in order to update an inode.
- */
-
-int file_update_time(struct file *file)
+static int need_file_update_time(struct inode *inode, struct file *file,
+				struct timespec64 *now)
 {
-	struct inode *inode = file_inode(file);
-	struct timespec64 now;
 	int sync_it = 0;
-	int ret;
+
+	if (unlikely(file->f_mode & FMODE_NOCMTIME))
+		return 0;
 
 	/* First try to exhaust all avenues to not sync */
 	if (IS_NOCMTIME(inode))
 		return 0;
 
-	now = current_time(inode);
-	if (!timespec64_equal(&inode->i_mtime, &now))
+	if (!timespec64_equal(&inode->i_mtime, now))
 		sync_it = S_MTIME;
 
-	if (!timespec64_equal(&inode->i_ctime, &now))
+	if (!timespec64_equal(&inode->i_ctime, now))
 		sync_it |= S_CTIME;
 
 	if (IS_I_VERSION(inode) && inode_iversion_need_inc(inode))
@@ -2091,15 +2078,49 @@  int file_update_time(struct file *file)
 	if (!sync_it)
 		return 0;
 
+	return sync_it;
+}
+
+static int do_file_update_time(struct inode *inode, struct file *file,
+			struct timespec64 *now, int sync_mode)
+{
+	int ret;
+
 	/* Finally allowed to write? Takes lock. */
 	if (__mnt_want_write_file(file))
 		return 0;
 
-	ret = inode_update_time(inode, &now, sync_it);
+	ret = inode_update_time(inode, now, sync_mode);
 	__mnt_drop_write_file(file);
 
 	return ret;
 }
+
+/**
+ *	file_update_time	-	update mtime and ctime time
+ *	@file: file accessed
+ *
+ *	Update the mtime and ctime members of an inode and mark the inode
+ *	for writeback.  Note that this function is meant exclusively for
+ *	usage in the file write path of filesystems, and filesystems may
+ *	choose to explicitly ignore update via this function with the
+ *	S_NOCMTIME inode flag, e.g. for network filesystem where these
+ *	timestamps are handled by the server.  This can return an error for
+ *	file systems who need to allocate space in order to update an inode.
+ */
+
+int file_update_time(struct file *file)
+{
+	int err;
+	struct inode *inode = file_inode(file);
+	struct timespec64 now = current_time(inode);
+
+	err = need_file_update_time(inode, file, &now);
+	if (err < 0)
+		return err;
+
+	return do_file_update_time(inode, file, &now, err);
+}
 EXPORT_SYMBOL(file_update_time);
 
 /* Caller must hold the file's inode lock */
@@ -2108,6 +2129,7 @@  int file_modified(struct file *file)
 	int ret;
 	struct dentry *dentry = file_dentry(file);
 	struct inode *inode = file_inode(file);
+	struct timespec64 now = current_time(inode);
 
 	/*
 	 * Clear the security bits if the process is not being run by root.
@@ -2122,10 +2144,11 @@  int file_modified(struct file *file)
 			return ret;
 	}
 
-	if (unlikely(file->f_mode & FMODE_NOCMTIME))
-		return 0;
+	ret = need_file_update_time(inode, file, &now);
+	if (ret <= 0)
+		return ret;
 
-	return file_update_time(file);
+	return do_file_update_time(inode, file, &now, ret);
 }
 EXPORT_SYMBOL(file_modified);