summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Layton <jlayton@kernel.org>2019-06-06 00:24:22 +0300
committerIlya Dryomov <idryomov@gmail.com>2019-07-08 15:01:43 +0300
commit441d367644e2f60b37f36bfc656deee551acba5b (patch)
tree3f982314323d35df283530d228bda9047e99ed69
parent58981784a6926e14964bb0e41dca38d75976b946 (diff)
downloadlinux-441d367644e2f60b37f36bfc656deee551acba5b.tar.xz
iversion: add a routine to update a raw value with a larger one
Under ceph, clients can be independently updating iversion themselves, while working under comprehensive sets of caps on an inode. In that situation we always want to prefer the largest value of a change attribute. Add a new function that will update a raw value with a larger one, but otherwise leave it alone. Signed-off-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: "Yan, Zheng" <zyan@redhat.com> Signed-off-by: Ilya Dryomov <idryomov@gmail.com>
-rw-r--r--include/linux/iversion.h24
1 files changed, 24 insertions, 0 deletions
diff --git a/include/linux/iversion.h b/include/linux/iversion.h
index be50ef7cedab..2917ef990d43 100644
--- a/include/linux/iversion.h
+++ b/include/linux/iversion.h
@@ -113,6 +113,30 @@ inode_peek_iversion_raw(const struct inode *inode)
}
/**
+ * inode_set_max_iversion_raw - update i_version new value is larger
+ * @inode: inode to set
+ * @val: new i_version to set
+ *
+ * Some self-managed filesystems (e.g Ceph) will only update the i_version
+ * value if the new value is larger than the one we already have.
+ */
+static inline void
+inode_set_max_iversion_raw(struct inode *inode, u64 val)
+{
+ u64 cur, old;
+
+ cur = inode_peek_iversion_raw(inode);
+ for (;;) {
+ if (cur > val)
+ break;
+ old = atomic64_cmpxchg(&inode->i_version, cur, val);
+ if (likely(old == cur))
+ break;
+ cur = old;
+ }
+}
+
+/**
* inode_set_iversion - set i_version to a particular value
* @inode: inode to set
* @val: new i_version value to set