如何从 FreeBSD(ZFS 和 UFS)上的 inode 获取路径?
How to get a path from an inode on FreeBSD (ZFS and UFS)?
Windows (NtQueryObject), Linux (/proc/self/fd/x) 和 OS X (F_GETPATH) 都有获取当前对象路径的方法打开文件描述符。据说 FreeBSD 也是通过类似下面的代码:
size_t len;
int mib[4]={CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC, getpid()};
BOOST_AFIO_ERRHOS(sysctl(mib, 4, NULL, &len, NULL, 0));
std::vector<char> buffer(len*2);
BOOST_AFIO_ERRHOS(sysctl(mib, 4, buffer.data(), &len, NULL, 0));
for(char *p=buffer.data(); p<buffer.data()+len;)
{
struct kinfo_file *kif=(struct kinfo_file *) p;
if(kif->kf_fd==fd)
{
lock_guard<pathlock_t> g(pathlock);
_path=path::string_type(kif->kf_path);
return _path;
}
p+=kif->kf_structsize;
}
这令人恼火地适用于几乎所有类型的文件描述符 除了 常规文件 return 一个空路径,至少在 FreeBSD 10 中是这样。我认为这是一个从检查内核代码的监督来看,return 路径似乎微不足道,尽管可能出于性能原因不这样做。
procstat 使用与上面相同的 API,因此也只有 returns 路径用于除常规文件之外的所有内容。使用 statfs() 我至少可以获得文件的挂载点路径,但是检索挂载点和实际文件之间的路径片段是问题所在。
所以让我问这个问题:是否可以要求 UFS 或 ZFS return 来自 inode 的路径片段,可能使用一些神奇的 ioctl 或 sysctl,甚至一些实用程序库?有问题的代码不需要 the 打开文件描述符的路径,它只需要 some 当前可以找到文件描述符的规范路径at(这是为了处理 proposed Boost.AFIO 的跟踪第三方文件重命名)。
在此先感谢您的帮助。 FreeBSD 是主要操作系统中此功能的唯一亮点,没有它,就不可能编写文件系统竞争安全检测代码:(
编辑: 我在 http://comments.gmane.org/gmane.os.solaris.opensolaris.zfs/38277 找到了关于让 ZFS 将 inode 转换为路径的讨论。显然有一个 ZFS_IOC_OBJ_TO_PATH ioctl,但从 google
来看,这不是一个很好的代码路径
事实证明,KERN_PROC_FILEDESC 不起作用的事实实际上是 FreeBSD 内核中的一个错误。我已经在 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=197695.
记录了它
KERN_PROC_FILEDESC 非常适合目录文件描述符,包括跟踪重命名和删除。它不完美地适用于常规文件描述符,有时会返回一个路径,然后突然返回一个空路径,然后随机地再次返回一个路径。我认为 10.x 版本中某处有问题:(
希望对遇到类似问题的其他人有所帮助。
Windows (NtQueryObject), Linux (/proc/self/fd/x) 和 OS X (F_GETPATH) 都有获取当前对象路径的方法打开文件描述符。据说 FreeBSD 也是通过类似下面的代码:
size_t len;
int mib[4]={CTL_KERN, KERN_PROC, KERN_PROC_FILEDESC, getpid()};
BOOST_AFIO_ERRHOS(sysctl(mib, 4, NULL, &len, NULL, 0));
std::vector<char> buffer(len*2);
BOOST_AFIO_ERRHOS(sysctl(mib, 4, buffer.data(), &len, NULL, 0));
for(char *p=buffer.data(); p<buffer.data()+len;)
{
struct kinfo_file *kif=(struct kinfo_file *) p;
if(kif->kf_fd==fd)
{
lock_guard<pathlock_t> g(pathlock);
_path=path::string_type(kif->kf_path);
return _path;
}
p+=kif->kf_structsize;
}
这令人恼火地适用于几乎所有类型的文件描述符 除了 常规文件 return 一个空路径,至少在 FreeBSD 10 中是这样。我认为这是一个从检查内核代码的监督来看,return 路径似乎微不足道,尽管可能出于性能原因不这样做。
procstat 使用与上面相同的 API,因此也只有 returns 路径用于除常规文件之外的所有内容。使用 statfs() 我至少可以获得文件的挂载点路径,但是检索挂载点和实际文件之间的路径片段是问题所在。
所以让我问这个问题:是否可以要求 UFS 或 ZFS return 来自 inode 的路径片段,可能使用一些神奇的 ioctl 或 sysctl,甚至一些实用程序库?有问题的代码不需要 the 打开文件描述符的路径,它只需要 some 当前可以找到文件描述符的规范路径at(这是为了处理 proposed Boost.AFIO 的跟踪第三方文件重命名)。
在此先感谢您的帮助。 FreeBSD 是主要操作系统中此功能的唯一亮点,没有它,就不可能编写文件系统竞争安全检测代码:(
编辑: 我在 http://comments.gmane.org/gmane.os.solaris.opensolaris.zfs/38277 找到了关于让 ZFS 将 inode 转换为路径的讨论。显然有一个 ZFS_IOC_OBJ_TO_PATH ioctl,但从 google
来看,这不是一个很好的代码路径事实证明,KERN_PROC_FILEDESC 不起作用的事实实际上是 FreeBSD 内核中的一个错误。我已经在 https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=197695.
记录了它KERN_PROC_FILEDESC 非常适合目录文件描述符,包括跟踪重命名和删除。它不完美地适用于常规文件描述符,有时会返回一个路径,然后突然返回一个空路径,然后随机地再次返回一个路径。我认为 10.x 版本中某处有问题:(
希望对遇到类似问题的其他人有所帮助。