diff --git a/sys/fs/tmpfs/tmpfs.h b/sys/fs/tmpfs/tmpfs.h index b077489c47c0..cf1e3fa3cac9 100644 --- a/sys/fs/tmpfs/tmpfs.h +++ b/sys/fs/tmpfs/tmpfs.h @@ -199,7 +199,9 @@ struct tmpfs_node { * allocated for it or it has been reclaimed). */ struct vnode * tn_vnode; - /* interlock to protect tn_vpstate */ + /* Interlock to protect tn_vpstate, and tn_status under shared + * vnode lock. + */ struct mtx tn_interlock; /* Identify if current node has vnode assiocate with @@ -420,6 +422,7 @@ int tmpfs_chtimes(struct vnode *, struct vattr *, struct ucred *cred, void tmpfs_itimes(struct vnode *, const struct timespec *, const struct timespec *); +void tmpfs_set_status(struct tmpfs_node *node, int status); void tmpfs_update(struct vnode *); int tmpfs_truncate(struct vnode *, off_t); diff --git a/sys/fs/tmpfs/tmpfs_fifoops.c b/sys/fs/tmpfs/tmpfs_fifoops.c index 289ca0215aad..f1743db50de9 100644 --- a/sys/fs/tmpfs/tmpfs_fifoops.c +++ b/sys/fs/tmpfs/tmpfs_fifoops.c @@ -52,11 +52,11 @@ static int tmpfs_fifo_close(struct vop_close_args *v) { struct tmpfs_node *node; - node = VP_TO_TMPFS_NODE(v->a_vp); - node->tn_status |= TMPFS_NODE_ACCESSED; + node = VP_TO_TMPFS_NODE(v->a_vp); + tmpfs_set_status(node, TMPFS_NODE_ACCESSED); tmpfs_update(v->a_vp); - return fifo_specops.vop_close(v); + return (fifo_specops.vop_close(v)); } /* diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index c37a83810d07..a7d5f5b72d06 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -1092,9 +1092,9 @@ tmpfs_dir_getdotdent(struct tmpfs_node *node, struct uio *uio) else error = uiomove(&dent, dent.d_reclen, uio); - node->tn_status |= TMPFS_NODE_ACCESSED; + tmpfs_set_status(node, TMPFS_NODE_ACCESSED); - return error; + return (error); } /* @@ -1137,9 +1137,9 @@ tmpfs_dir_getdotdotdent(struct tmpfs_node *node, struct uio *uio) else error = uiomove(&dent, dent.d_reclen, uio); - node->tn_status |= TMPFS_NODE_ACCESSED; + tmpfs_set_status(node, TMPFS_NODE_ACCESSED); - return error; + return (error); } /* @@ -1282,7 +1282,7 @@ tmpfs_dir_getdents(struct tmpfs_node *node, struct uio *uio, int maxcookies, node->tn_dir.tn_readdir_lastn = off; node->tn_dir.tn_readdir_lastp = de; - node->tn_status |= TMPFS_NODE_ACCESSED; + tmpfs_set_status(node, TMPFS_NODE_ACCESSED); return error; } @@ -1735,15 +1735,25 @@ tmpfs_chtimes(struct vnode *vp, struct vattr *vap, return (0); } -/* Sync timestamps */ void -tmpfs_itimes(struct vnode *vp, const struct timespec *acc, +tmpfs_set_status(struct tmpfs_node *node, int status) +{ + + if ((node->tn_status & status) == status) + return; + TMPFS_NODE_LOCK(node); + node->tn_status |= status; + TMPFS_NODE_UNLOCK(node); +} + +/* Sync timestamps */ +static void +tmpfs_itimes_locked(struct tmpfs_node *node, const struct timespec *acc, const struct timespec *mod) { - struct tmpfs_node *node; struct timespec now; - node = VP_TO_TMPFS_NODE(vp); + TMPFS_ASSERT_LOCKED(node); if ((node->tn_status & (TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED | TMPFS_NODE_CHANGED)) == 0) @@ -1760,11 +1770,25 @@ tmpfs_itimes(struct vnode *vp, const struct timespec *acc, mod = &now; node->tn_mtime = *mod; } - if (node->tn_status & TMPFS_NODE_CHANGED) { + if (node->tn_status & TMPFS_NODE_CHANGED) node->tn_ctime = now; - } - node->tn_status &= - ~(TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED | TMPFS_NODE_CHANGED); + node->tn_status &= ~(TMPFS_NODE_ACCESSED | TMPFS_NODE_MODIFIED | + TMPFS_NODE_CHANGED); +} + +void +tmpfs_itimes(struct vnode *vp, const struct timespec *acc, + const struct timespec *mod) +{ + struct tmpfs_node *node; + + ASSERT_VOP_LOCKED(vp, "tmpfs_itimes"); + node = VP_TO_TMPFS_NODE(vp); + + TMPFS_NODE_LOCK(node); + tmpfs_itimes_locked(node, acc, mod); + TMPFS_NODE_UNLOCK(node); + /* XXX: FIX? The entropy here is desirable, but the harvesting may be expensive */ random_harvest_queue(node, sizeof(*node), 1, RANDOM_FS_ATIME); } @@ -1798,14 +1822,13 @@ tmpfs_truncate(struct vnode *vp, off_t length) return (EFBIG); error = tmpfs_reg_resize(vp, length, FALSE); - if (error == 0) { + if (error == 0) node->tn_status |= TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED; - } out: tmpfs_update(vp); - return error; + return (error); } static __inline int diff --git a/sys/fs/tmpfs/tmpfs_vnops.c b/sys/fs/tmpfs/tmpfs_vnops.c index ed6de9bfd7e8..2e2fe9f11af8 100644 --- a/sys/fs/tmpfs/tmpfs_vnops.c +++ b/sys/fs/tmpfs/tmpfs_vnops.c @@ -445,7 +445,7 @@ tmpfs_read(struct vop_read_args *v) if (uio->uio_offset < 0) return (EINVAL); node = VP_TO_TMPFS_NODE(vp); - node->tn_status |= TMPFS_NODE_ACCESSED; + tmpfs_set_status(node, TMPFS_NODE_ACCESSED); return (uiomove_object(node->tn_reg.tn_aobj, node->tn_size, uio)); } @@ -1082,8 +1082,8 @@ tmpfs_rmdir(struct vop_rmdir_args *v) v->a_cnp->cn_namelen)); /* Check flags to see if we are allowed to remove the directory. */ - if (dnode->tn_flags & APPEND - || node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) { + if ((dnode->tn_flags & APPEND) != 0 || + (node->tn_flags & (NOUNLINK | IMMUTABLE | APPEND)) != 0) { error = EPERM; goto out; } @@ -1099,7 +1099,7 @@ tmpfs_rmdir(struct vop_rmdir_args *v) TMPFS_ASSERT_ELOCKED(node); node->tn_links--; node->tn_dir.tn_parent = NULL; - node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | \ + node->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED; TMPFS_NODE_UNLOCK(node); @@ -1107,8 +1107,8 @@ tmpfs_rmdir(struct vop_rmdir_args *v) TMPFS_NODE_LOCK(dnode); TMPFS_ASSERT_ELOCKED(dnode); dnode->tn_links--; - dnode->tn_status |= TMPFS_NODE_ACCESSED | \ - TMPFS_NODE_CHANGED | TMPFS_NODE_MODIFIED; + dnode->tn_status |= TMPFS_NODE_ACCESSED | TMPFS_NODE_CHANGED | + TMPFS_NODE_MODIFIED; TMPFS_NODE_UNLOCK(dnode); cache_purge(dvp); @@ -1220,9 +1220,9 @@ tmpfs_readlink(struct vop_readlink_args *v) error = uiomove(node->tn_link, MIN(node->tn_size, uio->uio_resid), uio); - node->tn_status |= TMPFS_NODE_ACCESSED; + tmpfs_set_status(node, TMPFS_NODE_ACCESSED); - return error; + return (error); } static int