Skip site navigation (1)Skip section navigation (2)
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>