From da78889d76f641dfcbb80164be32b85e880bb97f Mon Sep 17 00:00:00 2001 From: Sage Weil Date: Wed, 18 Mar 2015 13:49:20 -0700 Subject: [PATCH] os/chain_xattr: handle read on chnk-aligned xattr 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 (cherry picked from commit 8614dcebf384b74b283cd352001a65fa26ba925c) Conflicts: src/test/objectstore/chain_xattr.cc added #define FILENAME --- src/os/chain_xattr.cc | 8 ++++++ src/test/objectstore/chain_xattr.cc | 39 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/src/os/chain_xattr.cc b/src/os/chain_xattr.cc index c020c9db84398..e90462af71964 100644 --- a/src/os/chain_xattr.cc +++ b/src/os/chain_xattr.cc @@ -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; diff --git a/src/test/objectstore/chain_xattr.cc b/src/test/objectstore/chain_xattr.cc index 8346c02b2b160..7c0896210e0e3 100644 --- a/src/test/objectstore/chain_xattr.cc +++ b/src/test/objectstore/chain_xattr.cc @@ -29,6 +29,7 @@ #include #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); -- 2.39.5