diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/client.c | 4 | ||||
-rw-r--r-- | fs/nfs/getroot.c | 115 | ||||
-rw-r--r-- | fs/nfs/internal.h | 4 |
3 files changed, 25 insertions, 98 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index acc9c4943b84..ac5ff21bef16 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
@@ -1364,7 +1364,7 @@ struct nfs_server *nfs4_create_server(const struct nfs_parsed_mount_data *data, | |||
1364 | goto error; | 1364 | goto error; |
1365 | 1365 | ||
1366 | /* Probe the root fh to retrieve its FSID */ | 1366 | /* Probe the root fh to retrieve its FSID */ |
1367 | error = nfs4_path_walk(server, mntfh, data->nfs_server.export_path); | 1367 | error = nfs4_get_rootfh(server, mntfh); |
1368 | if (error < 0) | 1368 | if (error < 0) |
1369 | goto error; | 1369 | goto error; |
1370 | 1370 | ||
@@ -1443,7 +1443,7 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data, | |||
1443 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); | 1443 | BUG_ON(!server->nfs_client->rpc_ops->file_inode_ops); |
1444 | 1444 | ||
1445 | /* Probe the root fh to retrieve its FSID and filehandle */ | 1445 | /* Probe the root fh to retrieve its FSID and filehandle */ |
1446 | error = nfs4_path_walk(server, mntfh, data->mnt_path); | 1446 | error = nfs4_get_rootfh(server, mntfh); |
1447 | if (error < 0) | 1447 | if (error < 0) |
1448 | goto error; | 1448 | goto error; |
1449 | 1449 | ||
diff --git a/fs/nfs/getroot.c b/fs/nfs/getroot.c index b35d2a616066..ada369a5647b 100644 --- a/fs/nfs/getroot.c +++ b/fs/nfs/getroot.c | |||
@@ -122,115 +122,44 @@ struct dentry *nfs_get_root(struct super_block *sb, struct nfs_fh *mntfh) | |||
122 | 122 | ||
123 | #ifdef CONFIG_NFS_V4 | 123 | #ifdef CONFIG_NFS_V4 |
124 | 124 | ||
125 | /* | 125 | int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh) |
126 | * Do a simple pathwalk from the root FH of the server to the nominated target | ||
127 | * of the mountpoint | ||
128 | * - give error on symlinks | ||
129 | * - give error on ".." occurring in the path | ||
130 | * - follow traversals | ||
131 | */ | ||
132 | int nfs4_path_walk(struct nfs_server *server, | ||
133 | struct nfs_fh *mntfh, | ||
134 | const char *path) | ||
135 | { | 126 | { |
136 | struct nfs_fsinfo fsinfo; | 127 | struct nfs_fsinfo fsinfo; |
137 | struct nfs_fattr fattr; | 128 | int ret = -ENOMEM; |
138 | struct nfs_fh lastfh; | ||
139 | struct qstr name; | ||
140 | int ret; | ||
141 | 129 | ||
142 | dprintk("--> nfs4_path_walk(,,%s)\n", path); | 130 | dprintk("--> nfs4_get_rootfh()\n"); |
143 | 131 | ||
144 | fsinfo.fattr = &fattr; | 132 | fsinfo.fattr = nfs_alloc_fattr(); |
145 | nfs_fattr_init(&fattr); | 133 | if (fsinfo.fattr == NULL) |
146 | 134 | goto out; | |
147 | /* Eat leading slashes */ | ||
148 | while (*path == '/') | ||
149 | path++; | ||
150 | 135 | ||
151 | /* Start by getting the root filehandle from the server */ | 136 | /* Start by getting the root filehandle from the server */ |
152 | ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); | 137 | ret = server->nfs_client->rpc_ops->getroot(server, mntfh, &fsinfo); |
153 | if (ret < 0) { | 138 | if (ret < 0) { |
154 | dprintk("nfs4_get_root: getroot error = %d\n", -ret); | 139 | dprintk("nfs4_get_rootfh: getroot error = %d\n", -ret); |
155 | return ret; | 140 | goto out; |
156 | } | 141 | } |
157 | 142 | ||
158 | if (!S_ISDIR(fattr.mode)) { | 143 | if (!(fsinfo.fattr->valid & NFS_ATTR_FATTR_MODE) |
159 | printk(KERN_ERR "nfs4_get_root:" | 144 | || !S_ISDIR(fsinfo.fattr->mode)) { |
145 | printk(KERN_ERR "nfs4_get_rootfh:" | ||
160 | " getroot encountered non-directory\n"); | 146 | " getroot encountered non-directory\n"); |
161 | return -ENOTDIR; | 147 | ret = -ENOTDIR; |
148 | goto out; | ||
162 | } | 149 | } |
163 | 150 | ||
164 | /* FIXME: It is quite valid for the server to return a referral here */ | 151 | if (fsinfo.fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) { |
165 | if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { | 152 | printk(KERN_ERR "nfs4_get_rootfh:" |
166 | printk(KERN_ERR "nfs4_get_root:" | ||
167 | " getroot obtained referral\n"); | 153 | " getroot obtained referral\n"); |
168 | return -EREMOTE; | 154 | ret = -EREMOTE; |
155 | goto out; | ||
169 | } | 156 | } |
170 | 157 | ||
171 | next_component: | 158 | memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid)); |
172 | dprintk("Next: %s\n", path); | 159 | out: |
173 | 160 | nfs_free_fattr(fsinfo.fattr); | |
174 | /* extract the next bit of the path */ | 161 | dprintk("<-- nfs4_get_rootfh() = %d\n", ret); |
175 | if (!*path) | 162 | return ret; |
176 | goto path_walk_complete; | ||
177 | |||
178 | name.name = path; | ||
179 | while (*path && *path != '/') | ||
180 | path++; | ||
181 | name.len = path - (const char *) name.name; | ||
182 | |||
183 | if (name.len > NFS4_MAXNAMLEN) | ||
184 | return -ENAMETOOLONG; | ||
185 | |||
186 | eat_dot_dir: | ||
187 | while (*path == '/') | ||
188 | path++; | ||
189 | |||
190 | if (path[0] == '.' && (path[1] == '/' || !path[1])) { | ||
191 | path += 2; | ||
192 | goto eat_dot_dir; | ||
193 | } | ||
194 | |||
195 | /* FIXME: Why shouldn't the user be able to use ".." in the path? */ | ||
196 | if (path[0] == '.' && path[1] == '.' && (path[2] == '/' || !path[2]) | ||
197 | ) { | ||
198 | printk(KERN_ERR "nfs4_get_root:" | ||
199 | " Mount path contains reference to \"..\"\n"); | ||
200 | return -EINVAL; | ||
201 | } | ||
202 | |||
203 | /* lookup the next FH in the sequence */ | ||
204 | memcpy(&lastfh, mntfh, sizeof(lastfh)); | ||
205 | |||
206 | dprintk("LookupFH: %*.*s [%s]\n", name.len, name.len, name.name, path); | ||
207 | |||
208 | ret = server->nfs_client->rpc_ops->lookupfh(server, &lastfh, &name, | ||
209 | mntfh, &fattr); | ||
210 | if (ret < 0) { | ||
211 | dprintk("nfs4_get_root: getroot error = %d\n", -ret); | ||
212 | return ret; | ||
213 | } | ||
214 | |||
215 | if (!S_ISDIR(fattr.mode)) { | ||
216 | printk(KERN_ERR "nfs4_get_root:" | ||
217 | " lookupfh encountered non-directory\n"); | ||
218 | return -ENOTDIR; | ||
219 | } | ||
220 | |||
221 | /* FIXME: Referrals are quite valid here too */ | ||
222 | if (fattr.valid & NFS_ATTR_FATTR_V4_REFERRAL) { | ||
223 | printk(KERN_ERR "nfs4_get_root:" | ||
224 | " lookupfh obtained referral\n"); | ||
225 | return -EREMOTE; | ||
226 | } | ||
227 | |||
228 | goto next_component; | ||
229 | |||
230 | path_walk_complete: | ||
231 | memcpy(&server->fsid, &fattr.fsid, sizeof(server->fsid)); | ||
232 | dprintk("<-- nfs4_path_walk() = 0\n"); | ||
233 | return 0; | ||
234 | } | 163 | } |
235 | 164 | ||
236 | /* | 165 | /* |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 11f82f03c5de..d8bd619e386c 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -244,9 +244,7 @@ extern struct dentry *nfs_get_root(struct super_block *, struct nfs_fh *); | |||
244 | #ifdef CONFIG_NFS_V4 | 244 | #ifdef CONFIG_NFS_V4 |
245 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); | 245 | extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); |
246 | 246 | ||
247 | extern int nfs4_path_walk(struct nfs_server *server, | 247 | extern int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh); |
248 | struct nfs_fh *mntfh, | ||
249 | const char *path); | ||
250 | #endif | 248 | #endif |
251 | 249 | ||
252 | /* read.c */ | 250 | /* read.c */ |