Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 20 May 2022 22:39:01 +0300
From:      Dmitry Chagin <dchagin@freebsd.org>
To:        Mateusz Guzik <mjg@freebsd.org>
Cc:        src-committers@freebsd.org, dev-commits-src-all@freebsd.org, dev-commits-src-main@freebsd.org
Subject:   Re: git: ec3c225711ae - main - vfs: call vn_truncate_locked from kern_truncate
Message-ID:  <YofuVed3crX0V%2B91@heemeyer.club>
In-Reply-To: <202205201725.24KHPxLt058778@gitrepo.freebsd.org>
References:  <202205201725.24KHPxLt058778@gitrepo.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help

--QcIKgUAnjsmZRbWM
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

On Fri, May 20, 2022 at 05:25:59PM +0000, Mateusz Guzik wrote:
> The branch main has been updated by mjg:
> 
> URL: https://cgit.FreeBSD.org/src/commit/?id=ec3c225711ae7d5b8e71ed036aada09ef91149ec
> 
> commit ec3c225711ae7d5b8e71ed036aada09ef91149ec
> Author:     Mateusz Guzik <mjg@FreeBSD.org>
> AuthorDate: 2022-05-16 01:28:22 +0000
> Commit:     Mateusz Guzik <mjg@FreeBSD.org>
> CommitDate: 2022-05-20 17:25:51 +0000
> 
>     vfs: call vn_truncate_locked from kern_truncate
>     
>     This fixes a bug where the syscall would not bump writecount.
>     
>     PR:     263999
> ---
>  sys/kern/vfs_syscalls.c | 22 ++++++++++++----------
>  1 file changed, 12 insertions(+), 10 deletions(-)
> 
> diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
> index 86ef3fc7a095..600299fbe6eb 100644
> --- a/sys/kern/vfs_syscalls.c
> +++ b/sys/kern/vfs_syscalls.c
> @@ -3460,7 +3460,6 @@ kern_truncate(struct thread *td, const char *path, enum uio_seg pathseg,
>  	struct mount *mp;
>  	struct vnode *vp;
>  	void *rl_cookie;
> -	struct vattr vattr;
>  	struct nameidata nd;
>  	int error;
>  
> @@ -3480,18 +3479,21 @@ retry:
>  		return (error);
>  	}
>  	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
> -	if (vp->v_type == VDIR)
> +	if (vp->v_type == VDIR) {
>  		error = EISDIR;
> -#ifdef MAC
> -	else if ((error = mac_vnode_check_write(td->td_ucred, NOCRED, vp))) {
> +		goto out;
>  	}
> +#ifdef MAC
> +	error = mac_vnode_check_write(td->td_ucred, NOCRED, vp);
> +	if (error != 0)
> +		goto out;
>  #endif
> -	else if ((error = vn_writechk(vp)) == 0 &&
> -	    (error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td)) == 0) {
> -		VATTR_NULL(&vattr);
> -		vattr.va_size = length;
> -		error = VOP_SETATTR(vp, &vattr, td->td_ucred);
> -	}
> +	error = VOP_ACCESS(vp, VWRITE, td->td_ucred, td);
> +	if (error != 0)
> +		goto out;
> +
> +	error = vn_truncate_locked(vp, 0, false, td->td_ucred);
> +out:
>  	VOP_UNLOCK(vp);
>  	vn_finished_write(mp);
>  	vn_rangelock_unlock(vp, rl_cookie);

seems this broke truncate, test attached.



--QcIKgUAnjsmZRbWM
Content-Type: text/x-csrc; charset=us-ascii
Content-Disposition: attachment; filename="tst-tc.c"

#include <sys/types.h>
#include <sys/stat.h>

#include <stdio.h>
#include <string.h>
#include <unistd.h>


static char *temp_filename;
static int temp_fd;


#define FAIL(str) \
  do { printf ("error: %s (line %d)\n", str, __LINE__); return 1; } while (0)

int
main(void)
{
  struct stat st;
  char buf[1000];
  off_t offset=0;

  asprintf(&temp_filename, "/%s/%sXXXXXX", "tmp", "trunc");

  temp_fd = mkstemp(temp_filename);

  memset (buf, 0xcf, sizeof (buf));

  if (pwrite (temp_fd, buf, sizeof (buf), offset) != sizeof (buf))
    FAIL ("write failed");
  if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + sizeof (buf)))
    FAIL ("initial size wrong");

  if (ftruncate (temp_fd, offset + 800) < 0)
    FAIL ("size reduction with ftruncate failed");
  if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
    FAIL ("size after reduction with ftruncate is incorrect");

  /* The following test covers more than POSIX.  POSIX does not require
     that ftruncate() can increase the file size.  But we are testing
     Unix systems.  */
  if (ftruncate (temp_fd, offset + 1200) < 0)
    FAIL ("size increate with ftruncate failed");
  if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
    FAIL ("size after increase is incorrect");

  if (truncate (temp_filename, offset + 800) < 0)
    FAIL ("size reduction with truncate failed");
  if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 800))
    FAIL ("size after reduction with truncate incorrect");

  /* The following test covers more than POSIX.  POSIX does not require
     that truncate() can increase the file size.  But we are testing
     Unix systems.  */
  if (truncate (temp_filename, (offset + 1200)) < 0)
    FAIL ("size increase with truncate failed");
  if (fstat (temp_fd, &st) < 0 || st.st_size != (offset + 1200))
    FAIL ("size increase with truncate is incorrect");

  return 0;
}

--QcIKgUAnjsmZRbWM--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?YofuVed3crX0V%2B91>