Lock tmpfs node tn_status updates done under the shared vnode lock.
If tmpfs vnode is only shared locked, tn_status field still needs updates to note the access time modification. Use the same locking scheme as for UFS, protect tn_status with the node interlock + shared vnode lock. Fix nearby style. Noted and reviewed by: mjg Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week
This commit is contained in:
parent
305b422966
commit
5dc1128656
@ -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);
|
||||
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user