summaryrefslogtreecommitdiffstats
path: root/sys/fs/tmpfs
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2017-01-13 12:38:25 +0000
committerkib <kib@FreeBSD.org>2017-01-13 12:38:25 +0000
commit2eaa0f81174966046fba99f19c1f0563fe8ccd78 (patch)
treeea79090e80681e42ff75ca6afdc57f660808aa39 /sys/fs/tmpfs
parent97cc8fe7187504cc7c43ea2ed2bf35e5a729ddc5 (diff)
downloadFreeBSD-src-2eaa0f81174966046fba99f19c1f0563fe8ccd78.zip
FreeBSD-src-2eaa0f81174966046fba99f19c1f0563fe8ccd78.tar.gz
MFC r311525:
Lock tmpfs node tn_status updates done under the shared vnode lock.
Diffstat (limited to 'sys/fs/tmpfs')
-rw-r--r--sys/fs/tmpfs/tmpfs.h5
-rw-r--r--sys/fs/tmpfs/tmpfs_fifoops.c6
-rw-r--r--sys/fs/tmpfs/tmpfs_subr.c55
-rw-r--r--sys/fs/tmpfs/tmpfs_vnops.c16
4 files changed, 54 insertions, 28 deletions
diff --git a/sys/fs/tmpfs/tmpfs.h b/sys/fs/tmpfs/tmpfs.h
index b077489..cf1e3fa 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 289ca02..f1743db 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 3122ba0..f1bf51c 100644
--- a/sys/fs/tmpfs/tmpfs_subr.c
+++ b/sys/fs/tmpfs/tmpfs_subr.c
@@ -1093,9 +1093,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);
}
/*
@@ -1138,9 +1138,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);
}
/*
@@ -1283,7 +1283,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;
}
@@ -1731,15 +1731,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)
@@ -1756,11 +1766,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);
}
@@ -1794,14 +1818,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 c302771..a6bfbae 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
OpenPOWER on IntegriCloud