Commit 5680d48be88d12cd987e5579a6072a4ca34ca6ea
Committed by
Trond Myklebust
1 parent
9eaa67c6a5
Exists in
master
and in
7 other branches
NFS: Clean-up: Define macros for maximum host and export path name lengths
Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Showing 2 changed files with 3 additions and 3 deletions Inline Diff
fs/nfs/super.c
1 | /* | 1 | /* |
2 | * linux/fs/nfs/super.c | 2 | * linux/fs/nfs/super.c |
3 | * | 3 | * |
4 | * Copyright (C) 1992 Rick Sladkey | 4 | * Copyright (C) 1992 Rick Sladkey |
5 | * | 5 | * |
6 | * nfs superblock handling functions | 6 | * nfs superblock handling functions |
7 | * | 7 | * |
8 | * Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some | 8 | * Modularised by Alan Cox <Alan.Cox@linux.org>, while hacking some |
9 | * experimental NFS changes. Modularisation taken straight from SYS5 fs. | 9 | * experimental NFS changes. Modularisation taken straight from SYS5 fs. |
10 | * | 10 | * |
11 | * Change to nfs_read_super() to permit NFS mounts to multi-homed hosts. | 11 | * Change to nfs_read_super() to permit NFS mounts to multi-homed hosts. |
12 | * J.S.Peatfield@damtp.cam.ac.uk | 12 | * J.S.Peatfield@damtp.cam.ac.uk |
13 | * | 13 | * |
14 | * Split from inode.c by David Howells <dhowells@redhat.com> | 14 | * Split from inode.c by David Howells <dhowells@redhat.com> |
15 | * | 15 | * |
16 | * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a | 16 | * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a |
17 | * particular server are held in the same superblock | 17 | * particular server are held in the same superblock |
18 | * - NFS superblocks can have several effective roots to the dentry tree | 18 | * - NFS superblocks can have several effective roots to the dentry tree |
19 | * - directory type roots are spliced into the tree when a path from one root reaches the root | 19 | * - directory type roots are spliced into the tree when a path from one root reaches the root |
20 | * of another (see nfs_lookup()) | 20 | * of another (see nfs_lookup()) |
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | 25 | ||
26 | #include <linux/time.h> | 26 | #include <linux/time.h> |
27 | #include <linux/kernel.h> | 27 | #include <linux/kernel.h> |
28 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
29 | #include <linux/string.h> | 29 | #include <linux/string.h> |
30 | #include <linux/stat.h> | 30 | #include <linux/stat.h> |
31 | #include <linux/errno.h> | 31 | #include <linux/errno.h> |
32 | #include <linux/unistd.h> | 32 | #include <linux/unistd.h> |
33 | #include <linux/sunrpc/clnt.h> | 33 | #include <linux/sunrpc/clnt.h> |
34 | #include <linux/sunrpc/stats.h> | 34 | #include <linux/sunrpc/stats.h> |
35 | #include <linux/sunrpc/metrics.h> | 35 | #include <linux/sunrpc/metrics.h> |
36 | #include <linux/nfs_fs.h> | 36 | #include <linux/nfs_fs.h> |
37 | #include <linux/nfs_mount.h> | 37 | #include <linux/nfs_mount.h> |
38 | #include <linux/nfs4_mount.h> | 38 | #include <linux/nfs4_mount.h> |
39 | #include <linux/lockd/bind.h> | 39 | #include <linux/lockd/bind.h> |
40 | #include <linux/smp_lock.h> | 40 | #include <linux/smp_lock.h> |
41 | #include <linux/seq_file.h> | 41 | #include <linux/seq_file.h> |
42 | #include <linux/mount.h> | 42 | #include <linux/mount.h> |
43 | #include <linux/nfs_idmap.h> | 43 | #include <linux/nfs_idmap.h> |
44 | #include <linux/vfs.h> | 44 | #include <linux/vfs.h> |
45 | #include <linux/inet.h> | 45 | #include <linux/inet.h> |
46 | #include <linux/nfs_xdr.h> | 46 | #include <linux/nfs_xdr.h> |
47 | #include <linux/magic.h> | 47 | #include <linux/magic.h> |
48 | 48 | ||
49 | #include <asm/system.h> | 49 | #include <asm/system.h> |
50 | #include <asm/uaccess.h> | 50 | #include <asm/uaccess.h> |
51 | 51 | ||
52 | #include "nfs4_fs.h" | 52 | #include "nfs4_fs.h" |
53 | #include "callback.h" | 53 | #include "callback.h" |
54 | #include "delegation.h" | 54 | #include "delegation.h" |
55 | #include "iostat.h" | 55 | #include "iostat.h" |
56 | #include "internal.h" | 56 | #include "internal.h" |
57 | 57 | ||
58 | #define NFSDBG_FACILITY NFSDBG_VFS | 58 | #define NFSDBG_FACILITY NFSDBG_VFS |
59 | 59 | ||
60 | static void nfs_umount_begin(struct vfsmount *, int); | 60 | static void nfs_umount_begin(struct vfsmount *, int); |
61 | static int nfs_statfs(struct dentry *, struct kstatfs *); | 61 | static int nfs_statfs(struct dentry *, struct kstatfs *); |
62 | static int nfs_show_options(struct seq_file *, struct vfsmount *); | 62 | static int nfs_show_options(struct seq_file *, struct vfsmount *); |
63 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); | 63 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); |
64 | static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); | 64 | static int nfs_get_sb(struct file_system_type *, int, const char *, void *, struct vfsmount *); |
65 | static int nfs_xdev_get_sb(struct file_system_type *fs_type, | 65 | static int nfs_xdev_get_sb(struct file_system_type *fs_type, |
66 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 66 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); |
67 | static void nfs_kill_super(struct super_block *); | 67 | static void nfs_kill_super(struct super_block *); |
68 | 68 | ||
69 | static struct file_system_type nfs_fs_type = { | 69 | static struct file_system_type nfs_fs_type = { |
70 | .owner = THIS_MODULE, | 70 | .owner = THIS_MODULE, |
71 | .name = "nfs", | 71 | .name = "nfs", |
72 | .get_sb = nfs_get_sb, | 72 | .get_sb = nfs_get_sb, |
73 | .kill_sb = nfs_kill_super, | 73 | .kill_sb = nfs_kill_super, |
74 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 74 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
75 | }; | 75 | }; |
76 | 76 | ||
77 | struct file_system_type nfs_xdev_fs_type = { | 77 | struct file_system_type nfs_xdev_fs_type = { |
78 | .owner = THIS_MODULE, | 78 | .owner = THIS_MODULE, |
79 | .name = "nfs", | 79 | .name = "nfs", |
80 | .get_sb = nfs_xdev_get_sb, | 80 | .get_sb = nfs_xdev_get_sb, |
81 | .kill_sb = nfs_kill_super, | 81 | .kill_sb = nfs_kill_super, |
82 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 82 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static const struct super_operations nfs_sops = { | 85 | static const struct super_operations nfs_sops = { |
86 | .alloc_inode = nfs_alloc_inode, | 86 | .alloc_inode = nfs_alloc_inode, |
87 | .destroy_inode = nfs_destroy_inode, | 87 | .destroy_inode = nfs_destroy_inode, |
88 | .write_inode = nfs_write_inode, | 88 | .write_inode = nfs_write_inode, |
89 | .statfs = nfs_statfs, | 89 | .statfs = nfs_statfs, |
90 | .clear_inode = nfs_clear_inode, | 90 | .clear_inode = nfs_clear_inode, |
91 | .umount_begin = nfs_umount_begin, | 91 | .umount_begin = nfs_umount_begin, |
92 | .show_options = nfs_show_options, | 92 | .show_options = nfs_show_options, |
93 | .show_stats = nfs_show_stats, | 93 | .show_stats = nfs_show_stats, |
94 | }; | 94 | }; |
95 | 95 | ||
96 | #ifdef CONFIG_NFS_V4 | 96 | #ifdef CONFIG_NFS_V4 |
97 | static int nfs4_get_sb(struct file_system_type *fs_type, | 97 | static int nfs4_get_sb(struct file_system_type *fs_type, |
98 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 98 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); |
99 | static int nfs4_xdev_get_sb(struct file_system_type *fs_type, | 99 | static int nfs4_xdev_get_sb(struct file_system_type *fs_type, |
100 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 100 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); |
101 | static int nfs4_referral_get_sb(struct file_system_type *fs_type, | 101 | static int nfs4_referral_get_sb(struct file_system_type *fs_type, |
102 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); | 102 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt); |
103 | static void nfs4_kill_super(struct super_block *sb); | 103 | static void nfs4_kill_super(struct super_block *sb); |
104 | 104 | ||
105 | static struct file_system_type nfs4_fs_type = { | 105 | static struct file_system_type nfs4_fs_type = { |
106 | .owner = THIS_MODULE, | 106 | .owner = THIS_MODULE, |
107 | .name = "nfs4", | 107 | .name = "nfs4", |
108 | .get_sb = nfs4_get_sb, | 108 | .get_sb = nfs4_get_sb, |
109 | .kill_sb = nfs4_kill_super, | 109 | .kill_sb = nfs4_kill_super, |
110 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 110 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
111 | }; | 111 | }; |
112 | 112 | ||
113 | struct file_system_type nfs4_xdev_fs_type = { | 113 | struct file_system_type nfs4_xdev_fs_type = { |
114 | .owner = THIS_MODULE, | 114 | .owner = THIS_MODULE, |
115 | .name = "nfs4", | 115 | .name = "nfs4", |
116 | .get_sb = nfs4_xdev_get_sb, | 116 | .get_sb = nfs4_xdev_get_sb, |
117 | .kill_sb = nfs4_kill_super, | 117 | .kill_sb = nfs4_kill_super, |
118 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 118 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
119 | }; | 119 | }; |
120 | 120 | ||
121 | struct file_system_type nfs4_referral_fs_type = { | 121 | struct file_system_type nfs4_referral_fs_type = { |
122 | .owner = THIS_MODULE, | 122 | .owner = THIS_MODULE, |
123 | .name = "nfs4", | 123 | .name = "nfs4", |
124 | .get_sb = nfs4_referral_get_sb, | 124 | .get_sb = nfs4_referral_get_sb, |
125 | .kill_sb = nfs4_kill_super, | 125 | .kill_sb = nfs4_kill_super, |
126 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 126 | .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
127 | }; | 127 | }; |
128 | 128 | ||
129 | static const struct super_operations nfs4_sops = { | 129 | static const struct super_operations nfs4_sops = { |
130 | .alloc_inode = nfs_alloc_inode, | 130 | .alloc_inode = nfs_alloc_inode, |
131 | .destroy_inode = nfs_destroy_inode, | 131 | .destroy_inode = nfs_destroy_inode, |
132 | .write_inode = nfs_write_inode, | 132 | .write_inode = nfs_write_inode, |
133 | .statfs = nfs_statfs, | 133 | .statfs = nfs_statfs, |
134 | .clear_inode = nfs4_clear_inode, | 134 | .clear_inode = nfs4_clear_inode, |
135 | .umount_begin = nfs_umount_begin, | 135 | .umount_begin = nfs_umount_begin, |
136 | .show_options = nfs_show_options, | 136 | .show_options = nfs_show_options, |
137 | .show_stats = nfs_show_stats, | 137 | .show_stats = nfs_show_stats, |
138 | }; | 138 | }; |
139 | #endif | 139 | #endif |
140 | 140 | ||
141 | static struct shrinker *acl_shrinker; | 141 | static struct shrinker *acl_shrinker; |
142 | 142 | ||
143 | /* | 143 | /* |
144 | * Register the NFS filesystems | 144 | * Register the NFS filesystems |
145 | */ | 145 | */ |
146 | int __init register_nfs_fs(void) | 146 | int __init register_nfs_fs(void) |
147 | { | 147 | { |
148 | int ret; | 148 | int ret; |
149 | 149 | ||
150 | ret = register_filesystem(&nfs_fs_type); | 150 | ret = register_filesystem(&nfs_fs_type); |
151 | if (ret < 0) | 151 | if (ret < 0) |
152 | goto error_0; | 152 | goto error_0; |
153 | 153 | ||
154 | ret = nfs_register_sysctl(); | 154 | ret = nfs_register_sysctl(); |
155 | if (ret < 0) | 155 | if (ret < 0) |
156 | goto error_1; | 156 | goto error_1; |
157 | #ifdef CONFIG_NFS_V4 | 157 | #ifdef CONFIG_NFS_V4 |
158 | ret = register_filesystem(&nfs4_fs_type); | 158 | ret = register_filesystem(&nfs4_fs_type); |
159 | if (ret < 0) | 159 | if (ret < 0) |
160 | goto error_2; | 160 | goto error_2; |
161 | #endif | 161 | #endif |
162 | acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker); | 162 | acl_shrinker = set_shrinker(DEFAULT_SEEKS, nfs_access_cache_shrinker); |
163 | return 0; | 163 | return 0; |
164 | 164 | ||
165 | #ifdef CONFIG_NFS_V4 | 165 | #ifdef CONFIG_NFS_V4 |
166 | error_2: | 166 | error_2: |
167 | nfs_unregister_sysctl(); | 167 | nfs_unregister_sysctl(); |
168 | #endif | 168 | #endif |
169 | error_1: | 169 | error_1: |
170 | unregister_filesystem(&nfs_fs_type); | 170 | unregister_filesystem(&nfs_fs_type); |
171 | error_0: | 171 | error_0: |
172 | return ret; | 172 | return ret; |
173 | } | 173 | } |
174 | 174 | ||
175 | /* | 175 | /* |
176 | * Unregister the NFS filesystems | 176 | * Unregister the NFS filesystems |
177 | */ | 177 | */ |
178 | void __exit unregister_nfs_fs(void) | 178 | void __exit unregister_nfs_fs(void) |
179 | { | 179 | { |
180 | if (acl_shrinker != NULL) | 180 | if (acl_shrinker != NULL) |
181 | remove_shrinker(acl_shrinker); | 181 | remove_shrinker(acl_shrinker); |
182 | #ifdef CONFIG_NFS_V4 | 182 | #ifdef CONFIG_NFS_V4 |
183 | unregister_filesystem(&nfs4_fs_type); | 183 | unregister_filesystem(&nfs4_fs_type); |
184 | nfs_unregister_sysctl(); | 184 | nfs_unregister_sysctl(); |
185 | #endif | 185 | #endif |
186 | unregister_filesystem(&nfs_fs_type); | 186 | unregister_filesystem(&nfs_fs_type); |
187 | } | 187 | } |
188 | 188 | ||
189 | /* | 189 | /* |
190 | * Deliver file system statistics to userspace | 190 | * Deliver file system statistics to userspace |
191 | */ | 191 | */ |
192 | static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) | 192 | static int nfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
193 | { | 193 | { |
194 | struct nfs_server *server = NFS_SB(dentry->d_sb); | 194 | struct nfs_server *server = NFS_SB(dentry->d_sb); |
195 | unsigned char blockbits; | 195 | unsigned char blockbits; |
196 | unsigned long blockres; | 196 | unsigned long blockres; |
197 | struct nfs_fh *fh = NFS_FH(dentry->d_inode); | 197 | struct nfs_fh *fh = NFS_FH(dentry->d_inode); |
198 | struct nfs_fattr fattr; | 198 | struct nfs_fattr fattr; |
199 | struct nfs_fsstat res = { | 199 | struct nfs_fsstat res = { |
200 | .fattr = &fattr, | 200 | .fattr = &fattr, |
201 | }; | 201 | }; |
202 | int error; | 202 | int error; |
203 | 203 | ||
204 | lock_kernel(); | 204 | lock_kernel(); |
205 | 205 | ||
206 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); | 206 | error = server->nfs_client->rpc_ops->statfs(server, fh, &res); |
207 | if (error < 0) | 207 | if (error < 0) |
208 | goto out_err; | 208 | goto out_err; |
209 | buf->f_type = NFS_SUPER_MAGIC; | 209 | buf->f_type = NFS_SUPER_MAGIC; |
210 | 210 | ||
211 | /* | 211 | /* |
212 | * Current versions of glibc do not correctly handle the | 212 | * Current versions of glibc do not correctly handle the |
213 | * case where f_frsize != f_bsize. Eventually we want to | 213 | * case where f_frsize != f_bsize. Eventually we want to |
214 | * report the value of wtmult in this field. | 214 | * report the value of wtmult in this field. |
215 | */ | 215 | */ |
216 | buf->f_frsize = dentry->d_sb->s_blocksize; | 216 | buf->f_frsize = dentry->d_sb->s_blocksize; |
217 | 217 | ||
218 | /* | 218 | /* |
219 | * On most *nix systems, f_blocks, f_bfree, and f_bavail | 219 | * On most *nix systems, f_blocks, f_bfree, and f_bavail |
220 | * are reported in units of f_frsize. Linux hasn't had | 220 | * are reported in units of f_frsize. Linux hasn't had |
221 | * an f_frsize field in its statfs struct until recently, | 221 | * an f_frsize field in its statfs struct until recently, |
222 | * thus historically Linux's sys_statfs reports these | 222 | * thus historically Linux's sys_statfs reports these |
223 | * fields in units of f_bsize. | 223 | * fields in units of f_bsize. |
224 | */ | 224 | */ |
225 | buf->f_bsize = dentry->d_sb->s_blocksize; | 225 | buf->f_bsize = dentry->d_sb->s_blocksize; |
226 | blockbits = dentry->d_sb->s_blocksize_bits; | 226 | blockbits = dentry->d_sb->s_blocksize_bits; |
227 | blockres = (1 << blockbits) - 1; | 227 | blockres = (1 << blockbits) - 1; |
228 | buf->f_blocks = (res.tbytes + blockres) >> blockbits; | 228 | buf->f_blocks = (res.tbytes + blockres) >> blockbits; |
229 | buf->f_bfree = (res.fbytes + blockres) >> blockbits; | 229 | buf->f_bfree = (res.fbytes + blockres) >> blockbits; |
230 | buf->f_bavail = (res.abytes + blockres) >> blockbits; | 230 | buf->f_bavail = (res.abytes + blockres) >> blockbits; |
231 | 231 | ||
232 | buf->f_files = res.tfiles; | 232 | buf->f_files = res.tfiles; |
233 | buf->f_ffree = res.afiles; | 233 | buf->f_ffree = res.afiles; |
234 | 234 | ||
235 | buf->f_namelen = server->namelen; | 235 | buf->f_namelen = server->namelen; |
236 | 236 | ||
237 | unlock_kernel(); | 237 | unlock_kernel(); |
238 | return 0; | 238 | return 0; |
239 | 239 | ||
240 | out_err: | 240 | out_err: |
241 | dprintk("%s: statfs error = %d\n", __FUNCTION__, -error); | 241 | dprintk("%s: statfs error = %d\n", __FUNCTION__, -error); |
242 | unlock_kernel(); | 242 | unlock_kernel(); |
243 | return error; | 243 | return error; |
244 | } | 244 | } |
245 | 245 | ||
246 | /* | 246 | /* |
247 | * Map the security flavour number to a name | 247 | * Map the security flavour number to a name |
248 | */ | 248 | */ |
249 | static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) | 249 | static const char *nfs_pseudoflavour_to_name(rpc_authflavor_t flavour) |
250 | { | 250 | { |
251 | static const struct { | 251 | static const struct { |
252 | rpc_authflavor_t flavour; | 252 | rpc_authflavor_t flavour; |
253 | const char *str; | 253 | const char *str; |
254 | } sec_flavours[] = { | 254 | } sec_flavours[] = { |
255 | { RPC_AUTH_NULL, "null" }, | 255 | { RPC_AUTH_NULL, "null" }, |
256 | { RPC_AUTH_UNIX, "sys" }, | 256 | { RPC_AUTH_UNIX, "sys" }, |
257 | { RPC_AUTH_GSS_KRB5, "krb5" }, | 257 | { RPC_AUTH_GSS_KRB5, "krb5" }, |
258 | { RPC_AUTH_GSS_KRB5I, "krb5i" }, | 258 | { RPC_AUTH_GSS_KRB5I, "krb5i" }, |
259 | { RPC_AUTH_GSS_KRB5P, "krb5p" }, | 259 | { RPC_AUTH_GSS_KRB5P, "krb5p" }, |
260 | { RPC_AUTH_GSS_LKEY, "lkey" }, | 260 | { RPC_AUTH_GSS_LKEY, "lkey" }, |
261 | { RPC_AUTH_GSS_LKEYI, "lkeyi" }, | 261 | { RPC_AUTH_GSS_LKEYI, "lkeyi" }, |
262 | { RPC_AUTH_GSS_LKEYP, "lkeyp" }, | 262 | { RPC_AUTH_GSS_LKEYP, "lkeyp" }, |
263 | { RPC_AUTH_GSS_SPKM, "spkm" }, | 263 | { RPC_AUTH_GSS_SPKM, "spkm" }, |
264 | { RPC_AUTH_GSS_SPKMI, "spkmi" }, | 264 | { RPC_AUTH_GSS_SPKMI, "spkmi" }, |
265 | { RPC_AUTH_GSS_SPKMP, "spkmp" }, | 265 | { RPC_AUTH_GSS_SPKMP, "spkmp" }, |
266 | { -1, "unknown" } | 266 | { -1, "unknown" } |
267 | }; | 267 | }; |
268 | int i; | 268 | int i; |
269 | 269 | ||
270 | for (i=0; sec_flavours[i].flavour != -1; i++) { | 270 | for (i=0; sec_flavours[i].flavour != -1; i++) { |
271 | if (sec_flavours[i].flavour == flavour) | 271 | if (sec_flavours[i].flavour == flavour) |
272 | break; | 272 | break; |
273 | } | 273 | } |
274 | return sec_flavours[i].str; | 274 | return sec_flavours[i].str; |
275 | } | 275 | } |
276 | 276 | ||
277 | /* | 277 | /* |
278 | * Describe the mount options in force on this server representation | 278 | * Describe the mount options in force on this server representation |
279 | */ | 279 | */ |
280 | static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults) | 280 | static void nfs_show_mount_options(struct seq_file *m, struct nfs_server *nfss, int showdefaults) |
281 | { | 281 | { |
282 | static const struct proc_nfs_info { | 282 | static const struct proc_nfs_info { |
283 | int flag; | 283 | int flag; |
284 | const char *str; | 284 | const char *str; |
285 | const char *nostr; | 285 | const char *nostr; |
286 | } nfs_info[] = { | 286 | } nfs_info[] = { |
287 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, | 287 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, |
288 | { NFS_MOUNT_INTR, ",intr", "" }, | 288 | { NFS_MOUNT_INTR, ",intr", "" }, |
289 | { NFS_MOUNT_NOCTO, ",nocto", "" }, | 289 | { NFS_MOUNT_NOCTO, ",nocto", "" }, |
290 | { NFS_MOUNT_NOAC, ",noac", "" }, | 290 | { NFS_MOUNT_NOAC, ",noac", "" }, |
291 | { NFS_MOUNT_NONLM, ",nolock", "" }, | 291 | { NFS_MOUNT_NONLM, ",nolock", "" }, |
292 | { NFS_MOUNT_NOACL, ",noacl", "" }, | 292 | { NFS_MOUNT_NOACL, ",noacl", "" }, |
293 | { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" }, | 293 | { NFS_MOUNT_NORDIRPLUS, ",nordirplus", "" }, |
294 | { 0, NULL, NULL } | 294 | { 0, NULL, NULL } |
295 | }; | 295 | }; |
296 | const struct proc_nfs_info *nfs_infop; | 296 | const struct proc_nfs_info *nfs_infop; |
297 | struct nfs_client *clp = nfss->nfs_client; | 297 | struct nfs_client *clp = nfss->nfs_client; |
298 | char buf[12]; | 298 | char buf[12]; |
299 | const char *proto; | 299 | const char *proto; |
300 | 300 | ||
301 | seq_printf(m, ",vers=%d", clp->rpc_ops->version); | 301 | seq_printf(m, ",vers=%d", clp->rpc_ops->version); |
302 | seq_printf(m, ",rsize=%d", nfss->rsize); | 302 | seq_printf(m, ",rsize=%d", nfss->rsize); |
303 | seq_printf(m, ",wsize=%d", nfss->wsize); | 303 | seq_printf(m, ",wsize=%d", nfss->wsize); |
304 | if (nfss->acregmin != 3*HZ || showdefaults) | 304 | if (nfss->acregmin != 3*HZ || showdefaults) |
305 | seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ); | 305 | seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ); |
306 | if (nfss->acregmax != 60*HZ || showdefaults) | 306 | if (nfss->acregmax != 60*HZ || showdefaults) |
307 | seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ); | 307 | seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ); |
308 | if (nfss->acdirmin != 30*HZ || showdefaults) | 308 | if (nfss->acdirmin != 30*HZ || showdefaults) |
309 | seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ); | 309 | seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ); |
310 | if (nfss->acdirmax != 60*HZ || showdefaults) | 310 | if (nfss->acdirmax != 60*HZ || showdefaults) |
311 | seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ); | 311 | seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ); |
312 | for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) { | 312 | for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) { |
313 | if (nfss->flags & nfs_infop->flag) | 313 | if (nfss->flags & nfs_infop->flag) |
314 | seq_puts(m, nfs_infop->str); | 314 | seq_puts(m, nfs_infop->str); |
315 | else | 315 | else |
316 | seq_puts(m, nfs_infop->nostr); | 316 | seq_puts(m, nfs_infop->nostr); |
317 | } | 317 | } |
318 | switch (nfss->client->cl_xprt->prot) { | 318 | switch (nfss->client->cl_xprt->prot) { |
319 | case IPPROTO_TCP: | 319 | case IPPROTO_TCP: |
320 | proto = "tcp"; | 320 | proto = "tcp"; |
321 | break; | 321 | break; |
322 | case IPPROTO_UDP: | 322 | case IPPROTO_UDP: |
323 | proto = "udp"; | 323 | proto = "udp"; |
324 | break; | 324 | break; |
325 | default: | 325 | default: |
326 | snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot); | 326 | snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot); |
327 | proto = buf; | 327 | proto = buf; |
328 | } | 328 | } |
329 | seq_printf(m, ",proto=%s", proto); | 329 | seq_printf(m, ",proto=%s", proto); |
330 | seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); | 330 | seq_printf(m, ",timeo=%lu", 10U * clp->retrans_timeo / HZ); |
331 | seq_printf(m, ",retrans=%u", clp->retrans_count); | 331 | seq_printf(m, ",retrans=%u", clp->retrans_count); |
332 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); | 332 | seq_printf(m, ",sec=%s", nfs_pseudoflavour_to_name(nfss->client->cl_auth->au_flavor)); |
333 | } | 333 | } |
334 | 334 | ||
335 | /* | 335 | /* |
336 | * Describe the mount options on this VFS mountpoint | 336 | * Describe the mount options on this VFS mountpoint |
337 | */ | 337 | */ |
338 | static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | 338 | static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) |
339 | { | 339 | { |
340 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); | 340 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); |
341 | 341 | ||
342 | nfs_show_mount_options(m, nfss, 0); | 342 | nfs_show_mount_options(m, nfss, 0); |
343 | 343 | ||
344 | seq_puts(m, ",addr="); | 344 | seq_puts(m, ",addr="); |
345 | seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\"); | 345 | seq_escape(m, nfss->nfs_client->cl_hostname, " \t\n\\"); |
346 | 346 | ||
347 | return 0; | 347 | return 0; |
348 | } | 348 | } |
349 | 349 | ||
350 | /* | 350 | /* |
351 | * Present statistical information for this VFS mountpoint | 351 | * Present statistical information for this VFS mountpoint |
352 | */ | 352 | */ |
353 | static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) | 353 | static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) |
354 | { | 354 | { |
355 | int i, cpu; | 355 | int i, cpu; |
356 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); | 356 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); |
357 | struct rpc_auth *auth = nfss->client->cl_auth; | 357 | struct rpc_auth *auth = nfss->client->cl_auth; |
358 | struct nfs_iostats totals = { }; | 358 | struct nfs_iostats totals = { }; |
359 | 359 | ||
360 | seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS); | 360 | seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS); |
361 | 361 | ||
362 | /* | 362 | /* |
363 | * Display all mount option settings | 363 | * Display all mount option settings |
364 | */ | 364 | */ |
365 | seq_printf(m, "\n\topts:\t"); | 365 | seq_printf(m, "\n\topts:\t"); |
366 | seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw"); | 366 | seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw"); |
367 | seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : ""); | 367 | seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : ""); |
368 | seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : ""); | 368 | seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : ""); |
369 | seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : ""); | 369 | seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : ""); |
370 | nfs_show_mount_options(m, nfss, 1); | 370 | nfs_show_mount_options(m, nfss, 1); |
371 | 371 | ||
372 | seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ); | 372 | seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ); |
373 | 373 | ||
374 | seq_printf(m, "\n\tcaps:\t"); | 374 | seq_printf(m, "\n\tcaps:\t"); |
375 | seq_printf(m, "caps=0x%x", nfss->caps); | 375 | seq_printf(m, "caps=0x%x", nfss->caps); |
376 | seq_printf(m, ",wtmult=%d", nfss->wtmult); | 376 | seq_printf(m, ",wtmult=%d", nfss->wtmult); |
377 | seq_printf(m, ",dtsize=%d", nfss->dtsize); | 377 | seq_printf(m, ",dtsize=%d", nfss->dtsize); |
378 | seq_printf(m, ",bsize=%d", nfss->bsize); | 378 | seq_printf(m, ",bsize=%d", nfss->bsize); |
379 | seq_printf(m, ",namelen=%d", nfss->namelen); | 379 | seq_printf(m, ",namelen=%d", nfss->namelen); |
380 | 380 | ||
381 | #ifdef CONFIG_NFS_V4 | 381 | #ifdef CONFIG_NFS_V4 |
382 | if (nfss->nfs_client->cl_nfsversion == 4) { | 382 | if (nfss->nfs_client->cl_nfsversion == 4) { |
383 | seq_printf(m, "\n\tnfsv4:\t"); | 383 | seq_printf(m, "\n\tnfsv4:\t"); |
384 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); | 384 | seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); |
385 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); | 385 | seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); |
386 | seq_printf(m, ",acl=0x%x", nfss->acl_bitmask); | 386 | seq_printf(m, ",acl=0x%x", nfss->acl_bitmask); |
387 | } | 387 | } |
388 | #endif | 388 | #endif |
389 | 389 | ||
390 | /* | 390 | /* |
391 | * Display security flavor in effect for this mount | 391 | * Display security flavor in effect for this mount |
392 | */ | 392 | */ |
393 | seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor); | 393 | seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor); |
394 | if (auth->au_flavor) | 394 | if (auth->au_flavor) |
395 | seq_printf(m, ",pseudoflavor=%d", auth->au_flavor); | 395 | seq_printf(m, ",pseudoflavor=%d", auth->au_flavor); |
396 | 396 | ||
397 | /* | 397 | /* |
398 | * Display superblock I/O counters | 398 | * Display superblock I/O counters |
399 | */ | 399 | */ |
400 | for_each_possible_cpu(cpu) { | 400 | for_each_possible_cpu(cpu) { |
401 | struct nfs_iostats *stats; | 401 | struct nfs_iostats *stats; |
402 | 402 | ||
403 | preempt_disable(); | 403 | preempt_disable(); |
404 | stats = per_cpu_ptr(nfss->io_stats, cpu); | 404 | stats = per_cpu_ptr(nfss->io_stats, cpu); |
405 | 405 | ||
406 | for (i = 0; i < __NFSIOS_COUNTSMAX; i++) | 406 | for (i = 0; i < __NFSIOS_COUNTSMAX; i++) |
407 | totals.events[i] += stats->events[i]; | 407 | totals.events[i] += stats->events[i]; |
408 | for (i = 0; i < __NFSIOS_BYTESMAX; i++) | 408 | for (i = 0; i < __NFSIOS_BYTESMAX; i++) |
409 | totals.bytes[i] += stats->bytes[i]; | 409 | totals.bytes[i] += stats->bytes[i]; |
410 | 410 | ||
411 | preempt_enable(); | 411 | preempt_enable(); |
412 | } | 412 | } |
413 | 413 | ||
414 | seq_printf(m, "\n\tevents:\t"); | 414 | seq_printf(m, "\n\tevents:\t"); |
415 | for (i = 0; i < __NFSIOS_COUNTSMAX; i++) | 415 | for (i = 0; i < __NFSIOS_COUNTSMAX; i++) |
416 | seq_printf(m, "%lu ", totals.events[i]); | 416 | seq_printf(m, "%lu ", totals.events[i]); |
417 | seq_printf(m, "\n\tbytes:\t"); | 417 | seq_printf(m, "\n\tbytes:\t"); |
418 | for (i = 0; i < __NFSIOS_BYTESMAX; i++) | 418 | for (i = 0; i < __NFSIOS_BYTESMAX; i++) |
419 | seq_printf(m, "%Lu ", totals.bytes[i]); | 419 | seq_printf(m, "%Lu ", totals.bytes[i]); |
420 | seq_printf(m, "\n"); | 420 | seq_printf(m, "\n"); |
421 | 421 | ||
422 | rpc_print_iostats(m, nfss->client); | 422 | rpc_print_iostats(m, nfss->client); |
423 | 423 | ||
424 | return 0; | 424 | return 0; |
425 | } | 425 | } |
426 | 426 | ||
427 | /* | 427 | /* |
428 | * Begin unmount by attempting to remove all automounted mountpoints we added | 428 | * Begin unmount by attempting to remove all automounted mountpoints we added |
429 | * in response to xdev traversals and referrals | 429 | * in response to xdev traversals and referrals |
430 | */ | 430 | */ |
431 | static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) | 431 | static void nfs_umount_begin(struct vfsmount *vfsmnt, int flags) |
432 | { | 432 | { |
433 | struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); | 433 | struct nfs_server *server = NFS_SB(vfsmnt->mnt_sb); |
434 | struct rpc_clnt *rpc; | 434 | struct rpc_clnt *rpc; |
435 | 435 | ||
436 | shrink_submounts(vfsmnt, &nfs_automount_list); | 436 | shrink_submounts(vfsmnt, &nfs_automount_list); |
437 | 437 | ||
438 | if (!(flags & MNT_FORCE)) | 438 | if (!(flags & MNT_FORCE)) |
439 | return; | 439 | return; |
440 | /* -EIO all pending I/O */ | 440 | /* -EIO all pending I/O */ |
441 | rpc = server->client_acl; | 441 | rpc = server->client_acl; |
442 | if (!IS_ERR(rpc)) | 442 | if (!IS_ERR(rpc)) |
443 | rpc_killall_tasks(rpc); | 443 | rpc_killall_tasks(rpc); |
444 | rpc = server->client; | 444 | rpc = server->client; |
445 | if (!IS_ERR(rpc)) | 445 | if (!IS_ERR(rpc)) |
446 | rpc_killall_tasks(rpc); | 446 | rpc_killall_tasks(rpc); |
447 | } | 447 | } |
448 | 448 | ||
449 | /* | 449 | /* |
450 | * Validate the NFS2/NFS3 mount data | 450 | * Validate the NFS2/NFS3 mount data |
451 | * - fills in the mount root filehandle | 451 | * - fills in the mount root filehandle |
452 | */ | 452 | */ |
453 | static int nfs_validate_mount_data(struct nfs_mount_data *data, | 453 | static int nfs_validate_mount_data(struct nfs_mount_data *data, |
454 | struct nfs_fh *mntfh) | 454 | struct nfs_fh *mntfh) |
455 | { | 455 | { |
456 | if (data == NULL) { | 456 | if (data == NULL) { |
457 | dprintk("%s: missing data argument\n", __FUNCTION__); | 457 | dprintk("%s: missing data argument\n", __FUNCTION__); |
458 | return -EINVAL; | 458 | return -EINVAL; |
459 | } | 459 | } |
460 | 460 | ||
461 | if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { | 461 | if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { |
462 | dprintk("%s: bad mount version\n", __FUNCTION__); | 462 | dprintk("%s: bad mount version\n", __FUNCTION__); |
463 | return -EINVAL; | 463 | return -EINVAL; |
464 | } | 464 | } |
465 | 465 | ||
466 | switch (data->version) { | 466 | switch (data->version) { |
467 | case 1: | 467 | case 1: |
468 | data->namlen = 0; | 468 | data->namlen = 0; |
469 | case 2: | 469 | case 2: |
470 | data->bsize = 0; | 470 | data->bsize = 0; |
471 | case 3: | 471 | case 3: |
472 | if (data->flags & NFS_MOUNT_VER3) { | 472 | if (data->flags & NFS_MOUNT_VER3) { |
473 | dprintk("%s: mount structure version %d does not support NFSv3\n", | 473 | dprintk("%s: mount structure version %d does not support NFSv3\n", |
474 | __FUNCTION__, | 474 | __FUNCTION__, |
475 | data->version); | 475 | data->version); |
476 | return -EINVAL; | 476 | return -EINVAL; |
477 | } | 477 | } |
478 | data->root.size = NFS2_FHSIZE; | 478 | data->root.size = NFS2_FHSIZE; |
479 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); | 479 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); |
480 | case 4: | 480 | case 4: |
481 | if (data->flags & NFS_MOUNT_SECFLAVOUR) { | 481 | if (data->flags & NFS_MOUNT_SECFLAVOUR) { |
482 | dprintk("%s: mount structure version %d does not support strong security\n", | 482 | dprintk("%s: mount structure version %d does not support strong security\n", |
483 | __FUNCTION__, | 483 | __FUNCTION__, |
484 | data->version); | 484 | data->version); |
485 | return -EINVAL; | 485 | return -EINVAL; |
486 | } | 486 | } |
487 | case 5: | 487 | case 5: |
488 | memset(data->context, 0, sizeof(data->context)); | 488 | memset(data->context, 0, sizeof(data->context)); |
489 | } | 489 | } |
490 | 490 | ||
491 | /* Set the pseudoflavor */ | 491 | /* Set the pseudoflavor */ |
492 | if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) | 492 | if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) |
493 | data->pseudoflavor = RPC_AUTH_UNIX; | 493 | data->pseudoflavor = RPC_AUTH_UNIX; |
494 | 494 | ||
495 | #ifndef CONFIG_NFS_V3 | 495 | #ifndef CONFIG_NFS_V3 |
496 | /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ | 496 | /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ |
497 | if (data->flags & NFS_MOUNT_VER3) { | 497 | if (data->flags & NFS_MOUNT_VER3) { |
498 | dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); | 498 | dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); |
499 | return -EPROTONOSUPPORT; | 499 | return -EPROTONOSUPPORT; |
500 | } | 500 | } |
501 | #endif /* CONFIG_NFS_V3 */ | 501 | #endif /* CONFIG_NFS_V3 */ |
502 | 502 | ||
503 | /* We now require that the mount process passes the remote address */ | 503 | /* We now require that the mount process passes the remote address */ |
504 | if (data->addr.sin_addr.s_addr == INADDR_ANY) { | 504 | if (data->addr.sin_addr.s_addr == INADDR_ANY) { |
505 | dprintk("%s: mount program didn't pass remote address!\n", | 505 | dprintk("%s: mount program didn't pass remote address!\n", |
506 | __FUNCTION__); | 506 | __FUNCTION__); |
507 | return -EINVAL; | 507 | return -EINVAL; |
508 | } | 508 | } |
509 | 509 | ||
510 | /* Prepare the root filehandle */ | 510 | /* Prepare the root filehandle */ |
511 | if (data->flags & NFS_MOUNT_VER3) | 511 | if (data->flags & NFS_MOUNT_VER3) |
512 | mntfh->size = data->root.size; | 512 | mntfh->size = data->root.size; |
513 | else | 513 | else |
514 | mntfh->size = NFS2_FHSIZE; | 514 | mntfh->size = NFS2_FHSIZE; |
515 | 515 | ||
516 | if (mntfh->size > sizeof(mntfh->data)) { | 516 | if (mntfh->size > sizeof(mntfh->data)) { |
517 | dprintk("%s: invalid root filehandle\n", __FUNCTION__); | 517 | dprintk("%s: invalid root filehandle\n", __FUNCTION__); |
518 | return -EINVAL; | 518 | return -EINVAL; |
519 | } | 519 | } |
520 | 520 | ||
521 | memcpy(mntfh->data, data->root.data, mntfh->size); | 521 | memcpy(mntfh->data, data->root.data, mntfh->size); |
522 | if (mntfh->size < sizeof(mntfh->data)) | 522 | if (mntfh->size < sizeof(mntfh->data)) |
523 | memset(mntfh->data + mntfh->size, 0, | 523 | memset(mntfh->data + mntfh->size, 0, |
524 | sizeof(mntfh->data) - mntfh->size); | 524 | sizeof(mntfh->data) - mntfh->size); |
525 | 525 | ||
526 | return 0; | 526 | return 0; |
527 | } | 527 | } |
528 | 528 | ||
529 | /* | 529 | /* |
530 | * Initialise the common bits of the superblock | 530 | * Initialise the common bits of the superblock |
531 | */ | 531 | */ |
532 | static inline void nfs_initialise_sb(struct super_block *sb) | 532 | static inline void nfs_initialise_sb(struct super_block *sb) |
533 | { | 533 | { |
534 | struct nfs_server *server = NFS_SB(sb); | 534 | struct nfs_server *server = NFS_SB(sb); |
535 | 535 | ||
536 | sb->s_magic = NFS_SUPER_MAGIC; | 536 | sb->s_magic = NFS_SUPER_MAGIC; |
537 | 537 | ||
538 | /* We probably want something more informative here */ | 538 | /* We probably want something more informative here */ |
539 | snprintf(sb->s_id, sizeof(sb->s_id), | 539 | snprintf(sb->s_id, sizeof(sb->s_id), |
540 | "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); | 540 | "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); |
541 | 541 | ||
542 | if (sb->s_blocksize == 0) | 542 | if (sb->s_blocksize == 0) |
543 | sb->s_blocksize = nfs_block_bits(server->wsize, | 543 | sb->s_blocksize = nfs_block_bits(server->wsize, |
544 | &sb->s_blocksize_bits); | 544 | &sb->s_blocksize_bits); |
545 | 545 | ||
546 | if (server->flags & NFS_MOUNT_NOAC) | 546 | if (server->flags & NFS_MOUNT_NOAC) |
547 | sb->s_flags |= MS_SYNCHRONOUS; | 547 | sb->s_flags |= MS_SYNCHRONOUS; |
548 | 548 | ||
549 | nfs_super_set_maxbytes(sb, server->maxfilesize); | 549 | nfs_super_set_maxbytes(sb, server->maxfilesize); |
550 | } | 550 | } |
551 | 551 | ||
552 | /* | 552 | /* |
553 | * Finish setting up an NFS2/3 superblock | 553 | * Finish setting up an NFS2/3 superblock |
554 | */ | 554 | */ |
555 | static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data) | 555 | static void nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data) |
556 | { | 556 | { |
557 | struct nfs_server *server = NFS_SB(sb); | 557 | struct nfs_server *server = NFS_SB(sb); |
558 | 558 | ||
559 | sb->s_blocksize_bits = 0; | 559 | sb->s_blocksize_bits = 0; |
560 | sb->s_blocksize = 0; | 560 | sb->s_blocksize = 0; |
561 | if (data->bsize) | 561 | if (data->bsize) |
562 | sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); | 562 | sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); |
563 | 563 | ||
564 | if (server->flags & NFS_MOUNT_VER3) { | 564 | if (server->flags & NFS_MOUNT_VER3) { |
565 | /* The VFS shouldn't apply the umask to mode bits. We will do | 565 | /* The VFS shouldn't apply the umask to mode bits. We will do |
566 | * so ourselves when necessary. | 566 | * so ourselves when necessary. |
567 | */ | 567 | */ |
568 | sb->s_flags |= MS_POSIXACL; | 568 | sb->s_flags |= MS_POSIXACL; |
569 | sb->s_time_gran = 1; | 569 | sb->s_time_gran = 1; |
570 | } | 570 | } |
571 | 571 | ||
572 | sb->s_op = &nfs_sops; | 572 | sb->s_op = &nfs_sops; |
573 | nfs_initialise_sb(sb); | 573 | nfs_initialise_sb(sb); |
574 | } | 574 | } |
575 | 575 | ||
576 | /* | 576 | /* |
577 | * Finish setting up a cloned NFS2/3 superblock | 577 | * Finish setting up a cloned NFS2/3 superblock |
578 | */ | 578 | */ |
579 | static void nfs_clone_super(struct super_block *sb, | 579 | static void nfs_clone_super(struct super_block *sb, |
580 | const struct super_block *old_sb) | 580 | const struct super_block *old_sb) |
581 | { | 581 | { |
582 | struct nfs_server *server = NFS_SB(sb); | 582 | struct nfs_server *server = NFS_SB(sb); |
583 | 583 | ||
584 | sb->s_blocksize_bits = old_sb->s_blocksize_bits; | 584 | sb->s_blocksize_bits = old_sb->s_blocksize_bits; |
585 | sb->s_blocksize = old_sb->s_blocksize; | 585 | sb->s_blocksize = old_sb->s_blocksize; |
586 | sb->s_maxbytes = old_sb->s_maxbytes; | 586 | sb->s_maxbytes = old_sb->s_maxbytes; |
587 | 587 | ||
588 | if (server->flags & NFS_MOUNT_VER3) { | 588 | if (server->flags & NFS_MOUNT_VER3) { |
589 | /* The VFS shouldn't apply the umask to mode bits. We will do | 589 | /* The VFS shouldn't apply the umask to mode bits. We will do |
590 | * so ourselves when necessary. | 590 | * so ourselves when necessary. |
591 | */ | 591 | */ |
592 | sb->s_flags |= MS_POSIXACL; | 592 | sb->s_flags |= MS_POSIXACL; |
593 | sb->s_time_gran = 1; | 593 | sb->s_time_gran = 1; |
594 | } | 594 | } |
595 | 595 | ||
596 | sb->s_op = old_sb->s_op; | 596 | sb->s_op = old_sb->s_op; |
597 | nfs_initialise_sb(sb); | 597 | nfs_initialise_sb(sb); |
598 | } | 598 | } |
599 | 599 | ||
600 | static int nfs_set_super(struct super_block *s, void *_server) | 600 | static int nfs_set_super(struct super_block *s, void *_server) |
601 | { | 601 | { |
602 | struct nfs_server *server = _server; | 602 | struct nfs_server *server = _server; |
603 | int ret; | 603 | int ret; |
604 | 604 | ||
605 | s->s_fs_info = server; | 605 | s->s_fs_info = server; |
606 | ret = set_anon_super(s, server); | 606 | ret = set_anon_super(s, server); |
607 | if (ret == 0) | 607 | if (ret == 0) |
608 | server->s_dev = s->s_dev; | 608 | server->s_dev = s->s_dev; |
609 | return ret; | 609 | return ret; |
610 | } | 610 | } |
611 | 611 | ||
612 | static int nfs_compare_super(struct super_block *sb, void *data) | 612 | static int nfs_compare_super(struct super_block *sb, void *data) |
613 | { | 613 | { |
614 | struct nfs_server *server = data, *old = NFS_SB(sb); | 614 | struct nfs_server *server = data, *old = NFS_SB(sb); |
615 | 615 | ||
616 | if (old->nfs_client != server->nfs_client) | 616 | if (old->nfs_client != server->nfs_client) |
617 | return 0; | 617 | return 0; |
618 | if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0) | 618 | if (memcmp(&old->fsid, &server->fsid, sizeof(old->fsid)) != 0) |
619 | return 0; | 619 | return 0; |
620 | return 1; | 620 | return 1; |
621 | } | 621 | } |
622 | 622 | ||
623 | static int nfs_get_sb(struct file_system_type *fs_type, | 623 | static int nfs_get_sb(struct file_system_type *fs_type, |
624 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | 624 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
625 | { | 625 | { |
626 | struct nfs_server *server = NULL; | 626 | struct nfs_server *server = NULL; |
627 | struct super_block *s; | 627 | struct super_block *s; |
628 | struct nfs_fh mntfh; | 628 | struct nfs_fh mntfh; |
629 | struct nfs_mount_data *data = raw_data; | 629 | struct nfs_mount_data *data = raw_data; |
630 | struct dentry *mntroot; | 630 | struct dentry *mntroot; |
631 | int error; | 631 | int error; |
632 | 632 | ||
633 | /* Validate the mount data */ | 633 | /* Validate the mount data */ |
634 | error = nfs_validate_mount_data(data, &mntfh); | 634 | error = nfs_validate_mount_data(data, &mntfh); |
635 | if (error < 0) | 635 | if (error < 0) |
636 | return error; | 636 | return error; |
637 | 637 | ||
638 | /* Get a volume representation */ | 638 | /* Get a volume representation */ |
639 | server = nfs_create_server(data, &mntfh); | 639 | server = nfs_create_server(data, &mntfh); |
640 | if (IS_ERR(server)) { | 640 | if (IS_ERR(server)) { |
641 | error = PTR_ERR(server); | 641 | error = PTR_ERR(server); |
642 | goto out_err_noserver; | 642 | goto out_err_noserver; |
643 | } | 643 | } |
644 | 644 | ||
645 | /* Get a superblock - note that we may end up sharing one that already exists */ | 645 | /* Get a superblock - note that we may end up sharing one that already exists */ |
646 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); | 646 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); |
647 | if (IS_ERR(s)) { | 647 | if (IS_ERR(s)) { |
648 | error = PTR_ERR(s); | 648 | error = PTR_ERR(s); |
649 | goto out_err_nosb; | 649 | goto out_err_nosb; |
650 | } | 650 | } |
651 | 651 | ||
652 | if (s->s_fs_info != server) { | 652 | if (s->s_fs_info != server) { |
653 | nfs_free_server(server); | 653 | nfs_free_server(server); |
654 | server = NULL; | 654 | server = NULL; |
655 | } | 655 | } |
656 | 656 | ||
657 | if (!s->s_root) { | 657 | if (!s->s_root) { |
658 | /* initial superblock/root creation */ | 658 | /* initial superblock/root creation */ |
659 | s->s_flags = flags; | 659 | s->s_flags = flags; |
660 | nfs_fill_super(s, data); | 660 | nfs_fill_super(s, data); |
661 | } | 661 | } |
662 | 662 | ||
663 | mntroot = nfs_get_root(s, &mntfh); | 663 | mntroot = nfs_get_root(s, &mntfh); |
664 | if (IS_ERR(mntroot)) { | 664 | if (IS_ERR(mntroot)) { |
665 | error = PTR_ERR(mntroot); | 665 | error = PTR_ERR(mntroot); |
666 | goto error_splat_super; | 666 | goto error_splat_super; |
667 | } | 667 | } |
668 | 668 | ||
669 | s->s_flags |= MS_ACTIVE; | 669 | s->s_flags |= MS_ACTIVE; |
670 | mnt->mnt_sb = s; | 670 | mnt->mnt_sb = s; |
671 | mnt->mnt_root = mntroot; | 671 | mnt->mnt_root = mntroot; |
672 | return 0; | 672 | return 0; |
673 | 673 | ||
674 | out_err_nosb: | 674 | out_err_nosb: |
675 | nfs_free_server(server); | 675 | nfs_free_server(server); |
676 | out_err_noserver: | 676 | out_err_noserver: |
677 | return error; | 677 | return error; |
678 | 678 | ||
679 | error_splat_super: | 679 | error_splat_super: |
680 | up_write(&s->s_umount); | 680 | up_write(&s->s_umount); |
681 | deactivate_super(s); | 681 | deactivate_super(s); |
682 | return error; | 682 | return error; |
683 | } | 683 | } |
684 | 684 | ||
685 | /* | 685 | /* |
686 | * Destroy an NFS2/3 superblock | 686 | * Destroy an NFS2/3 superblock |
687 | */ | 687 | */ |
688 | static void nfs_kill_super(struct super_block *s) | 688 | static void nfs_kill_super(struct super_block *s) |
689 | { | 689 | { |
690 | struct nfs_server *server = NFS_SB(s); | 690 | struct nfs_server *server = NFS_SB(s); |
691 | 691 | ||
692 | kill_anon_super(s); | 692 | kill_anon_super(s); |
693 | nfs_free_server(server); | 693 | nfs_free_server(server); |
694 | } | 694 | } |
695 | 695 | ||
696 | /* | 696 | /* |
697 | * Clone an NFS2/3 server record on xdev traversal (FSID-change) | 697 | * Clone an NFS2/3 server record on xdev traversal (FSID-change) |
698 | */ | 698 | */ |
699 | static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | 699 | static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, |
700 | const char *dev_name, void *raw_data, | 700 | const char *dev_name, void *raw_data, |
701 | struct vfsmount *mnt) | 701 | struct vfsmount *mnt) |
702 | { | 702 | { |
703 | struct nfs_clone_mount *data = raw_data; | 703 | struct nfs_clone_mount *data = raw_data; |
704 | struct super_block *s; | 704 | struct super_block *s; |
705 | struct nfs_server *server; | 705 | struct nfs_server *server; |
706 | struct dentry *mntroot; | 706 | struct dentry *mntroot; |
707 | int error; | 707 | int error; |
708 | 708 | ||
709 | dprintk("--> nfs_xdev_get_sb()\n"); | 709 | dprintk("--> nfs_xdev_get_sb()\n"); |
710 | 710 | ||
711 | /* create a new volume representation */ | 711 | /* create a new volume representation */ |
712 | server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); | 712 | server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); |
713 | if (IS_ERR(server)) { | 713 | if (IS_ERR(server)) { |
714 | error = PTR_ERR(server); | 714 | error = PTR_ERR(server); |
715 | goto out_err_noserver; | 715 | goto out_err_noserver; |
716 | } | 716 | } |
717 | 717 | ||
718 | /* Get a superblock - note that we may end up sharing one that already exists */ | 718 | /* Get a superblock - note that we may end up sharing one that already exists */ |
719 | s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); | 719 | s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); |
720 | if (IS_ERR(s)) { | 720 | if (IS_ERR(s)) { |
721 | error = PTR_ERR(s); | 721 | error = PTR_ERR(s); |
722 | goto out_err_nosb; | 722 | goto out_err_nosb; |
723 | } | 723 | } |
724 | 724 | ||
725 | if (s->s_fs_info != server) { | 725 | if (s->s_fs_info != server) { |
726 | nfs_free_server(server); | 726 | nfs_free_server(server); |
727 | server = NULL; | 727 | server = NULL; |
728 | } | 728 | } |
729 | 729 | ||
730 | if (!s->s_root) { | 730 | if (!s->s_root) { |
731 | /* initial superblock/root creation */ | 731 | /* initial superblock/root creation */ |
732 | s->s_flags = flags; | 732 | s->s_flags = flags; |
733 | nfs_clone_super(s, data->sb); | 733 | nfs_clone_super(s, data->sb); |
734 | } | 734 | } |
735 | 735 | ||
736 | mntroot = nfs_get_root(s, data->fh); | 736 | mntroot = nfs_get_root(s, data->fh); |
737 | if (IS_ERR(mntroot)) { | 737 | if (IS_ERR(mntroot)) { |
738 | error = PTR_ERR(mntroot); | 738 | error = PTR_ERR(mntroot); |
739 | goto error_splat_super; | 739 | goto error_splat_super; |
740 | } | 740 | } |
741 | 741 | ||
742 | s->s_flags |= MS_ACTIVE; | 742 | s->s_flags |= MS_ACTIVE; |
743 | mnt->mnt_sb = s; | 743 | mnt->mnt_sb = s; |
744 | mnt->mnt_root = mntroot; | 744 | mnt->mnt_root = mntroot; |
745 | 745 | ||
746 | dprintk("<-- nfs_xdev_get_sb() = 0\n"); | 746 | dprintk("<-- nfs_xdev_get_sb() = 0\n"); |
747 | return 0; | 747 | return 0; |
748 | 748 | ||
749 | out_err_nosb: | 749 | out_err_nosb: |
750 | nfs_free_server(server); | 750 | nfs_free_server(server); |
751 | out_err_noserver: | 751 | out_err_noserver: |
752 | dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error); | 752 | dprintk("<-- nfs_xdev_get_sb() = %d [error]\n", error); |
753 | return error; | 753 | return error; |
754 | 754 | ||
755 | error_splat_super: | 755 | error_splat_super: |
756 | up_write(&s->s_umount); | 756 | up_write(&s->s_umount); |
757 | deactivate_super(s); | 757 | deactivate_super(s); |
758 | dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); | 758 | dprintk("<-- nfs_xdev_get_sb() = %d [splat]\n", error); |
759 | return error; | 759 | return error; |
760 | } | 760 | } |
761 | 761 | ||
762 | #ifdef CONFIG_NFS_V4 | 762 | #ifdef CONFIG_NFS_V4 |
763 | 763 | ||
764 | /* | 764 | /* |
765 | * Finish setting up a cloned NFS4 superblock | 765 | * Finish setting up a cloned NFS4 superblock |
766 | */ | 766 | */ |
767 | static void nfs4_clone_super(struct super_block *sb, | 767 | static void nfs4_clone_super(struct super_block *sb, |
768 | const struct super_block *old_sb) | 768 | const struct super_block *old_sb) |
769 | { | 769 | { |
770 | sb->s_blocksize_bits = old_sb->s_blocksize_bits; | 770 | sb->s_blocksize_bits = old_sb->s_blocksize_bits; |
771 | sb->s_blocksize = old_sb->s_blocksize; | 771 | sb->s_blocksize = old_sb->s_blocksize; |
772 | sb->s_maxbytes = old_sb->s_maxbytes; | 772 | sb->s_maxbytes = old_sb->s_maxbytes; |
773 | sb->s_time_gran = 1; | 773 | sb->s_time_gran = 1; |
774 | sb->s_op = old_sb->s_op; | 774 | sb->s_op = old_sb->s_op; |
775 | nfs_initialise_sb(sb); | 775 | nfs_initialise_sb(sb); |
776 | } | 776 | } |
777 | 777 | ||
778 | /* | 778 | /* |
779 | * Set up an NFS4 superblock | 779 | * Set up an NFS4 superblock |
780 | */ | 780 | */ |
781 | static void nfs4_fill_super(struct super_block *sb) | 781 | static void nfs4_fill_super(struct super_block *sb) |
782 | { | 782 | { |
783 | sb->s_time_gran = 1; | 783 | sb->s_time_gran = 1; |
784 | sb->s_op = &nfs4_sops; | 784 | sb->s_op = &nfs4_sops; |
785 | nfs_initialise_sb(sb); | 785 | nfs_initialise_sb(sb); |
786 | } | 786 | } |
787 | 787 | ||
788 | static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) | 788 | static void *nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) |
789 | { | 789 | { |
790 | void *p = NULL; | 790 | void *p = NULL; |
791 | 791 | ||
792 | if (!src->len) | 792 | if (!src->len) |
793 | return ERR_PTR(-EINVAL); | 793 | return ERR_PTR(-EINVAL); |
794 | if (src->len < maxlen) | 794 | if (src->len < maxlen) |
795 | maxlen = src->len; | 795 | maxlen = src->len; |
796 | if (dst == NULL) { | 796 | if (dst == NULL) { |
797 | p = dst = kmalloc(maxlen + 1, GFP_KERNEL); | 797 | p = dst = kmalloc(maxlen + 1, GFP_KERNEL); |
798 | if (p == NULL) | 798 | if (p == NULL) |
799 | return ERR_PTR(-ENOMEM); | 799 | return ERR_PTR(-ENOMEM); |
800 | } | 800 | } |
801 | if (copy_from_user(dst, src->data, maxlen)) { | 801 | if (copy_from_user(dst, src->data, maxlen)) { |
802 | kfree(p); | 802 | kfree(p); |
803 | return ERR_PTR(-EFAULT); | 803 | return ERR_PTR(-EFAULT); |
804 | } | 804 | } |
805 | dst[maxlen] = '\0'; | 805 | dst[maxlen] = '\0'; |
806 | return dst; | 806 | return dst; |
807 | } | 807 | } |
808 | 808 | ||
809 | /* | 809 | /* |
810 | * Get the superblock for an NFS4 mountpoint | 810 | * Get the superblock for an NFS4 mountpoint |
811 | */ | 811 | */ |
812 | static int nfs4_get_sb(struct file_system_type *fs_type, | 812 | static int nfs4_get_sb(struct file_system_type *fs_type, |
813 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) | 813 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
814 | { | 814 | { |
815 | struct nfs4_mount_data *data = raw_data; | 815 | struct nfs4_mount_data *data = raw_data; |
816 | struct super_block *s; | 816 | struct super_block *s; |
817 | struct nfs_server *server; | 817 | struct nfs_server *server; |
818 | struct sockaddr_in addr; | 818 | struct sockaddr_in addr; |
819 | rpc_authflavor_t authflavour; | 819 | rpc_authflavor_t authflavour; |
820 | struct nfs_fh mntfh; | 820 | struct nfs_fh mntfh; |
821 | struct dentry *mntroot; | 821 | struct dentry *mntroot; |
822 | char *mntpath = NULL, *hostname = NULL, ip_addr[16]; | 822 | char *mntpath = NULL, *hostname = NULL, ip_addr[16]; |
823 | void *p; | 823 | void *p; |
824 | int error; | 824 | int error; |
825 | 825 | ||
826 | if (data == NULL) { | 826 | if (data == NULL) { |
827 | dprintk("%s: missing data argument\n", __FUNCTION__); | 827 | dprintk("%s: missing data argument\n", __FUNCTION__); |
828 | return -EINVAL; | 828 | return -EINVAL; |
829 | } | 829 | } |
830 | if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { | 830 | if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { |
831 | dprintk("%s: bad mount version\n", __FUNCTION__); | 831 | dprintk("%s: bad mount version\n", __FUNCTION__); |
832 | return -EINVAL; | 832 | return -EINVAL; |
833 | } | 833 | } |
834 | 834 | ||
835 | /* We now require that the mount process passes the remote address */ | 835 | /* We now require that the mount process passes the remote address */ |
836 | if (data->host_addrlen != sizeof(addr)) | 836 | if (data->host_addrlen != sizeof(addr)) |
837 | return -EINVAL; | 837 | return -EINVAL; |
838 | 838 | ||
839 | if (copy_from_user(&addr, data->host_addr, sizeof(addr))) | 839 | if (copy_from_user(&addr, data->host_addr, sizeof(addr))) |
840 | return -EFAULT; | 840 | return -EFAULT; |
841 | 841 | ||
842 | if (addr.sin_family != AF_INET || | 842 | if (addr.sin_family != AF_INET || |
843 | addr.sin_addr.s_addr == INADDR_ANY | 843 | addr.sin_addr.s_addr == INADDR_ANY |
844 | ) { | 844 | ) { |
845 | dprintk("%s: mount program didn't pass remote IP address!\n", | 845 | dprintk("%s: mount program didn't pass remote IP address!\n", |
846 | __FUNCTION__); | 846 | __FUNCTION__); |
847 | return -EINVAL; | 847 | return -EINVAL; |
848 | } | 848 | } |
849 | /* RFC3530: The default port for NFS is 2049 */ | 849 | /* RFC3530: The default port for NFS is 2049 */ |
850 | if (addr.sin_port == 0) | 850 | if (addr.sin_port == 0) |
851 | addr.sin_port = htons(NFS_PORT); | 851 | addr.sin_port = htons(NFS_PORT); |
852 | 852 | ||
853 | /* Grab the authentication type */ | 853 | /* Grab the authentication type */ |
854 | authflavour = RPC_AUTH_UNIX; | 854 | authflavour = RPC_AUTH_UNIX; |
855 | if (data->auth_flavourlen != 0) { | 855 | if (data->auth_flavourlen != 0) { |
856 | if (data->auth_flavourlen != 1) { | 856 | if (data->auth_flavourlen != 1) { |
857 | dprintk("%s: Invalid number of RPC auth flavours %d.\n", | 857 | dprintk("%s: Invalid number of RPC auth flavours %d.\n", |
858 | __FUNCTION__, data->auth_flavourlen); | 858 | __FUNCTION__, data->auth_flavourlen); |
859 | error = -EINVAL; | 859 | error = -EINVAL; |
860 | goto out_err_noserver; | 860 | goto out_err_noserver; |
861 | } | 861 | } |
862 | 862 | ||
863 | if (copy_from_user(&authflavour, data->auth_flavours, | 863 | if (copy_from_user(&authflavour, data->auth_flavours, |
864 | sizeof(authflavour))) { | 864 | sizeof(authflavour))) { |
865 | error = -EFAULT; | 865 | error = -EFAULT; |
866 | goto out_err_noserver; | 866 | goto out_err_noserver; |
867 | } | 867 | } |
868 | } | 868 | } |
869 | 869 | ||
870 | p = nfs_copy_user_string(NULL, &data->hostname, 256); | 870 | p = nfs_copy_user_string(NULL, &data->hostname, NFS4_MAXNAMLEN); |
871 | if (IS_ERR(p)) | 871 | if (IS_ERR(p)) |
872 | goto out_err; | 872 | goto out_err; |
873 | hostname = p; | 873 | hostname = p; |
874 | 874 | ||
875 | p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); | 875 | p = nfs_copy_user_string(NULL, &data->mnt_path, NFS4_MAXPATHLEN); |
876 | if (IS_ERR(p)) | 876 | if (IS_ERR(p)) |
877 | goto out_err; | 877 | goto out_err; |
878 | mntpath = p; | 878 | mntpath = p; |
879 | 879 | ||
880 | dprintk("MNTPATH: %s\n", mntpath); | 880 | dprintk("MNTPATH: %s\n", mntpath); |
881 | 881 | ||
882 | p = nfs_copy_user_string(ip_addr, &data->client_addr, | 882 | p = nfs_copy_user_string(ip_addr, &data->client_addr, |
883 | sizeof(ip_addr) - 1); | 883 | sizeof(ip_addr) - 1); |
884 | if (IS_ERR(p)) | 884 | if (IS_ERR(p)) |
885 | goto out_err; | 885 | goto out_err; |
886 | 886 | ||
887 | /* Get a volume representation */ | 887 | /* Get a volume representation */ |
888 | server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, | 888 | server = nfs4_create_server(data, hostname, &addr, mntpath, ip_addr, |
889 | authflavour, &mntfh); | 889 | authflavour, &mntfh); |
890 | if (IS_ERR(server)) { | 890 | if (IS_ERR(server)) { |
891 | error = PTR_ERR(server); | 891 | error = PTR_ERR(server); |
892 | goto out_err_noserver; | 892 | goto out_err_noserver; |
893 | } | 893 | } |
894 | 894 | ||
895 | /* Get a superblock - note that we may end up sharing one that already exists */ | 895 | /* Get a superblock - note that we may end up sharing one that already exists */ |
896 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); | 896 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); |
897 | if (IS_ERR(s)) { | 897 | if (IS_ERR(s)) { |
898 | error = PTR_ERR(s); | 898 | error = PTR_ERR(s); |
899 | goto out_free; | 899 | goto out_free; |
900 | } | 900 | } |
901 | 901 | ||
902 | if (s->s_fs_info != server) { | 902 | if (s->s_fs_info != server) { |
903 | nfs_free_server(server); | 903 | nfs_free_server(server); |
904 | server = NULL; | 904 | server = NULL; |
905 | } | 905 | } |
906 | 906 | ||
907 | if (!s->s_root) { | 907 | if (!s->s_root) { |
908 | /* initial superblock/root creation */ | 908 | /* initial superblock/root creation */ |
909 | s->s_flags = flags; | 909 | s->s_flags = flags; |
910 | nfs4_fill_super(s); | 910 | nfs4_fill_super(s); |
911 | } | 911 | } |
912 | 912 | ||
913 | mntroot = nfs4_get_root(s, &mntfh); | 913 | mntroot = nfs4_get_root(s, &mntfh); |
914 | if (IS_ERR(mntroot)) { | 914 | if (IS_ERR(mntroot)) { |
915 | error = PTR_ERR(mntroot); | 915 | error = PTR_ERR(mntroot); |
916 | goto error_splat_super; | 916 | goto error_splat_super; |
917 | } | 917 | } |
918 | 918 | ||
919 | s->s_flags |= MS_ACTIVE; | 919 | s->s_flags |= MS_ACTIVE; |
920 | mnt->mnt_sb = s; | 920 | mnt->mnt_sb = s; |
921 | mnt->mnt_root = mntroot; | 921 | mnt->mnt_root = mntroot; |
922 | kfree(mntpath); | 922 | kfree(mntpath); |
923 | kfree(hostname); | 923 | kfree(hostname); |
924 | return 0; | 924 | return 0; |
925 | 925 | ||
926 | out_err: | 926 | out_err: |
927 | error = PTR_ERR(p); | 927 | error = PTR_ERR(p); |
928 | goto out_err_noserver; | 928 | goto out_err_noserver; |
929 | 929 | ||
930 | out_free: | 930 | out_free: |
931 | nfs_free_server(server); | 931 | nfs_free_server(server); |
932 | out_err_noserver: | 932 | out_err_noserver: |
933 | kfree(mntpath); | 933 | kfree(mntpath); |
934 | kfree(hostname); | 934 | kfree(hostname); |
935 | return error; | 935 | return error; |
936 | 936 | ||
937 | error_splat_super: | 937 | error_splat_super: |
938 | up_write(&s->s_umount); | 938 | up_write(&s->s_umount); |
939 | deactivate_super(s); | 939 | deactivate_super(s); |
940 | goto out_err_noserver; | 940 | goto out_err_noserver; |
941 | } | 941 | } |
942 | 942 | ||
943 | static void nfs4_kill_super(struct super_block *sb) | 943 | static void nfs4_kill_super(struct super_block *sb) |
944 | { | 944 | { |
945 | struct nfs_server *server = NFS_SB(sb); | 945 | struct nfs_server *server = NFS_SB(sb); |
946 | 946 | ||
947 | nfs_return_all_delegations(sb); | 947 | nfs_return_all_delegations(sb); |
948 | kill_anon_super(sb); | 948 | kill_anon_super(sb); |
949 | 949 | ||
950 | nfs4_renewd_prepare_shutdown(server); | 950 | nfs4_renewd_prepare_shutdown(server); |
951 | nfs_free_server(server); | 951 | nfs_free_server(server); |
952 | } | 952 | } |
953 | 953 | ||
954 | /* | 954 | /* |
955 | * Clone an NFS4 server record on xdev traversal (FSID-change) | 955 | * Clone an NFS4 server record on xdev traversal (FSID-change) |
956 | */ | 956 | */ |
957 | static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, | 957 | static int nfs4_xdev_get_sb(struct file_system_type *fs_type, int flags, |
958 | const char *dev_name, void *raw_data, | 958 | const char *dev_name, void *raw_data, |
959 | struct vfsmount *mnt) | 959 | struct vfsmount *mnt) |
960 | { | 960 | { |
961 | struct nfs_clone_mount *data = raw_data; | 961 | struct nfs_clone_mount *data = raw_data; |
962 | struct super_block *s; | 962 | struct super_block *s; |
963 | struct nfs_server *server; | 963 | struct nfs_server *server; |
964 | struct dentry *mntroot; | 964 | struct dentry *mntroot; |
965 | int error; | 965 | int error; |
966 | 966 | ||
967 | dprintk("--> nfs4_xdev_get_sb()\n"); | 967 | dprintk("--> nfs4_xdev_get_sb()\n"); |
968 | 968 | ||
969 | /* create a new volume representation */ | 969 | /* create a new volume representation */ |
970 | server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); | 970 | server = nfs_clone_server(NFS_SB(data->sb), data->fh, data->fattr); |
971 | if (IS_ERR(server)) { | 971 | if (IS_ERR(server)) { |
972 | error = PTR_ERR(server); | 972 | error = PTR_ERR(server); |
973 | goto out_err_noserver; | 973 | goto out_err_noserver; |
974 | } | 974 | } |
975 | 975 | ||
976 | /* Get a superblock - note that we may end up sharing one that already exists */ | 976 | /* Get a superblock - note that we may end up sharing one that already exists */ |
977 | s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); | 977 | s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); |
978 | if (IS_ERR(s)) { | 978 | if (IS_ERR(s)) { |
979 | error = PTR_ERR(s); | 979 | error = PTR_ERR(s); |
980 | goto out_err_nosb; | 980 | goto out_err_nosb; |
981 | } | 981 | } |
982 | 982 | ||
983 | if (s->s_fs_info != server) { | 983 | if (s->s_fs_info != server) { |
984 | nfs_free_server(server); | 984 | nfs_free_server(server); |
985 | server = NULL; | 985 | server = NULL; |
986 | } | 986 | } |
987 | 987 | ||
988 | if (!s->s_root) { | 988 | if (!s->s_root) { |
989 | /* initial superblock/root creation */ | 989 | /* initial superblock/root creation */ |
990 | s->s_flags = flags; | 990 | s->s_flags = flags; |
991 | nfs4_clone_super(s, data->sb); | 991 | nfs4_clone_super(s, data->sb); |
992 | } | 992 | } |
993 | 993 | ||
994 | mntroot = nfs4_get_root(s, data->fh); | 994 | mntroot = nfs4_get_root(s, data->fh); |
995 | if (IS_ERR(mntroot)) { | 995 | if (IS_ERR(mntroot)) { |
996 | error = PTR_ERR(mntroot); | 996 | error = PTR_ERR(mntroot); |
997 | goto error_splat_super; | 997 | goto error_splat_super; |
998 | } | 998 | } |
999 | 999 | ||
1000 | s->s_flags |= MS_ACTIVE; | 1000 | s->s_flags |= MS_ACTIVE; |
1001 | mnt->mnt_sb = s; | 1001 | mnt->mnt_sb = s; |
1002 | mnt->mnt_root = mntroot; | 1002 | mnt->mnt_root = mntroot; |
1003 | 1003 | ||
1004 | dprintk("<-- nfs4_xdev_get_sb() = 0\n"); | 1004 | dprintk("<-- nfs4_xdev_get_sb() = 0\n"); |
1005 | return 0; | 1005 | return 0; |
1006 | 1006 | ||
1007 | out_err_nosb: | 1007 | out_err_nosb: |
1008 | nfs_free_server(server); | 1008 | nfs_free_server(server); |
1009 | out_err_noserver: | 1009 | out_err_noserver: |
1010 | dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error); | 1010 | dprintk("<-- nfs4_xdev_get_sb() = %d [error]\n", error); |
1011 | return error; | 1011 | return error; |
1012 | 1012 | ||
1013 | error_splat_super: | 1013 | error_splat_super: |
1014 | up_write(&s->s_umount); | 1014 | up_write(&s->s_umount); |
1015 | deactivate_super(s); | 1015 | deactivate_super(s); |
1016 | dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); | 1016 | dprintk("<-- nfs4_xdev_get_sb() = %d [splat]\n", error); |
1017 | return error; | 1017 | return error; |
1018 | } | 1018 | } |
1019 | 1019 | ||
1020 | /* | 1020 | /* |
1021 | * Create an NFS4 server record on referral traversal | 1021 | * Create an NFS4 server record on referral traversal |
1022 | */ | 1022 | */ |
1023 | static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags, | 1023 | static int nfs4_referral_get_sb(struct file_system_type *fs_type, int flags, |
1024 | const char *dev_name, void *raw_data, | 1024 | const char *dev_name, void *raw_data, |
1025 | struct vfsmount *mnt) | 1025 | struct vfsmount *mnt) |
1026 | { | 1026 | { |
1027 | struct nfs_clone_mount *data = raw_data; | 1027 | struct nfs_clone_mount *data = raw_data; |
1028 | struct super_block *s; | 1028 | struct super_block *s; |
1029 | struct nfs_server *server; | 1029 | struct nfs_server *server; |
1030 | struct dentry *mntroot; | 1030 | struct dentry *mntroot; |
1031 | struct nfs_fh mntfh; | 1031 | struct nfs_fh mntfh; |
1032 | int error; | 1032 | int error; |
1033 | 1033 | ||
1034 | dprintk("--> nfs4_referral_get_sb()\n"); | 1034 | dprintk("--> nfs4_referral_get_sb()\n"); |
1035 | 1035 | ||
1036 | /* create a new volume representation */ | 1036 | /* create a new volume representation */ |
1037 | server = nfs4_create_referral_server(data, &mntfh); | 1037 | server = nfs4_create_referral_server(data, &mntfh); |
1038 | if (IS_ERR(server)) { | 1038 | if (IS_ERR(server)) { |
1039 | error = PTR_ERR(server); | 1039 | error = PTR_ERR(server); |
1040 | goto out_err_noserver; | 1040 | goto out_err_noserver; |
1041 | } | 1041 | } |
1042 | 1042 | ||
1043 | /* Get a superblock - note that we may end up sharing one that already exists */ | 1043 | /* Get a superblock - note that we may end up sharing one that already exists */ |
1044 | s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); | 1044 | s = sget(&nfs_fs_type, nfs_compare_super, nfs_set_super, server); |
1045 | if (IS_ERR(s)) { | 1045 | if (IS_ERR(s)) { |
1046 | error = PTR_ERR(s); | 1046 | error = PTR_ERR(s); |
1047 | goto out_err_nosb; | 1047 | goto out_err_nosb; |
1048 | } | 1048 | } |
1049 | 1049 | ||
1050 | if (s->s_fs_info != server) { | 1050 | if (s->s_fs_info != server) { |
1051 | nfs_free_server(server); | 1051 | nfs_free_server(server); |
1052 | server = NULL; | 1052 | server = NULL; |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | if (!s->s_root) { | 1055 | if (!s->s_root) { |
1056 | /* initial superblock/root creation */ | 1056 | /* initial superblock/root creation */ |
1057 | s->s_flags = flags; | 1057 | s->s_flags = flags; |
1058 | nfs4_fill_super(s); | 1058 | nfs4_fill_super(s); |
1059 | } | 1059 | } |
1060 | 1060 | ||
1061 | mntroot = nfs4_get_root(s, &mntfh); | 1061 | mntroot = nfs4_get_root(s, &mntfh); |
1062 | if (IS_ERR(mntroot)) { | 1062 | if (IS_ERR(mntroot)) { |
1063 | error = PTR_ERR(mntroot); | 1063 | error = PTR_ERR(mntroot); |
1064 | goto error_splat_super; | 1064 | goto error_splat_super; |
1065 | } | 1065 | } |
1066 | 1066 | ||
1067 | s->s_flags |= MS_ACTIVE; | 1067 | s->s_flags |= MS_ACTIVE; |
1068 | mnt->mnt_sb = s; | 1068 | mnt->mnt_sb = s; |
1069 | mnt->mnt_root = mntroot; | 1069 | mnt->mnt_root = mntroot; |
1070 | 1070 | ||
1071 | dprintk("<-- nfs4_referral_get_sb() = 0\n"); | 1071 | dprintk("<-- nfs4_referral_get_sb() = 0\n"); |
1072 | return 0; | 1072 | return 0; |
1073 | 1073 | ||
1074 | out_err_nosb: | 1074 | out_err_nosb: |
1075 | nfs_free_server(server); | 1075 | nfs_free_server(server); |
1076 | out_err_noserver: | 1076 | out_err_noserver: |
1077 | dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error); | 1077 | dprintk("<-- nfs4_referral_get_sb() = %d [error]\n", error); |
1078 | return error; | 1078 | return error; |
1079 | 1079 | ||
1080 | error_splat_super: | 1080 | error_splat_super: |
1081 | up_write(&s->s_umount); | 1081 | up_write(&s->s_umount); |
1082 | deactivate_super(s); | 1082 | deactivate_super(s); |
1083 | dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); | 1083 | dprintk("<-- nfs4_referral_get_sb() = %d [splat]\n", error); |
1084 | return error; | 1084 | return error; |
1085 | } | 1085 | } |
1086 | 1086 | ||
1087 | #endif /* CONFIG_NFS_V4 */ | 1087 | #endif /* CONFIG_NFS_V4 */ |
1088 | 1088 |
include/linux/nfs_mount.h
1 | #ifndef _LINUX_NFS_MOUNT_H | 1 | #ifndef _LINUX_NFS_MOUNT_H |
2 | #define _LINUX_NFS_MOUNT_H | 2 | #define _LINUX_NFS_MOUNT_H |
3 | 3 | ||
4 | /* | 4 | /* |
5 | * linux/include/linux/nfs_mount.h | 5 | * linux/include/linux/nfs_mount.h |
6 | * | 6 | * |
7 | * Copyright (C) 1992 Rick Sladkey | 7 | * Copyright (C) 1992 Rick Sladkey |
8 | * | 8 | * |
9 | * structure passed from user-space to kernel-space during an nfs mount | 9 | * structure passed from user-space to kernel-space during an nfs mount |
10 | */ | 10 | */ |
11 | #include <linux/in.h> | 11 | #include <linux/in.h> |
12 | #include <linux/nfs.h> | 12 | #include <linux/nfs.h> |
13 | #include <linux/nfs2.h> | 13 | #include <linux/nfs2.h> |
14 | #include <linux/nfs3.h> | 14 | #include <linux/nfs3.h> |
15 | 15 | ||
16 | /* | 16 | /* |
17 | * WARNING! Do not delete or change the order of these fields. If | 17 | * WARNING! Do not delete or change the order of these fields. If |
18 | * a new field is required then add it to the end. The version field | 18 | * a new field is required then add it to the end. The version field |
19 | * tracks which fields are present. This will ensure some measure of | 19 | * tracks which fields are present. This will ensure some measure of |
20 | * mount-to-kernel version compatibility. Some of these aren't used yet | 20 | * mount-to-kernel version compatibility. Some of these aren't used yet |
21 | * but here they are anyway. | 21 | * but here they are anyway. |
22 | */ | 22 | */ |
23 | #define NFS_MOUNT_VERSION 6 | 23 | #define NFS_MOUNT_VERSION 6 |
24 | #define NFS_MAX_CONTEXT_LEN 256 | 24 | #define NFS_MAX_CONTEXT_LEN 256 |
25 | 25 | ||
26 | struct nfs_mount_data { | 26 | struct nfs_mount_data { |
27 | int version; /* 1 */ | 27 | int version; /* 1 */ |
28 | int fd; /* 1 */ | 28 | int fd; /* 1 */ |
29 | struct nfs2_fh old_root; /* 1 */ | 29 | struct nfs2_fh old_root; /* 1 */ |
30 | int flags; /* 1 */ | 30 | int flags; /* 1 */ |
31 | int rsize; /* 1 */ | 31 | int rsize; /* 1 */ |
32 | int wsize; /* 1 */ | 32 | int wsize; /* 1 */ |
33 | int timeo; /* 1 */ | 33 | int timeo; /* 1 */ |
34 | int retrans; /* 1 */ | 34 | int retrans; /* 1 */ |
35 | int acregmin; /* 1 */ | 35 | int acregmin; /* 1 */ |
36 | int acregmax; /* 1 */ | 36 | int acregmax; /* 1 */ |
37 | int acdirmin; /* 1 */ | 37 | int acdirmin; /* 1 */ |
38 | int acdirmax; /* 1 */ | 38 | int acdirmax; /* 1 */ |
39 | struct sockaddr_in addr; /* 1 */ | 39 | struct sockaddr_in addr; /* 1 */ |
40 | char hostname[256]; /* 1 */ | 40 | char hostname[NFS_MAXNAMLEN + 1]; /* 1 */ |
41 | int namlen; /* 2 */ | 41 | int namlen; /* 2 */ |
42 | unsigned int bsize; /* 3 */ | 42 | unsigned int bsize; /* 3 */ |
43 | struct nfs3_fh root; /* 4 */ | 43 | struct nfs3_fh root; /* 4 */ |
44 | int pseudoflavor; /* 5 */ | 44 | int pseudoflavor; /* 5 */ |
45 | char context[NFS_MAX_CONTEXT_LEN + 1]; /* 6 */ | 45 | char context[NFS_MAX_CONTEXT_LEN + 1]; /* 6 */ |
46 | }; | 46 | }; |
47 | 47 | ||
48 | /* bits in the flags field */ | 48 | /* bits in the flags field */ |
49 | 49 | ||
50 | #define NFS_MOUNT_SOFT 0x0001 /* 1 */ | 50 | #define NFS_MOUNT_SOFT 0x0001 /* 1 */ |
51 | #define NFS_MOUNT_INTR 0x0002 /* 1 */ | 51 | #define NFS_MOUNT_INTR 0x0002 /* 1 */ |
52 | #define NFS_MOUNT_SECURE 0x0004 /* 1 */ | 52 | #define NFS_MOUNT_SECURE 0x0004 /* 1 */ |
53 | #define NFS_MOUNT_POSIX 0x0008 /* 1 */ | 53 | #define NFS_MOUNT_POSIX 0x0008 /* 1 */ |
54 | #define NFS_MOUNT_NOCTO 0x0010 /* 1 */ | 54 | #define NFS_MOUNT_NOCTO 0x0010 /* 1 */ |
55 | #define NFS_MOUNT_NOAC 0x0020 /* 1 */ | 55 | #define NFS_MOUNT_NOAC 0x0020 /* 1 */ |
56 | #define NFS_MOUNT_TCP 0x0040 /* 2 */ | 56 | #define NFS_MOUNT_TCP 0x0040 /* 2 */ |
57 | #define NFS_MOUNT_VER3 0x0080 /* 3 */ | 57 | #define NFS_MOUNT_VER3 0x0080 /* 3 */ |
58 | #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ | 58 | #define NFS_MOUNT_KERBEROS 0x0100 /* 3 */ |
59 | #define NFS_MOUNT_NONLM 0x0200 /* 3 */ | 59 | #define NFS_MOUNT_NONLM 0x0200 /* 3 */ |
60 | #define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */ | 60 | #define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */ |
61 | #define NFS_MOUNT_NOACL 0x0800 /* 4 */ | 61 | #define NFS_MOUNT_NOACL 0x0800 /* 4 */ |
62 | #define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */ | 62 | #define NFS_MOUNT_STRICTLOCK 0x1000 /* reserved for NFSv4 */ |
63 | #define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */ | 63 | #define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */ |
64 | #define NFS_MOUNT_NORDIRPLUS 0x4000 /* 5 */ | 64 | #define NFS_MOUNT_NORDIRPLUS 0x4000 /* 5 */ |
65 | #define NFS_MOUNT_FLAGMASK 0xFFFF | 65 | #define NFS_MOUNT_FLAGMASK 0xFFFF |
66 | 66 | ||
67 | #endif | 67 | #endif |
68 | 68 |