Re: using connected UDP socket to contact to portmapper?
|[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]|
On 06.06.2012 08:12, Ian Kent wrote: > On Tue, 2012-06-05 at 10:26 +0400, Michael Tokarev wrote:  >> In order to eliminate this timeout, the socket used to contact >> the remote portmapper needs to be connected - this way, the >> OS will report ECONNREFUSED error instantly and the mount >> operation will proceed without delays even if the remote >> portmapper is not available. > > Right, but the recent changes have changed the order to TCP then UDP so > I'm not sure this is still accurate now, although I may not have changed > them all, I need to check that. > > But I thought ECONNREFUSED meant just that, in which case UDP should be > tried following that, in case only the TCP port is blocked. I tried exactly with the very recent changes. My test version is 09d4edb2469f9415f6ca33760d83b3c85b517de7, "autofs-5.0.6 - fix libtirpc name clash". Here's the debug output (with a few fprintf's I added): Starting automounter version 5.0.6, master map /etc/auto.master using kernel protocol version 5.02 lookup_nss_read_master: reading master file /etc/auto.master parse_init: parse(sun): init gathered global options: (null) spawn_mount: mtab link detected, passing -n to mount spawn_umount: mtab link detected, passing -n to mount lookup_read_master: lookup(file): read entry /misc lookup_read_master: lookup(file): read entry +dir:/etc/auto.master.d lookup_nss_read_master: reading master dir /etc/auto.master.d lookup(dir): dir map /etc/auto.master.d missing or not readable lookup(file): failed to read included master map dir:/etc/auto.master.d master_do_mount: mounting /misc automount_path_to_fifo: fifo name /run/autofs.fifo-misc lookup_nss_read_map: reading map file /etc/auto.misc parse_init: parse(sun): init gathered global options: (null) spawn_mount: mtab link detected, passing -n to mount spawn_umount: mtab link detected, passing -n to mount mounted indirect on /misc with timeout 300, freq 75 seconds st_ready: st_ready(): state = 0 path /misc handle_packet: type = 3 handle_packet_missing_indirect: token 101, name test, request pid 14024 attempting to mount entry /misc/test lookup_mount: lookup(file): looking up test lookup_mount: lookup(file): test -> -vers=4 gnome:/data parse_mount: parse(sun): expanded entry: -vers=4 gnome:/data parse_mount: parse(sun): gathered options: vers=4 parse_mount: parse(sun): dequote("gnome:/data") -> gnome:/data parse_mount: parse(sun): core of entry: options=vers=4, loc=gnome:/data sun_mount: parse(sun): mounting root /misc, mountpoint test, what gnome:/data, fstype nfs, options vers=4 mount_mount: mount(nfs): root=/misc name=test what=gnome:/data, fstype=nfs, options=vers=4 mount_mount: mount(nfs): nfs options="vers=4", nobind=0, nosymlink=0, ro=0 get_nfs_info: called with host gnome(192.168.88.4) proto tcp version 0x70 get_nfs_info: nfs v4 rpc ping time: 0.004577 get_nfs_info.portmap_getclient begin rpc_portmap_getclient.create_client begin rpc_portmap_getclient.create_client end get_nfs_info.portmap_getclient end get_nfs_info: host gnome cost 4576 weight 0 get_nfs_info: done get_nfs_info: called with host gnome(192.168.88.4) proto udp version 0x70 get_nfs_info: nfs v4 rpc ping time: 0.000387 get_nfs_info.portmap_getclient begin rpc_portmap_getclient.create_client begin rpc_portmap_getclient.create_client end get_nfs_info.portmap_getclient end get_nfs_info.portmap_getport begin rpc_portmap_getport.clnt_call begin [several seconds pause here] rpc_portmap_getport.clnt_call end get_nfs_info.portmap_getport end get_nfs_info: host gnome cost 386 weight 0 get_nfs_info: done prune_host_list: selected subset of hosts that support NFS4 over TCP mount_mount: mount(nfs): calling mkdir_path /misc/test mount_mount: mount(nfs): calling mount -t nfs -s -o vers=4 gnome:/data /misc/test spawn_mount: mtab link detected, passing -n to mount mount_mount: mount(nfs): mounted gnome:/data on /misc/test dev_ioctl_send_ready: token = 101 mounted /misc/test It is doing first clnt_call() in rpc_portmap_getport(), which is PMAPPROC_NULL, over UDP which times out. After that it just mounts things. >> This is rpc_portmap_getport() function. >> >> I tried to follow the code, but the logic there is so twisted >> I've lost track of things quite quickly. > > Yes, it is a bit convoluted. > > This code was originally written for two reasons. > First to take control over the timeouts to avoid lengthy waits and > second to reduce socket usage by allowing callers to reuse socket file > descriptors. Is that okay to made these sockets connected? I mean, is the same socket can be reused to connect to different destination (host or port)? >> The question is: is it possible to use connected UDP sockets >> there in all cases, or is conn_info->client reused for >> something else? If it is, I guess we may just get rid of >> cached (UDP) client and create new client for each call. > > Don't think so. >> Or is this completely backwards? I mean, UDP is really >> unreliable protocol, for it to actually work the app >> should retry sending packet in case of timeout, and the >> protocol is easy to spoof too... > > Backward in the sense that we probably should (and should already) be > using TCP first. If you mean TCP for the portmapper access, well, maybe it actually does, but obviously the portmapper does not respond there if it isn't even running on the remote host. Even with TCP, in case the portmapper port is firewalled, we may get timeout. But this should be easy to work around in the configuration -- when port is specified explicltly, portmapper isn't consulted at all. > Another thing is that, since the change to mount.nfs(8), we now also > need to change to probing on simple automounts (as well as multi-mounts) > in order to maintain a reasonable interactive response. I need to write another lengthly email about this. I think the whole approach to checking for /sbin/modprobe and /proc (neither of which is actually used in the code), /sbin/mount.nfs, fsck.ext* at configure time is wrong: instead, you should assume nothing at compile time and call these programs when needed at runtime using either fixed - standard paths or searching in $PATH, probing their existance if necessary. It turned out that Debian autofs package has never used the "new" nfs mount code at all, because during compile time mount.nfs has never been available (the compile is done in a chroot), so the code never checked the "symbolic" mount.nfs argument and always used the fallback. But that's for another email. For now I just want to understand what to do with this UDP portmap probing, the trivial fix for the problem at hand (assuming the portmap port isn't firewalled) is to make UDP socket connected, so ECONNREFUSED for UDP will be noticed immediately without resorting to timeout. This will keep the general potential problem of using UDP in the first place, and this might want a separate solution (maybe eliminating UDP altogether), but I'm not sure I want to change that much in one go :) >> Alternatively, we may try to contact 2049 port first, >> and if that one does not respond, try to contact the >> portmapper. But I'm not sure if this is right thing >> to do to start with. > > Don't know that yet either. Currently it doesn't work with at all /net map. I asked several times on IRC about this very case, -- whenever it is ever possible to enumerate (nfsv4) exports without portmapper, but no one replied :( Note: I know right to nothing about this RPC internals. Thanks, /mjt -- To unsubscribe from this list: send the line "unsubscribe autofs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html