Date: Wed, 25 Jan 2012 12:54:14 +1100 (EST) From: Bruce Evans <brde@optusnet.com.au> To: Rick Macklem <rmacklem@FreeBSD.org> Cc: svn-src-head@FreeBSD.org, svn-src-all@FreeBSD.org, src-committers@FreeBSD.org Subject: Re: svn commit: r230516 - in head/sys: fs/nfsclient nfsclient Message-ID: <20120125121210.A1045@besplex.bde.org> In-Reply-To: <201201250022.q0P0MsEY098760@svn.freebsd.org> References: <201201250022.q0P0MsEY098760@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, 25 Jan 2012, Rick Macklem wrote: > Log: > If a mount -u is done to either NFS client that switches it > from TCP to UDP and the rsize/wsize/readdirsize is greater > than NFS_MAXDGRAMDATA, it is possible for a thread doing an > I/O RPC to get stuck repeatedly doing retries. This happens > because the RPC will use a resize/wsize/readdirsize that won't > work for UDP and, as such, it will keep failing indefinitely. > This patch returns an error for this case, to avoid the problem. > A discussion on freebsd-fs@ seemed to indicate that returning > an error was preferable to silently ignoring the "udp"/"mntudp" > option. Could it wait for the old i/o to complete (and not start any new i/o?). This is little different from having to wait when changing from rw to ro. The latter is not easy, and at least the old nfs client seems to not even dream of it. ffs has always called a flushfiles() function, but until relatively recently had lots of bugs in this area. It now uses complicated suspension of i/o to prevent starting new i/o. It is still the only file system in FreeBSD that uses MNTK_SUSPEND* or vfs_write_suspend(). (geom journal also uses vfs_write_suspend(), but I think it only works with ffs. vfs_write_suspend() uses MNT_SUSPEND in its call to VFS_SYNC(), but ffs_sync() is the only sync function that references MNT_SUSPEND.) I wonder how zfs handles this. > This problem was discovered while investigating a problem reported > by pjd@ via email. This problem has annoyed me for years. I now know a workaround :-). It doesn't help that, at least without nmount(), you can't see any of the udp/tcp, rsize or wsize parameters. The behaviour of mount -u should probably be to not change anything that is not an explicit parameter, but this is not traditional (mount -u <no parameters> traditionally means mount -u -o rw...) and is impossible for at least mount() to determine the current parameters, so it was passed a complete set of defaults. So for mount -u, you have to tell it all the current parameters that are not the default unless you want them changed back to the default, and it is just as impossible for you as for mount() to tell what the current parameters are. You have to remember what you set them to. When you forgot what they were or mistype type, you sometimes switch tcp back to udp when you meant to keep tcp, and see the bug. The rsize and wsize parameters give the additional problem that when switching between udp and tcp, the defaults for the size parameters change, so you normally don't want to keep the old parameters; but when testing which combination works best, you need to control the new parameters; in particular, it is useful to know what the defaults are; but the defaults are of course only documented in the source code, and the source code that sets the defaults is very large. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20120125121210.A1045>