All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] afs: Fix updating of i_blocks on file/dir extension
@ 2021-09-08 21:22 David Howells
  2021-09-09 10:30 ` Marc Dionne
  0 siblings, 1 reply; 2+ messages in thread
From: David Howells @ 2021-09-08 21:22 UTC (permalink / raw)
  To: markus.suvanto
  Cc: linux-afs, dhowells, marc.dionne, linux-fsdevel, linux-kernel

When an afs file or directory is modified locally such that the total file
size is extended, i_blocks needs to be recalculated too.

Fix this by making afs_write_end() and afs_edit_dir_add() call
afs_set_i_size() rather than setting inode->i_size directly as that also
recalculates inode->i_blocks.

This can be tested by creating and writing into directories and files and
then examining them with du.  Without this change, directories show a 4
blocks (they start out at 2048 bytes) and files show 0 blocks; with this
change, they should show a number of blocks proportional to the file size
rounded up to 1024.

Fixes: 31143d5d515ece617ffccb7df5ff75e4d1dfa120 ("AFS: implement basic file write support")
Fixes: 63a4681ff39c ("afs: Locally edit directory data for mkdir/create/unlink/...")
Reported-by: Markus Suvanto <markus.suvanto@gmail.com>
Signed-off-by: David Howells <dhowells@redhat.com>
cc: linux-afs@lists.infradead.org
---

 fs/afs/dir_edit.c |    4 ++--
 fs/afs/inode.c    |   10 ----------
 fs/afs/internal.h |   10 ++++++++++
 fs/afs/write.c    |    2 +-
 4 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/fs/afs/dir_edit.c b/fs/afs/dir_edit.c
index f4600c1353ad..540b9fc96824 100644
--- a/fs/afs/dir_edit.c
+++ b/fs/afs/dir_edit.c
@@ -263,7 +263,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
 		if (b == nr_blocks) {
 			_debug("init %u", b);
 			afs_edit_init_block(meta, block, b);
-			i_size_write(&vnode->vfs_inode, (b + 1) * AFS_DIR_BLOCK_SIZE);
+			afs_set_i_size(vnode, (b + 1) * AFS_DIR_BLOCK_SIZE);
 		}
 
 		/* Only lower dir pages have a counter in the header. */
@@ -296,7 +296,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
 new_directory:
 	afs_edit_init_block(meta, meta, 0);
 	i_size = AFS_DIR_BLOCK_SIZE;
-	i_size_write(&vnode->vfs_inode, i_size);
+	afs_set_i_size(vnode, i_size);
 	slot = AFS_DIR_RESV_BLOCKS0;
 	page = page0;
 	block = meta;
diff --git a/fs/afs/inode.c b/fs/afs/inode.c
index 126daf9969db..8fcffea2daf5 100644
--- a/fs/afs/inode.c
+++ b/fs/afs/inode.c
@@ -53,16 +53,6 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren
 		dump_stack();
 }
 
-/*
- * Set the file size and block count.  Estimate the number of 512 bytes blocks
- * used, rounded up to nearest 1K for consistency with other AFS clients.
- */
-static void afs_set_i_size(struct afs_vnode *vnode, u64 size)
-{
-	i_size_write(&vnode->vfs_inode, size);
-	vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1;
-}
-
 /*
  * Initialise an inode from the vnode status.
  */
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index c97618855b46..12b2bdae6d1a 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1595,6 +1595,16 @@ static inline void afs_update_dentry_version(struct afs_operation *op,
 			(void *)(unsigned long)dir_vp->scb.status.data_version;
 }
 
+/*
+ * Set the file size and block count.  Estimate the number of 512 bytes blocks
+ * used, rounded up to nearest 1K for consistency with other AFS clients.
+ */
+static inline void afs_set_i_size(struct afs_vnode *vnode, u64 size)
+{
+	i_size_write(&vnode->vfs_inode, size);
+	vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1;
+}
+
 /*
  * Check for a conflicting operation on a directory that we just unlinked from.
  * If someone managed to sneak a link or an unlink in on the file we just
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 32a764c24284..2dfe3b3a53d6 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -137,7 +137,7 @@ int afs_write_end(struct file *file, struct address_space *mapping,
 		write_seqlock(&vnode->cb_lock);
 		i_size = i_size_read(&vnode->vfs_inode);
 		if (maybe_i_size > i_size)
-			i_size_write(&vnode->vfs_inode, maybe_i_size);
+			afs_set_i_size(vnode, maybe_i_size);
 		write_sequnlock(&vnode->cb_lock);
 	}
 



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] afs: Fix updating of i_blocks on file/dir extension
  2021-09-08 21:22 [PATCH] afs: Fix updating of i_blocks on file/dir extension David Howells
@ 2021-09-09 10:30 ` Marc Dionne
  0 siblings, 0 replies; 2+ messages in thread
From: Marc Dionne @ 2021-09-09 10:30 UTC (permalink / raw)
  To: David Howells
  Cc: Markus Suvanto, linux-afs, linux-fsdevel, Linux Kernel Mailing List

