Is it the correct NFS behavior for non-uid-0 users opendir() calls to not update st.st_atime, but uid-0 opendir() calls to do so?
No. In fact, "opendir()", unless it does read-ahead, shouldn't update the access time of the directory being opened, period; opens don't modify the access time, just reads, on the UNIX-flavored systems I've seen.
I've got a filesystem mounted from the NetApp to the FreeBSD machine, exported as:
/vol/vol0/home -access=client_hostname,anon=0
It's mounted on the client rw,intr,nfsv2.
When I run a program as uid 0 that does simply an opendir()/closedir() on a directory, the directory's st.st_atime gets updated.
A quick look at the FreeBSD 2.2.7 code doesn't show anything that should cause any reads to be done from the file when you do an "opendir()", although I'd have to look closer at "_seekdir()" to see if "closedir()" might somehow cause reading (that'd be silly, but perhaps there's either a bug, or that silliness is worth whatever other benefits it brings).
When I run the same program as uid > 0 (in this case, 51, to be exact), atime does not get updated.
It might be interesting to run the program under a system call tracer, both as root and non-root, to see if the access time updating is being done from userland or if it's buried in the kernel.