nfs4super.c (5eb005caf5383dd328199f0f2114cd7dad731d3d) | nfs4super.c (f2aedb713c284429987dc66c7aaf38decfc8da2a) |
---|---|
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2012 Bryan Schumaker <bjschuma@netapp.com> 4 */ 5#include <linux/init.h> 6#include <linux/module.h> | 1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Copyright (c) 2012 Bryan Schumaker <bjschuma@netapp.com> 4 */ 5#include <linux/init.h> 6#include <linux/module.h> |
7#include <linux/mount.h> |
|
7#include <linux/nfs4_mount.h> 8#include <linux/nfs_fs.h> 9#include "delegation.h" 10#include "internal.h" 11#include "nfs4_fs.h" 12#include "nfs4idmap.h" 13#include "dns_resolve.h" 14#include "pnfs.h" 15#include "nfs.h" 16 17#define NFSDBG_FACILITY NFSDBG_VFS 18 19static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc); 20static void nfs4_evict_inode(struct inode *inode); | 8#include <linux/nfs4_mount.h> 9#include <linux/nfs_fs.h> 10#include "delegation.h" 11#include "internal.h" 12#include "nfs4_fs.h" 13#include "nfs4idmap.h" 14#include "dns_resolve.h" 15#include "pnfs.h" 16#include "nfs.h" 17 18#define NFSDBG_FACILITY NFSDBG_VFS 19 20static int nfs4_write_inode(struct inode *inode, struct writeback_control *wbc); 21static void nfs4_evict_inode(struct inode *inode); |
21static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, 22 int flags, const char *dev_name, void *raw_data); | |
23 | 22 |
24struct file_system_type nfs4_referral_fs_type = { 25 .owner = THIS_MODULE, 26 .name = "nfs4", 27 .mount = nfs4_referral_mount, 28 .kill_sb = nfs_kill_super, 29 .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, 30}; 31 | |
32static const struct super_operations nfs4_sops = { 33 .alloc_inode = nfs_alloc_inode, 34 .free_inode = nfs_free_inode, 35 .write_inode = nfs4_write_inode, 36 .drop_inode = nfs_drop_inode, 37 .statfs = nfs_statfs, 38 .evict_inode = nfs4_evict_inode, 39 .umount_begin = nfs_umount_begin, 40 .show_options = nfs_show_options, 41 .show_devname = nfs_show_devname, 42 .show_path = nfs_show_path, 43 .show_stats = nfs_show_stats, | 23static const struct super_operations nfs4_sops = { 24 .alloc_inode = nfs_alloc_inode, 25 .free_inode = nfs_free_inode, 26 .write_inode = nfs4_write_inode, 27 .drop_inode = nfs_drop_inode, 28 .statfs = nfs_statfs, 29 .evict_inode = nfs4_evict_inode, 30 .umount_begin = nfs_umount_begin, 31 .show_options = nfs_show_options, 32 .show_devname = nfs_show_devname, 33 .show_path = nfs_show_path, 34 .show_stats = nfs_show_stats, |
44 .remount_fs = nfs_remount, | |
45}; 46 47struct nfs_subversion nfs_v4 = { 48 .owner = THIS_MODULE, 49 .nfs_fs = &nfs4_fs_type, 50 .rpc_vers = &nfs_version4, 51 .rpc_ops = &nfs_v4_clientops, 52 .sops = &nfs4_sops, --- 89 unchanged lines hidden (view full) --- 142 if (p->referral_count == 0) 143 list_del(&p->list); 144 else 145 p = NULL; 146 spin_unlock(&nfs_referral_count_list_lock); 147 kfree(p); 148} 149 | 35}; 36 37struct nfs_subversion nfs_v4 = { 38 .owner = THIS_MODULE, 39 .nfs_fs = &nfs4_fs_type, 40 .rpc_vers = &nfs_version4, 41 .rpc_ops = &nfs_v4_clientops, 42 .sops = &nfs4_sops, --- 89 unchanged lines hidden (view full) --- 132 if (p->referral_count == 0) 133 list_del(&p->list); 134 else 135 p = NULL; 136 spin_unlock(&nfs_referral_count_list_lock); 137 kfree(p); 138} 139 |
150static struct dentry *do_nfs4_mount(struct nfs_server *server, int flags, 151 struct nfs_mount_info *info, 152 const char *hostname, 153 const char *export_path) | 140static int do_nfs4_mount(struct nfs_server *server, 141 struct fs_context *fc, 142 const char *hostname, 143 const char *export_path) |
154{ | 144{ |
145 struct nfs_fs_context *root_ctx; 146 struct fs_context *root_fc; |
|
155 struct vfsmount *root_mnt; 156 struct dentry *dentry; | 147 struct vfsmount *root_mnt; 148 struct dentry *dentry; |
157 char *root_devname; 158 int err; | |
159 size_t len; | 149 size_t len; |
150 int ret; |
|
160 | 151 |
152 struct fs_parameter param = { 153 .key = "source", 154 .type = fs_value_is_string, 155 .dirfd = -1, 156 }; 157 |
|
161 if (IS_ERR(server)) | 158 if (IS_ERR(server)) |
162 return ERR_CAST(server); | 159 return PTR_ERR(server); |
163 | 160 |
164 len = strlen(hostname) + 5; 165 root_devname = kmalloc(len, GFP_KERNEL); 166 if (root_devname == NULL) { | 161 root_fc = vfs_dup_fs_context(fc); 162 if (IS_ERR(root_fc)) { |
167 nfs_free_server(server); | 163 nfs_free_server(server); |
168 return ERR_PTR(-ENOMEM); | 164 return PTR_ERR(root_fc); |
169 } | 165 } |
166 kfree(root_fc->source); 167 root_fc->source = NULL; |
|
170 | 168 |
169 root_ctx = nfs_fc2context(root_fc); 170 root_ctx->internal = true; 171 root_ctx->mount_info.server = server; 172 /* We leave export_path unset as it's not used to find the root. */ 173 174 len = strlen(hostname) + 5; 175 param.string = kmalloc(len, GFP_KERNEL); 176 if (param.string == NULL) { 177 put_fs_context(root_fc); 178 return -ENOMEM; 179 } 180 |
|
171 /* Does hostname needs to be enclosed in brackets? */ 172 if (strchr(hostname, ':')) | 181 /* Does hostname needs to be enclosed in brackets? */ 182 if (strchr(hostname, ':')) |
173 snprintf(root_devname, len, "[%s]:/", hostname); | 183 param.size = snprintf(param.string, len, "[%s]:/", hostname); |
174 else | 184 else |
175 snprintf(root_devname, len, "%s:/", hostname); 176 info->server = server; 177 root_mnt = vfs_kern_mount(&nfs_prepared_fs_type, flags, root_devname, info); 178 if (info->server) 179 nfs_free_server(info->server); 180 info->server = NULL; 181 kfree(root_devname); | 185 param.size = snprintf(param.string, len, "%s:/", hostname); 186 ret = vfs_parse_fs_param(root_fc, ¶m); 187 kfree(param.string); 188 if (ret < 0) { 189 put_fs_context(root_fc); 190 return ret; 191 } 192 root_mnt = fc_mount(root_fc); 193 put_fs_context(root_fc); |
182 183 if (IS_ERR(root_mnt)) | 194 195 if (IS_ERR(root_mnt)) |
184 return ERR_CAST(root_mnt); | 196 return PTR_ERR(root_mnt); |
185 | 197 |
186 err = nfs_referral_loop_protect(); 187 if (err) { | 198 ret = nfs_referral_loop_protect(); 199 if (ret) { |
188 mntput(root_mnt); | 200 mntput(root_mnt); |
189 return ERR_PTR(err); | 201 return ret; |
190 } 191 192 dentry = mount_subtree(root_mnt, export_path); 193 nfs_referral_loop_unprotect(); 194 | 202 } 203 204 dentry = mount_subtree(root_mnt, export_path); 205 nfs_referral_loop_unprotect(); 206 |
195 return dentry; | 207 if (IS_ERR(dentry)) 208 return PTR_ERR(dentry); 209 210 fc->root = dentry; 211 return 0; |
196} 197 | 212} 213 |
198struct dentry *nfs4_try_mount(int flags, const char *dev_name, 199 struct nfs_mount_info *mount_info) | 214int nfs4_try_get_tree(struct fs_context *fc) |
200{ | 215{ |
201 struct nfs_fs_context *ctx = mount_info->ctx; 202 struct dentry *res; | 216 struct nfs_fs_context *ctx = nfs_fc2context(fc); 217 int err; |
203 | 218 |
204 dfprintk(MOUNT, "--> nfs4_try_mount()\n"); | 219 dfprintk(MOUNT, "--> nfs4_try_get_tree()\n"); |
205 | 220 |
206 res = do_nfs4_mount(nfs4_create_server(mount_info), 207 flags, mount_info, 208 ctx->nfs_server.hostname, 209 ctx->nfs_server.export_path); 210 211 dfprintk(MOUNT, "<-- nfs4_try_mount() = %d%s\n", 212 PTR_ERR_OR_ZERO(res), 213 IS_ERR(res) ? " [error]" : ""); 214 return res; | 221 /* We create a mount for the server's root, walk to the requested 222 * location and then create another mount for that. 223 */ 224 err= do_nfs4_mount(nfs4_create_server(&ctx->mount_info), 225 fc, ctx->nfs_server.hostname, 226 ctx->nfs_server.export_path); 227 if (err) { 228 dfprintk(MOUNT, "<-- nfs4_try_get_tree() = %d [error]\n", err); 229 } else { 230 dfprintk(MOUNT, "<-- nfs4_try_get_tree() = 0\n"); 231 } 232 return err; |
215} 216 217/* 218 * Create an NFS4 server record on referral traversal 219 */ | 233} 234 235/* 236 * Create an NFS4 server record on referral traversal 237 */ |
220static struct dentry *nfs4_referral_mount(struct file_system_type *fs_type, 221 int flags, const char *dev_name, void *raw_data) | 238int nfs4_get_referral_tree(struct fs_context *fc) |
222{ | 239{ |
223 struct nfs_clone_mount *data = raw_data; 224 struct nfs_mount_info mount_info = { 225 .cloned = data, 226 .nfs_mod = &nfs_v4, 227 }; 228 struct dentry *res; | 240 struct nfs_fs_context *ctx = nfs_fc2context(fc); 241 int err; |
229 230 dprintk("--> nfs4_referral_mount()\n"); 231 | 242 243 dprintk("--> nfs4_referral_mount()\n"); 244 |
232 mount_info.mntfh = nfs_alloc_fhandle(); 233 if (!mount_info.mntfh) 234 return ERR_PTR(-ENOMEM); 235 236 res = do_nfs4_mount(nfs4_create_referral_server(mount_info.cloned, 237 mount_info.mntfh), 238 flags, &mount_info, data->hostname, data->mnt_path); 239 240 dprintk("<-- nfs4_referral_mount() = %d%s\n", 241 PTR_ERR_OR_ZERO(res), 242 IS_ERR(res) ? " [error]" : ""); 243 244 nfs_free_fhandle(mount_info.mntfh); 245 return res; | 245 /* create a new volume representation */ 246 err = do_nfs4_mount(nfs4_create_referral_server(&ctx->clone_data, ctx->mount_info.mntfh), 247 fc, ctx->nfs_server.hostname, 248 ctx->nfs_server.export_path); 249 if (err) { 250 dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = %d [error]\n", err); 251 } else { 252 dfprintk(MOUNT, "<-- nfs4_get_referral_tree() = 0\n"); 253 } 254 return err; |
246} 247 248 249static int __init init_nfs_v4(void) 250{ 251 int err; 252 253 err = nfs_dns_resolver_init(); --- 36 unchanged lines hidden --- | 255} 256 257 258static int __init init_nfs_v4(void) 259{ 260 int err; 261 262 err = nfs_dns_resolver_init(); --- 36 unchanged lines hidden --- |