diff mbox

[1/2] support for xattrs in libceph

Message ID 1305056329-482-2-git-send-email-brchrisman@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Brian Chrisman May 10, 2011, 7:38 p.m. UTC
From: Brian Chrisman <bchrisman@gmail.com>


Signed-off-by: Brian Chrisman <brchrisman@gmail.com>
---
 src/client/Client.cc       |   67 +++++++++++++++++++++++++++++++++++++++++++-
 src/client/Client.h        |   10 ++++++
 src/include/ceph/libceph.h |   15 ++++++++++
 src/libceph.cc             |   42 +++++++++++++++++++++++++++
 4 files changed, 133 insertions(+), 1 deletions(-)

Comments

Gregory Farnum May 10, 2011, 7:44 p.m. UTC | #1
What are the 'l'-prefixed functions for? They look like they're just
duplicates except for the prefix.
-Greg

On Tue, May 10, 2011 at 12:38 PM, Brian Chrisman <brchrisman@gmail.com> wrote:
> From: Brian Chrisman <bchrisman@gmail.com>
>
>
> Signed-off-by: Brian Chrisman <brchrisman@gmail.com>
> ---
>  src/client/Client.cc       |   67 +++++++++++++++++++++++++++++++++++++++++++-
>  src/client/Client.h        |   10 ++++++
>  src/include/ceph/libceph.h |   15 ++++++++++
>  src/libceph.cc             |   42 +++++++++++++++++++++++++++
>  4 files changed, 133 insertions(+), 1 deletions(-)
>
> diff --git a/src/client/Client.cc b/src/client/Client.cc
> index 6a27273..5083e99 100644
> --- a/src/client/Client.cc
> +++ b/src/client/Client.cc
> @@ -5563,6 +5563,71 @@ int Client::ll_setattr(vinodeno_t vino, struct stat *attr, int mask, int uid, in
>  // ----------
>  // xattrs
>
> +int Client::getxattr(const char *path, const char *name, void *value, size_t size)
> +{
> +  Mutex::Locker lock(client_lock);
> +  Inode *ceph_inode;
> +  Client::path_walk(path, &ceph_inode, true);
> +  return Client::_getxattr(ceph_inode, name, value, size, getuid(), getgid());
> +}
> +
> +int Client::lgetxattr(const char *path, const char *name, void *value, size_t size)
> +{
> +  Mutex::Locker lock(client_lock);
> +  Inode *ceph_inode;
> +  Client::path_walk(path, &ceph_inode, false);
> +  return Client::_getxattr(ceph_inode, name, value, size, getuid(), getgid());
> +}
> +
> +int Client::listxattr(const char *path, char *list, size_t size)
> +{
> +  Mutex::Locker lock(client_lock);
> +  Inode *ceph_inode;
> +  Client::path_walk(path, &ceph_inode, true);
> +  return Client::_listxattr(ceph_inode, list, size, getuid(), getgid());
> +}
> +
> +int Client::llistxattr(const char *path, char *list, size_t size)
> +{
> +  Mutex::Locker lock(client_lock);
> +  Inode *ceph_inode;
> +  Client::path_walk(path, &ceph_inode, false);
> +  return Client::_listxattr(ceph_inode, list, size, getuid(), getgid());
> +}
> +
> +int Client::removexattr(const char *path, const char *name)
> +{
> +  Mutex::Locker lock(client_lock);
> +  Inode *ceph_inode;
> +  Client::path_walk(path, &ceph_inode, true);
> +  return Client::_removexattr(ceph_inode, name, getuid(), getgid());
> +}
> +
> +int Client::lremovexattr(const char *path, const char *name)
> +{
> +  Mutex::Locker lock(client_lock);
> +  Inode *ceph_inode;
> +  Client::path_walk(path, &ceph_inode, false);
> +  return Client::_removexattr(ceph_inode, name, getuid(), getgid());
> +}
> +
> +int Client::setxattr(const char *path, const char *name, const void *value, size_t size, int flags)
> +{
> +  Mutex::Locker lock(client_lock);
> +  Inode *ceph_inode;
> +  Client::path_walk(path, &ceph_inode, true);
> +  return Client::_setxattr(ceph_inode, name, value, size, flags, getuid(), getgid());
> +}
> +
> +int Client::lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags)
> +{
> +  Mutex::Locker lock(client_lock);
> +  Inode *ceph_inode;
> +  Client::path_walk(path, &ceph_inode, false);
> +  return Client::_setxattr(ceph_inode, name, value, size, flags, getuid(), getgid());
> +}
> +
> +
>  int Client::_getxattr(Inode *in, const char *name, void *value, size_t size,
>                      int uid, int gid)
>  {
> @@ -5708,7 +5773,7 @@ int Client::ll_removexattr(vinodeno_t vino, const char *name, int uid, int gid)
>   tout << name << std::endl;
>
>   // only user xattrs, for now
> -  if (strncmp(name, "user.", 5))
> +  if (strncmp(name, "user.", 5) && strncmp(name, "security.", 9) && strncmp(name, "trusted.", 8))
>     return -EOPNOTSUPP;
>
>   Inode *in = _ll_get_inode(vino);
> diff --git a/src/client/Client.h b/src/client/Client.h
> index ab21dc8..b36621d 100644
> --- a/src/client/Client.h
> +++ b/src/client/Client.h
> @@ -1258,6 +1258,16 @@ public:
>   int fsync(int fd, bool syncdataonly);
>   int fstat(int fd, struct stat *stbuf);
>
> +  // full path xattr ops
> +  int getxattr(const char *path, const char *name, void *value, size_t size);
> +  int lgetxattr(const char *path, const char *name, void *value, size_t size);
> +  int listxattr(const char *path, char *list, size_t size);
> +  int llistxattr(const char *path, char *list, size_t size);
> +  int removexattr(const char *path, const char *name);
> +  int lremovexattr(const char *path, const char *name);
> +  int setxattr(const char *path, const char *name, const void *value, size_t size, int flags);
> +  int lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags);
> +
>   int sync_fs();
>   int64_t drop_caches();
>
> diff --git a/src/include/ceph/libceph.h b/src/include/ceph/libceph.h
> index 3ed3369..f9fc29e 100644
> --- a/src/include/ceph/libceph.h
> +++ b/src/include/ceph/libceph.h
> @@ -121,6 +121,21 @@ int ceph_fstat(struct ceph_mount_info *cmount, int fd, struct stat *stbuf);
>
>  int ceph_sync_fs(struct ceph_mount_info *cmount);
>
> +/* xattr support */
> +int ceph_getxattr(struct ceph_mount_info *cmount, const char *path, const char *name,
> +       void *value, size_t size);
> +int ceph_lgetxattr(struct ceph_mount_info *cmount, const char *path, const char *name,
> +       void *value, size_t size);
> +int ceph_listxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size);
> +int ceph_llistxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size);
> +int ceph_removexattr(struct ceph_mount_info *cmount, const char *path, const char *name);
> +int ceph_lremovexattr(struct ceph_mount_info *cmount, const char *path, const char *name);
> +int ceph_setxattr(struct ceph_mount_info *cmount, const char *path, const char *name,
> +       const void *value, size_t size, int flags);
> +int ceph_lsetxattr(struct ceph_mount_info *cmount, const char *path, const char *name,
> +       const void *value, size_t size, int flags);
> +
> +
>
>  /* expose file layout */
>  int ceph_get_file_stripe_unit(struct ceph_mount_info *cmount, int fh);
> diff --git a/src/libceph.cc b/src/libceph.cc
> index d1143d6..6388bde 100644
> --- a/src/libceph.cc
> +++ b/src/libceph.cc
> @@ -416,6 +416,48 @@ extern "C" int ceph_setattr(struct ceph_mount_info *cmount, const char *relpath,
>   return cmount->get_client()->setattr(relpath, attr, mask);
>  }
>
> +// *xattr() calls supporting samba/vfs
> +extern "C" int ceph_getxattr(struct ceph_mount_info *cmount, const char *path, const char *name, void *value, size_t size)
> +{
> +  return cmount->get_client()->getxattr(path, name, value, size);
> +}
> +
> +extern "C" int ceph_lgetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, void *value, size_t size)
> +{
> +  return cmount->get_client()->lgetxattr(path, name, value, size);
> +}
> +
> +extern "C" int ceph_listxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size)
> +{
> +  return cmount->get_client()->listxattr(path, list, size);
> +}
> +
> +extern "C" int ceph_llistxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size)
> +{
> +  return cmount->get_client()->llistxattr(path, list, size);
> +}
> +
> +extern "C" int ceph_removexattr(struct ceph_mount_info *cmount, const char *path, const char *name)
> +{
> +  return cmount->get_client()->removexattr(path, name);
> +}
> +
> +extern "C" int ceph_lremovexattr(struct ceph_mount_info *cmount, const char *path, const char *name)
> +{
> +  return cmount->get_client()->lremovexattr(path, name);
> +}
> +
> +extern "C" int ceph_setxattr(struct ceph_mount_info *cmount, const char *path, const char *name, const void *value, size_t size, int flags)
> +{
> +  return cmount->get_client()->setxattr(path, name, value, size, flags);
> +}
> +
> +extern "C" int ceph_lsetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, const void *value, size_t size, int flags)
> +{
> +  return cmount->get_client()->lsetxattr(path, name, value, size, flags);
> +}
> +/* end xattr support */
> +
>  extern "C" int ceph_chmod(struct ceph_mount_info *cmount, const char *path, mode_t mode)
>  {
>   return cmount->get_client()->chmod(path, mode);
> --
> 1.7.1
>
> --
> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Brian Chrisman May 10, 2011, 8:22 p.m. UTC | #2
They differentiate between xattrs on symlinks or on the files at which
they point.
If I recall, it's a slight difference internally to the Client class
whether a value is passed to path_walk as true/false, though I may be
misinterpreting that.  I can look at that again.

On Tue, May 10, 2011 at 12:44 PM, Gregory Farnum <gregf@hq.newdream.net> wrote:
> What are the 'l'-prefixed functions for? They look like they're just
> duplicates except for the prefix.
> -Greg
>
> On Tue, May 10, 2011 at 12:38 PM, Brian Chrisman <brchrisman@gmail.com> wrote:
>> From: Brian Chrisman <bchrisman@gmail.com>
>>
>>
>> Signed-off-by: Brian Chrisman <brchrisman@gmail.com>
>> ---
>>  src/client/Client.cc       |   67 +++++++++++++++++++++++++++++++++++++++++++-
>>  src/client/Client.h        |   10 ++++++
>>  src/include/ceph/libceph.h |   15 ++++++++++
>>  src/libceph.cc             |   42 +++++++++++++++++++++++++++
>>  4 files changed, 133 insertions(+), 1 deletions(-)
>>
>> diff --git a/src/client/Client.cc b/src/client/Client.cc
>> index 6a27273..5083e99 100644
>> --- a/src/client/Client.cc
>> +++ b/src/client/Client.cc
>> @@ -5563,6 +5563,71 @@ int Client::ll_setattr(vinodeno_t vino, struct stat *attr, int mask, int uid, in
>>  // ----------
>>  // xattrs
>>
>> +int Client::getxattr(const char *path, const char *name, void *value, size_t size)
>> +{
>> +  Mutex::Locker lock(client_lock);
>> +  Inode *ceph_inode;
>> +  Client::path_walk(path, &ceph_inode, true);
>> +  return Client::_getxattr(ceph_inode, name, value, size, getuid(), getgid());
>> +}
>> +
>> +int Client::lgetxattr(const char *path, const char *name, void *value, size_t size)
>> +{
>> +  Mutex::Locker lock(client_lock);
>> +  Inode *ceph_inode;
>> +  Client::path_walk(path, &ceph_inode, false);
>> +  return Client::_getxattr(ceph_inode, name, value, size, getuid(), getgid());
>> +}
>> +
>> +int Client::listxattr(const char *path, char *list, size_t size)
>> +{
>> +  Mutex::Locker lock(client_lock);
>> +  Inode *ceph_inode;
>> +  Client::path_walk(path, &ceph_inode, true);
>> +  return Client::_listxattr(ceph_inode, list, size, getuid(), getgid());
>> +}
>> +
>> +int Client::llistxattr(const char *path, char *list, size_t size)
>> +{
>> +  Mutex::Locker lock(client_lock);
>> +  Inode *ceph_inode;
>> +  Client::path_walk(path, &ceph_inode, false);
>> +  return Client::_listxattr(ceph_inode, list, size, getuid(), getgid());
>> +}
>> +
>> +int Client::removexattr(const char *path, const char *name)
>> +{
>> +  Mutex::Locker lock(client_lock);
>> +  Inode *ceph_inode;
>> +  Client::path_walk(path, &ceph_inode, true);
>> +  return Client::_removexattr(ceph_inode, name, getuid(), getgid());
>> +}
>> +
>> +int Client::lremovexattr(const char *path, const char *name)
>> +{
>> +  Mutex::Locker lock(client_lock);
>> +  Inode *ceph_inode;
>> +  Client::path_walk(path, &ceph_inode, false);
>> +  return Client::_removexattr(ceph_inode, name, getuid(), getgid());
>> +}
>> +
>> +int Client::setxattr(const char *path, const char *name, const void *value, size_t size, int flags)
>> +{
>> +  Mutex::Locker lock(client_lock);
>> +  Inode *ceph_inode;
>> +  Client::path_walk(path, &ceph_inode, true);
>> +  return Client::_setxattr(ceph_inode, name, value, size, flags, getuid(), getgid());
>> +}
>> +
>> +int Client::lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags)
>> +{
>> +  Mutex::Locker lock(client_lock);
>> +  Inode *ceph_inode;
>> +  Client::path_walk(path, &ceph_inode, false);
>> +  return Client::_setxattr(ceph_inode, name, value, size, flags, getuid(), getgid());
>> +}
>> +
>> +
>>  int Client::_getxattr(Inode *in, const char *name, void *value, size_t size,
>>                      int uid, int gid)
>>  {
>> @@ -5708,7 +5773,7 @@ int Client::ll_removexattr(vinodeno_t vino, const char *name, int uid, int gid)
>>   tout << name << std::endl;
>>
>>   // only user xattrs, for now
>> -  if (strncmp(name, "user.", 5))
>> +  if (strncmp(name, "user.", 5) && strncmp(name, "security.", 9) && strncmp(name, "trusted.", 8))
>>     return -EOPNOTSUPP;
>>
>>   Inode *in = _ll_get_inode(vino);
>> diff --git a/src/client/Client.h b/src/client/Client.h
>> index ab21dc8..b36621d 100644
>> --- a/src/client/Client.h
>> +++ b/src/client/Client.h
>> @@ -1258,6 +1258,16 @@ public:
>>   int fsync(int fd, bool syncdataonly);
>>   int fstat(int fd, struct stat *stbuf);
>>
>> +  // full path xattr ops
>> +  int getxattr(const char *path, const char *name, void *value, size_t size);
>> +  int lgetxattr(const char *path, const char *name, void *value, size_t size);
>> +  int listxattr(const char *path, char *list, size_t size);
>> +  int llistxattr(const char *path, char *list, size_t size);
>> +  int removexattr(const char *path, const char *name);
>> +  int lremovexattr(const char *path, const char *name);
>> +  int setxattr(const char *path, const char *name, const void *value, size_t size, int flags);
>> +  int lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags);
>> +
>>   int sync_fs();
>>   int64_t drop_caches();
>>
>> diff --git a/src/include/ceph/libceph.h b/src/include/ceph/libceph.h
>> index 3ed3369..f9fc29e 100644
>> --- a/src/include/ceph/libceph.h
>> +++ b/src/include/ceph/libceph.h
>> @@ -121,6 +121,21 @@ int ceph_fstat(struct ceph_mount_info *cmount, int fd, struct stat *stbuf);
>>
>>  int ceph_sync_fs(struct ceph_mount_info *cmount);
>>
>> +/* xattr support */
>> +int ceph_getxattr(struct ceph_mount_info *cmount, const char *path, const char *name,
>> +       void *value, size_t size);
>> +int ceph_lgetxattr(struct ceph_mount_info *cmount, const char *path, const char *name,
>> +       void *value, size_t size);
>> +int ceph_listxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size);
>> +int ceph_llistxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size);
>> +int ceph_removexattr(struct ceph_mount_info *cmount, const char *path, const char *name);
>> +int ceph_lremovexattr(struct ceph_mount_info *cmount, const char *path, const char *name);
>> +int ceph_setxattr(struct ceph_mount_info *cmount, const char *path, const char *name,
>> +       const void *value, size_t size, int flags);
>> +int ceph_lsetxattr(struct ceph_mount_info *cmount, const char *path, const char *name,
>> +       const void *value, size_t size, int flags);
>> +
>> +
>>
>>  /* expose file layout */
>>  int ceph_get_file_stripe_unit(struct ceph_mount_info *cmount, int fh);
>> diff --git a/src/libceph.cc b/src/libceph.cc
>> index d1143d6..6388bde 100644
>> --- a/src/libceph.cc
>> +++ b/src/libceph.cc
>> @@ -416,6 +416,48 @@ extern "C" int ceph_setattr(struct ceph_mount_info *cmount, const char *relpath,
>>   return cmount->get_client()->setattr(relpath, attr, mask);
>>  }
>>
>> +// *xattr() calls supporting samba/vfs
>> +extern "C" int ceph_getxattr(struct ceph_mount_info *cmount, const char *path, const char *name, void *value, size_t size)
>> +{
>> +  return cmount->get_client()->getxattr(path, name, value, size);
>> +}
>> +
>> +extern "C" int ceph_lgetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, void *value, size_t size)
>> +{
>> +  return cmount->get_client()->lgetxattr(path, name, value, size);
>> +}
>> +
>> +extern "C" int ceph_listxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size)
>> +{
>> +  return cmount->get_client()->listxattr(path, list, size);
>> +}
>> +
>> +extern "C" int ceph_llistxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size)
>> +{
>> +  return cmount->get_client()->llistxattr(path, list, size);
>> +}
>> +
>> +extern "C" int ceph_removexattr(struct ceph_mount_info *cmount, const char *path, const char *name)
>> +{
>> +  return cmount->get_client()->removexattr(path, name);
>> +}
>> +
>> +extern "C" int ceph_lremovexattr(struct ceph_mount_info *cmount, const char *path, const char *name)
>> +{
>> +  return cmount->get_client()->lremovexattr(path, name);
>> +}
>> +
>> +extern "C" int ceph_setxattr(struct ceph_mount_info *cmount, const char *path, const char *name, const void *value, size_t size, int flags)
>> +{
>> +  return cmount->get_client()->setxattr(path, name, value, size, flags);
>> +}
>> +
>> +extern "C" int ceph_lsetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, const void *value, size_t size, int flags)
>> +{
>> +  return cmount->get_client()->lsetxattr(path, name, value, size, flags);
>> +}
>> +/* end xattr support */
>> +
>>  extern "C" int ceph_chmod(struct ceph_mount_info *cmount, const char *path, mode_t mode)
>>  {
>>   return cmount->get_client()->chmod(path, mode);
>> --
>> 1.7.1
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Gregory Farnum May 10, 2011, 8:28 p.m. UTC | #3
On Tue, May 10, 2011 at 1:22 PM, Brian Chrisman <brchrisman@gmail.com> wrote:
> They differentiate between xattrs on symlinks or on the files at which
> they point.
> If I recall, it's a slight difference internally to the Client class
> whether a value is passed to path_walk as true/false, though I may be
> misinterpreting that.  I can look at that again.
>
> On Tue, May 10, 2011 at 12:44 PM, Gregory Farnum <gregf@hq.newdream.net> wrote:
>> What are the 'l'-prefixed functions for? They look like they're just
>> duplicates except for the prefix.
>> -Greg

Ah, right. I didn't notice the different flag values in the call to
path_walk. :) I think you're right about what it means, though!
Maybe we could give them more descriptive names or something?
-Greg
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Yehuda Sadeh Weinraub May 10, 2011, 8:30 p.m. UTC | #4
On Tue, May 10, 2011 at 12:38 PM, Brian Chrisman <brchrisman@gmail.com> wrote:
> @@ -5708,7 +5773,7 @@ int Client::ll_removexattr(vinodeno_t vino, const char *name, int uid, int gid)
>   tout << name << std::endl;
>
>   // only user xattrs, for now
> -  if (strncmp(name, "user.", 5))
> +  if (strncmp(name, "user.", 5) && strncmp(name, "security.", 9) && strncmp(name, "trusted.", 8))
>     return -EOPNOTSUPP;
>
>   Inode *in = _ll_get_inode(vino);

