Date: Wed, 11 Feb 2015 09:02:22 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r278571 - in stable/10/sys: fs/tmpfs vm Message-ID: <201502110902.t1B92MKa064448@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Wed Feb 11 09:02:21 2015 New Revision: 278571 URL: https://svnweb.freebsd.org/changeset/base/278571 Log: MFC r277828: Update mtime for tmpfs files modified through memory mapping. MFC r277969: Update both ctime and mtime for writes to tmpfs files. MFC r277972: Remove single-use boolean. MFC r278151: Remove duplicated assignment. Modified: stable/10/sys/fs/tmpfs/tmpfs.h stable/10/sys/fs/tmpfs/tmpfs_subr.c stable/10/sys/fs/tmpfs/tmpfs_vfsops.c stable/10/sys/fs/tmpfs/tmpfs_vnops.c stable/10/sys/vm/vm_fault.c stable/10/sys/vm/vm_object.c stable/10/sys/vm/vm_object.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/fs/tmpfs/tmpfs.h ============================================================================== --- stable/10/sys/fs/tmpfs/tmpfs.h Wed Feb 11 09:00:22 2015 (r278570) +++ stable/10/sys/fs/tmpfs/tmpfs.h Wed Feb 11 09:02:21 2015 (r278571) @@ -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: stable/10/sys/fs/tmpfs/tmpfs_subr.c ============================================================================== --- stable/10/sys/fs/tmpfs/tmpfs_subr.c Wed Feb 11 09:00:22 2015 (r278570) +++ stable/10/sys/fs/tmpfs/tmpfs_subr.c Wed Feb 11 09:02:21 2015 (r278571) @@ -1417,6 +1417,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; + 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 | + TMPFS_NODE_CHANGED; + } + VM_OBJECT_WUNLOCK(obj); + } +} + /* * Change flags of the given vnode. * Caller should execute tmpfs_update on vp after a successful execution. Modified: stable/10/sys/fs/tmpfs/tmpfs_vfsops.c ============================================================================== --- stable/10/sys/fs/tmpfs/tmpfs_vfsops.c Wed Feb 11 09:00:22 2015 (r278570) +++ stable/10/sys/fs/tmpfs/tmpfs_vfsops.c Wed Feb 11 09:02:21 2015 (r278571) @@ -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> @@ -417,11 +418,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: stable/10/sys/fs/tmpfs/tmpfs_vnops.c ============================================================================== --- stable/10/sys/fs/tmpfs/tmpfs_vnops.c Wed Feb 11 09:00:22 2015 (r278570) +++ stable/10/sys/fs/tmpfs/tmpfs_vnops.c Wed Feb 11 09:02:21 2015 (r278571) @@ -453,7 +453,6 @@ tmpfs_write(struct vop_write_args *v) struct tmpfs_node *node; off_t oldsize; int error, ioflag; - boolean_t extended; vp = v->a_vp; uio = v->a_uio; @@ -473,8 +472,7 @@ tmpfs_write(struct vop_write_args *v) return (EFBIG); if (vn_rlimit_fsize(vp, uio, uio->uio_td)) return (EFBIG); - extended = uio->uio_offset + uio->uio_resid > node->tn_size; - if (extended) { + if (uio->uio_offset + uio->uio_resid > node->tn_size) { error = tmpfs_reg_resize(vp, uio->uio_offset + uio->uio_resid, FALSE); if (error != 0) @@ -483,7 +481,7 @@ tmpfs_write(struct vop_write_args *v) error = uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio); node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED | - (extended ? TMPFS_NODE_CHANGED : 0); + TMPFS_NODE_CHANGED; if (node->tn_mode & (S_ISUID | S_ISGID)) { if (priv_check_cred(v->a_cred, PRIV_VFS_RETAINSUGID, 0)) node->tn_mode &= ~(S_ISUID | S_ISGID); @@ -505,6 +503,7 @@ tmpfs_fsync(struct vop_fsync_args *v) MPASS(VOP_ISLOCKED(vp)); + tmpfs_check_mtime(vp); tmpfs_update(vp); return 0; @@ -1222,16 +1221,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: stable/10/sys/vm/vm_fault.c ============================================================================== --- stable/10/sys/vm/vm_fault.c Wed Feb 11 09:00:22 2015 (r278570) +++ stable/10/sys/vm/vm_fault.c Wed Feb 11 09:02:21 2015 (r278571) @@ -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: stable/10/sys/vm/vm_object.c ============================================================================== --- stable/10/sys/vm/vm_object.c Wed Feb 11 09:00:22 2015 (r278570) +++ stable/10/sys/vm/vm_object.c Wed Feb 11 09:02:21 2015 (r278571) @@ -2200,8 +2200,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: stable/10/sys/vm/vm_object.h ============================================================================== --- stable/10/sys/vm/vm_object.h Wed Feb 11 09:00:22 2015 (r278570) +++ stable/10/sys/vm/vm_object.h Wed Feb 11 09:02:21 2015 (r278571) @@ -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 */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502110902.t1B92MKa064448>