diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-04-16 16:22:48 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-14 15:09:23 -0400 |
commit | 8bac9db9cf85f2518cb523bb1d69c481975c1f9a (patch) | |
tree | 30c3d3cd02d34386e28f07b0fb3d172e1088cc47 /fs/nfs/getroot.c | |
parent | 04ffdbe2e69beb0f1745f921871fbe0f97dc4697 (diff) |
NFSv4: Reduce stack footprint of nfs4_get_root()
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/getroot.c')
-rw-r--r-- | fs/nfs/getroot.c | 76 |
1 files changed, 46 insertions, 30 deletions
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index ada369a5647b..7428f7d6273b 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -78,46 +78,52 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
78 | { | 78 | { |
79 | struct nfs_server *server = NFS_SB(sb); | 79 | struct nfs_server *server = NFS_SB(sb); |
80 | struct nfs_fsinfo fsinfo; | 80 | struct nfs_fsinfo fsinfo; |
81 | struct nfs_fattr fattr; | 81 | struct dentry *ret; |
82 | struct dentry *mntroot; | ||
83 | struct inode *inode; | 82 | struct inode *inode; |
84 | int error; | 83 | int error; |
85 | 84 | ||
86 | /* get the actual root for this mount */ | 85 | /* get the actual root for this mount */ |
87 | fsinfo.fattr = &fattr; | 86 | fsinfo.fattr = nfs_alloc_fattr(); |
87 | if (fsinfo.fattr == NULL) | ||
88 | return ERR_PTR(-ENOMEM); | ||
88 | 89 | ||
89 | error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); | 90 | error = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); |
90 | if (error < 0) { | 91 | if (error < 0) { |
91 | dprintk("nfs_get_root: getattr error = %d\n", -error); | 92 | dprintk("nfs_get_root: getattr error = %d\n", -error); |
92 | return ERR_PTR(error); | 93 | ret = ERR_PTR(error); |
94 | goto out; | ||
93 | } | 95 | } |
94 | 96 | ||
95 | inode = nfs_fhget(sb, mntfh, fsinfo.fattr); | 97 | inode = nfs_fhget(sb, mntfh, fsinfo.fattr); |
96 | if (IS_ERR(inode)) { | 98 | if (IS_ERR(inode)) { |
97 | dprintk("nfs_get_root: get root inode failed\n"); | 99 | dprintk("nfs_get_root: get root inode failed\n"); |
98 | return ERR_CAST(inode); | 100 | ret = ERR_CAST(inode); |
101 | goto out; | ||
99 | } | 102 | } |
100 | 103 | ||
101 | error = nfs_superblock_set_dummy_root(sb, inode); | 104 | error = nfs_superblock_set_dummy_root(sb, inode); |
102 | if (error != 0) | 105 | if (error != 0) { |
103 | return ERR_PTR(error); | 106 | ret = ERR_PTR(error); |
107 | goto out; | ||
108 | } | ||
104 | 109 | ||
105 | /* root dentries normally start off anonymous and get spliced in later | 110 | /* root dentries normally start off anonymous and get spliced in later |
106 | * if the dentry tree reaches them; however if the dentry already | 111 | * if the dentry tree reaches them; however if the dentry already |
107 | * exists, we'll pick it up at this point and use it as the root | 112 | * exists, we'll pick it up at this point and use it as the root |
108 | */ | 113 | */ |
109 | mntroot = d_obtain_alias(inode); | 114 | ret = d_obtain_alias(inode); |
110 | if (IS_ERR(mntroot)) { | 115 | if (IS_ERR(ret)) { |
111 | dprintk("nfs_get_root: get root dentry failed\n"); | 116 | dprintk("nfs_get_root: get root dentry failed\n"); |
112 | return mntroot; | 117 | goto out; |
113 | } | 118 | } |
114 | 119 | ||
115 | security_d_instantiate(mntroot, inode); | 120 | security_d_instantiate(ret, inode); |
116 | 121 | ||
117 | if (!mntroot->d_op) | 122 | if (ret->d_op == NULL) |
118 | mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; | 123 | ret->d_op = server->nfs_client->rpc_ops->dentry_ops; |
119 | 124 | out: | |
120 | return mntroot; | 125 | nfs_free_fattr(fsinfo.fattr); |
126 | return ret; | ||
121 | } | 127 | } |
122 | 128 | ||
123 | #ifdef CONFIG_NFS_V4 | 129 | #ifdef CONFIG_NFS_V4 |
@@ -168,8 +174,8 @@ out: | |||
168 | struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | 174 | struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) |
169 | { | 175 | { |
170 | struct nfs_server *server = NFS_SB(sb); | 176 | struct nfs_server *server = NFS_SB(sb); |
171 | struct nfs_fattr fattr; | 177 | struct nfs_fattr *fattr = NULL; |
172 | struct dentry *mntroot; | 178 | struct dentry *ret; |
173 | struct inode *inode; | 179 | struct inode *inode; |
174 | int error; | 180 | int error; |
175 | 181 | ||
@@ -183,40 +189,50 @@ struct dentry *nfs4_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
183 | return ERR_PTR(error); | 189 | return ERR_PTR(error); |
184 | } | 190 | } |
185 | 191 | ||
192 | fattr = nfs_alloc_fattr(); | ||
193 | if (fattr == NULL) | ||
194 | return ERR_PTR(-ENOMEM);; | ||
195 | |||
186 | /* get the actual root for this mount */ | 196 | /* get the actual root for this mount */ |
187 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, &fattr); | 197 | error = server->nfs_client->rpc_ops->getattr(server, mntfh, fattr); |
188 | if (error < 0) { | 198 | if (error < 0) { |
189 | dprintk("nfs_get_root: getattr error = %d\n", -error); | 199 | dprintk("nfs_get_root: getattr error = %d\n", -error); |
190 | return ERR_PTR(error); | 200 | ret = ERR_PTR(error); |
201 | goto out; | ||
191 | } | 202 | } |
192 | 203 | ||
193 | inode = nfs_fhget(sb, mntfh, &fattr); | 204 | inode = nfs_fhget(sb, mntfh, fattr); |
194 | if (IS_ERR(inode)) { | 205 | if (IS_ERR(inode)) { |
195 | dprintk("nfs_get_root: get root inode failed\n"); | 206 | dprintk("nfs_get_root: get root inode failed\n"); |
196 | return ERR_CAST(inode); | 207 | ret = ERR_CAST(inode); |
208 | goto out; | ||
197 | } | 209 | } |
198 | 210 | ||
199 | error = nfs_superblock_set_dummy_root(sb, inode); | 211 | error = nfs_superblock_set_dummy_root(sb, inode); |
200 | if (error != 0) | 212 | if (error != 0) { |
201 | return ERR_PTR(error); | 213 | ret = ERR_PTR(error); |
214 | goto out; | ||
215 | } | ||
202 | 216 | ||
203 | /* root dentries normally start off anonymous and get spliced in later | 217 | /* root dentries normally start off anonymous and get spliced in later |
204 | * if the dentry tree reaches them; however if the dentry already | 218 | * if the dentry tree reaches them; however if the dentry already |
205 | * exists, we'll pick it up at this point and use it as the root | 219 | * exists, we'll pick it up at this point and use it as the root |
206 | */ | 220 | */ |
207 | mntroot = d_obtain_alias(inode); | 221 | ret = d_obtain_alias(inode); |
208 | if (IS_ERR(mntroot)) { | 222 | if (IS_ERR(ret)) { |
209 | dprintk("nfs_get_root: get root dentry failed\n"); | 223 | dprintk("nfs_get_root: get root dentry failed\n"); |
210 | return mntroot; | 224 | goto out; |
211 | } | 225 | } |
212 | 226 | ||
213 | security_d_instantiate(mntroot, inode); | 227 | security_d_instantiate(ret, inode); |
214 | 228 | ||
215 | if (!mntroot->d_op) | 229 | if (ret->d_op == NULL) |
216 | mntroot->d_op = server->nfs_client->rpc_ops->dentry_ops; | 230 | ret->d_op = server->nfs_client->rpc_ops->dentry_ops; |
217 | 231 | ||
232 | out: | ||
233 | nfs_free_fattr(fattr); | ||
218 | dprintk("<-- nfs4_get_root()\n"); | 234 | dprintk("<-- nfs4_get_root()\n"); |
219 | return mntroot; | 235 | return ret; |
220 | } | 236 | } |
221 | 237 | ||
222 | #endif /* CONFIG_NFS_V4 */ | 238 | #endif /* CONFIG_NFS_V4 */ |