Good catch. That should be applied separately, and maybe go to the
stable branch too.

Thanks,
Yehuda
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Yehuda Sadeh Weinraub May 10, 2011, 8:34 p.m. UTC | #5
On Tue, May 10, 2011 at 1:28 PM, Gregory Farnum <gregf@hq.newdream.net> wrote:
> On Tue, May 10, 2011 at 1:22 PM, Brian Chrisman <brchrisman@gmail.com> wrote:
>> They differentiate between xattrs on symlinks or on the files at which
>> they point.
>> If I recall, it's a slight difference internally to the Client class
>> whether a value is passed to path_walk as true/false, though I may be
>> misinterpreting that.  I can look at that again.
>>
>> On Tue, May 10, 2011 at 12:44 PM, Gregory Farnum <gregf@hq.newdream.net> wrote:
>>> What are the 'l'-prefixed functions for? They look like they're just
>>> duplicates except for the prefix.
>>> -Greg
>
> Ah, right. I didn't notice the different flag values in the call to
> path_walk. :) I think you're right about what it means, though!
> Maybe we could give them more descriptive names or something?


lsetxattr and friends are known linux API functions, and have
corresponding system calls with the same name. I say let's keep them
as is.

Yehuda
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Gregory Farnum May 10, 2011, 8:35 p.m. UTC | #6
On Tue, May 10, 2011 at 1:34 PM, Yehuda Sadeh Weinraub
<yehudasa@gmail.com> wrote:
> lsetxattr and friends are known linux API functions, and have
> corresponding system calls with the same name. I say let's keep them
> as is.

