diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/nfs4namespace.c | 84 |
1 files changed, 46 insertions, 38 deletions
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index b112857301f7..956cbbc2ae9f 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c | |||
@@ -110,6 +110,48 @@ static inline int valid_ipaddr4(const char *buf) | |||
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | 112 | ||
113 | static struct vfsmount *try_location(struct nfs_clone_mount *mountdata, | ||
114 | char *page, char *page2, | ||
115 | const struct nfs4_fs_location *location) | ||
116 | { | ||
117 | struct vfsmount *mnt = ERR_PTR(-ENOENT); | ||
118 | char *mnt_path; | ||
119 | unsigned int s = 0; | ||
120 | |||
121 | mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE); | ||
122 | if (IS_ERR(mnt_path)) | ||
123 | return mnt; | ||
124 | mountdata->mnt_path = mnt_path; | ||
125 | |||
126 | while (s < location->nservers) { | ||
127 | struct sockaddr_in addr = { | ||
128 | .sin_family = AF_INET, | ||
129 | .sin_port = htons(NFS_PORT), | ||
130 | }; | ||
131 | |||
132 | if (location->servers[s].len <= 0 || | ||
133 | valid_ipaddr4(location->servers[s].data) < 0) { | ||
134 | s++; | ||
135 | continue; | ||
136 | } | ||
137 | |||
138 | mountdata->hostname = location->servers[s].data; | ||
139 | addr.sin_addr.s_addr = in_aton(mountdata->hostname), | ||
140 | mountdata->addr = (struct sockaddr *)&addr; | ||
141 | mountdata->addrlen = sizeof(addr); | ||
142 | |||
143 | snprintf(page, PAGE_SIZE, "%s:%s", | ||
144 | mountdata->hostname, | ||
145 | mountdata->mnt_path); | ||
146 | |||
147 | mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, mountdata); | ||
148 | if (!IS_ERR(mnt)) | ||
149 | break; | ||
150 | s++; | ||
151 | } | ||
152 | return mnt; | ||
153 | } | ||
154 | |||
113 | /** | 155 | /** |
114 | * nfs_follow_referral - set up mountpoint when hitting a referral on moved error | 156 | * nfs_follow_referral - set up mountpoint when hitting a referral on moved error |
115 | * @mnt_parent - mountpoint of parent directory | 157 | * @mnt_parent - mountpoint of parent directory |
@@ -128,7 +170,6 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
128 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, | 170 | .authflavor = NFS_SB(mnt_parent->mnt_sb)->client->cl_auth->au_flavor, |
129 | }; | 171 | }; |
130 | char *page = NULL, *page2 = NULL; | 172 | char *page = NULL, *page2 = NULL; |
131 | unsigned int s; | ||
132 | int loc, error; | 173 | int loc, error; |
133 | 174 | ||
134 | if (locations == NULL || locations->nlocations <= 0) | 175 | if (locations == NULL || locations->nlocations <= 0) |
@@ -153,9 +194,8 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
153 | } | 194 | } |
154 | 195 | ||
155 | loc = 0; | 196 | loc = 0; |
156 | while (loc < locations->nlocations && IS_ERR(mnt)) { | 197 | while (loc < locations->nlocations) { |
157 | const struct nfs4_fs_location *location = &locations->locations[loc]; | 198 | const struct nfs4_fs_location *location = &locations->locations[loc]; |
158 | char *mnt_path; | ||
159 | 199 | ||
160 | if (location == NULL || location->nservers <= 0 || | 200 | if (location == NULL || location->nservers <= 0 || |
161 | location->rootpath.ncomponents == 0) { | 201 | location->rootpath.ncomponents == 0) { |
@@ -163,41 +203,9 @@ static struct vfsmount *nfs_follow_referral(const struct vfsmount *mnt_parent, | |||
163 | continue; | 203 | continue; |
164 | } | 204 | } |
165 | 205 | ||
166 | mnt_path = nfs4_pathname_string(&location->rootpath, page2, PAGE_SIZE); | 206 | mnt = try_location(&mountdata, page, page2, location); |
167 | if (IS_ERR(mnt_path)) { | 207 | if (!IS_ERR(mnt)) |
168 | loc++; | 208 | break; |
169 | continue; | ||
170 | } | ||
171 | mountdata.mnt_path = mnt_path; | ||
172 | |||
173 | s = 0; | ||
174 | while (s < location->nservers) { | ||
175 | struct sockaddr_in addr = { | ||
176 | .sin_family = AF_INET, | ||
177 | .sin_port = htons(NFS_PORT), | ||
178 | }; | ||
179 | |||
180 | if (location->servers[s].len <= 0 || | ||
181 | valid_ipaddr4(location->servers[s].data) < 0) { | ||
182 | s++; | ||
183 | continue; | ||
184 | } | ||
185 | |||
186 | mountdata.hostname = location->servers[s].data; | ||
187 | addr.sin_addr.s_addr = in_aton(mountdata.hostname), | ||
188 | mountdata.addr = (struct sockaddr *)&addr; | ||
189 | mountdata.addrlen = sizeof(addr); | ||
190 | |||
191 | snprintf(page, PAGE_SIZE, "%s:%s", | ||
192 | mountdata.hostname, | ||
193 | mountdata.mnt_path); | ||
194 | |||
195 | mnt = vfs_kern_mount(&nfs4_referral_fs_type, 0, page, &mountdata); | ||
196 | if (!IS_ERR(mnt)) { | ||
197 | break; | ||
198 | } | ||
199 | s++; | ||
200 | } | ||
201 | loc++; | 209 | loc++; |
202 | } | 210 | } |
203 | 211 | ||