[PATCH v3 5/7] Introduce getfdnlproto to obtain netlink protocol from fd

Dmitry V. Levin ldv at altlinux.org
Fri Jun 17 12:12:28 UTC 2016


On Wed, Jun 15, 2016 at 12:43:03PM +0000, Fabien Siron wrote:
> * defs.h (getfdnlproto): Add.

getfdnlproto?  getfdpath is already quite hard to read, but getfdnlproto?

> * utils.c (getfdinode): New function.
> (getfdnlproto): Likewise.
> ---
>  defs.h |  1 +
>  util.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
>  2 files changed, 63 insertions(+), 6 deletions(-)
> 
> diff --git a/defs.h b/defs.h
> index e9a9392..95bfc5a 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -556,6 +556,7 @@ extern void pathtrace_select(const char *);
>  extern int pathtrace_match(struct tcb *);
>  extern int getfdpath(struct tcb *, int, char *, unsigned);
>  extern enum sock_proto getfdproto(struct tcb *, int);
> +extern int getfdnlproto(struct tcb *, int, const struct xlat *);
>  
>  extern const char *xlookup(const struct xlat *, const uint64_t);
>  extern const char *xlat_search(const struct xlat *, const size_t, const uint64_t);
> diff --git a/util.c b/util.c
> index c3bcaba..c1ce8c4 100644
> --- a/util.c
> +++ b/util.c
> @@ -502,21 +502,77 @@ getfdproto(struct tcb *tcp, int fd)
>  #endif
>  }
>  
> -void
> -printfd(struct tcb *tcp, int fd)
> +static unsigned long
> +getfdinode(struct tcb *tcp, int fd)
>  {
>  	char path[PATH_MAX + 1];
> -	if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
> +	if (getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
>  		static const char socket_prefix[] = "socket:[";
>  		const size_t socket_prefix_len = sizeof(socket_prefix) - 1;
>  		const size_t path_len = strlen(path);
>  
> -		tprintf("%d<", fd);
> -		if (show_fd_path > 1 &&
> -		    strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
> +		if (strncmp(path, socket_prefix, socket_prefix_len) == 0 &&
>  		    path[path_len - 1] == ']') {
>  			unsigned long inode =
>  				strtoul(path + socket_prefix_len, NULL, 10);
> +			return inode;
> +		}
> +	}
> +	return -1;
> +}
> +
> +int
> +getfdnlproto(struct tcb *tcp, int fd, const struct xlat *xprotocols)
> +{
> +	unsigned long inode = getfdinode(tcp, fd);
> +
> +	if (inode != 0) {
> +		char *nl_proto = NULL;
> +		static const char socket_prefix[] = "NETLINK:[";
> +		const size_t socket_prefix_len =
> +				sizeof(socket_prefix) -1;
> +		nl_proto = get_sockaddr_by_inode_cached(inode);
> +		if (nl_proto == NULL) {
> +			enum sock_proto proto = getfdproto(tcp, fd);
> +			nl_proto = get_sockaddr_by_inode(inode, proto);
> +		}
> +		if (nl_proto == NULL)
> +			return -1;
> +
> +		if (strncmp(nl_proto, socket_prefix,
> +			    socket_prefix_len) == 0) {
> +			static const char define_prefix[] = "NETLINK_";
> +			const size_t define_prefix_len =
> +				sizeof(define_prefix) -1;
> +			nl_proto += socket_prefix_len;
> +
> +			for (;xprotocols->str != NULL; xprotocols++) {
> +				if (strncmp(xprotocols->str,
> +					       define_prefix,
> +					    define_prefix_len) != 0)
> +					return -1;
> +				if (strncmp(nl_proto,
> +					    xprotocols->str + define_prefix_len,
> +					    strlen(xprotocols->str +
> +						   define_prefix_len)) == 0)
> +					return xprotocols->val;
> +			}

Something odd has happened with indentation, cannot review.

> +		}
> +	}
> +
> +	return -1;
> +}
> +
> +void
> +printfd(struct tcb *tcp, int fd)
> +{
> +	char path[PATH_MAX + 1];
> +	if (show_fd_path && getfdpath(tcp, fd, path, sizeof(path)) >= 0) {
> +		const size_t path_len = strlen(path);
> +
> +		tprintf("%d<", fd);
> +		if (show_fd_path > 1) {
> +				unsigned long inode = getfdinode(tcp, fd);

getfdpath is invoked right before getfdinode which in turn invokes
getfdpath, and each getfdpath invocation costs one getxattr syscall...


-- 
ldv
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20160617/e60d249f/attachment.bin>


More information about the Strace-devel mailing list