iversion: add a routine to update a raw value with a larger one
authorJeff Layton <jlayton@kernel.org>
Wed, 5 Jun 2019 21:24:22 +0000 (17:24 -0400)
committerIlya Dryomov <idryomov@gmail.com>
Mon, 8 Jul 2019 12:01:43 +0000 (14:01 +0200)
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>
include/linux/iversion.h

index be50ef7cedab21a23aa847a6f8fe91967416aa9e..2917ef990d435f2b747d30d6dd4c546337afc496 100644 (file)
@@ -112,6 +112,30 @@ inode_peek_iversion_raw(const struct inode *inode)
        return atomic64_read(&inode->i_version);
 }
 
+/**
+ * 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