本方法适用于linux 2.6.x内核。
1. 先获取dentry所属文件系统对应的挂载点,基本原理是遍历文件系统vfsmount树,找到与dentry有相同超级块的vfsmount,实现如下
next_mnt函数实现了先根遍历法,遍历以root为根的文件系统挂载点,p为遍历过程中的当前结点,返回p的下一个挂载点;vfsmnt_lock可通过内核函数kallsyms_on_each_symbol或kallsyms_lookup_name查找获得。
2. 再调用内核函数d_path,接口封装如下
![]()
1. 先获取dentry所属文件系统对应的挂载点,基本原理是遍历文件系统vfsmount树,找到与dentry有相同超级块的vfsmount,实现如下
1
extern spinlock_t *vfsmnt_lock;
2![]()
3
static struct vfsmount* next_mnt(struct vfsmount *p, struct vfsmount *root)
4
{
5
struct list_head *next = p->mnt_mounts.next;
6
if (next == &p->mnt_mounts) {
7
while (1) {
8
if (p == root)
9
return NULL;
10
next = p->mnt_child.next;
11
if (next != &p->mnt_parent->mnt_mounts)
12
break;
13
p = p->mnt_parent;
14
}
15
}
16
return list_entry(next, struct vfsmount, mnt_child);
17
}
18![]()
19
static struct vfsmount* get_dentry_mnt(struct dentry *dentry)
20
{
21
struct vfsmount *p, *root;
22
struct fs_struct *fs = current->fs;
23![]()
24
read_lock(&fs->lock);
25
root = fs->root.mnt;
26
mntget(root);
27
read_unlock(&fs->lock);
28![]()
29
spin_lock(vfsmnt_lock);
30
for(p = root; p; p = next_mnt(p,root)){
31
if(p->mnt_sb == dentry->d_sb){
32
mntget(p);
33
break;
34
}
35
}
36
spin_unlock(vfsmnt_lock);
37![]()
38
mntput(root);
39
40
return p;
41
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

2. 再调用内核函数d_path,接口封装如下
1
char* get_dentry_path(struct dentry *dentry,char *buf,int len)
2
{
3
char *p = "";
4
struct vfsmount *mnt = get_dentry_mnt(dentry);
5
6
if(mnt){
7
struct path ph = {.dentry = dentry, .mnt = mnt};
8
p = d_path(&ph,buf,len);
9
if(IS_ERR(p))
10
p = "";
11
mntput(mnt);
12
}
13
14
return p;
15
}

2

3

4

5

6

7

8

9

10

11

12

13

14

15
