Linux 3.2.2内核
我检查了fs / namei.c中的源代码,发现do_unlinkat执行整个操作但是使用了用户空间指针。我想知道是否有一个函数执行此操作,除了在内核空间(我确实有文件的结构路径,inode和dentry) 我可以将函数中的代码复制到我自己的代码中。但我只是想知道它是如何运作的?
答案 0 :(得分:0)
您完全了解fs/namei.c:do_unlinkat()
功能吗?除了使用
error = user_path_parent(dfd, pathname, &nd, &name);
if (error)
return error;
查找struct nameidata
。如果成功,pathname
的内核端副本将存储在name
中(必须使用putname(name)
释放。)
但是,同一个文件也包含user_path_parent()
函数的实现。这很简单,所以你应该毫不费力地理解它的作用。实际上,除了将用户空间 - pathname
复制到内核端name
之外,它实际上只是进行do_path_lookup()
调用,它仅在内核端结构上运行。
使用上述内容,您可以对do_unlinkat()
进行少量修改,以实现您自己的内核端unlinkat()
功能。如果这是代码,你希望有一天会被上游接受,你也应该重构这两个函数,这样就没有重复的代码了。
/*
* Make sure that the actual truncation of the file will occur outside its
* directory's i_mutex. Truncate can take a long time if there is a lot of
* writeout happening, and we don't want to prevent access to the directory
* while waiting on the I/O.
*/
static long kern_unlinkat(int dfd, const char *name)
{
long error;
struct dentry *dentry;
struct nameidata nd;
struct inode *inode = NULL;
error = do_path_lookup(dfd, name, LOOKUP_PARENT, &nd);
if (error)
return error;
error = -EISDIR;
if (nd.last_type != LAST_NORM)
goto exit1;
nd.flags &= ~LOOKUP_PARENT;
error = mnt_want_write(nd.path.mnt);
if (error)
goto exit1;
mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
dentry = lookup_hash(&nd);
error = PTR_ERR(dentry);
if (!IS_ERR(dentry)) {
/* Why not before? Because we want correct error value */
if (nd.last.name[nd.last.len])
goto slashes;
inode = dentry->d_inode;
if (!inode)
goto slashes;
ihold(inode);
error = security_path_unlink(&nd.path, dentry);
if (error)
goto exit2;
error = vfs_unlink(nd.path.dentry->d_inode, dentry);
exit2:
dput(dentry);
}
mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
if (inode)
iput(inode); /* truncate the inode here */
mnt_drop_write(nd.path.mnt);
exit1:
path_put(&nd.path);
return error;
slashes:
error = !dentry->d_inode ? -ENOENT :
S_ISDIR(dentry->d_inode->i_mode) ? -EISDIR : -ENOTDIR;
goto exit2;
}
static long do_unlinkat(int dfd, const char __user *pathname)
{
long error;
char *name = getname(pathname);
if (IS_ERR(name))
return PTR_ERR(name);
error = kern_unlinkat(dfd, name);
putname(name);
return error;
}
EXPORT_SYMBOL(kern_unlink);
如果以上工作 - 我没有费心去测试它;所有由您决定的 - 然后您可以在自己的内核模块中使用kern_unlinkat(directoryfd, pathname)
或kern_unlinkat(AT_FDCWD, pathname)
通过在内核端字符串pathname
中指定其路径名来删除文件。 / p>
如果您已经拥有了nameidata,那么您显然可以更改上述内容以匹配常见代码和不代码代码。但是,考虑到细节的棘手(特别是dentry锁定),如果我是你,我只会使用路径名。
快乐的黑客,祝你好运。