Heh. Should probably just ignore clueless me in that case. :)
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/src/client/Client.cc b/src/client/Client.cc
index 6a27273..5083e99 100644
--- a/src/client/Client.cc
+++ b/src/client/Client.cc
@@ -5563,6 +5563,71 @@  int Client::ll_setattr(vinodeno_t vino, struct stat *attr, int mask, int uid, in
 // ----------
 // xattrs
 
+int Client::getxattr(const char *path, const char *name, void *value, size_t size)
+{
+  Mutex::Locker lock(client_lock);
+  Inode *ceph_inode;
+  Client::path_walk(path, &ceph_inode, true);
+  return Client::_getxattr(ceph_inode, name, value, size, getuid(), getgid());
+}
+
+int Client::lgetxattr(const char *path, const char *name, void *value, size_t size)
+{
+  Mutex::Locker lock(client_lock);
+  Inode *ceph_inode;
+  Client::path_walk(path, &ceph_inode, false);
+  return Client::_getxattr(ceph_inode, name, value, size, getuid(), getgid());
+}
+
+int Client::listxattr(const char *path, char *list, size_t size)
+{
+  Mutex::Locker lock(client_lock);
+  Inode *ceph_inode;
+  Client::path_walk(path, &ceph_inode, true);
+  return Client::_listxattr(ceph_inode, list, size, getuid(), getgid());
+}
+
+int Client::llistxattr(const char *path, char *list, size_t size)
+{
+  Mutex::Locker lock(client_lock);
+  Inode *ceph_inode;
+  Client::path_walk(path, &ceph_inode, false);
+  return Client::_listxattr(ceph_inode, list, size, getuid(), getgid());
+}
+
+int Client::removexattr(const char *path, const char *name)
+{
+  Mutex::Locker lock(client_lock);
+  Inode *ceph_inode;
+  Client::path_walk(path, &ceph_inode, true);
+  return Client::_removexattr(ceph_inode, name, getuid(), getgid());
+}
+
+int Client::lremovexattr(const char *path, const char *name)
+{
+  Mutex::Locker lock(client_lock);
+  Inode *ceph_inode;
+  Client::path_walk(path, &ceph_inode, false);
+  return Client::_removexattr(ceph_inode, name, getuid(), getgid());
+}
+
+int Client::setxattr(const char *path, const char *name, const void *value, size_t size, int flags)
+{
+  Mutex::Locker lock(client_lock);
+  Inode *ceph_inode;
+  Client::path_walk(path, &ceph_inode, true);
+  return Client::_setxattr(ceph_inode, name, value, size, flags, getuid(), getgid());
+}
+
+int Client::lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags)
+{
+  Mutex::Locker lock(client_lock);
+  Inode *ceph_inode;
+  Client::path_walk(path, &ceph_inode, false);
+  return Client::_setxattr(ceph_inode, name, value, size, flags, getuid(), getgid());
+}
+
+
 int Client::_getxattr(Inode *in, const char *name, void *value, size_t size,
 		      int uid, int gid)
 {
@@ -5708,7 +5773,7 @@  int Client::ll_removexattr(vinodeno_t vino, const char *name, int uid, int gid)
   tout << name << std::endl;
 
   // only user xattrs, for now
-  if (strncmp(name, "user.", 5))
+  if (strncmp(name, "user.", 5) && strncmp(name, "security.", 9) && strncmp(name, "trusted.", 8))
     return -EOPNOTSUPP;
 
   Inode *in = _ll_get_inode(vino);
diff --git a/src/client/Client.h b/src/client/Client.h
index ab21dc8..b36621d 100644
--- a/src/client/Client.h
+++ b/src/client/Client.h
@@ -1258,6 +1258,16 @@  public:
   int fsync(int fd, bool syncdataonly);
   int fstat(int fd, struct stat *stbuf);
 
+  // full path xattr ops
+  int getxattr(const char *path, const char *name, void *value, size_t size);
+  int lgetxattr(const char *path, const char *name, void *value, size_t size);
+  int listxattr(const char *path, char *list, size_t size);
+  int llistxattr(const char *path, char *list, size_t size);
+  int removexattr(const char *path, const char *name);
+  int lremovexattr(const char *path, const char *name);
+  int setxattr(const char *path, const char *name, const void *value, size_t size, int flags);
+  int lsetxattr(const char *path, const char *name, const void *value, size_t size, int flags);
+
   int sync_fs();
   int64_t drop_caches();
 
diff --git a/src/include/ceph/libceph.h b/src/include/ceph/libceph.h
index 3ed3369..f9fc29e 100644
--- a/src/include/ceph/libceph.h
+++ b/src/include/ceph/libceph.h
@@ -121,6 +121,21 @@  int ceph_fstat(struct ceph_mount_info *cmount, int fd, struct stat *stbuf);
 
 int ceph_sync_fs(struct ceph_mount_info *cmount);
 
+/* xattr support */
+int ceph_getxattr(struct ceph_mount_info *cmount, const char *path, const char *name, 
+	void *value, size_t size);
+int ceph_lgetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, 
+	void *value, size_t size);
+int ceph_listxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size);
+int ceph_llistxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size);
+int ceph_removexattr(struct ceph_mount_info *cmount, const char *path, const char *name);
+int ceph_lremovexattr(struct ceph_mount_info *cmount, const char *path, const char *name);
+int ceph_setxattr(struct ceph_mount_info *cmount, const char *path, const char *name, 
+	const void *value, size_t size, int flags);
+int ceph_lsetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, 
+	const void *value, size_t size, int flags);
+
+
 
 /* expose file layout */
 int ceph_get_file_stripe_unit(struct ceph_mount_info *cmount, int fh);
