From b3229d20f64aa401837c779122c5d6c5bf10e03d Mon Sep 17 00:00:00 2001 From: Casey Bodley Date: Thu, 5 Apr 2012 12:02:07 -0400 Subject: [PATCH] ea: query each superblock for named attr support adds a new function nfs41_superblock_getattr(), which adds an OPENATTR call with createdir=0 after the GETATTR to check for named attribute support. OPENATTR will either return ERR_NOTSUPP if not supported, or OK/ERR_NOENT depending on whether named attributes are present on the given file. we can't query for the 'named_attr' attribute, because it only tells us whether the given file contains named attributes if named attributes are supported on a superblock, it will return FILE_SUPPORTS_EXTENDED_ATTRIBUTES for associated volume queries Signed-off-by: Casey Bodley --- daemon/nfs41.h | 1 + daemon/nfs41_ops.c | 66 +++++++++++++++++++++++++++++++++++++++ daemon/nfs41_ops.h | 7 +++++ daemon/nfs41_superblock.c | 9 ++++-- daemon/volume.c | 2 ++ 5 files changed, 82 insertions(+), 3 deletions(-) diff --git a/daemon/nfs41.h b/daemon/nfs41.h index ee003cf..8dc6c06 100644 --- a/daemon/nfs41.h +++ b/daemon/nfs41.h @@ -49,6 +49,7 @@ typedef struct __nfs41_superblock { unsigned int cansettime : 1; unsigned int link_support : 1; unsigned int symlink_support : 1; + unsigned int ea_support : 1; unsigned int case_preserving : 1; unsigned int case_insensitive : 1; diff --git a/daemon/nfs41_ops.c b/daemon/nfs41_ops.c index 79689a1..30fdd94 100644 --- a/daemon/nfs41_ops.c +++ b/daemon/nfs41_ops.c @@ -1135,6 +1135,72 @@ out: return status; } +int nfs41_superblock_getattr( + IN nfs41_session *session, + IN nfs41_path_fh *file, + IN bitmap4 *attr_request, + OUT nfs41_file_info *info, + OUT bool_t *supports_named_attrs) +{ + int status; + nfs41_compound compound; + nfs_argop4 argops[4]; + nfs_resop4 resops[4]; + nfs41_sequence_args sequence_args; + nfs41_sequence_res sequence_res; + nfs41_putfh_args putfh_args; + nfs41_putfh_res putfh_res; + nfs41_getattr_args getattr_args; + nfs41_getattr_res getattr_res; + nfs41_openattr_args openattr_args; + nfs41_openattr_res openattr_res; + + compound_init(&compound, argops, resops, "getfsattr"); + + compound_add_op(&compound, OP_SEQUENCE, &sequence_args, &sequence_res); + status = nfs41_session_sequence(&sequence_args, session, 0); + if (status) + goto out; + + compound_add_op(&compound, OP_PUTFH, &putfh_args, &putfh_res); + putfh_args.file = file; + putfh_args.in_recovery = 0; + + compound_add_op(&compound, OP_GETATTR, &getattr_args, &getattr_res); + getattr_args.attr_request = attr_request; + getattr_res.obj_attributes.attr_vals_len = NFS4_OPAQUE_LIMIT; + getattr_res.info = info; + + compound_add_op(&compound, OP_OPENATTR, &openattr_args, &openattr_res); + openattr_args.createdir = 0; + + status = compound_encode_send_decode(session, &compound, TRUE); + if (status) + goto out; + + status = sequence_res.sr_status; + if (status) goto out; + status = putfh_res.status; + if (status) goto out; + status = getattr_res.status; + if (status) goto out; + + switch (status = openattr_res.status) { + case NFS4ERR_NOTSUPP: + *supports_named_attrs = 0; + status = NFS4_OK; + break; + + case NFS4ERR_NOENT: + case NFS4_OK: + *supports_named_attrs = 1; + status = NFS4_OK; + break; + } +out: + return status; +} + int nfs41_remove( IN nfs41_session *session, IN nfs41_path_fh *parent, diff --git a/daemon/nfs41_ops.h b/daemon/nfs41_ops.h index f51d6ad..4c8f7d0 100644 --- a/daemon/nfs41_ops.h +++ b/daemon/nfs41_ops.h @@ -1129,6 +1129,13 @@ int nfs41_getattr( IN bitmap4 *attr_request, OUT nfs41_file_info *info); +int nfs41_superblock_getattr( + IN nfs41_session *session, + IN nfs41_path_fh *file, + IN bitmap4 *attr_request, + OUT nfs41_file_info *info, + OUT bool_t *supports_named_attrs); + /* getattr.c */ int nfs41_cached_getattr( IN nfs41_session *session, diff --git a/daemon/nfs41_superblock.c b/daemon/nfs41_superblock.c index eebfe96..6df0237 100644 --- a/daemon/nfs41_superblock.c +++ b/daemon/nfs41_superblock.c @@ -75,6 +75,7 @@ static int get_superblock_attrs( IN nfs41_superblock *superblock, IN nfs41_path_fh *file) { + bool_t supports_named_attrs; int status; bitmap4 attr_request; nfs41_file_info info = { 0 }; @@ -93,10 +94,11 @@ static int get_superblock_attrs( info.suppattr_exclcreat = &superblock->suppattr_exclcreat; info.time_delta = &superblock->time_delta; - status = nfs41_getattr(session, file, &attr_request, &info); + status = nfs41_superblock_getattr(session, file, + &attr_request, &info, &supports_named_attrs); if (status) { - eprintf("nfs41_getattr() failed with %s when fetching attributes for " - "fsid(%llu,%llu)\n", nfs_error_string(status), + eprintf("nfs41_superblock_getattr() failed with %s when fetching " + "attributes for fsid(%llu,%llu)\n", nfs_error_string(status), superblock->fsid.major, superblock->fsid.minor); goto out; } @@ -115,6 +117,7 @@ static int get_superblock_attrs( superblock->aclsupport = info.aclsupport; superblock->link_support = info.link_support; superblock->symlink_support = info.symlink_support; + superblock->ea_support = supports_named_attrs; superblock->case_preserving = info.case_preserving; superblock->case_insensitive = info.case_insensitive; diff --git a/daemon/volume.c b/daemon/volume.c index fe662ba..9b05e99 100644 --- a/daemon/volume.c +++ b/daemon/volume.c @@ -124,6 +124,8 @@ static void handle_volume_attributes( attr->FileSystemAttributes |= FILE_SUPPORTS_HARD_LINKS; if (superblock->symlink_support) attr->FileSystemAttributes |= FILE_SUPPORTS_REPARSE_POINTS; + if (superblock->ea_support) + attr->FileSystemAttributes |= FILE_SUPPORTS_EXTENDED_ATTRIBUTES; if (superblock->case_preserving) attr->FileSystemAttributes |= FILE_CASE_PRESERVED_NAMES; if (!superblock->case_insensitive)