On Wed, Sep 8, 2021 at 6:22 PM David Howells <dhowells@redhat.com> wrote:
>
> When an afs file or directory is modified locally such that the total file
> size is extended, i_blocks needs to be recalculated too.
>
> Fix this by making afs_write_end() and afs_edit_dir_add() call
> afs_set_i_size() rather than setting inode->i_size directly as that also
> recalculates inode->i_blocks.
>
> This can be tested by creating and writing into directories and files and
> then examining them with du.  Without this change, directories show a 4
> blocks (they start out at 2048 bytes) and files show 0 blocks; with this
> change, they should show a number of blocks proportional to the file size
> rounded up to 1024.
>
> Fixes: 31143d5d515ece617ffccb7df5ff75e4d1dfa120 ("AFS: implement basic file write support")
> Fixes: 63a4681ff39c ("afs: Locally edit directory data for mkdir/create/unlink/...")
> Reported-by: Markus Suvanto <markus.suvanto@gmail.com>
> Signed-off-by: David Howells <dhowells@redhat.com>
> cc: linux-afs@lists.infradead.org
> ---
>
>  fs/afs/dir_edit.c |    4 ++--
>  fs/afs/inode.c    |   10 ----------
>  fs/afs/internal.h |   10 ++++++++++
>  fs/afs/write.c    |    2 +-
>  4 files changed, 13 insertions(+), 13 deletions(-)
>
> diff --git a/fs/afs/dir_edit.c b/fs/afs/dir_edit.c
> index f4600c1353ad..540b9fc96824 100644
> --- a/fs/afs/dir_edit.c
> +++ b/fs/afs/dir_edit.c
> @@ -263,7 +263,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
>                 if (b == nr_blocks) {
>                         _debug("init %u", b);
>                         afs_edit_init_block(meta, block, b);
> -                       i_size_write(&vnode->vfs_inode, (b + 1) * AFS_DIR_BLOCK_SIZE);
> +                       afs_set_i_size(vnode, (b + 1) * AFS_DIR_BLOCK_SIZE);
>                 }
>
>                 /* Only lower dir pages have a counter in the header. */
> @@ -296,7 +296,7 @@ void afs_edit_dir_add(struct afs_vnode *vnode,
>  new_directory:
>         afs_edit_init_block(meta, meta, 0);
>         i_size = AFS_DIR_BLOCK_SIZE;
> -       i_size_write(&vnode->vfs_inode, i_size);
> +       afs_set_i_size(vnode, i_size);
>         slot = AFS_DIR_RESV_BLOCKS0;
>         page = page0;
>         block = meta;
> diff --git a/fs/afs/inode.c b/fs/afs/inode.c
> index 126daf9969db..8fcffea2daf5 100644
> --- a/fs/afs/inode.c
> +++ b/fs/afs/inode.c
> @@ -53,16 +53,6 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren
>                 dump_stack();
>  }
>
> -/*
> - * Set the file size and block count.  Estimate the number of 512 bytes blocks
> - * used, rounded up to nearest 1K for consistency with other AFS clients.
> - */
> -static void afs_set_i_size(struct afs_vnode *vnode, u64 size)
> -{
> -       i_size_write(&vnode->vfs_inode, size);
> -       vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1;
> -}
> -
>  /*
>   * Initialise an inode from the vnode status.
>   */
> diff --git a/fs/afs/internal.h b/fs/afs/internal.h
> index c97618855b46..12b2bdae6d1a 100644
> --- a/fs/afs/internal.h
> +++ b/fs/afs/internal.h
> @@ -1595,6 +1595,16 @@ static inline void afs_update_dentry_version(struct afs_operation *op,
>                         (void *)(unsigned long)dir_vp->scb.status.data_version;
>  }
>
> +/*
> + * Set the file size and block count.  Estimate the number of 512 bytes blocks
> + * used, rounded up to nearest 1K for consistency with other AFS clients.
> + */
> +static inline void afs_set_i_size(struct afs_vnode *vnode, u64 size)
> +{
> +       i_size_write(&vnode->vfs_inode, size);
> +       vnode->vfs_inode.i_blocks = ((size + 1023) >> 10) << 1;
> +}
> +
>  /*
>   * Check for a conflicting operation on a directory that we just unlinked from.
>   * If someone managed to sneak a link or an unlink in on the file we just
> diff --git a/fs/afs/write.c b/fs/afs/write.c
> index 32a764c24284..2dfe3b3a53d6 100644
> --- a/fs/afs/write.c
> +++ b/fs/afs/write.c
> @@ -137,7 +137,7 @@ int afs_write_end(struct file *file, struct address_space *mapping,
>                 write_seqlock(&vnode->cb_lock);
>                 i_size = i_size_read(&vnode->vfs_inode);
>                 if (maybe_i_size > i_size)
> -                       i_size_write(&vnode->vfs_inode, maybe_i_size);
> +                       afs_set_i_size(vnode, maybe_i_size);
>                 write_sequnlock(&vnode->cb_lock);
>         }
>
>
>
>
> _______________________________________________
> linux-afs mailing list
> http://lists.infradead.org/mailman/listinfo/linux-afs

Reviewed-by: Marc Dionne <marc.dionne@auristor.com>

Marc

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-09-09 10:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-08 21:22 [PATCH] afs: Fix updating of i_blocks on file/dir extension David Howells
2021-09-09 10:30 ` Marc Dionne

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.