Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
fs
nfs
getroot.c
Go to the documentation of this file.
1
/* getroot.c: get the root dentry for an NFS mount
2
*
3
* Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
4
* Written by David Howells (
[email protected]
)
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version
9
* 2 of the License, or (at your option) any later version.
10
*/
11
12
#include <linux/module.h>
13
#include <
linux/init.h
>
14
15
#include <linux/time.h>
16
#include <linux/kernel.h>
17
#include <
linux/mm.h
>
18
#include <linux/string.h>
19
#include <linux/stat.h>
20
#include <linux/errno.h>
21
#include <
linux/unistd.h
>
22
#include <
linux/sunrpc/clnt.h
>
23
#include <
linux/sunrpc/stats.h
>
24
#include <linux/nfs_fs.h>
25
#include <
linux/nfs_mount.h
>
26
#include <
linux/lockd/bind.h
>
27
#include <
linux/seq_file.h
>
28
#include <
linux/mount.h
>
29
#include <
linux/vfs.h
>
30
#include <
linux/namei.h
>
31
#include <
linux/security.h
>
32
33
#include <asm/uaccess.h>
34
35
#include "
internal.h
"
36
37
#define NFSDBG_FACILITY NFSDBG_CLIENT
38
39
/*
40
* Set the superblock root dentry.
41
* Note that this function frees the inode in case of error.
42
*/
43
static
int
nfs_superblock_set_dummy_root(
struct
super_block
*
sb
,
struct
inode
*
inode
)
44
{
45
/* The mntroot acts as the dummy root dentry for this superblock */
46
if
(sb->
s_root
==
NULL
) {
47
sb->
s_root
=
d_make_root
(inode);
48
if
(sb->
s_root
==
NULL
)
49
return
-
ENOMEM
;
50
ihold
(inode);
51
/*
52
* Ensure that this dentry is invisible to d_find_alias().
53
* Otherwise, it may be spliced into the tree by
54
* d_materialise_unique if a parent directory from the same
55
* filesystem gets mounted at a later time.
56
* This again causes shrink_dcache_for_umount_subtree() to
57
* Oops, since the test for IS_ROOT() will fail.
58
*/
59
spin_lock(&sb->
s_root
->d_inode->i_lock);
60
spin_lock(&sb->
s_root
->d_lock);
61
hlist_del_init(&sb->
s_root
->d_alias);
62
spin_unlock(&sb->
s_root
->d_lock);
63
spin_unlock(&sb->
s_root
->d_inode->i_lock);
64
}
65
return
0;
66
}
67
68
/*
69
* get an NFS2/NFS3 root dentry from the root filehandle
70
*/
71
struct
dentry
*
nfs_get_root
(
struct
super_block
*
sb
,
struct
nfs_fh
*mntfh,
72
const
char
*devname)
73
{
74
struct
nfs_server
*server = NFS_SB(sb);
75
struct
nfs_fsinfo
fsinfo;
76
struct
dentry
*
ret
;
77
struct
inode
*
inode
;
78
void
*
name
=
kstrdup
(devname,
GFP_KERNEL
);
79
int
error
;
80
81
if
(!name)
82
return
ERR_PTR(-
ENOMEM
);
83
84
/* get the actual root for this mount */
85
fsinfo.
fattr
=
nfs_alloc_fattr
();
86
if
(fsinfo.
fattr
==
NULL
) {
87
kfree
(name);
88
return
ERR_PTR(-
ENOMEM
);
89
}
90
91
error = server->
nfs_client
->rpc_ops->getroot(server, mntfh, &fsinfo);
92
if
(error < 0) {
93
dprintk
(
"nfs_get_root: getattr error = %d\n"
, -error);
94
ret = ERR_PTR(error);
95
goto
out
;
96
}
97
98
inode =
nfs_fhget
(sb, mntfh, fsinfo.
fattr
);
99
if
(IS_ERR(inode)) {
100
dprintk
(
"nfs_get_root: get root inode failed\n"
);
101
ret = ERR_CAST(inode);
102
goto
out
;
103
}
104
105
error = nfs_superblock_set_dummy_root(sb, inode);
106
if
(error != 0) {
107
ret = ERR_PTR(error);
108
goto
out
;
109
}
110
111
/* root dentries normally start off anonymous and get spliced in later
112
* if the dentry tree reaches them; however if the dentry already
113
* exists, we'll pick it up at this point and use it as the root
114
*/
115
ret =
d_obtain_alias
(inode);
116
if
(IS_ERR(ret)) {
117
dprintk
(
"nfs_get_root: get root dentry failed\n"
);
118
goto
out
;
119
}
120
121
security_d_instantiate
(ret, inode);
122
spin_lock(&ret->
d_lock
);
123
if
(
IS_ROOT
(ret) && !(ret->
d_flags
&
DCACHE_NFSFS_RENAMED
)) {
124
ret->
d_fsdata
=
name
;
125
name =
NULL
;
126
}
127
spin_unlock(&ret->
d_lock
);
128
out
:
129
if
(name)
130
kfree
(name);
131
nfs_free_fattr(fsinfo.
fattr
);
132
return
ret
;
133
}
Generated on Thu Jan 10 2013 14:48:24 for Linux Kernel by
1.8.2