diff options
author | kib <kib@FreeBSD.org> | 2015-01-28 10:37:23 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2015-01-28 10:37:23 +0000 |
commit | 19abfd469885b67c5047dba2d04b3dc3b921f0a3 (patch) | |
tree | 8e9a74f326054d217c814329e5be52b441d536f0 /sys/fs/tmpfs/tmpfs_vfsops.c | |
parent | 53810519b4c0da8a9f8bcdafa10465c8d423a70c (diff) | |
download | FreeBSD-src-19abfd469885b67c5047dba2d04b3dc3b921f0a3.zip FreeBSD-src-19abfd469885b67c5047dba2d04b3dc3b921f0a3.tar.gz |
Update mtime for tmpfs files modified through memory mapping. Similar
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
Diffstat (limited to 'sys/fs/tmpfs/tmpfs_vfsops.c')
-rw-r--r-- | sys/fs/tmpfs/tmpfs_vfsops.c | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/sys/fs/tmpfs/tmpfs_vfsops.c b/sys/fs/tmpfs/tmpfs_vfsops.c index fbd7a63..2942e5a 100644 --- a/sys/fs/tmpfs/tmpfs_vfsops.c +++ b/sys/fs/tmpfs/tmpfs_vfsops.c @@ -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 statfs *sbp) 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); } |