Date: Thu, 14 Mar 2013 11:29:11 +0400 From: Noskov Ilia <phantom@phantom.su> To: freebsd-fs@freebsd.org Subject: Re: should vn_fullpath1() ever return a path with "." in it? Message-ID: <51417C47.8010304@phantom.su> In-Reply-To: <1208475167.3432384.1362099531469.JavaMail.root@erie.cs.uoguelph.ca> References: <1208475167.3432384.1362099531469.JavaMail.root@erie.cs.uoguelph.ca>
next in thread | previous in thread | raw e-mail | index | archive | help
On 03/01/2013 04:58 AM, Rick Macklem wrote: > Kostik Belousov wrote: >> On Wed, Feb 27, 2013 at 09:59:22PM -0500, Rick Macklem wrote: >>> Hi, >>> >>> Sergey Kandaurov reported a problem where getcwd() returns a >>> path with "/./" imbedded in it for an NFSv4 mount. This is >>> caused by a mount point crossing on the server when at the >>> server's root because vn_fullpath1() uses VV_ROOT to spot >>> mount point crossings. >>> >>> The current workaround is to use the sysctls: >>> debug.disablegetcwd=1 >>> debug.disablefullpath=1 >>> >>> However, it would be nice to fix this when vn_fullpath1() >>> is being used. >>> >>> A simple fix is to have vn_fullpath1() fail when it finds >>> "." as a directory match in the path. When vn_fullpath1() >>> fails, the syscalls fail and that allows the libc algorithm >>> to be used (which works for this case because it doesn't >>> depend on VV_ROOT being set, etc). >>> >>> So, I am wondering if a patch (I have attached one) that >>> makes vn_fullpath1() fail when it matches "." will break >>> anything else? (I don't think so, since the code checks >>> for VV_ROOT in the loop above the check for a match of >>> ".", but I am not sure?) >>> >>> Thanks for any input w.r.t. this, rick >> >>> --- kern/vfs_cache.c.sav 2013-02-27 20:44:42.000000000 -0500 >>> +++ kern/vfs_cache.c 2013-02-27 21:10:39.000000000 -0500 >>> @@ -1333,6 +1333,20 @@ vn_fullpath1(struct thread *td, struct v >>> startvp, NULL, 0, 0); >>> break; >>> } >>> + if (buf[buflen] == '.' && (buf[buflen + 1] == '\0' || >>> + buf[buflen + 1] == '/')) { >>> + /* >>> + * Fail if it matched ".". This should only happen >>> + * for NFSv4 mounts that cross server mount points. >>> + */ >>> + CACHE_RUNLOCK(); >>> + vrele(vp); >>> + numfullpathfail1++; >>> + error = ENOENT; >>> + SDT_PROBE(vfs, namecache, fullpath, return, >>> + error, vp, NULL, 0, 0); >>> + break; >>> + } >>> buf[--buflen] = '/'; >>> slash_prefixed = 1; >>> } >> >> I do not quite understand this. Did the dvp (parent) vnode returned by >> VOP_VPTOCNP() equal to vp (child) vnode in the case of the "." name ? >> It must be, for the correct operation, but also it should cause the >> almost >> infinite loop in the vn_fullpath1(). The loop is not really infinite >> due >> to a limited size of the buffer where the infinite amount of "./" is >> placed. >> >> Anyway, I think we should do better than this patch, even if it is >> legitimate. I think that the better place to check the condition is >> the >> default implementation of VOP_VPTOCNP(). Am I right that this is where >> it broke for you ? >> >> diff --git a/sys/kern/vfs_default.c b/sys/kern/vfs_default.c >> index 00d064e..1dd0185 100644 >> --- a/sys/kern/vfs_default.c >> +++ b/sys/kern/vfs_default.c >> @@ -856,8 +856,12 @@ vop_stdvptocnp(struct vop_vptocnp_args *ap) >> error = ENOMEM; >> goto out; >> } >> - bcopy(dp->d_name, buf + i, dp->d_namlen); >> - error = 0; >> + if (dp->d_namlen == 1 && dp->d_name[0] == '.') { >> + error = ENOENT; >> + } else { >> + bcopy(dp->d_name, buf + i, dp->d_namlen); >> + error = 0; >> + } >> goto out; >> } >> } while (len > 0 || !eofflag); > > Yes, this patch fixes the problem too. If you think it is safe to > do this, I can commit the patch in mid-April. Maybe Sergey can > test it? > > Thanks yet again, rick Hi, Rick. Strange behavior on nfs-client after apply this patch: sysctl debug.disablecwd=0 sysctl debug.disablefullpath=0 # mount -v -t nfs 192.168.168.1:/pool on /home (nfs, noatime, nfsv4acls, fsid 02ff003a3a000000) # ls /home | wc -l 4946 # cd /home/user6308/.ro # time pwd /home/user6308/.ro 0.008u 0.269s 0:08.47 3.0% 4+157k 0+0io 0pf+0w # ktrace -t+ -i pwd ktrace.out is big (1MB). Attach or not? A small piece of trace: 19527 pwd CALL mmap(0,0x400000,0x3<PROT_READ|PROT_WRITE>,0x1002<MAP_PRIVATE|MAP_ANON>,0xffffffff,0) 19527 pwd RET mmap 34376515584/0x801000000 19527 pwd CALL __getcwd(0x801006400,0x400) 19527 pwd NAMI ".." 19527 pwd NAMI ".." 19527 pwd RET __getcwd -1 errno 2 No such file or directory 19527 pwd CALL stat(0x800947a14,0x7fffffffd940) 19527 pwd NAMI "/" 19527 pwd STRU struct stat {dev=98, ino=2, mode=drwxr-xr-x , nlink=19, uid=0, gid=0, rdev=2120, atime=1363244893, stime=1362653279, ctime=1362653279, birthtime=1200836451, size=1024, blksize=16384, blocks=4, flags=0x0 } 19527 pwd RET stat 0 19527 pwd CALL lstat(0x80094779c,0x7fffffffd940) 19527 pwd NAMI "." 19527 pwd STRU struct stat {dev=1230702064, ino=145, mode=drwxr-xr-x , nlink=2, uid=0, gid=0, rdev=4294967295, atime=1363244672.246785874, stime=1363244792.864201338, ctime=1363244792.864201338, birthtime=-1, size=3, blksize=4096, blocks=3, flags=0x0 } 19527 pwd RET lstat 0 19527 pwd CALL openat(0xffffff9c,0x80094779b,0x100000,0x2) 19527 pwd NAMI ".." 19527 pwd RET openat 3 19527 pwd CALL fstat(0x3,0x7fffffffd880) 19527 pwd STRU struct stat {dev=1230702064, ino=4, mode=drwxr-xr-x , nlink=9, uid=0, gid=0, rdev=4294967295, atime=1363244665.232140704, stime=1363010116.496298252, ctime=1363010116.496298252, birthtime=-1, size=14, blksize=4096, blocks=3, flags=0x0 } 19527 pwd RET fstat 0 19527 pwd CALL fcntl(0x3,F_SETFD,FD_CLOEXEC) 19527 pwd RET fcntl 0 19527 pwd CALL fstatfs(0x3,0x7fffffffd660) 19527 pwd RET fstatfs 0 19527 pwd CALL fstat(0x3,0x7fffffffd940) 19527 pwd STRU struct stat {dev=1230702064, ino=4, mode=drwxr-xr-x , nlink=9, uid=0, gid=0, rdev=4294967295, atime=1363244665.232140704, stime=1363010116.496298252, ctime=1363010116.496298252, birthtime=-1, size=14, blksize=4096, blocks=3, flags=0x0 } 19527 pwd RET fstat 0 19527 pwd CALL getdirentries(0x3,0x801018000,0x1000,0x8010160a8) 19527 pwd RET getdirentries 4096/0x1000 19527 pwd CALL fstat(0x3,0x7fffffffd940) 19527 pwd STRU struct stat {dev=1230702064, ino=4, mode=drwxr-xr-x , nlink=9, uid=0, gid=0, rdev=4294967295, atime=1363244665.232140704, stime=1363010116.496298252, ctime=1363010116.496298252, birthtime=-1, size=14, blksize=4096, blocks=3, flags=0x0 } 19527 pwd RET fstat 0 19527 pwd CALL openat(0x3,0x80094779b,0x100000,0) 19527 pwd NAMI ".." 19527 pwd RET openat 4 [..............................] 19527 pwd CALL madvise(0x801016000,0x1000,MADV_FREE) 19527 pwd RET madvise 0 19527 pwd CALL madvise(0x801018000,0x2000,MADV_FREE) 19527 pwd RET madvise 0 19527 pwd CALL close(0x3) 19527 pwd RET close 0 19527 pwd CALL fstat(0x4,0x7fffffffd880) 19527 pwd STRU struct stat {dev=973143810, ino=4, mode=drwxr-xr-x , nlink=4948, uid=0, gid=0, rdev=4294967295, atime=1363244767.460164771, stime=1363172100.380266923, ctime=1363172100.380266923, birthtime=-1, size=4948, blksize=4096, blocks=713, flags=0x0 } 19527 pwd RET fstat 0 19527 pwd CALL fcntl(0x4,F_SETFD,FD_CLOEXEC) 19527 pwd RET fcntl 0 19527 pwd CALL fstatfs(0x4,0x7fffffffd660) 19527 pwd RET fstatfs 0 19527 pwd CALL fstat(0x4,0x7fffffffd940) 19527 pwd STRU struct stat {dev=973143810, ino=4, mode=drwxr-xr-x , nlink=4948, uid=0, gid=0, rdev=4294967295, atime=1363244767.460164771, stime=1363172100.380266923, ctime=1363172100.380266923, birthtime=-1, size=4948, blksize=4096, blocks=713, flags=0x0 } 19527 pwd RET fstat 0 19527 pwd CALL getdirentries(0x4,0x801018000,0x1000,0x8010160a8) 19527 pwd RET getdirentries 4096/0x1000 19527 pwd CALL fstatat(0x4,0x801018030,0x7fffffffd940,0x200) 19527 pwd NAMI "user6158" 19527 pwd STRU struct stat {dev=1774902232, ino=4, mode=drwxr-xr-x , nlink=9, uid=0, gid=0, rdev=4294967295, atime=1363009687.040357529, stime=1363010116.496298252, ctime=1363010116.496298252, birthtime=-1, size=14, blksize=4096, blocks=3, flags=0x0 } 19527 pwd RET fstatat 0 19527 pwd CALL fstatat(0x4,0x80101804c,0x7fffffffd940,0x200) 19527 pwd NAMI "user2289" 19527 pwd STRU struct stat {dev=1988229825, ino=4, mode=drwxr-xr-x , nlink=9, uid=0, gid=0, rdev=4294967295, atime=1363009687.040357529, stime=1363010116.496298252, ctime=1363010116.496298252, birthtime=-1, size=14, blksize=4096, blocks=3, flags=0x0 } 19527 pwd RET fstatat 0 19527 pwd CALL fstatat(0x4,0x801018068,0x7fffffffd940,0x200) 19527 pwd NAMI "user4761" 19527 pwd STRU struct stat {dev=2438657130, ino=4, mode=drwxr-xr-x , nlink=9, uid=0, gid=0, rdev=4294967295, atime=1363009687.040357529, stime=1363010116.496298252, ctime=1363010116.496298252, birthtime=-1, size=14, blksize=4096, blocks=3, flags=0x0 } 19527 pwd RET fstatat 0 19527 pwd CALL fstatat(0x4,0x801018084,0x7fffffffd940,0x200) 19527 pwd NAMI "user6055" [.........................................] and next get stat of all directories in /home > > _______________________________________________ > freebsd-fs@freebsd.org mailing list > http://lists.freebsd.org/mailman/listinfo/freebsd-fs > To unsubscribe, send any mail to "freebsd-fs-unsubscribe@freebsd.org" > -- Best Regards, Ilia Noskov Regional Network Information Center (RU-CENTER) phone: +7 495 737-0601 fax: +7 495 737-0602 http://www.nic.ru
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?51417C47.8010304>