Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Jan 2015 15:27:33 +0100
From:      "Ronald Klop" <ronald-lists@klop.ws>
To:        svn-src-all@freebsd.org, "Konstantin Belousov" <kib@freebsd.org>
Subject:   Re: svn commit: r277828 - in head/sys: fs/tmpfs vm
Message-ID:  <op.xs6fr7avkndu52@82-171-231-144.ip.telfort.nl>
In-Reply-To: <201501281037.t0SAbNR3053095@svn.freebsd.org>
References:  <201501281037.t0SAbNR3053095@svn.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 28 Jan 2015 11:37:23 +0100, Konstantin Belousov <kib@freebsd.org>  
wrote:

> Author: kib
> Date: Wed Jan 28 10:37:23 2015
> New Revision: 277828
> URL: https://svnweb.freebsd.org/changeset/base/277828
>
> Log:
>   Update mtime for tmpfs files modified through memory mapping.  Similar


Thanks a lot. It runs now and seems to work pretty well.

FreeBSD 11.0-CURRENT #3 r277829M: Wed Jan 28 14:54:24 CET 2015
     root@******:/usr/obj-arm/arm.arm/usr/src-arm/sys/SHEEVAPLUG arm

Regards,
Ronald.


>   to UFS, perform updates during syncer scans, which in particular means
>   that tmpfs now performs scan on sync.  Also, this means that a mtime
>   update may be delayed up to 30 seconds after the write.
>  The vm_object' OBJ_TMPFS_DIRTY flag for tmpfs swap object is similar
>   to the OBJ_MIGHTBEDIRTY flag for the vnode object, it indicates that
>   object could have been dirtied.  Adapt fast page fault handler and
>   vm_object_set_writeable_dirty() to handle OBJ_TMPFS_NODE same as
>   OBJT_VNODE.
>  Reported by:	Ronald Klop <ronald-lists@klop.ws>
>   Tested by:	pho
>   Sponsored by:	The FreeBSD Foundation
>   MFC after:	2 weeks
>
> Modified:
>   head/sys/fs/tmpfs/tmpfs.h
>   head/sys/fs/tmpfs/tmpfs_subr.c
>   head/sys/fs/tmpfs/tmpfs_vfsops.c
>   head/sys/fs/tmpfs/tmpfs_vnops.c
>   head/sys/vm/vm_fault.c
>   head/sys/vm/vm_object.c
>   head/sys/vm/vm_object.h
>
> Modified: head/sys/fs/tmpfs/tmpfs.h
> ==============================================================================
> --- head/sys/fs/tmpfs/tmpfs.h	Wed Jan 28 10:25:35 2015	(r277827)
> +++ head/sys/fs/tmpfs/tmpfs.h	Wed Jan 28 10:37:23 2015	(r277828)
> @@ -398,6 +398,7 @@ int	tmpfs_alloc_vp(struct mount *, struc
>  void	tmpfs_free_vp(struct vnode *);
>  int	tmpfs_alloc_file(struct vnode *, struct vnode **, struct vattr *,
>  	    struct componentname *, char *);
> +void	tmpfs_check_mtime(struct vnode *);
>  void	tmpfs_dir_attach(struct vnode *, struct tmpfs_dirent *);
>  void	tmpfs_dir_detach(struct vnode *, struct tmpfs_dirent *);
>  void	tmpfs_dir_destroy(struct tmpfs_mount *, struct tmpfs_node *);
>
> Modified: head/sys/fs/tmpfs/tmpfs_subr.c
> ==============================================================================
> --- head/sys/fs/tmpfs/tmpfs_subr.c	Wed Jan 28 10:25:35 2015	(r277827)
> +++ head/sys/fs/tmpfs/tmpfs_subr.c	Wed Jan 28 10:37:23 2015	(r277828)
> @@ -1415,6 +1415,31 @@ retry:
>  	return (0);
>  }
> +void
> +tmpfs_check_mtime(struct vnode *vp)
> +{
> +	struct tmpfs_node *node;
> +	struct vm_object *obj;
> +
> +	ASSERT_VOP_ELOCKED(vp, "check_mtime");
> +	if (vp->v_type != VREG)
> +		return;
> +	node = VP_TO_TMPFS_NODE(vp);
> +	obj = vp->v_object;
> +	KASSERT((obj->flags & (OBJ_TMPFS_NODE | OBJ_TMPFS)) ==
> +	    (OBJ_TMPFS_NODE | OBJ_TMPFS), ("non-tmpfs obj"));
> +	/* unlocked read */
> +	if ((obj->flags & OBJ_TMPFS_DIRTY) != 0) {
> +		VM_OBJECT_WLOCK(obj);
> +		if ((obj->flags & OBJ_TMPFS_DIRTY) != 0) {
> +			obj->flags &= ~OBJ_TMPFS_DIRTY;
> +			node = VP_TO_TMPFS_NODE(vp);
> +			node->tn_status |= TMPFS_NODE_MODIFIED;
> +		}
> +		VM_OBJECT_WUNLOCK(obj);
> +	}
> +}
> +
>  /*
>   * Change flags of the given vnode.
>   * Caller should execute tmpfs_update on vp after a successful  
> execution.
>
> Modified: head/sys/fs/tmpfs/tmpfs_vfsops.c
> ==============================================================================
> --- head/sys/fs/tmpfs/tmpfs_vfsops.c	Wed Jan 28 10:25:35 2015	(r277827)
> +++ head/sys/fs/tmpfs/tmpfs_vfsops.c	Wed Jan 28 10:37:23 2015	(r277828)
> @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
>  #include <sys/proc.h>
>  #include <sys/jail.h>
>  #include <sys/kernel.h>
> +#include <sys/rwlock.h>
>  #include <sys/stat.h>
>  #include <sys/systm.h>
>  #include <sys/sysctl.h>
> @@ -418,11 +419,45 @@ tmpfs_statfs(struct mount *mp, struct st
>  static int
>  tmpfs_sync(struct mount *mp, int waitfor)
>  {
> +	struct vnode *vp, *mvp;
> +	struct vm_object *obj;
> 	if (waitfor == MNT_SUSPEND) {
>  		MNT_ILOCK(mp);
>  		mp->mnt_kern_flag |= MNTK_SUSPEND2 | MNTK_SUSPENDED;
>  		MNT_IUNLOCK(mp);
> +	} else if (waitfor == MNT_LAZY) {
> +		/*
> +		 * Handle lazy updates of mtime from writes to mmaped
> +		 * regions.  Use MNT_VNODE_FOREACH_ALL instead of
> +		 * MNT_VNODE_FOREACH_ACTIVE, since unmap of the
> +		 * tmpfs-backed vnode does not call vinactive(), due
> +		 * to vm object type is OBJT_SWAP.
> +		 */
> +		MNT_VNODE_FOREACH_ALL(vp, mp, mvp) {
> +			if (vp->v_type != VREG) {
> +				VI_UNLOCK(vp);
> +				continue;
> +			}
> +			obj = vp->v_object;
> +			KASSERT((obj->flags & (OBJ_TMPFS_NODE | OBJ_TMPFS)) ==
> +			    (OBJ_TMPFS_NODE | OBJ_TMPFS), ("non-tmpfs obj"));
> +
> +			/*
> +			 * Unlocked read, avoid taking vnode lock if
> +			 * not needed.  Lost update will be handled on
> +			 * the next call.
> +			 */
> +			if ((obj->flags & OBJ_TMPFS_DIRTY) == 0) {
> +				VI_UNLOCK(vp);
> +				continue;
> +			}
> +			if (vget(vp, LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK,
> +			    curthread) != 0)
> +				continue;
> +			tmpfs_check_mtime(vp);
> +			vput(vp);
> +		}
>  	}
>  	return (0);
>  }
>
> Modified: head/sys/fs/tmpfs/tmpfs_vnops.c
> ==============================================================================
> --- head/sys/fs/tmpfs/tmpfs_vnops.c	Wed Jan 28 10:25:35 2015	(r277827)
> +++ head/sys/fs/tmpfs/tmpfs_vnops.c	Wed Jan 28 10:37:23 2015	(r277828)
> @@ -505,6 +505,7 @@ tmpfs_fsync(struct vop_fsync_args *v)
> 	MPASS(VOP_ISLOCKED(vp));
> +	tmpfs_check_mtime(vp);
>  	tmpfs_update(vp);
> 	return 0;
> @@ -1222,16 +1223,16 @@ tmpfs_readlink(struct vop_readlink_args
>  static int
>  tmpfs_inactive(struct vop_inactive_args *v)
>  {
> -	struct vnode *vp = v->a_vp;
> -
> +	struct vnode *vp;
>  	struct tmpfs_node *node;
> +	vp = v->a_vp;
>  	node = VP_TO_TMPFS_NODE(vp);
> -
>  	if (node->tn_links == 0)
>  		vrecycle(vp);
> -
> -	return 0;
> +	else
> +		tmpfs_check_mtime(vp);
> +	return (0);
>  }
> int
>
> Modified: head/sys/vm/vm_fault.c
> ==============================================================================
> --- head/sys/vm/vm_fault.c	Wed Jan 28 10:25:35 2015	(r277827)
> +++ head/sys/vm/vm_fault.c	Wed Jan 28 10:37:23 2015	(r277828)
> @@ -358,11 +358,13 @@ RetryFault:;
>  	    (fault_flags & (VM_FAULT_CHANGE_WIRING | VM_FAULT_DIRTY)) == 0 &&
>  	    /* avoid calling vm_object_set_writeable_dirty() */
>  	    ((prot & VM_PROT_WRITE) == 0 ||
> -	    fs.first_object->type != OBJT_VNODE ||
> +	    (fs.first_object->type != OBJT_VNODE &&
> +	    (fs.first_object->flags & OBJ_TMPFS_NODE) == 0) ||
>  	    (fs.first_object->flags & OBJ_MIGHTBEDIRTY) != 0)) {
>  		VM_OBJECT_RLOCK(fs.first_object);
>  		if ((prot & VM_PROT_WRITE) != 0 &&
> -		    fs.first_object->type == OBJT_VNODE &&
> +		    (fs.first_object->type == OBJT_VNODE ||
> +		    (fs.first_object->flags & OBJ_TMPFS_NODE) != 0) &&
>  		    (fs.first_object->flags & OBJ_MIGHTBEDIRTY) == 0)
>  			goto fast_failed;
>  		m = vm_page_lookup(fs.first_object, fs.first_pindex);
>
> Modified: head/sys/vm/vm_object.c
> ==============================================================================
> --- head/sys/vm/vm_object.c	Wed Jan 28 10:25:35 2015	(r277827)
> +++ head/sys/vm/vm_object.c	Wed Jan 28 10:37:23 2015	(r277828)
> @@ -2199,8 +2199,13 @@ vm_object_set_writeable_dirty(vm_object_
>  {
> 	VM_OBJECT_ASSERT_WLOCKED(object);
> -	if (object->type != OBJT_VNODE)
> +	if (object->type != OBJT_VNODE) {
> +		if ((object->flags & OBJ_TMPFS_NODE) != 0) {
> +			KASSERT(object->type == OBJT_SWAP, ("non-swap tmpfs"));
> +			vm_object_set_flag(object, OBJ_TMPFS_DIRTY);
> +		}
>  		return;
> +	}
>  	object->generation++;
>  	if ((object->flags & OBJ_MIGHTBEDIRTY) != 0)
>  		return;
>
> Modified: head/sys/vm/vm_object.h
> ==============================================================================
> --- head/sys/vm/vm_object.h	Wed Jan 28 10:25:35 2015	(r277827)
> +++ head/sys/vm/vm_object.h	Wed Jan 28 10:37:23 2015	(r277828)
> @@ -187,6 +187,7 @@ struct vm_object {
>  #define OBJ_PIPWNT	0x0040		/* paging in progress wanted */
>  #define OBJ_MIGHTBEDIRTY 0x0100		/* object might be dirty, only for  
> vnode */
>  #define	OBJ_TMPFS_NODE	0x0200		/* object belongs to tmpfs VREG node */
> +#define	OBJ_TMPFS_DIRTY	0x0400		/* dirty tmpfs obj */
>  #define	OBJ_COLORED	0x1000		/* pg_color is defined */
>  #define	OBJ_ONEMAPPING	0x2000		/* One USE (a single, non-forked)  
> mapping flag */
>  #define	OBJ_DISCONNECTWNT 0x4000	/* disconnect from vnode wanted */
> _______________________________________________
> svn-src-all@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/svn-src-all
> To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?op.xs6fr7avkndu52>