aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-04-16 16:22:46 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-05-14 15:09:21 -0400
commit815409d22df870ea0b0d86f2a3bf33c35bcef55c (patch)
tree99fa8d5ac56d3f14fa1313739d3f9b65176f4e8f /fs
parent2d36bfde8565b315e624302d12da5a7c9d195522 (diff)
NFSv4: Eliminate nfs4_path_walk()
All we really want is the ability to retrieve the root file handle. We no longer need the ability to walk down the path, since that is now done in nfs_follow_remote_path(). Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs')
-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 */