aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/client.c4
-rw-r--r--fs/nfs/getroot.c115
-rw-r--r--fs/nfs/internal.h4
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/* 125int 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 */
132int 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
171next_component: 158 memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid));
172 dprintk("Next: %s\n", path); 159out:
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
186eat_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
230path_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
245extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *); 245extern struct dentry *nfs4_get_root(struct super_block *, struct nfs_fh *);
246 246
247extern int nfs4_path_walk(struct nfs_server *server, 247extern 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 */