应用场景
第一次ll
操作返回正常的显示信息,第二次做ll
操作报no such file
的错误信息模拟,实验可以成功模拟出来下效果。
记录一下,此次试验的小知识点。模拟中,是在lookup
函数中修改dentry
内容,主要内存块拷贝+延迟的操作。需要利用到内核线程的启动。
#include <linux/sched.h>
#include <linux/errno.h>
#include <linux/kthread.h>
struct d_replace{ // 参数传递
struct dentry *old_dentry;
struct dentry *new_dentry;
};
static void func_d_replace(void *data){ // 替换函数
msleep(2000);
dfprintk(VFS, "into func dentry replace");
struct d_replace *d = (struct d_replace *)data;
dfprintk(VFS, "d replace new name is %s \n", d->new_dentry->d_name.name);
dfprintk(VFS, "d replace old name is %s \n", d->old_dentry->d_name.name);
//d->old_dentry = d->new_dentry;
memcpy(d->old_dentry, d->new_dentry, sizeof(*(d->old_dentry)));
dfprintk(VFS, "cover dentry new name is %s \n", d->new_dentry->d_name.name);
dfprintk(VFS, "cover dentry old name is %s \n", d->old_dentry->d_name.name);
}
struct dentry *nfs_lookup(struct inode *dir, struct dentry * jhash_size, unsigned int flags)
{
struct dentry *res;
struct dentry *parent;
struct inode *inode = NULL;
struct nfs_fh *fhandle = NULL;
struct nfs_fattr *fattr = NULL;
int error;
struct task_struct *task; // 声明补充变量
const unsigned char *name;
struct d_replace *d_rep;
struct dentry *d_new;
d_new = d_alloc(dentry->d_parent, &dentry->d_name); // 创建一个dentry
d_rep = kmalloc(sizeof(*d_rep), GFP_KERNEL); // 申请结构体空间
dfprintk(VFS, "NFS: lookup(%s/%s)\n",
dentry->d_parent->d_name.name, dentry->d_name.name);
nfs_inc_stats(dir, NFSIOS_VFSLOOKUP);
res = ERR_PTR(-ENAMETOOLONG);
if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
goto out;
/*
* If we're doing an exclusive create, optimize away the lookup
* but don't hash the dentry.
*/
if (nfs_is_exclusive_create(dir, flags)) {
d_instantiate(dentry, NULL);
res = NULL;
goto out;
}
res = ERR_PTR(-ENOMEM);
fhandle = nfs_alloc_fhandle();
fattr = nfs_alloc_fattr();
if (fhandle == NULL || fattr == NULL)
goto out;
parent = dentry->d_parent;
/* Protect against concurrent sillydeletes */
nfs_block_sillyrename(parent);
error = NFS_PROTO(dir)->lookup(dir, &dentry->d_name, fhandle, fattr);
if (error == -ENOENT)
goto no_entry;
if (error < 0) {
res = ERR_PTR(error);
goto out_unblock_sillyrename;
}
inode = nfs_fhget(dentry->d_sb, fhandle, fattr);
res = ERR_CAST(inode);
if (IS_ERR(res))
goto out_unblock_sillyrename;
/* Success: notify readdir to use READDIRPLUS */
nfs_advise_use_readdirplus(dir);
no_entry:
res = d_materialise_unique(dentry, inode);
if (res != NULL) {
if (IS_ERR(res))
goto out_unblock_sillyrename;
dentry = res;
}
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
out_unblock_sillyrename:
nfs_unblock_sillyrename(parent);
out:
nfs_free_fattr(fattr);
nfs_free_fhandle(fhandle);
name = "debug"; //特殊目录名,修改它的dentry
if(strcasecmp(dentry->d_name.name, name) == 0){ // 创建线程
dfprintk(VFS, "name is debug, ready...");
d_rep->old_dentry = dentry;
d_rep->new_dentry = d_new;
dfprintk(VFS, "new name is %s", d_rep->new_dentry->d_name.name);
dfprintk(VFS, "old name is %s", d_rep->old_dentry->d_name.name);
task = kthread_create(func_d_replace, d_rep, "replace dentry");
if(IS_ERR(task)){
dfprintk(VFS, "unable to start kernel thread");
}
wake_up_process(task);
}
return res;
}
EXPORT_SYMBOL_GPL(nfs_lookup);