]> git.apps.os.sepia.ceph.com Git - ceph.git/commitdiff
os/chain_xattr: handle read on chnk-aligned xattr 5235/head
authorSage Weil <sage@redhat.com>
Wed, 18 Mar 2015 20:49:20 +0000 (13:49 -0700)
committerNathan Cutler <ncutler@suse.com>
Wed, 15 Jul 2015 08:52:30 +0000 (10:52 +0200)
If we wrote an xattr that was a multiple of a chunk, we will try to read
the next chunk and get ENODATA.  If that happens bail out of the loop and
assume we've read the whole thing.

Backport: hammer, firefly
Signed-off-by: Sage Weil <sage@redhat.com>
(cherry picked from commit 8614dcebf384b74b283cd352001a65fa26ba925c)

Conflicts:
    src/test/objectstore/chain_xattr.cc
        added #define FILENAME

src/os/chain_xattr.cc
src/test/objectstore/chain_xattr.cc

index c020c9db843987b02ea5c31b8957869a0cfd0441..e90462af71964fab925df69032780859542fcda1 100644 (file)
@@ -138,6 +138,10 @@ int chain_getxattr(const char *fn, const char *name, void *val, size_t size)
     size -= chunk_size;
 
     r = sys_getxattr(fn, raw_name, (char *)val + pos, chunk_size);
+    if (i && r == -ENODATA) {
+      ret = pos;
+      break;
+    }
     if (r < 0) {
       ret = r;
       break;
@@ -201,6 +205,10 @@ int chain_fgetxattr(int fd, const char *name, void *val, size_t size)
     size -= chunk_size;
 
     r = sys_fgetxattr(fd, raw_name, (char *)val + pos, chunk_size);
+    if (i && r == -ENODATA) {
+      ret = pos;
+      break;
+    }
     if (r < 0) {
       ret = r;
       break;
index 8346c02b2b160e5ebe74027f29cd86a7bdd25c72..7c0896210e0e30af6fbf0fd4ee28a6acf5df16cd 100644 (file)
@@ -29,6 +29,7 @@
 #include <gtest/gtest.h>
 
 #define LARGE_BLOCK_LEN CHAIN_XATTR_MAX_BLOCK_LEN + 1024
+#define FILENAME "bufferlist"
 
 TEST(chain_xattr, get_and_set) {
   const char* file = "testfile";
@@ -147,6 +148,44 @@ TEST(chain_xattr, get_and_set) {
   ::unlink(file);
 }
 
+TEST(chain_xattr, chunk_aligned) {
+  const char* file = FILENAME;
+  ::unlink(file);
+  int fd = ::open(file, O_CREAT|O_WRONLY|O_TRUNC, 0700);
+  const string user("user.");
+
+  // set N* chunk size
+  const string name = "user.foo";
+  const string name2 = "user.bar";
+
+  for (int len = CHAIN_XATTR_MAX_BLOCK_LEN - 10;
+       len < CHAIN_XATTR_MAX_BLOCK_LEN + 10;
+       ++len) {
+    cout << len << std::endl;
+    const string x(len, 'x');
+    char buf[len*2];
+    ASSERT_EQ(len, chain_setxattr(file, name.c_str(), x.c_str(), len));
+    char attrbuf[4096];
+    int l = ceph_os_listxattr(file, attrbuf, sizeof(attrbuf));
+    for (char *p = attrbuf; p - attrbuf < l; p += strlen(p) + 1) {
+      cout << "  attr " << p << std::endl;
+    }
+    ASSERT_EQ(len, chain_getxattr(file, name.c_str(), buf, len*2));
+    ASSERT_EQ(0, chain_removexattr(file, name.c_str()));
+
+    ASSERT_EQ(len, chain_fsetxattr(fd, name2.c_str(), x.c_str(), len));
+    l = ceph_os_flistxattr(fd, attrbuf, sizeof(attrbuf));
+    for (char *p = attrbuf; p - attrbuf < l; p += strlen(p) + 1) {
+      cout << "  attr " << p << std::endl;
+    }
+    ASSERT_EQ(len, chain_fgetxattr(fd, name2.c_str(), buf, len*2));
+    ASSERT_EQ(0, chain_fremovexattr(fd, name2.c_str()));
+  }
+
+  ::close(fd);
+  ::unlink(file);
+}
+
 TEST(chain_xattr, listxattr) {
   const char* file = "testfile";
   ::unlink(file);