diff options
| author | Vikas Gorur <vikas@zresearch.com> | 2009-03-03 16:00:58 +0530 | 
|---|---|---|
| committer | Anand V. Avati <avati@amp.gluster.com> | 2009-03-07 02:08:41 +0530 | 
| commit | 0991858fca6dc93de685e9527fb9ff47d77f616f (patch) | |
| tree | adcdf627d40c1fe90a8535c7b0bc27d057901788 /xlators | |
| parent | d092dff9a6e23d5fdef64154b6f3d6211f7482a6 (diff) | |
added fgetxattr and fsetxattr FOPs
Signed-off-by: Anand V. Avati <avati@amp.gluster.com>
Diffstat (limited to 'xlators')
| -rw-r--r-- | xlators/protocol/client/src/client-protocol.c | 170 | ||||
| -rw-r--r-- | xlators/protocol/server/src/server-protocol.c | 204 | ||||
| -rw-r--r-- | xlators/storage/posix/src/posix.c | 223 | 
3 files changed, 596 insertions, 1 deletions
diff --git a/xlators/protocol/client/src/client-protocol.c b/xlators/protocol/client/src/client-protocol.c index bcc98d0f15a..2a636a18fef 100644 --- a/xlators/protocol/client/src/client-protocol.c +++ b/xlators/protocol/client/src/client-protocol.c @@ -2350,6 +2350,97 @@ unwind:  	return 0;  } + +/** + * client_fsetxattr - fsetxattr function for client protocol + * @frame: call frame + * @this: this translator structure + * @fd: fd + * @dict: dictionary which contains key:value to be set. + * @flags: + * + * external reference through client_protocol_xlator->fops->fsetxattr + */ +int32_t +client_fsetxattr (call_frame_t *frame, +                  xlator_t *this, +                  fd_t *fd, +                  dict_t *dict, +                  int32_t flags) +{ +	gf_hdr_common_t       *hdr = NULL; +	gf_fop_fsetxattr_req_t *req = NULL; +	size_t hdrlen = 0; +	size_t dict_len = 0; +        ino_t  ino; +	int    ret = -1; +	int64_t remote_fd = -1; +	client_conf_t *conf = this->private; + +	if (conf->child) { +		/* */ +		STACK_WIND (frame, +			    default_fsetxattr_cbk, +			    conf->child, +			    conf->child->fops->fsetxattr, +			    fd, +			    dict, +			    flags); + +		return 0; +	} + +	dict_len = dict_serialized_length (dict); +	if (dict_len < 0) { +		gf_log (this->name, GF_LOG_ERROR, +			"failed to get serialized length of dict(%p)", +			dict); +		goto unwind; +	} + +        ret = this_fd_get (fd, this, &remote_fd); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get remote fd. returning EBADFD", +                        fd->inode->ino); +                goto unwind; +        } +        ino = fd->inode->ino; + +	hdrlen = gf_hdr_len (req, dict_len); +	hdr    = gf_hdr_new (req, dict_len); + +	GF_VALIDATE_OR_GOTO(this->name, hdr, unwind); + +	req    = gf_param (hdr); + +	req->ino   = hton64 (ino); +        req->fd    = hton64 (remote_fd); +	req->flags = hton32 (flags); +	req->dict_len = hton32 (dict_len); + +	ret = dict_serialize (dict, req->dict); +	if (ret < 0) { +		gf_log (this->name, GF_LOG_ERROR, +			"failed to serialize dictionary(%p)", +			dict); +		goto unwind; +	} + +	ret = protocol_client_xfer (frame, this, +				    CLIENT_CHANNEL (this, CHANNEL_BULK), +				    GF_OP_TYPE_FOP_REQUEST, GF_FOP_FSETXATTR, +				    hdr, hdrlen, NULL, 0, NULL); +	return ret; +unwind: +	if (hdr) +		free (hdr); + +	STACK_UNWIND(frame, -1, EINVAL); +	return 0; +} + +  /**   * client_getxattr - getxattr function for client protocol   * @frame: call frame @@ -2416,6 +2507,83 @@ unwind:  	return 0;  } + +/** + * client_fgetxattr - fgetxattr function for client protocol + * @frame: call frame + * @this: this translator structure + * @fd: fd + * + * external reference through client_protocol_xlator->fops->fgetxattr + */ + +int32_t +client_fgetxattr (call_frame_t *frame, +                  xlator_t *this, +                  fd_t *fd, +                  const char *name) +{ +	int ret = -1; +	gf_hdr_common_t *hdr = NULL; +	gf_fop_fgetxattr_req_t *req = NULL; +	size_t hdrlen = 0; +        int64_t remote_fd = -1; +	size_t namelen = 0; +	ino_t  ino = 0; +	client_conf_t *conf = this->private; + +	if (conf->child) { +		/* */ +		STACK_WIND (frame, +			    default_fgetxattr_cbk, +			    conf->child, +			    conf->child->fops->fgetxattr, +			    fd, +			    name); + +		return 0; +	} + +	if (name) +		namelen = STRLEN_0(name); + +        ret = this_fd_get (fd, this, &remote_fd); +        if (ret == -1) { +                gf_log (this->name, GF_LOG_DEBUG, +                        "(%"PRId64"): failed to get remote fd. returning EBADFD", +                        fd->inode->ino); +                goto unwind; +        } +        ino = fd->inode->ino; + +	hdrlen = gf_hdr_len (req, namelen); +	hdr    = gf_hdr_new (req, namelen); + +	GF_VALIDATE_OR_GOTO(frame->this->name, hdr, unwind); + +	req    = gf_param (hdr); + +	req->ino   = hton64 (ino); +        req->fd    = hton64 (remote_fd); +	req->namelen = hton32 (namelen); + +	if (name) +		strcpy (req->name, name); + +	ret = protocol_client_xfer (frame, this, +				    CLIENT_CHANNEL (this, CHANNEL_LOWLAT), +				    GF_OP_TYPE_FOP_REQUEST, GF_FOP_FGETXATTR, +				    hdr, hdrlen, NULL, 0, NULL); +	return ret; +unwind: +	if (hdr) +		free (hdr); + +	STACK_UNWIND(frame, -1, EINVAL, NULL); +	return 0; +} + +  /**   * client_removexattr - removexattr function for client protocol   * @frame: call frame @@ -6703,6 +6871,8 @@ struct xlator_fops fops = {  	.fsync       = client_fsync,  	.setxattr    = client_setxattr,  	.getxattr    = client_getxattr, +        .fsetxattr   = client_fsetxattr, +        .fgetxattr   = client_fgetxattr,  	.removexattr = client_removexattr,  	.opendir     = client_opendir,  	.readdir     = client_readdir, diff --git a/xlators/protocol/server/src/server-protocol.c b/xlators/protocol/server/src/server-protocol.c index 4e06aaa5e99..0a3e3e0110b 100644 --- a/xlators/protocol/server/src/server-protocol.c +++ b/xlators/protocol/server/src/server-protocol.c @@ -1339,6 +1339,67 @@ server_getxattr_cbk (call_frame_t *frame,  	return 0;  } + +int32_t +server_fgetxattr_cbk (call_frame_t *frame, +                      void *cookie, +                      xlator_t *this, +                      int32_t op_ret, +                      int32_t op_errno, +                      dict_t *dict) +{ +	gf_hdr_common_t       *hdr  = NULL; +	gf_fop_fgetxattr_rsp_t *rsp = NULL; +	server_state_t *state = NULL; +	size_t  hdrlen = 0; +	int32_t len = 0; +	int32_t gf_errno = 0; +	int32_t ret = -1; + +	state = CALL_STATE(frame); + +	if (op_ret >= 0) { +		len = dict_serialized_length (dict); +		if (len < 0) { +			gf_log (this->name, GF_LOG_ERROR, +				"%s (%"PRId64"): failed to get serialized length of " +				"reply dict", +				state->loc.path, state->ino); +			op_ret   = -1; +			op_errno = EINVAL; +			len = 0; +		} +	} + +	hdrlen = gf_hdr_len (rsp, len + 1); +	hdr    = gf_hdr_new (rsp, len + 1); +	rsp    = gf_param (hdr); + +	if (op_ret >= 0) { +		ret = dict_serialize (dict, rsp->dict); +		if (len < 0) { +			gf_log (this->name, GF_LOG_ERROR, +				"%s (%"PRId64"): failed to serialize reply dict", +				state->loc.path, state->ino); +			op_ret = -1; +			op_errno = -ret; +		} +	} +	rsp->dict_len = hton32 (len); + +	hdr->rsp.op_ret = hton32 (op_ret); +	gf_errno        = gf_errno_to_error (op_errno); +	hdr->rsp.op_errno = hton32 (gf_errno); + +	fd_unref (state->fd); + +	protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FGETXATTR, +			       hdr, hdrlen, NULL, 0, NULL); + +	return 0; +} + +  /*   * server_setxattr_cbk - setxattr callback for server protocol   * @frame: call frame @@ -1380,6 +1441,35 @@ server_setxattr_cbk (call_frame_t *frame,  } +int32_t +server_fsetxattr_cbk (call_frame_t *frame, +                      void *cookie, +                      xlator_t *this, +                      int32_t op_ret, +                      int32_t op_errno) +{ +	gf_hdr_common_t        *hdr = NULL; +	gf_fop_fsetxattr_rsp_t *rsp = NULL; +	server_state_t *state = NULL; +	size_t  hdrlen = 0; +	int32_t gf_errno = 0; +	state = CALL_STATE(frame); + +	hdrlen = gf_hdr_len (rsp, 0); +	hdr    = gf_hdr_new (rsp, 0); +	rsp    = gf_param (hdr); + +	hdr->rsp.op_ret = hton32 (op_ret); +	gf_errno        = gf_errno_to_error (op_errno); +	hdr->rsp.op_errno = hton32 (gf_errno); + +	protocol_server_reply (frame, GF_OP_TYPE_FOP_REPLY, GF_FOP_FSETXATTR, +			       hdr, hdrlen, NULL, 0, NULL); + +	return 0; +} + +  /*   * server_rename_cbk - rename callback for server protocol   * @frame: call frame @@ -4696,10 +4786,82 @@ fail:  	server_setxattr_cbk (frame, NULL, frame->this,  			     -1, ENOENT);  	return 0; -	 +  } +int32_t +server_fsetxattr (call_frame_t *frame, +                  xlator_t *bound_xl, +                  gf_hdr_common_t *hdr, size_t hdrlen, +                  char *buf, size_t buflen) +{ +        server_connection_t *conn   = NULL; +	gf_fop_fsetxattr_req_t *req = NULL; + +	dict_t *dict = NULL; +	server_state_t *state = NULL; +	int32_t ret = -1; +	size_t pathlen = 0; +	size_t dict_len = 0; +	char *req_dictbuf = NULL; + +        conn = SERVER_CONNECTION (frame); + +	req = gf_param (hdr); +	state = CALL_STATE(frame); +	{ +                state->fd_no = ntoh64 (req->fd); +                if (state->fd_no >= 0) +                        state->fd = gf_fd_fdptr_get (conn->fdtable, +                                                     state->fd_no); +		dict_len = ntoh32 (req->dict_len); + +		pathlen = STRLEN_0(state->path); +		state->ino   = ntoh64 (req->ino); + +		state->flags = ntoh32 (req->flags); +	} + +        /* Unserialize the dictionary */ +        req_dictbuf = memdup (req->dict, dict_len); +        GF_VALIDATE_OR_GOTO(bound_xl->name, req_dictbuf, fail); + +        dict = dict_new (); +        GF_VALIDATE_OR_GOTO(bound_xl->name, dict, fail); +         +        ret = dict_unserialize (req_dictbuf, dict_len, &dict); +        if (ret < 0) { +                gf_log (bound_xl->name, GF_LOG_ERROR, +                        "%"PRId64": %s (%"PRId64"): failed to " +                        "unserialize request buffer to dictionary", +                        frame->root->unique, state->loc.path, +                        state->ino); +                free (req_dictbuf); +                goto fail; +        } else{ +                dict->extra_free = req_dictbuf; +        } + +        STACK_WIND (frame,  +                    server_setxattr_cbk, +                    BOUND_XL(frame), +                    BOUND_XL(frame)->fops->fsetxattr, +                    state->fd, dict, state->flags); + +	if (dict) +		dict_unref (dict); + +        return 0; +fail: +	if (dict) +		dict_unref (dict); + +	server_fsetxattr_cbk (frame, NULL, frame->this, +                              -1, ENOENT); +	return 0; +} +  int32_t  server_fxattrop (call_frame_t *frame, @@ -4950,6 +5112,44 @@ server_getxattr (call_frame_t *frame,  } +int32_t +server_fgetxattr (call_frame_t *frame, +                  xlator_t *bound_xl, +                  gf_hdr_common_t *hdr, size_t hdrlen, +                  char *buf, size_t buflen) +{ +        server_connection_t    *conn = NULL; +	gf_fop_fgetxattr_req_t *req  = NULL; +	server_state_t *state        = NULL; + +	size_t namelen = 0; + +        conn = SERVER_CONNECTION (frame); + +	req   = gf_param (hdr); +	state = CALL_STATE(frame); +	{ +                state->fd_no   = ntoh64 (req->fd); +                if (state->fd_no >= 0) +                        state->fd = gf_fd_fdptr_get (conn->fdtable, +                                                     state->fd_no); + +		state->ino     = ntoh64 (req->ino); + +		namelen = ntoh32 (req->namelen); +		if (namelen) +			state->name = (req->name); +	} + +	STACK_WIND (frame, +		    server_fgetxattr_cbk, +		    BOUND_XL(frame), +		    BOUND_XL(frame)->fops->fgetxattr, +		    state->fd, +		    state->name); +	return 0; +} +  int32_t  server_removexattr_resume (call_frame_t *frame, @@ -7640,6 +7840,8 @@ static gf_op_t gf_fops[] = {  	[GF_FOP_FSYNC]        =  server_fsync,  	[GF_FOP_SETXATTR]     =  server_setxattr,  	[GF_FOP_GETXATTR]     =  server_getxattr, +        [GF_FOP_FGETXATTR]    =  server_fgetxattr, +        [GF_FOP_FSETXATTR]    =  server_fsetxattr,  	[GF_FOP_REMOVEXATTR]  =  server_removexattr,  	[GF_FOP_OPENDIR]      =  server_opendir,  	[GF_FOP_GETDENTS]     =  server_getdents, diff --git a/xlators/storage/posix/src/posix.c b/xlators/storage/posix/src/posix.c index bbcdc93de5c..9ee6ed5105c 100644 --- a/xlators/storage/posix/src/posix.c +++ b/xlators/storage/posix/src/posix.c @@ -2279,6 +2279,227 @@ posix_getxattr (call_frame_t *frame, xlator_t *this,          return 0;  } + +int32_t +posix_fgetxattr (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, const char *name) +{ +        int32_t           op_ret         = -1; +        int32_t           op_errno       = ENOENT; +        uint64_t          tmp_pfd        = 0; +        struct posix_fd * pfd            = NULL; +        int               _fd            = -1; +        int32_t           list_offset    = 0; +        size_t            size           = 0; +        size_t            remaining_size = 0; +        char              key[1024]      = {0,}; +        char *            value          = NULL; +        char *            list           = NULL; +        dict_t *          dict           = NULL; +        int               ret            = -1; + +        DECLARE_OLD_FS_ID_VAR; + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); + +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        ret = fd_ctx_get (fd, this, &tmp_pfd); +        if (ret < 0) { +                op_errno = -ret; +                gf_log (this->name, GF_LOG_ERROR, +			"pfd is NULL from fd=%p", fd); +                goto out; +        } +	pfd = (struct posix_fd *)(long)tmp_pfd; + +        _fd = pfd->fd; + +        /* Get the total size */ +        dict = get_new_dict (); +        if (!dict) { +                gf_log (this->name, GF_LOG_ERROR, "out of memory :("); +                goto out; +        } + +        size = flistxattr (_fd, NULL, 0); +        if (size == -1) { +                op_errno = errno; +                if ((errno == ENOTSUP) || (errno == ENOSYS)) { +                        GF_LOG_OCCASIONALLY (gf_posix_xattr_enotsup_log, +                                             this->name, GF_LOG_WARNING, +                                             "Extended attributes not " +					     "supported."); +                } +                else { +                        gf_log (this->name, GF_LOG_ERROR, +				"listxattr failed on %p: %s", +                                fd, strerror (op_errno)); +                } +                goto out; +        } + +        if (size == 0) +                goto done; + +        list = alloca (size + 1); +        if (!list) { +                op_errno = errno; +                gf_log (this->name, GF_LOG_ERROR, "out of memory :("); +                goto out; +        } + +        size = flistxattr (_fd, list, size); + +        remaining_size = size; +        list_offset = 0; +        while (remaining_size > 0) { +                if(*(list + list_offset) == '\0') +                        break; + +                strcpy (key, list + list_offset); +                op_ret = fgetxattr (_fd, key, NULL, 0); +                if (op_ret == -1) +                        break; + +                value = CALLOC (op_ret + 1, sizeof(char)); +                if (!value) { +                        op_errno = errno; +                        gf_log (this->name, GF_LOG_ERROR, "out of memory :("); +                        goto out; +                } + +                op_ret = fgetxattr (_fd, key, value, op_ret); +                if (op_ret == -1) +                        break; + +                value [op_ret] = '\0'; +                dict_set (dict, key, data_from_dynptr (value, op_ret)); +                remaining_size -= strlen (key) + 1; +                list_offset += strlen (key) + 1; + +        } /* while (remaining_size > 0) */ + + done: +        op_ret = size; + +        if (dict) { +                dict_ref (dict); +        } + + out: +        SET_TO_OLD_FS_ID (); +        frame->root->rsp_refs = NULL; +        STACK_UNWIND (frame, op_ret, op_errno, dict); + +        if (dict) +                dict_unref (dict); + +        return 0; +} + + +int +fhandle_pair (xlator_t *this, int fd, +              data_pair_t *trav, int flags) +{ +        int sys_ret = -1; +        int ret     = 0; + +        sys_ret = fsetxattr (fd, trav->key, trav->value->data, +                             trav->value->len, flags); +         +        if (sys_ret < 0) { +                if (errno == ENOTSUP) { +                        GF_LOG_OCCASIONALLY(gf_posix_xattr_enotsup_log, +                                            this->name,GF_LOG_WARNING, +                                            "Extended attributes not " +                                            "supported"); +                } else if (errno == ENOENT) { +                        gf_log (this->name, GF_LOG_DEBUG, +                                "fsetxattr on fd=%d failed: %s", fd, +                                strerror (errno)); +                } else { +                         +#ifdef GF_DARWIN_HOST_OS +                        gf_log (this->name, +                                ((errno == EINVAL) ? +                                 GF_LOG_DEBUG : GF_LOG_WARNING), +                                "fd=%d: key:%s error:%s", +                                fd, trav->key, +                                strerror (errno)); +#else /* ! DARWIN */ +                        gf_log (this->name, GF_LOG_WARNING, +                                "fd=%d: key:%s error:%s", +                                fd, trav->key, +                                strerror (errno)); +#endif /* DARWIN */ +                } +                 +                ret = -errno; +                goto out; +        } + +out: +        return ret; +} + + +int32_t +posix_fsetxattr (call_frame_t *frame, xlator_t *this, +                 fd_t *fd, dict_t *dict, int flags) +{ +        int32_t            op_ret       = -1; +        int32_t            op_errno     = 0; +        struct posix_fd *  pfd          = NULL; +        uint64_t           tmp_pfd      = 0; +        int                _fd          = -1; +        data_pair_t * trav              = NULL; +        int           ret               = -1; + +        DECLARE_OLD_FS_ID_VAR; +        SET_FS_ID (frame->root->uid, frame->root->gid); + +        VALIDATE_OR_GOTO (frame, out); +        VALIDATE_OR_GOTO (this, out); +        VALIDATE_OR_GOTO (fd, out); +        VALIDATE_OR_GOTO (dict, out); + +        ret = fd_ctx_get (fd, this, &tmp_pfd); +        if (ret < 0) { +                op_errno = -ret; +                gf_log (this->name, GF_LOG_ERROR, +			"pfd is NULL from fd=%p", fd); +                goto out; +        } +	pfd = (struct posix_fd *)(long)tmp_pfd; +        _fd = pfd->fd; + +        trav = dict->members_list; + +        while (trav) { +                ret = fhandle_pair (this, _fd, trav, flags); +                if (ret < 0) { +                        op_errno = -ret; +                        goto out; +                } +                trav = trav->next; +        } + +        op_ret = 0; + + out: +        SET_TO_OLD_FS_ID (); +        frame->root->rsp_refs = NULL; + +        STACK_UNWIND (frame, op_ret, op_errno); + +        return 0; +} + +  int32_t  posix_removexattr (call_frame_t *frame, xlator_t *this,                     loc_t *loc, const char *name) @@ -3739,7 +3960,9 @@ struct xlator_fops fops = {          .flush       = posix_flush,          .fsync       = posix_fsync,          .setxattr    = posix_setxattr, +        .fsetxattr   = posix_fsetxattr,          .getxattr    = posix_getxattr, +        .fgetxattr   = posix_fgetxattr,          .removexattr = posix_removexattr,          .fsyncdir    = posix_fsyncdir,          .access      = posix_access,  | 