diff --git a/src/libceph.cc b/src/libceph.cc
index d1143d6..6388bde 100644
--- a/src/libceph.cc
+++ b/src/libceph.cc
@@ -416,6 +416,48 @@  extern "C" int ceph_setattr(struct ceph_mount_info *cmount, const char *relpath,
   return cmount->get_client()->setattr(relpath, attr, mask);
 }
 
+// *xattr() calls supporting samba/vfs
+extern "C" int ceph_getxattr(struct ceph_mount_info *cmount, const char *path, const char *name, void *value, size_t size)
+{
+  return cmount->get_client()->getxattr(path, name, value, size);
+}
+
+extern "C" int ceph_lgetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, void *value, size_t size)
+{
+  return cmount->get_client()->lgetxattr(path, name, value, size);
+}
+
+extern "C" int ceph_listxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size)
+{
+  return cmount->get_client()->listxattr(path, list, size);
+}
+
+extern "C" int ceph_llistxattr(struct ceph_mount_info *cmount, const char *path, char *list, size_t size)
+{
+  return cmount->get_client()->llistxattr(path, list, size);
+}
+
+extern "C" int ceph_removexattr(struct ceph_mount_info *cmount, const char *path, const char *name)
+{
+  return cmount->get_client()->removexattr(path, name);
+}
+
+extern "C" int ceph_lremovexattr(struct ceph_mount_info *cmount, const char *path, const char *name)
+{
+  return cmount->get_client()->lremovexattr(path, name);
+}
+
+extern "C" int ceph_setxattr(struct ceph_mount_info *cmount, const char *path, const char *name, const void *value, size_t size, int flags)
+{
+  return cmount->get_client()->setxattr(path, name, value, size, flags);
+}
+
+extern "C" int ceph_lsetxattr(struct ceph_mount_info *cmount, const char *path, const char *name, const void *value, size_t size, int flags)
+{
+  return cmount->get_client()->lsetxattr(path, name, value, size, flags);
+}
+/* end xattr support */
+
 extern "C" int ceph_chmod(struct ceph_mount_info *cmount, const char *path, mode_t mode)
 {
   return cmount->get_client()->chmod(path, mode);