Commit 9b04c997b1120feefa1e6ee8e2902270bc055cd2
Committed by
Linus Torvalds
1 parent
6961ec8267
Exists in
master
and in
4 other branches
[PATCH] vfs: MS_VERBOSE should be MS_SILENT
The meaning of MS_VERBOSE is backwards; if the bit is set, it really means,
"don't be verbose". This is confusing and counter-intuitive.
In addition, there is also no way to set the MS_VERBOSE flag in the
mount(8) program in util-linux, but interesting, it does define options
which would do the right thing if MS_SILENT were defined, which
unfortunately we do not:
#ifdef MS_SILENT
{ "quiet", 0, 0, MS_SILENT }, /* be quiet */
{ "loud", 0, 1, MS_SILENT }, /* print out messages. */
#endif
So the obvious fix is to deprecate the use of MS_VERBOSE and replace it
with MS_SILENT.
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 7 changed files with 13 additions and 11 deletions Inline Diff
fs/afs/super.c
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2002 Red Hat, Inc. All rights reserved. | 2 | * Copyright (c) 2002 Red Hat, Inc. All rights reserved. |
| 3 | * | 3 | * |
| 4 | * This software may be freely redistributed under the terms of the | 4 | * This software may be freely redistributed under the terms of the |
| 5 | * GNU General Public License. | 5 | * GNU General Public License. |
| 6 | * | 6 | * |
| 7 | * You should have received a copy of the GNU General Public License | 7 | * You should have received a copy of the GNU General Public License |
| 8 | * along with this program; if not, write to the Free Software | 8 | * along with this program; if not, write to the Free Software |
| 9 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 9 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 10 | * | 10 | * |
| 11 | * Authors: David Howells <dhowells@redhat.com> | 11 | * Authors: David Howells <dhowells@redhat.com> |
| 12 | * David Woodhouse <dwmw2@cambridge.redhat.com> | 12 | * David Woodhouse <dwmw2@cambridge.redhat.com> |
| 13 | * | 13 | * |
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
| 20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
| 21 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
| 22 | #include "vnode.h" | 22 | #include "vnode.h" |
| 23 | #include "volume.h" | 23 | #include "volume.h" |
| 24 | #include "cell.h" | 24 | #include "cell.h" |
| 25 | #include "cmservice.h" | 25 | #include "cmservice.h" |
| 26 | #include "fsclient.h" | 26 | #include "fsclient.h" |
| 27 | #include "super.h" | 27 | #include "super.h" |
| 28 | #include "internal.h" | 28 | #include "internal.h" |
| 29 | 29 | ||
| 30 | #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ | 30 | #define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */ |
| 31 | 31 | ||
| 32 | struct afs_mount_params { | 32 | struct afs_mount_params { |
| 33 | int rwpath; | 33 | int rwpath; |
| 34 | struct afs_cell *default_cell; | 34 | struct afs_cell *default_cell; |
| 35 | struct afs_volume *volume; | 35 | struct afs_volume *volume; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | static void afs_i_init_once(void *foo, kmem_cache_t *cachep, | 38 | static void afs_i_init_once(void *foo, kmem_cache_t *cachep, |
| 39 | unsigned long flags); | 39 | unsigned long flags); |
| 40 | 40 | ||
| 41 | static struct super_block *afs_get_sb(struct file_system_type *fs_type, | 41 | static struct super_block *afs_get_sb(struct file_system_type *fs_type, |
| 42 | int flags, const char *dev_name, | 42 | int flags, const char *dev_name, |
| 43 | void *data); | 43 | void *data); |
| 44 | 44 | ||
| 45 | static struct inode *afs_alloc_inode(struct super_block *sb); | 45 | static struct inode *afs_alloc_inode(struct super_block *sb); |
| 46 | 46 | ||
| 47 | static void afs_put_super(struct super_block *sb); | 47 | static void afs_put_super(struct super_block *sb); |
| 48 | 48 | ||
| 49 | static void afs_destroy_inode(struct inode *inode); | 49 | static void afs_destroy_inode(struct inode *inode); |
| 50 | 50 | ||
| 51 | static struct file_system_type afs_fs_type = { | 51 | static struct file_system_type afs_fs_type = { |
| 52 | .owner = THIS_MODULE, | 52 | .owner = THIS_MODULE, |
| 53 | .name = "afs", | 53 | .name = "afs", |
| 54 | .get_sb = afs_get_sb, | 54 | .get_sb = afs_get_sb, |
| 55 | .kill_sb = kill_anon_super, | 55 | .kill_sb = kill_anon_super, |
| 56 | .fs_flags = FS_BINARY_MOUNTDATA, | 56 | .fs_flags = FS_BINARY_MOUNTDATA, |
| 57 | }; | 57 | }; |
| 58 | 58 | ||
| 59 | static struct super_operations afs_super_ops = { | 59 | static struct super_operations afs_super_ops = { |
| 60 | .statfs = simple_statfs, | 60 | .statfs = simple_statfs, |
| 61 | .alloc_inode = afs_alloc_inode, | 61 | .alloc_inode = afs_alloc_inode, |
| 62 | .drop_inode = generic_delete_inode, | 62 | .drop_inode = generic_delete_inode, |
| 63 | .destroy_inode = afs_destroy_inode, | 63 | .destroy_inode = afs_destroy_inode, |
| 64 | .clear_inode = afs_clear_inode, | 64 | .clear_inode = afs_clear_inode, |
| 65 | .put_super = afs_put_super, | 65 | .put_super = afs_put_super, |
| 66 | }; | 66 | }; |
| 67 | 67 | ||
| 68 | static kmem_cache_t *afs_inode_cachep; | 68 | static kmem_cache_t *afs_inode_cachep; |
| 69 | static atomic_t afs_count_active_inodes; | 69 | static atomic_t afs_count_active_inodes; |
| 70 | 70 | ||
| 71 | /*****************************************************************************/ | 71 | /*****************************************************************************/ |
| 72 | /* | 72 | /* |
| 73 | * initialise the filesystem | 73 | * initialise the filesystem |
| 74 | */ | 74 | */ |
| 75 | int __init afs_fs_init(void) | 75 | int __init afs_fs_init(void) |
| 76 | { | 76 | { |
| 77 | int ret; | 77 | int ret; |
| 78 | 78 | ||
| 79 | _enter(""); | 79 | _enter(""); |
| 80 | 80 | ||
| 81 | afs_timer_init(&afs_mntpt_expiry_timer, &afs_mntpt_expiry_timer_ops); | 81 | afs_timer_init(&afs_mntpt_expiry_timer, &afs_mntpt_expiry_timer_ops); |
| 82 | 82 | ||
| 83 | /* create ourselves an inode cache */ | 83 | /* create ourselves an inode cache */ |
| 84 | atomic_set(&afs_count_active_inodes, 0); | 84 | atomic_set(&afs_count_active_inodes, 0); |
| 85 | 85 | ||
| 86 | ret = -ENOMEM; | 86 | ret = -ENOMEM; |
| 87 | afs_inode_cachep = kmem_cache_create("afs_inode_cache", | 87 | afs_inode_cachep = kmem_cache_create("afs_inode_cache", |
| 88 | sizeof(struct afs_vnode), | 88 | sizeof(struct afs_vnode), |
| 89 | 0, | 89 | 0, |
| 90 | SLAB_HWCACHE_ALIGN, | 90 | SLAB_HWCACHE_ALIGN, |
| 91 | afs_i_init_once, | 91 | afs_i_init_once, |
| 92 | NULL); | 92 | NULL); |
| 93 | if (!afs_inode_cachep) { | 93 | if (!afs_inode_cachep) { |
| 94 | printk(KERN_NOTICE "kAFS: Failed to allocate inode cache\n"); | 94 | printk(KERN_NOTICE "kAFS: Failed to allocate inode cache\n"); |
| 95 | return ret; | 95 | return ret; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | /* now export our filesystem to lesser mortals */ | 98 | /* now export our filesystem to lesser mortals */ |
| 99 | ret = register_filesystem(&afs_fs_type); | 99 | ret = register_filesystem(&afs_fs_type); |
| 100 | if (ret < 0) { | 100 | if (ret < 0) { |
| 101 | kmem_cache_destroy(afs_inode_cachep); | 101 | kmem_cache_destroy(afs_inode_cachep); |
| 102 | kleave(" = %d", ret); | 102 | kleave(" = %d", ret); |
| 103 | return ret; | 103 | return ret; |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | kleave(" = 0"); | 106 | kleave(" = 0"); |
| 107 | return 0; | 107 | return 0; |
| 108 | } /* end afs_fs_init() */ | 108 | } /* end afs_fs_init() */ |
| 109 | 109 | ||
| 110 | /*****************************************************************************/ | 110 | /*****************************************************************************/ |
| 111 | /* | 111 | /* |
| 112 | * clean up the filesystem | 112 | * clean up the filesystem |
| 113 | */ | 113 | */ |
| 114 | void __exit afs_fs_exit(void) | 114 | void __exit afs_fs_exit(void) |
| 115 | { | 115 | { |
| 116 | unregister_filesystem(&afs_fs_type); | 116 | unregister_filesystem(&afs_fs_type); |
| 117 | 117 | ||
| 118 | if (atomic_read(&afs_count_active_inodes) != 0) { | 118 | if (atomic_read(&afs_count_active_inodes) != 0) { |
| 119 | printk("kAFS: %d active inode objects still present\n", | 119 | printk("kAFS: %d active inode objects still present\n", |
| 120 | atomic_read(&afs_count_active_inodes)); | 120 | atomic_read(&afs_count_active_inodes)); |
| 121 | BUG(); | 121 | BUG(); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | kmem_cache_destroy(afs_inode_cachep); | 124 | kmem_cache_destroy(afs_inode_cachep); |
| 125 | 125 | ||
| 126 | } /* end afs_fs_exit() */ | 126 | } /* end afs_fs_exit() */ |
| 127 | 127 | ||
| 128 | /*****************************************************************************/ | 128 | /*****************************************************************************/ |
| 129 | /* | 129 | /* |
| 130 | * check that an argument has a value | 130 | * check that an argument has a value |
| 131 | */ | 131 | */ |
| 132 | static int want_arg(char **_value, const char *option) | 132 | static int want_arg(char **_value, const char *option) |
| 133 | { | 133 | { |
| 134 | if (!_value || !*_value || !**_value) { | 134 | if (!_value || !*_value || !**_value) { |
| 135 | printk(KERN_NOTICE "kAFS: %s: argument missing\n", option); | 135 | printk(KERN_NOTICE "kAFS: %s: argument missing\n", option); |
| 136 | return 0; | 136 | return 0; |
| 137 | } | 137 | } |
| 138 | return 1; | 138 | return 1; |
| 139 | } /* end want_arg() */ | 139 | } /* end want_arg() */ |
| 140 | 140 | ||
| 141 | /*****************************************************************************/ | 141 | /*****************************************************************************/ |
| 142 | /* | 142 | /* |
| 143 | * check that there's no subsequent value | 143 | * check that there's no subsequent value |
| 144 | */ | 144 | */ |
| 145 | static int want_no_value(char *const *_value, const char *option) | 145 | static int want_no_value(char *const *_value, const char *option) |
| 146 | { | 146 | { |
| 147 | if (*_value && **_value) { | 147 | if (*_value && **_value) { |
| 148 | printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n", | 148 | printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n", |
| 149 | option, *_value); | 149 | option, *_value); |
| 150 | return 0; | 150 | return 0; |
| 151 | } | 151 | } |
| 152 | return 1; | 152 | return 1; |
| 153 | } /* end want_no_value() */ | 153 | } /* end want_no_value() */ |
| 154 | 154 | ||
| 155 | /*****************************************************************************/ | 155 | /*****************************************************************************/ |
| 156 | /* | 156 | /* |
| 157 | * parse the mount options | 157 | * parse the mount options |
| 158 | * - this function has been shamelessly adapted from the ext3 fs which | 158 | * - this function has been shamelessly adapted from the ext3 fs which |
| 159 | * shamelessly adapted it from the msdos fs | 159 | * shamelessly adapted it from the msdos fs |
| 160 | */ | 160 | */ |
| 161 | static int afs_super_parse_options(struct afs_mount_params *params, | 161 | static int afs_super_parse_options(struct afs_mount_params *params, |
| 162 | char *options, | 162 | char *options, |
| 163 | const char **devname) | 163 | const char **devname) |
| 164 | { | 164 | { |
| 165 | char *key, *value; | 165 | char *key, *value; |
| 166 | int ret; | 166 | int ret; |
| 167 | 167 | ||
| 168 | _enter("%s", options); | 168 | _enter("%s", options); |
| 169 | 169 | ||
| 170 | options[PAGE_SIZE - 1] = 0; | 170 | options[PAGE_SIZE - 1] = 0; |
| 171 | 171 | ||
| 172 | ret = 0; | 172 | ret = 0; |
| 173 | while ((key = strsep(&options, ",")) != 0) | 173 | while ((key = strsep(&options, ",")) != 0) |
| 174 | { | 174 | { |
| 175 | value = strchr(key, '='); | 175 | value = strchr(key, '='); |
| 176 | if (value) | 176 | if (value) |
| 177 | *value++ = 0; | 177 | *value++ = 0; |
| 178 | 178 | ||
| 179 | printk("kAFS: KEY: %s, VAL:%s\n", key, value ?: "-"); | 179 | printk("kAFS: KEY: %s, VAL:%s\n", key, value ?: "-"); |
| 180 | 180 | ||
| 181 | if (strcmp(key, "rwpath") == 0) { | 181 | if (strcmp(key, "rwpath") == 0) { |
| 182 | if (!want_no_value(&value, "rwpath")) | 182 | if (!want_no_value(&value, "rwpath")) |
| 183 | return -EINVAL; | 183 | return -EINVAL; |
| 184 | params->rwpath = 1; | 184 | params->rwpath = 1; |
| 185 | continue; | 185 | continue; |
| 186 | } | 186 | } |
| 187 | else if (strcmp(key, "vol") == 0) { | 187 | else if (strcmp(key, "vol") == 0) { |
| 188 | if (!want_arg(&value, "vol")) | 188 | if (!want_arg(&value, "vol")) |
| 189 | return -EINVAL; | 189 | return -EINVAL; |
| 190 | *devname = value; | 190 | *devname = value; |
| 191 | continue; | 191 | continue; |
| 192 | } | 192 | } |
| 193 | else if (strcmp(key, "cell") == 0) { | 193 | else if (strcmp(key, "cell") == 0) { |
| 194 | if (!want_arg(&value, "cell")) | 194 | if (!want_arg(&value, "cell")) |
| 195 | return -EINVAL; | 195 | return -EINVAL; |
| 196 | afs_put_cell(params->default_cell); | 196 | afs_put_cell(params->default_cell); |
| 197 | ret = afs_cell_lookup(value, | 197 | ret = afs_cell_lookup(value, |
| 198 | strlen(value), | 198 | strlen(value), |
| 199 | ¶ms->default_cell); | 199 | ¶ms->default_cell); |
| 200 | if (ret < 0) | 200 | if (ret < 0) |
| 201 | return -EINVAL; | 201 | return -EINVAL; |
| 202 | continue; | 202 | continue; |
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | printk("kAFS: Unknown mount option: '%s'\n", key); | 205 | printk("kAFS: Unknown mount option: '%s'\n", key); |
| 206 | ret = -EINVAL; | 206 | ret = -EINVAL; |
| 207 | goto error; | 207 | goto error; |
| 208 | } | 208 | } |
| 209 | 209 | ||
| 210 | ret = 0; | 210 | ret = 0; |
| 211 | 211 | ||
| 212 | error: | 212 | error: |
| 213 | _leave(" = %d", ret); | 213 | _leave(" = %d", ret); |
| 214 | return ret; | 214 | return ret; |
| 215 | } /* end afs_super_parse_options() */ | 215 | } /* end afs_super_parse_options() */ |
| 216 | 216 | ||
| 217 | /*****************************************************************************/ | 217 | /*****************************************************************************/ |
| 218 | /* | 218 | /* |
| 219 | * check a superblock to see if it's the one we're looking for | 219 | * check a superblock to see if it's the one we're looking for |
| 220 | */ | 220 | */ |
| 221 | static int afs_test_super(struct super_block *sb, void *data) | 221 | static int afs_test_super(struct super_block *sb, void *data) |
| 222 | { | 222 | { |
| 223 | struct afs_mount_params *params = data; | 223 | struct afs_mount_params *params = data; |
| 224 | struct afs_super_info *as = sb->s_fs_info; | 224 | struct afs_super_info *as = sb->s_fs_info; |
| 225 | 225 | ||
| 226 | return as->volume == params->volume; | 226 | return as->volume == params->volume; |
| 227 | } /* end afs_test_super() */ | 227 | } /* end afs_test_super() */ |
| 228 | 228 | ||
| 229 | /*****************************************************************************/ | 229 | /*****************************************************************************/ |
| 230 | /* | 230 | /* |
| 231 | * fill in the superblock | 231 | * fill in the superblock |
| 232 | */ | 232 | */ |
| 233 | static int afs_fill_super(struct super_block *sb, void *data, int silent) | 233 | static int afs_fill_super(struct super_block *sb, void *data, int silent) |
| 234 | { | 234 | { |
| 235 | struct afs_mount_params *params = data; | 235 | struct afs_mount_params *params = data; |
| 236 | struct afs_super_info *as = NULL; | 236 | struct afs_super_info *as = NULL; |
| 237 | struct afs_fid fid; | 237 | struct afs_fid fid; |
| 238 | struct dentry *root = NULL; | 238 | struct dentry *root = NULL; |
| 239 | struct inode *inode = NULL; | 239 | struct inode *inode = NULL; |
| 240 | int ret; | 240 | int ret; |
| 241 | 241 | ||
| 242 | kenter(""); | 242 | kenter(""); |
| 243 | 243 | ||
| 244 | /* allocate a superblock info record */ | 244 | /* allocate a superblock info record */ |
| 245 | as = kmalloc(sizeof(struct afs_super_info), GFP_KERNEL); | 245 | as = kmalloc(sizeof(struct afs_super_info), GFP_KERNEL); |
| 246 | if (!as) { | 246 | if (!as) { |
| 247 | _leave(" = -ENOMEM"); | 247 | _leave(" = -ENOMEM"); |
| 248 | return -ENOMEM; | 248 | return -ENOMEM; |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | memset(as, 0, sizeof(struct afs_super_info)); | 251 | memset(as, 0, sizeof(struct afs_super_info)); |
| 252 | 252 | ||
| 253 | afs_get_volume(params->volume); | 253 | afs_get_volume(params->volume); |
| 254 | as->volume = params->volume; | 254 | as->volume = params->volume; |
| 255 | 255 | ||
| 256 | /* fill in the superblock */ | 256 | /* fill in the superblock */ |
| 257 | sb->s_blocksize = PAGE_CACHE_SIZE; | 257 | sb->s_blocksize = PAGE_CACHE_SIZE; |
| 258 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 258 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
| 259 | sb->s_magic = AFS_FS_MAGIC; | 259 | sb->s_magic = AFS_FS_MAGIC; |
| 260 | sb->s_op = &afs_super_ops; | 260 | sb->s_op = &afs_super_ops; |
| 261 | sb->s_fs_info = as; | 261 | sb->s_fs_info = as; |
| 262 | 262 | ||
| 263 | /* allocate the root inode and dentry */ | 263 | /* allocate the root inode and dentry */ |
| 264 | fid.vid = as->volume->vid; | 264 | fid.vid = as->volume->vid; |
| 265 | fid.vnode = 1; | 265 | fid.vnode = 1; |
| 266 | fid.unique = 1; | 266 | fid.unique = 1; |
| 267 | ret = afs_iget(sb, &fid, &inode); | 267 | ret = afs_iget(sb, &fid, &inode); |
| 268 | if (ret < 0) | 268 | if (ret < 0) |
| 269 | goto error; | 269 | goto error; |
| 270 | 270 | ||
| 271 | ret = -ENOMEM; | 271 | ret = -ENOMEM; |
| 272 | root = d_alloc_root(inode); | 272 | root = d_alloc_root(inode); |
| 273 | if (!root) | 273 | if (!root) |
| 274 | goto error; | 274 | goto error; |
| 275 | 275 | ||
| 276 | sb->s_root = root; | 276 | sb->s_root = root; |
| 277 | 277 | ||
| 278 | kleave(" = 0"); | 278 | kleave(" = 0"); |
| 279 | return 0; | 279 | return 0; |
| 280 | 280 | ||
| 281 | error: | 281 | error: |
| 282 | iput(inode); | 282 | iput(inode); |
| 283 | afs_put_volume(as->volume); | 283 | afs_put_volume(as->volume); |
| 284 | kfree(as); | 284 | kfree(as); |
| 285 | 285 | ||
| 286 | sb->s_fs_info = NULL; | 286 | sb->s_fs_info = NULL; |
| 287 | 287 | ||
| 288 | kleave(" = %d", ret); | 288 | kleave(" = %d", ret); |
| 289 | return ret; | 289 | return ret; |
| 290 | } /* end afs_fill_super() */ | 290 | } /* end afs_fill_super() */ |
| 291 | 291 | ||
| 292 | /*****************************************************************************/ | 292 | /*****************************************************************************/ |
| 293 | /* | 293 | /* |
| 294 | * get an AFS superblock | 294 | * get an AFS superblock |
| 295 | * - TODO: don't use get_sb_nodev(), but rather call sget() directly | 295 | * - TODO: don't use get_sb_nodev(), but rather call sget() directly |
| 296 | */ | 296 | */ |
| 297 | static struct super_block *afs_get_sb(struct file_system_type *fs_type, | 297 | static struct super_block *afs_get_sb(struct file_system_type *fs_type, |
| 298 | int flags, | 298 | int flags, |
| 299 | const char *dev_name, | 299 | const char *dev_name, |
| 300 | void *options) | 300 | void *options) |
| 301 | { | 301 | { |
| 302 | struct afs_mount_params params; | 302 | struct afs_mount_params params; |
| 303 | struct super_block *sb; | 303 | struct super_block *sb; |
| 304 | int ret; | 304 | int ret; |
| 305 | 305 | ||
| 306 | _enter(",,%s,%p", dev_name, options); | 306 | _enter(",,%s,%p", dev_name, options); |
| 307 | 307 | ||
| 308 | memset(¶ms, 0, sizeof(params)); | 308 | memset(¶ms, 0, sizeof(params)); |
| 309 | 309 | ||
| 310 | /* start the cache manager */ | 310 | /* start the cache manager */ |
| 311 | ret = afscm_start(); | 311 | ret = afscm_start(); |
| 312 | if (ret < 0) { | 312 | if (ret < 0) { |
| 313 | _leave(" = %d", ret); | 313 | _leave(" = %d", ret); |
| 314 | return ERR_PTR(ret); | 314 | return ERR_PTR(ret); |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | /* parse the options */ | 317 | /* parse the options */ |
| 318 | if (options) { | 318 | if (options) { |
| 319 | ret = afs_super_parse_options(¶ms, options, &dev_name); | 319 | ret = afs_super_parse_options(¶ms, options, &dev_name); |
| 320 | if (ret < 0) | 320 | if (ret < 0) |
| 321 | goto error; | 321 | goto error; |
| 322 | if (!dev_name) { | 322 | if (!dev_name) { |
| 323 | printk("kAFS: no volume name specified\n"); | 323 | printk("kAFS: no volume name specified\n"); |
| 324 | ret = -EINVAL; | 324 | ret = -EINVAL; |
| 325 | goto error; | 325 | goto error; |
| 326 | } | 326 | } |
| 327 | } | 327 | } |
| 328 | 328 | ||
| 329 | /* parse the device name */ | 329 | /* parse the device name */ |
| 330 | ret = afs_volume_lookup(dev_name, | 330 | ret = afs_volume_lookup(dev_name, |
| 331 | params.default_cell, | 331 | params.default_cell, |
| 332 | params.rwpath, | 332 | params.rwpath, |
| 333 | ¶ms.volume); | 333 | ¶ms.volume); |
| 334 | if (ret < 0) | 334 | if (ret < 0) |
| 335 | goto error; | 335 | goto error; |
| 336 | 336 | ||
| 337 | /* allocate a deviceless superblock */ | 337 | /* allocate a deviceless superblock */ |
| 338 | sb = sget(fs_type, afs_test_super, set_anon_super, ¶ms); | 338 | sb = sget(fs_type, afs_test_super, set_anon_super, ¶ms); |
| 339 | if (IS_ERR(sb)) | 339 | if (IS_ERR(sb)) |
| 340 | goto error; | 340 | goto error; |
| 341 | 341 | ||
| 342 | sb->s_flags = flags; | 342 | sb->s_flags = flags; |
| 343 | 343 | ||
| 344 | ret = afs_fill_super(sb, ¶ms, flags & MS_VERBOSE ? 1 : 0); | 344 | ret = afs_fill_super(sb, ¶ms, flags & MS_SILENT ? 1 : 0); |
| 345 | if (ret < 0) { | 345 | if (ret < 0) { |
| 346 | up_write(&sb->s_umount); | 346 | up_write(&sb->s_umount); |
| 347 | deactivate_super(sb); | 347 | deactivate_super(sb); |
| 348 | goto error; | 348 | goto error; |
| 349 | } | 349 | } |
| 350 | sb->s_flags |= MS_ACTIVE; | 350 | sb->s_flags |= MS_ACTIVE; |
| 351 | 351 | ||
| 352 | afs_put_volume(params.volume); | 352 | afs_put_volume(params.volume); |
| 353 | afs_put_cell(params.default_cell); | 353 | afs_put_cell(params.default_cell); |
| 354 | _leave(" = %p", sb); | 354 | _leave(" = %p", sb); |
| 355 | return sb; | 355 | return sb; |
| 356 | 356 | ||
| 357 | error: | 357 | error: |
| 358 | afs_put_volume(params.volume); | 358 | afs_put_volume(params.volume); |
| 359 | afs_put_cell(params.default_cell); | 359 | afs_put_cell(params.default_cell); |
| 360 | afscm_stop(); | 360 | afscm_stop(); |
| 361 | _leave(" = %d", ret); | 361 | _leave(" = %d", ret); |
| 362 | return ERR_PTR(ret); | 362 | return ERR_PTR(ret); |
| 363 | } /* end afs_get_sb() */ | 363 | } /* end afs_get_sb() */ |
| 364 | 364 | ||
| 365 | /*****************************************************************************/ | 365 | /*****************************************************************************/ |
| 366 | /* | 366 | /* |
| 367 | * finish the unmounting process on the superblock | 367 | * finish the unmounting process on the superblock |
| 368 | */ | 368 | */ |
| 369 | static void afs_put_super(struct super_block *sb) | 369 | static void afs_put_super(struct super_block *sb) |
| 370 | { | 370 | { |
| 371 | struct afs_super_info *as = sb->s_fs_info; | 371 | struct afs_super_info *as = sb->s_fs_info; |
| 372 | 372 | ||
| 373 | _enter(""); | 373 | _enter(""); |
| 374 | 374 | ||
| 375 | afs_put_volume(as->volume); | 375 | afs_put_volume(as->volume); |
| 376 | afscm_stop(); | 376 | afscm_stop(); |
| 377 | 377 | ||
| 378 | _leave(""); | 378 | _leave(""); |
| 379 | } /* end afs_put_super() */ | 379 | } /* end afs_put_super() */ |
| 380 | 380 | ||
| 381 | /*****************************************************************************/ | 381 | /*****************************************************************************/ |
| 382 | /* | 382 | /* |
| 383 | * initialise an inode cache slab element prior to any use | 383 | * initialise an inode cache slab element prior to any use |
| 384 | */ | 384 | */ |
| 385 | static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep, | 385 | static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep, |
| 386 | unsigned long flags) | 386 | unsigned long flags) |
| 387 | { | 387 | { |
| 388 | struct afs_vnode *vnode = (struct afs_vnode *) _vnode; | 388 | struct afs_vnode *vnode = (struct afs_vnode *) _vnode; |
| 389 | 389 | ||
| 390 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | 390 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == |
| 391 | SLAB_CTOR_CONSTRUCTOR) { | 391 | SLAB_CTOR_CONSTRUCTOR) { |
| 392 | memset(vnode, 0, sizeof(*vnode)); | 392 | memset(vnode, 0, sizeof(*vnode)); |
| 393 | inode_init_once(&vnode->vfs_inode); | 393 | inode_init_once(&vnode->vfs_inode); |
| 394 | init_waitqueue_head(&vnode->update_waitq); | 394 | init_waitqueue_head(&vnode->update_waitq); |
| 395 | spin_lock_init(&vnode->lock); | 395 | spin_lock_init(&vnode->lock); |
| 396 | INIT_LIST_HEAD(&vnode->cb_link); | 396 | INIT_LIST_HEAD(&vnode->cb_link); |
| 397 | INIT_LIST_HEAD(&vnode->cb_hash_link); | 397 | INIT_LIST_HEAD(&vnode->cb_hash_link); |
| 398 | afs_timer_init(&vnode->cb_timeout, | 398 | afs_timer_init(&vnode->cb_timeout, |
| 399 | &afs_vnode_cb_timed_out_ops); | 399 | &afs_vnode_cb_timed_out_ops); |
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | } /* end afs_i_init_once() */ | 402 | } /* end afs_i_init_once() */ |
| 403 | 403 | ||
| 404 | /*****************************************************************************/ | 404 | /*****************************************************************************/ |
| 405 | /* | 405 | /* |
| 406 | * allocate an AFS inode struct from our slab cache | 406 | * allocate an AFS inode struct from our slab cache |
| 407 | */ | 407 | */ |
| 408 | static struct inode *afs_alloc_inode(struct super_block *sb) | 408 | static struct inode *afs_alloc_inode(struct super_block *sb) |
| 409 | { | 409 | { |
| 410 | struct afs_vnode *vnode; | 410 | struct afs_vnode *vnode; |
| 411 | 411 | ||
| 412 | vnode = (struct afs_vnode *) | 412 | vnode = (struct afs_vnode *) |
| 413 | kmem_cache_alloc(afs_inode_cachep, SLAB_KERNEL); | 413 | kmem_cache_alloc(afs_inode_cachep, SLAB_KERNEL); |
| 414 | if (!vnode) | 414 | if (!vnode) |
| 415 | return NULL; | 415 | return NULL; |
| 416 | 416 | ||
| 417 | atomic_inc(&afs_count_active_inodes); | 417 | atomic_inc(&afs_count_active_inodes); |
| 418 | 418 | ||
| 419 | memset(&vnode->fid, 0, sizeof(vnode->fid)); | 419 | memset(&vnode->fid, 0, sizeof(vnode->fid)); |
| 420 | memset(&vnode->status, 0, sizeof(vnode->status)); | 420 | memset(&vnode->status, 0, sizeof(vnode->status)); |
| 421 | 421 | ||
| 422 | vnode->volume = NULL; | 422 | vnode->volume = NULL; |
| 423 | vnode->update_cnt = 0; | 423 | vnode->update_cnt = 0; |
| 424 | vnode->flags = 0; | 424 | vnode->flags = 0; |
| 425 | 425 | ||
| 426 | return &vnode->vfs_inode; | 426 | return &vnode->vfs_inode; |
| 427 | } /* end afs_alloc_inode() */ | 427 | } /* end afs_alloc_inode() */ |
| 428 | 428 | ||
| 429 | /*****************************************************************************/ | 429 | /*****************************************************************************/ |
| 430 | /* | 430 | /* |
| 431 | * destroy an AFS inode struct | 431 | * destroy an AFS inode struct |
| 432 | */ | 432 | */ |
| 433 | static void afs_destroy_inode(struct inode *inode) | 433 | static void afs_destroy_inode(struct inode *inode) |
| 434 | { | 434 | { |
| 435 | _enter("{%lu}", inode->i_ino); | 435 | _enter("{%lu}", inode->i_ino); |
| 436 | 436 | ||
| 437 | kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode)); | 437 | kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode)); |
| 438 | 438 | ||
| 439 | atomic_dec(&afs_count_active_inodes); | 439 | atomic_dec(&afs_count_active_inodes); |
| 440 | 440 | ||
| 441 | } /* end afs_destroy_inode() */ | 441 | } /* end afs_destroy_inode() */ |
| 442 | 442 |
fs/cifs/cifsfs.c
| 1 | /* | 1 | /* |
| 2 | * fs/cifs/cifsfs.c | 2 | * fs/cifs/cifsfs.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) International Business Machines Corp., 2002,2004 | 4 | * Copyright (C) International Business Machines Corp., 2002,2004 |
| 5 | * Author(s): Steve French (sfrench@us.ibm.com) | 5 | * Author(s): Steve French (sfrench@us.ibm.com) |
| 6 | * | 6 | * |
| 7 | * Common Internet FileSystem (CIFS) client | 7 | * Common Internet FileSystem (CIFS) client |
| 8 | * | 8 | * |
| 9 | * This library is free software; you can redistribute it and/or modify | 9 | * This library is free software; you can redistribute it and/or modify |
| 10 | * it under the terms of the GNU Lesser General Public License as published | 10 | * it under the terms of the GNU Lesser General Public License as published |
| 11 | * by the Free Software Foundation; either version 2.1 of the License, or | 11 | * by the Free Software Foundation; either version 2.1 of the License, or |
| 12 | * (at your option) any later version. | 12 | * (at your option) any later version. |
| 13 | * | 13 | * |
| 14 | * This library is distributed in the hope that it will be useful, | 14 | * This library is distributed in the hope that it will be useful, |
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See | 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See |
| 17 | * the GNU Lesser General Public License for more details. | 17 | * the GNU Lesser General Public License for more details. |
| 18 | * | 18 | * |
| 19 | * You should have received a copy of the GNU Lesser General Public License | 19 | * You should have received a copy of the GNU Lesser General Public License |
| 20 | * along with this library; if not, write to the Free Software | 20 | * along with this library; if not, write to the Free Software |
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | /* Note that BB means BUGBUG (ie something to fix eventually) */ | 24 | /* Note that BB means BUGBUG (ie something to fix eventually) */ |
| 25 | 25 | ||
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
| 28 | #include <linux/mount.h> | 28 | #include <linux/mount.h> |
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
| 31 | #include <linux/list.h> | 31 | #include <linux/list.h> |
| 32 | #include <linux/seq_file.h> | 32 | #include <linux/seq_file.h> |
| 33 | #include <linux/vfs.h> | 33 | #include <linux/vfs.h> |
| 34 | #include <linux/mempool.h> | 34 | #include <linux/mempool.h> |
| 35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
| 36 | #include "cifsfs.h" | 36 | #include "cifsfs.h" |
| 37 | #include "cifspdu.h" | 37 | #include "cifspdu.h" |
| 38 | #define DECLARE_GLOBALS_HERE | 38 | #define DECLARE_GLOBALS_HERE |
| 39 | #include "cifsglob.h" | 39 | #include "cifsglob.h" |
| 40 | #include "cifsproto.h" | 40 | #include "cifsproto.h" |
| 41 | #include "cifs_debug.h" | 41 | #include "cifs_debug.h" |
| 42 | #include "cifs_fs_sb.h" | 42 | #include "cifs_fs_sb.h" |
| 43 | #include <linux/mm.h> | 43 | #include <linux/mm.h> |
| 44 | #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ | 44 | #define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */ |
| 45 | 45 | ||
| 46 | #ifdef CONFIG_CIFS_QUOTA | 46 | #ifdef CONFIG_CIFS_QUOTA |
| 47 | static struct quotactl_ops cifs_quotactl_ops; | 47 | static struct quotactl_ops cifs_quotactl_ops; |
| 48 | #endif | 48 | #endif |
| 49 | 49 | ||
| 50 | int cifsFYI = 0; | 50 | int cifsFYI = 0; |
| 51 | int cifsERROR = 1; | 51 | int cifsERROR = 1; |
| 52 | int traceSMB = 0; | 52 | int traceSMB = 0; |
| 53 | unsigned int oplockEnabled = 1; | 53 | unsigned int oplockEnabled = 1; |
| 54 | unsigned int experimEnabled = 0; | 54 | unsigned int experimEnabled = 0; |
| 55 | unsigned int linuxExtEnabled = 1; | 55 | unsigned int linuxExtEnabled = 1; |
| 56 | unsigned int lookupCacheEnabled = 1; | 56 | unsigned int lookupCacheEnabled = 1; |
| 57 | unsigned int multiuser_mount = 0; | 57 | unsigned int multiuser_mount = 0; |
| 58 | unsigned int extended_security = 0; | 58 | unsigned int extended_security = 0; |
| 59 | unsigned int ntlmv2_support = 0; | 59 | unsigned int ntlmv2_support = 0; |
| 60 | unsigned int sign_CIFS_PDUs = 1; | 60 | unsigned int sign_CIFS_PDUs = 1; |
| 61 | extern struct task_struct * oplockThread; /* remove sparse warning */ | 61 | extern struct task_struct * oplockThread; /* remove sparse warning */ |
| 62 | struct task_struct * oplockThread = NULL; | 62 | struct task_struct * oplockThread = NULL; |
| 63 | extern struct task_struct * dnotifyThread; /* remove sparse warning */ | 63 | extern struct task_struct * dnotifyThread; /* remove sparse warning */ |
| 64 | struct task_struct * dnotifyThread = NULL; | 64 | struct task_struct * dnotifyThread = NULL; |
| 65 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; | 65 | unsigned int CIFSMaxBufSize = CIFS_MAX_MSGSIZE; |
| 66 | module_param(CIFSMaxBufSize, int, 0); | 66 | module_param(CIFSMaxBufSize, int, 0); |
| 67 | MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); | 67 | MODULE_PARM_DESC(CIFSMaxBufSize,"Network buffer size (not including header). Default: 16384 Range: 8192 to 130048"); |
| 68 | unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; | 68 | unsigned int cifs_min_rcv = CIFS_MIN_RCV_POOL; |
| 69 | module_param(cifs_min_rcv, int, 0); | 69 | module_param(cifs_min_rcv, int, 0); |
| 70 | MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64"); | 70 | MODULE_PARM_DESC(cifs_min_rcv,"Network buffers in pool. Default: 4 Range: 1 to 64"); |
| 71 | unsigned int cifs_min_small = 30; | 71 | unsigned int cifs_min_small = 30; |
| 72 | module_param(cifs_min_small, int, 0); | 72 | module_param(cifs_min_small, int, 0); |
| 73 | MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256"); | 73 | MODULE_PARM_DESC(cifs_min_small,"Small network buffers in pool. Default: 30 Range: 2 to 256"); |
| 74 | unsigned int cifs_max_pending = CIFS_MAX_REQ; | 74 | unsigned int cifs_max_pending = CIFS_MAX_REQ; |
| 75 | module_param(cifs_max_pending, int, 0); | 75 | module_param(cifs_max_pending, int, 0); |
| 76 | MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256"); | 76 | MODULE_PARM_DESC(cifs_max_pending,"Simultaneous requests to server. Default: 50 Range: 2 to 256"); |
| 77 | 77 | ||
| 78 | static DECLARE_COMPLETION(cifs_oplock_exited); | 78 | static DECLARE_COMPLETION(cifs_oplock_exited); |
| 79 | static DECLARE_COMPLETION(cifs_dnotify_exited); | 79 | static DECLARE_COMPLETION(cifs_dnotify_exited); |
| 80 | 80 | ||
| 81 | extern mempool_t *cifs_sm_req_poolp; | 81 | extern mempool_t *cifs_sm_req_poolp; |
| 82 | extern mempool_t *cifs_req_poolp; | 82 | extern mempool_t *cifs_req_poolp; |
| 83 | extern mempool_t *cifs_mid_poolp; | 83 | extern mempool_t *cifs_mid_poolp; |
| 84 | 84 | ||
| 85 | extern kmem_cache_t *cifs_oplock_cachep; | 85 | extern kmem_cache_t *cifs_oplock_cachep; |
| 86 | 86 | ||
| 87 | static int | 87 | static int |
| 88 | cifs_read_super(struct super_block *sb, void *data, | 88 | cifs_read_super(struct super_block *sb, void *data, |
| 89 | const char *devname, int silent) | 89 | const char *devname, int silent) |
| 90 | { | 90 | { |
| 91 | struct inode *inode; | 91 | struct inode *inode; |
| 92 | struct cifs_sb_info *cifs_sb; | 92 | struct cifs_sb_info *cifs_sb; |
| 93 | int rc = 0; | 93 | int rc = 0; |
| 94 | 94 | ||
| 95 | sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ | 95 | sb->s_flags |= MS_NODIRATIME; /* and probably even noatime */ |
| 96 | sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); | 96 | sb->s_fs_info = kmalloc(sizeof(struct cifs_sb_info),GFP_KERNEL); |
| 97 | cifs_sb = CIFS_SB(sb); | 97 | cifs_sb = CIFS_SB(sb); |
| 98 | if(cifs_sb == NULL) | 98 | if(cifs_sb == NULL) |
| 99 | return -ENOMEM; | 99 | return -ENOMEM; |
| 100 | else | 100 | else |
| 101 | memset(cifs_sb,0,sizeof(struct cifs_sb_info)); | 101 | memset(cifs_sb,0,sizeof(struct cifs_sb_info)); |
| 102 | 102 | ||
| 103 | 103 | ||
| 104 | rc = cifs_mount(sb, cifs_sb, data, devname); | 104 | rc = cifs_mount(sb, cifs_sb, data, devname); |
| 105 | 105 | ||
| 106 | if (rc) { | 106 | if (rc) { |
| 107 | if (!silent) | 107 | if (!silent) |
| 108 | cERROR(1, | 108 | cERROR(1, |
| 109 | ("cifs_mount failed w/return code = %d", rc)); | 109 | ("cifs_mount failed w/return code = %d", rc)); |
| 110 | goto out_mount_failed; | 110 | goto out_mount_failed; |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | sb->s_magic = CIFS_MAGIC_NUMBER; | 113 | sb->s_magic = CIFS_MAGIC_NUMBER; |
| 114 | sb->s_op = &cifs_super_ops; | 114 | sb->s_op = &cifs_super_ops; |
| 115 | /* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) | 115 | /* if(cifs_sb->tcon->ses->server->maxBuf > MAX_CIFS_HDR_SIZE + 512) |
| 116 | sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ | 116 | sb->s_blocksize = cifs_sb->tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE; */ |
| 117 | #ifdef CONFIG_CIFS_QUOTA | 117 | #ifdef CONFIG_CIFS_QUOTA |
| 118 | sb->s_qcop = &cifs_quotactl_ops; | 118 | sb->s_qcop = &cifs_quotactl_ops; |
| 119 | #endif | 119 | #endif |
| 120 | sb->s_blocksize = CIFS_MAX_MSGSIZE; | 120 | sb->s_blocksize = CIFS_MAX_MSGSIZE; |
| 121 | sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ | 121 | sb->s_blocksize_bits = 14; /* default 2**14 = CIFS_MAX_MSGSIZE */ |
| 122 | inode = iget(sb, ROOT_I); | 122 | inode = iget(sb, ROOT_I); |
| 123 | 123 | ||
| 124 | if (!inode) { | 124 | if (!inode) { |
| 125 | rc = -ENOMEM; | 125 | rc = -ENOMEM; |
| 126 | goto out_no_root; | 126 | goto out_no_root; |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | sb->s_root = d_alloc_root(inode); | 129 | sb->s_root = d_alloc_root(inode); |
| 130 | 130 | ||
| 131 | if (!sb->s_root) { | 131 | if (!sb->s_root) { |
| 132 | rc = -ENOMEM; | 132 | rc = -ENOMEM; |
| 133 | goto out_no_root; | 133 | goto out_no_root; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | return 0; | 136 | return 0; |
| 137 | 137 | ||
| 138 | out_no_root: | 138 | out_no_root: |
| 139 | cERROR(1, ("cifs_read_super: get root inode failed")); | 139 | cERROR(1, ("cifs_read_super: get root inode failed")); |
| 140 | if (inode) | 140 | if (inode) |
| 141 | iput(inode); | 141 | iput(inode); |
| 142 | 142 | ||
| 143 | out_mount_failed: | 143 | out_mount_failed: |
| 144 | if(cifs_sb) { | 144 | if(cifs_sb) { |
| 145 | if(cifs_sb->local_nls) | 145 | if(cifs_sb->local_nls) |
| 146 | unload_nls(cifs_sb->local_nls); | 146 | unload_nls(cifs_sb->local_nls); |
| 147 | kfree(cifs_sb); | 147 | kfree(cifs_sb); |
| 148 | } | 148 | } |
| 149 | return rc; | 149 | return rc; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | static void | 152 | static void |
| 153 | cifs_put_super(struct super_block *sb) | 153 | cifs_put_super(struct super_block *sb) |
| 154 | { | 154 | { |
| 155 | int rc = 0; | 155 | int rc = 0; |
| 156 | struct cifs_sb_info *cifs_sb; | 156 | struct cifs_sb_info *cifs_sb; |
| 157 | 157 | ||
| 158 | cFYI(1, ("In cifs_put_super")); | 158 | cFYI(1, ("In cifs_put_super")); |
| 159 | cifs_sb = CIFS_SB(sb); | 159 | cifs_sb = CIFS_SB(sb); |
| 160 | if(cifs_sb == NULL) { | 160 | if(cifs_sb == NULL) { |
| 161 | cFYI(1,("Empty cifs superblock info passed to unmount")); | 161 | cFYI(1,("Empty cifs superblock info passed to unmount")); |
| 162 | return; | 162 | return; |
| 163 | } | 163 | } |
| 164 | rc = cifs_umount(sb, cifs_sb); | 164 | rc = cifs_umount(sb, cifs_sb); |
| 165 | if (rc) { | 165 | if (rc) { |
| 166 | cERROR(1, ("cifs_umount failed with return code %d", rc)); | 166 | cERROR(1, ("cifs_umount failed with return code %d", rc)); |
| 167 | } | 167 | } |
| 168 | unload_nls(cifs_sb->local_nls); | 168 | unload_nls(cifs_sb->local_nls); |
| 169 | kfree(cifs_sb); | 169 | kfree(cifs_sb); |
| 170 | return; | 170 | return; |
| 171 | } | 171 | } |
| 172 | 172 | ||
| 173 | static int | 173 | static int |
| 174 | cifs_statfs(struct super_block *sb, struct kstatfs *buf) | 174 | cifs_statfs(struct super_block *sb, struct kstatfs *buf) |
| 175 | { | 175 | { |
| 176 | int xid; | 176 | int xid; |
| 177 | int rc = -EOPNOTSUPP; | 177 | int rc = -EOPNOTSUPP; |
| 178 | struct cifs_sb_info *cifs_sb; | 178 | struct cifs_sb_info *cifs_sb; |
| 179 | struct cifsTconInfo *pTcon; | 179 | struct cifsTconInfo *pTcon; |
| 180 | 180 | ||
| 181 | xid = GetXid(); | 181 | xid = GetXid(); |
| 182 | 182 | ||
| 183 | cifs_sb = CIFS_SB(sb); | 183 | cifs_sb = CIFS_SB(sb); |
| 184 | pTcon = cifs_sb->tcon; | 184 | pTcon = cifs_sb->tcon; |
| 185 | 185 | ||
| 186 | buf->f_type = CIFS_MAGIC_NUMBER; | 186 | buf->f_type = CIFS_MAGIC_NUMBER; |
| 187 | 187 | ||
| 188 | /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */ | 188 | /* instead could get the real value via SMB_QUERY_FS_ATTRIBUTE_INFO */ |
| 189 | buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would | 189 | buf->f_namelen = PATH_MAX; /* PATH_MAX may be too long - it would |
| 190 | presumably be total path, but note | 190 | presumably be total path, but note |
| 191 | that some servers (includinng Samba 3) | 191 | that some servers (includinng Samba 3) |
| 192 | have a shorter maximum path */ | 192 | have a shorter maximum path */ |
| 193 | buf->f_files = 0; /* undefined */ | 193 | buf->f_files = 0; /* undefined */ |
| 194 | buf->f_ffree = 0; /* unlimited */ | 194 | buf->f_ffree = 0; /* unlimited */ |
| 195 | 195 | ||
| 196 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 196 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 197 | /* BB we could add a second check for a QFS Unix capability bit */ | 197 | /* BB we could add a second check for a QFS Unix capability bit */ |
| 198 | /* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */ | 198 | /* BB FIXME check CIFS_POSIX_EXTENSIONS Unix cap first FIXME BB */ |
| 199 | if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS & | 199 | if ((pTcon->ses->capabilities & CAP_UNIX) && (CIFS_POSIX_EXTENSIONS & |
| 200 | le64_to_cpu(pTcon->fsUnixInfo.Capability))) | 200 | le64_to_cpu(pTcon->fsUnixInfo.Capability))) |
| 201 | rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf); | 201 | rc = CIFSSMBQFSPosixInfo(xid, pTcon, buf); |
| 202 | 202 | ||
| 203 | /* Only need to call the old QFSInfo if failed | 203 | /* Only need to call the old QFSInfo if failed |
| 204 | on newer one */ | 204 | on newer one */ |
| 205 | if(rc) | 205 | if(rc) |
| 206 | #endif /* CIFS_EXPERIMENTAL */ | 206 | #endif /* CIFS_EXPERIMENTAL */ |
| 207 | rc = CIFSSMBQFSInfo(xid, pTcon, buf); | 207 | rc = CIFSSMBQFSInfo(xid, pTcon, buf); |
| 208 | 208 | ||
| 209 | /* Old Windows servers do not support level 103, retry with level | 209 | /* Old Windows servers do not support level 103, retry with level |
| 210 | one if old server failed the previous call */ | 210 | one if old server failed the previous call */ |
| 211 | if(rc) | 211 | if(rc) |
| 212 | rc = SMBOldQFSInfo(xid, pTcon, buf); | 212 | rc = SMBOldQFSInfo(xid, pTcon, buf); |
| 213 | /* | 213 | /* |
| 214 | int f_type; | 214 | int f_type; |
| 215 | __fsid_t f_fsid; | 215 | __fsid_t f_fsid; |
| 216 | int f_namelen; */ | 216 | int f_namelen; */ |
| 217 | /* BB get from info in tcon struct at mount time call to QFSAttrInfo */ | 217 | /* BB get from info in tcon struct at mount time call to QFSAttrInfo */ |
| 218 | FreeXid(xid); | 218 | FreeXid(xid); |
| 219 | return 0; /* always return success? what if volume is no | 219 | return 0; /* always return success? what if volume is no |
| 220 | longer available? */ | 220 | longer available? */ |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) | 223 | static int cifs_permission(struct inode * inode, int mask, struct nameidata *nd) |
| 224 | { | 224 | { |
| 225 | struct cifs_sb_info *cifs_sb; | 225 | struct cifs_sb_info *cifs_sb; |
| 226 | 226 | ||
| 227 | cifs_sb = CIFS_SB(inode->i_sb); | 227 | cifs_sb = CIFS_SB(inode->i_sb); |
| 228 | 228 | ||
| 229 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { | 229 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { |
| 230 | return 0; | 230 | return 0; |
| 231 | } else /* file mode might have been restricted at mount time | 231 | } else /* file mode might have been restricted at mount time |
| 232 | on the client (above and beyond ACL on servers) for | 232 | on the client (above and beyond ACL on servers) for |
| 233 | servers which do not support setting and viewing mode bits, | 233 | servers which do not support setting and viewing mode bits, |
| 234 | so allowing client to check permissions is useful */ | 234 | so allowing client to check permissions is useful */ |
| 235 | return generic_permission(inode, mask, NULL); | 235 | return generic_permission(inode, mask, NULL); |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | static kmem_cache_t *cifs_inode_cachep; | 238 | static kmem_cache_t *cifs_inode_cachep; |
| 239 | static kmem_cache_t *cifs_req_cachep; | 239 | static kmem_cache_t *cifs_req_cachep; |
| 240 | static kmem_cache_t *cifs_mid_cachep; | 240 | static kmem_cache_t *cifs_mid_cachep; |
| 241 | kmem_cache_t *cifs_oplock_cachep; | 241 | kmem_cache_t *cifs_oplock_cachep; |
| 242 | static kmem_cache_t *cifs_sm_req_cachep; | 242 | static kmem_cache_t *cifs_sm_req_cachep; |
| 243 | mempool_t *cifs_sm_req_poolp; | 243 | mempool_t *cifs_sm_req_poolp; |
| 244 | mempool_t *cifs_req_poolp; | 244 | mempool_t *cifs_req_poolp; |
| 245 | mempool_t *cifs_mid_poolp; | 245 | mempool_t *cifs_mid_poolp; |
| 246 | 246 | ||
| 247 | static struct inode * | 247 | static struct inode * |
| 248 | cifs_alloc_inode(struct super_block *sb) | 248 | cifs_alloc_inode(struct super_block *sb) |
| 249 | { | 249 | { |
| 250 | struct cifsInodeInfo *cifs_inode; | 250 | struct cifsInodeInfo *cifs_inode; |
| 251 | cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL); | 251 | cifs_inode = kmem_cache_alloc(cifs_inode_cachep, SLAB_KERNEL); |
| 252 | if (!cifs_inode) | 252 | if (!cifs_inode) |
| 253 | return NULL; | 253 | return NULL; |
| 254 | cifs_inode->cifsAttrs = 0x20; /* default */ | 254 | cifs_inode->cifsAttrs = 0x20; /* default */ |
| 255 | atomic_set(&cifs_inode->inUse, 0); | 255 | atomic_set(&cifs_inode->inUse, 0); |
| 256 | cifs_inode->time = 0; | 256 | cifs_inode->time = 0; |
| 257 | /* Until the file is open and we have gotten oplock | 257 | /* Until the file is open and we have gotten oplock |
| 258 | info back from the server, can not assume caching of | 258 | info back from the server, can not assume caching of |
| 259 | file data or metadata */ | 259 | file data or metadata */ |
| 260 | cifs_inode->clientCanCacheRead = FALSE; | 260 | cifs_inode->clientCanCacheRead = FALSE; |
| 261 | cifs_inode->clientCanCacheAll = FALSE; | 261 | cifs_inode->clientCanCacheAll = FALSE; |
| 262 | cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE; | 262 | cifs_inode->vfs_inode.i_blksize = CIFS_MAX_MSGSIZE; |
| 263 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ | 263 | cifs_inode->vfs_inode.i_blkbits = 14; /* 2**14 = CIFS_MAX_MSGSIZE */ |
| 264 | cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; | 264 | cifs_inode->vfs_inode.i_flags = S_NOATIME | S_NOCMTIME; |
| 265 | INIT_LIST_HEAD(&cifs_inode->openFileList); | 265 | INIT_LIST_HEAD(&cifs_inode->openFileList); |
| 266 | return &cifs_inode->vfs_inode; | 266 | return &cifs_inode->vfs_inode; |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | static void | 269 | static void |
| 270 | cifs_destroy_inode(struct inode *inode) | 270 | cifs_destroy_inode(struct inode *inode) |
| 271 | { | 271 | { |
| 272 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); | 272 | kmem_cache_free(cifs_inode_cachep, CIFS_I(inode)); |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | /* | 275 | /* |
| 276 | * cifs_show_options() is for displaying mount options in /proc/mounts. | 276 | * cifs_show_options() is for displaying mount options in /proc/mounts. |
| 277 | * Not all settable options are displayed but most of the important | 277 | * Not all settable options are displayed but most of the important |
| 278 | * ones are. | 278 | * ones are. |
| 279 | */ | 279 | */ |
| 280 | static int | 280 | static int |
| 281 | cifs_show_options(struct seq_file *s, struct vfsmount *m) | 281 | cifs_show_options(struct seq_file *s, struct vfsmount *m) |
| 282 | { | 282 | { |
| 283 | struct cifs_sb_info *cifs_sb; | 283 | struct cifs_sb_info *cifs_sb; |
| 284 | 284 | ||
| 285 | cifs_sb = CIFS_SB(m->mnt_sb); | 285 | cifs_sb = CIFS_SB(m->mnt_sb); |
| 286 | 286 | ||
| 287 | if (cifs_sb) { | 287 | if (cifs_sb) { |
| 288 | if (cifs_sb->tcon) { | 288 | if (cifs_sb->tcon) { |
| 289 | seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); | 289 | seq_printf(s, ",unc=%s", cifs_sb->tcon->treeName); |
| 290 | if (cifs_sb->tcon->ses) { | 290 | if (cifs_sb->tcon->ses) { |
| 291 | if (cifs_sb->tcon->ses->userName) | 291 | if (cifs_sb->tcon->ses->userName) |
| 292 | seq_printf(s, ",username=%s", | 292 | seq_printf(s, ",username=%s", |
| 293 | cifs_sb->tcon->ses->userName); | 293 | cifs_sb->tcon->ses->userName); |
| 294 | if(cifs_sb->tcon->ses->domainName) | 294 | if(cifs_sb->tcon->ses->domainName) |
| 295 | seq_printf(s, ",domain=%s", | 295 | seq_printf(s, ",domain=%s", |
| 296 | cifs_sb->tcon->ses->domainName); | 296 | cifs_sb->tcon->ses->domainName); |
| 297 | } | 297 | } |
| 298 | } | 298 | } |
| 299 | seq_printf(s, ",rsize=%d",cifs_sb->rsize); | 299 | seq_printf(s, ",rsize=%d",cifs_sb->rsize); |
| 300 | seq_printf(s, ",wsize=%d",cifs_sb->wsize); | 300 | seq_printf(s, ",wsize=%d",cifs_sb->wsize); |
| 301 | } | 301 | } |
| 302 | return 0; | 302 | return 0; |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | #ifdef CONFIG_CIFS_QUOTA | 305 | #ifdef CONFIG_CIFS_QUOTA |
| 306 | int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid, | 306 | int cifs_xquota_set(struct super_block * sb, int quota_type, qid_t qid, |
| 307 | struct fs_disk_quota * pdquota) | 307 | struct fs_disk_quota * pdquota) |
| 308 | { | 308 | { |
| 309 | int xid; | 309 | int xid; |
| 310 | int rc = 0; | 310 | int rc = 0; |
| 311 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 311 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 312 | struct cifsTconInfo *pTcon; | 312 | struct cifsTconInfo *pTcon; |
| 313 | 313 | ||
| 314 | if(cifs_sb) | 314 | if(cifs_sb) |
| 315 | pTcon = cifs_sb->tcon; | 315 | pTcon = cifs_sb->tcon; |
| 316 | else | 316 | else |
| 317 | return -EIO; | 317 | return -EIO; |
| 318 | 318 | ||
| 319 | 319 | ||
| 320 | xid = GetXid(); | 320 | xid = GetXid(); |
| 321 | if(pTcon) { | 321 | if(pTcon) { |
| 322 | cFYI(1,("set type: 0x%x id: %d",quota_type,qid)); | 322 | cFYI(1,("set type: 0x%x id: %d",quota_type,qid)); |
| 323 | } else { | 323 | } else { |
| 324 | return -EIO; | 324 | return -EIO; |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | FreeXid(xid); | 327 | FreeXid(xid); |
| 328 | return rc; | 328 | return rc; |
| 329 | } | 329 | } |
| 330 | 330 | ||
| 331 | int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid, | 331 | int cifs_xquota_get(struct super_block * sb, int quota_type, qid_t qid, |
| 332 | struct fs_disk_quota * pdquota) | 332 | struct fs_disk_quota * pdquota) |
| 333 | { | 333 | { |
| 334 | int xid; | 334 | int xid; |
| 335 | int rc = 0; | 335 | int rc = 0; |
| 336 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 336 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 337 | struct cifsTconInfo *pTcon; | 337 | struct cifsTconInfo *pTcon; |
| 338 | 338 | ||
| 339 | if(cifs_sb) | 339 | if(cifs_sb) |
| 340 | pTcon = cifs_sb->tcon; | 340 | pTcon = cifs_sb->tcon; |
| 341 | else | 341 | else |
| 342 | return -EIO; | 342 | return -EIO; |
| 343 | 343 | ||
| 344 | xid = GetXid(); | 344 | xid = GetXid(); |
| 345 | if(pTcon) { | 345 | if(pTcon) { |
| 346 | cFYI(1,("set type: 0x%x id: %d",quota_type,qid)); | 346 | cFYI(1,("set type: 0x%x id: %d",quota_type,qid)); |
| 347 | } else { | 347 | } else { |
| 348 | rc = -EIO; | 348 | rc = -EIO; |
| 349 | } | 349 | } |
| 350 | 350 | ||
| 351 | FreeXid(xid); | 351 | FreeXid(xid); |
| 352 | return rc; | 352 | return rc; |
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation) | 355 | int cifs_xstate_set(struct super_block * sb, unsigned int flags, int operation) |
| 356 | { | 356 | { |
| 357 | int xid; | 357 | int xid; |
| 358 | int rc = 0; | 358 | int rc = 0; |
| 359 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 359 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 360 | struct cifsTconInfo *pTcon; | 360 | struct cifsTconInfo *pTcon; |
| 361 | 361 | ||
| 362 | if(cifs_sb) | 362 | if(cifs_sb) |
| 363 | pTcon = cifs_sb->tcon; | 363 | pTcon = cifs_sb->tcon; |
| 364 | else | 364 | else |
| 365 | return -EIO; | 365 | return -EIO; |
| 366 | 366 | ||
| 367 | xid = GetXid(); | 367 | xid = GetXid(); |
| 368 | if(pTcon) { | 368 | if(pTcon) { |
| 369 | cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation)); | 369 | cFYI(1,("flags: 0x%x operation: 0x%x",flags,operation)); |
| 370 | } else { | 370 | } else { |
| 371 | rc = -EIO; | 371 | rc = -EIO; |
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | FreeXid(xid); | 374 | FreeXid(xid); |
| 375 | return rc; | 375 | return rc; |
| 376 | } | 376 | } |
| 377 | 377 | ||
| 378 | int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats) | 378 | int cifs_xstate_get(struct super_block * sb, struct fs_quota_stat *qstats) |
| 379 | { | 379 | { |
| 380 | int xid; | 380 | int xid; |
| 381 | int rc = 0; | 381 | int rc = 0; |
| 382 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); | 382 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 383 | struct cifsTconInfo *pTcon; | 383 | struct cifsTconInfo *pTcon; |
| 384 | 384 | ||
| 385 | if(cifs_sb) { | 385 | if(cifs_sb) { |
| 386 | pTcon = cifs_sb->tcon; | 386 | pTcon = cifs_sb->tcon; |
| 387 | } else { | 387 | } else { |
| 388 | return -EIO; | 388 | return -EIO; |
| 389 | } | 389 | } |
| 390 | xid = GetXid(); | 390 | xid = GetXid(); |
| 391 | if(pTcon) { | 391 | if(pTcon) { |
| 392 | cFYI(1,("pqstats %p",qstats)); | 392 | cFYI(1,("pqstats %p",qstats)); |
| 393 | } else { | 393 | } else { |
| 394 | rc = -EIO; | 394 | rc = -EIO; |
| 395 | } | 395 | } |
| 396 | 396 | ||
| 397 | FreeXid(xid); | 397 | FreeXid(xid); |
| 398 | return rc; | 398 | return rc; |
| 399 | } | 399 | } |
| 400 | 400 | ||
| 401 | static struct quotactl_ops cifs_quotactl_ops = { | 401 | static struct quotactl_ops cifs_quotactl_ops = { |
| 402 | .set_xquota = cifs_xquota_set, | 402 | .set_xquota = cifs_xquota_set, |
| 403 | .get_xquota = cifs_xquota_set, | 403 | .get_xquota = cifs_xquota_set, |
| 404 | .set_xstate = cifs_xstate_set, | 404 | .set_xstate = cifs_xstate_set, |
| 405 | .get_xstate = cifs_xstate_get, | 405 | .get_xstate = cifs_xstate_get, |
| 406 | }; | 406 | }; |
| 407 | #endif | 407 | #endif |
| 408 | 408 | ||
| 409 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 409 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 410 | static void cifs_umount_begin(struct super_block * sblock) | 410 | static void cifs_umount_begin(struct super_block * sblock) |
| 411 | { | 411 | { |
| 412 | struct cifs_sb_info *cifs_sb; | 412 | struct cifs_sb_info *cifs_sb; |
| 413 | struct cifsTconInfo * tcon; | 413 | struct cifsTconInfo * tcon; |
| 414 | 414 | ||
| 415 | cifs_sb = CIFS_SB(sblock); | 415 | cifs_sb = CIFS_SB(sblock); |
| 416 | if(cifs_sb == NULL) | 416 | if(cifs_sb == NULL) |
| 417 | return; | 417 | return; |
| 418 | 418 | ||
| 419 | tcon = cifs_sb->tcon; | 419 | tcon = cifs_sb->tcon; |
| 420 | if(tcon == NULL) | 420 | if(tcon == NULL) |
| 421 | return; | 421 | return; |
| 422 | down(&tcon->tconSem); | 422 | down(&tcon->tconSem); |
| 423 | if (atomic_read(&tcon->useCount) == 1) | 423 | if (atomic_read(&tcon->useCount) == 1) |
| 424 | tcon->tidStatus = CifsExiting; | 424 | tcon->tidStatus = CifsExiting; |
| 425 | up(&tcon->tconSem); | 425 | up(&tcon->tconSem); |
| 426 | 426 | ||
| 427 | /* cancel_brl_requests(tcon); */ | 427 | /* cancel_brl_requests(tcon); */ |
| 428 | /* cancel_notify_requests(tcon); */ | 428 | /* cancel_notify_requests(tcon); */ |
| 429 | if(tcon->ses && tcon->ses->server) | 429 | if(tcon->ses && tcon->ses->server) |
| 430 | { | 430 | { |
| 431 | cFYI(1,("wake up tasks now - umount begin not complete")); | 431 | cFYI(1,("wake up tasks now - umount begin not complete")); |
| 432 | wake_up_all(&tcon->ses->server->request_q); | 432 | wake_up_all(&tcon->ses->server->request_q); |
| 433 | wake_up_all(&tcon->ses->server->response_q); | 433 | wake_up_all(&tcon->ses->server->response_q); |
| 434 | msleep(1); /* yield */ | 434 | msleep(1); /* yield */ |
| 435 | /* we have to kick the requests once more */ | 435 | /* we have to kick the requests once more */ |
| 436 | wake_up_all(&tcon->ses->server->response_q); | 436 | wake_up_all(&tcon->ses->server->response_q); |
| 437 | msleep(1); | 437 | msleep(1); |
| 438 | } | 438 | } |
| 439 | /* BB FIXME - finish add checks for tidStatus BB */ | 439 | /* BB FIXME - finish add checks for tidStatus BB */ |
| 440 | 440 | ||
| 441 | return; | 441 | return; |
| 442 | } | 442 | } |
| 443 | #endif | 443 | #endif |
| 444 | 444 | ||
| 445 | static int cifs_remount(struct super_block *sb, int *flags, char *data) | 445 | static int cifs_remount(struct super_block *sb, int *flags, char *data) |
| 446 | { | 446 | { |
| 447 | *flags |= MS_NODIRATIME; | 447 | *flags |= MS_NODIRATIME; |
| 448 | return 0; | 448 | return 0; |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | struct super_operations cifs_super_ops = { | 451 | struct super_operations cifs_super_ops = { |
| 452 | .read_inode = cifs_read_inode, | 452 | .read_inode = cifs_read_inode, |
| 453 | .put_super = cifs_put_super, | 453 | .put_super = cifs_put_super, |
| 454 | .statfs = cifs_statfs, | 454 | .statfs = cifs_statfs, |
| 455 | .alloc_inode = cifs_alloc_inode, | 455 | .alloc_inode = cifs_alloc_inode, |
| 456 | .destroy_inode = cifs_destroy_inode, | 456 | .destroy_inode = cifs_destroy_inode, |
| 457 | /* .drop_inode = generic_delete_inode, | 457 | /* .drop_inode = generic_delete_inode, |
| 458 | .delete_inode = cifs_delete_inode, *//* Do not need the above two functions | 458 | .delete_inode = cifs_delete_inode, *//* Do not need the above two functions |
| 459 | unless later we add lazy close of inodes or unless the kernel forgets to call | 459 | unless later we add lazy close of inodes or unless the kernel forgets to call |
| 460 | us with the same number of releases (closes) as opens */ | 460 | us with the same number of releases (closes) as opens */ |
| 461 | .show_options = cifs_show_options, | 461 | .show_options = cifs_show_options, |
| 462 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 462 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 463 | .umount_begin = cifs_umount_begin, | 463 | .umount_begin = cifs_umount_begin, |
| 464 | #endif | 464 | #endif |
| 465 | .remount_fs = cifs_remount, | 465 | .remount_fs = cifs_remount, |
| 466 | }; | 466 | }; |
| 467 | 467 | ||
| 468 | static struct super_block * | 468 | static struct super_block * |
| 469 | cifs_get_sb(struct file_system_type *fs_type, | 469 | cifs_get_sb(struct file_system_type *fs_type, |
| 470 | int flags, const char *dev_name, void *data) | 470 | int flags, const char *dev_name, void *data) |
| 471 | { | 471 | { |
| 472 | int rc; | 472 | int rc; |
| 473 | struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); | 473 | struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); |
| 474 | 474 | ||
| 475 | cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); | 475 | cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); |
| 476 | 476 | ||
| 477 | if (IS_ERR(sb)) | 477 | if (IS_ERR(sb)) |
| 478 | return sb; | 478 | return sb; |
| 479 | 479 | ||
| 480 | sb->s_flags = flags; | 480 | sb->s_flags = flags; |
| 481 | 481 | ||
| 482 | rc = cifs_read_super(sb, data, dev_name, flags & MS_VERBOSE ? 1 : 0); | 482 | rc = cifs_read_super(sb, data, dev_name, flags & MS_SILENT ? 1 : 0); |
| 483 | if (rc) { | 483 | if (rc) { |
| 484 | up_write(&sb->s_umount); | 484 | up_write(&sb->s_umount); |
| 485 | deactivate_super(sb); | 485 | deactivate_super(sb); |
| 486 | return ERR_PTR(rc); | 486 | return ERR_PTR(rc); |
| 487 | } | 487 | } |
| 488 | sb->s_flags |= MS_ACTIVE; | 488 | sb->s_flags |= MS_ACTIVE; |
| 489 | return sb; | 489 | return sb; |
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov, | 492 | static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov, |
| 493 | unsigned long nr_segs, loff_t *ppos) | 493 | unsigned long nr_segs, loff_t *ppos) |
| 494 | { | 494 | { |
| 495 | struct inode *inode = file->f_dentry->d_inode; | 495 | struct inode *inode = file->f_dentry->d_inode; |
| 496 | ssize_t written; | 496 | ssize_t written; |
| 497 | 497 | ||
| 498 | written = generic_file_writev(file, iov, nr_segs, ppos); | 498 | written = generic_file_writev(file, iov, nr_segs, ppos); |
| 499 | if (!CIFS_I(inode)->clientCanCacheAll) | 499 | if (!CIFS_I(inode)->clientCanCacheAll) |
| 500 | filemap_fdatawrite(inode->i_mapping); | 500 | filemap_fdatawrite(inode->i_mapping); |
| 501 | return written; | 501 | return written; |
| 502 | } | 502 | } |
| 503 | 503 | ||
| 504 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf, | 504 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const char __user *buf, |
| 505 | size_t count, loff_t pos) | 505 | size_t count, loff_t pos) |
| 506 | { | 506 | { |
| 507 | struct inode *inode = iocb->ki_filp->f_dentry->d_inode; | 507 | struct inode *inode = iocb->ki_filp->f_dentry->d_inode; |
| 508 | ssize_t written; | 508 | ssize_t written; |
| 509 | 509 | ||
| 510 | written = generic_file_aio_write(iocb, buf, count, pos); | 510 | written = generic_file_aio_write(iocb, buf, count, pos); |
| 511 | if (!CIFS_I(inode)->clientCanCacheAll) | 511 | if (!CIFS_I(inode)->clientCanCacheAll) |
| 512 | filemap_fdatawrite(inode->i_mapping); | 512 | filemap_fdatawrite(inode->i_mapping); |
| 513 | return written; | 513 | return written; |
| 514 | } | 514 | } |
| 515 | 515 | ||
| 516 | static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) | 516 | static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) |
| 517 | { | 517 | { |
| 518 | /* origin == SEEK_END => we must revalidate the cached file length */ | 518 | /* origin == SEEK_END => we must revalidate the cached file length */ |
| 519 | if (origin == 2) { | 519 | if (origin == 2) { |
| 520 | int retval = cifs_revalidate(file->f_dentry); | 520 | int retval = cifs_revalidate(file->f_dentry); |
| 521 | if (retval < 0) | 521 | if (retval < 0) |
| 522 | return (loff_t)retval; | 522 | return (loff_t)retval; |
| 523 | } | 523 | } |
| 524 | return remote_llseek(file, offset, origin); | 524 | return remote_llseek(file, offset, origin); |
| 525 | } | 525 | } |
| 526 | 526 | ||
| 527 | static struct file_system_type cifs_fs_type = { | 527 | static struct file_system_type cifs_fs_type = { |
| 528 | .owner = THIS_MODULE, | 528 | .owner = THIS_MODULE, |
| 529 | .name = "cifs", | 529 | .name = "cifs", |
| 530 | .get_sb = cifs_get_sb, | 530 | .get_sb = cifs_get_sb, |
| 531 | .kill_sb = kill_anon_super, | 531 | .kill_sb = kill_anon_super, |
| 532 | /* .fs_flags */ | 532 | /* .fs_flags */ |
| 533 | }; | 533 | }; |
| 534 | struct inode_operations cifs_dir_inode_ops = { | 534 | struct inode_operations cifs_dir_inode_ops = { |
| 535 | .create = cifs_create, | 535 | .create = cifs_create, |
| 536 | .lookup = cifs_lookup, | 536 | .lookup = cifs_lookup, |
| 537 | .getattr = cifs_getattr, | 537 | .getattr = cifs_getattr, |
| 538 | .unlink = cifs_unlink, | 538 | .unlink = cifs_unlink, |
| 539 | .link = cifs_hardlink, | 539 | .link = cifs_hardlink, |
| 540 | .mkdir = cifs_mkdir, | 540 | .mkdir = cifs_mkdir, |
| 541 | .rmdir = cifs_rmdir, | 541 | .rmdir = cifs_rmdir, |
| 542 | .rename = cifs_rename, | 542 | .rename = cifs_rename, |
| 543 | .permission = cifs_permission, | 543 | .permission = cifs_permission, |
| 544 | /* revalidate:cifs_revalidate, */ | 544 | /* revalidate:cifs_revalidate, */ |
| 545 | .setattr = cifs_setattr, | 545 | .setattr = cifs_setattr, |
| 546 | .symlink = cifs_symlink, | 546 | .symlink = cifs_symlink, |
| 547 | .mknod = cifs_mknod, | 547 | .mknod = cifs_mknod, |
| 548 | #ifdef CONFIG_CIFS_XATTR | 548 | #ifdef CONFIG_CIFS_XATTR |
| 549 | .setxattr = cifs_setxattr, | 549 | .setxattr = cifs_setxattr, |
| 550 | .getxattr = cifs_getxattr, | 550 | .getxattr = cifs_getxattr, |
| 551 | .listxattr = cifs_listxattr, | 551 | .listxattr = cifs_listxattr, |
| 552 | .removexattr = cifs_removexattr, | 552 | .removexattr = cifs_removexattr, |
| 553 | #endif | 553 | #endif |
| 554 | }; | 554 | }; |
| 555 | 555 | ||
| 556 | struct inode_operations cifs_file_inode_ops = { | 556 | struct inode_operations cifs_file_inode_ops = { |
| 557 | /* revalidate:cifs_revalidate, */ | 557 | /* revalidate:cifs_revalidate, */ |
| 558 | .setattr = cifs_setattr, | 558 | .setattr = cifs_setattr, |
| 559 | .getattr = cifs_getattr, /* do we need this anymore? */ | 559 | .getattr = cifs_getattr, /* do we need this anymore? */ |
| 560 | .rename = cifs_rename, | 560 | .rename = cifs_rename, |
| 561 | .permission = cifs_permission, | 561 | .permission = cifs_permission, |
| 562 | #ifdef CONFIG_CIFS_XATTR | 562 | #ifdef CONFIG_CIFS_XATTR |
| 563 | .setxattr = cifs_setxattr, | 563 | .setxattr = cifs_setxattr, |
| 564 | .getxattr = cifs_getxattr, | 564 | .getxattr = cifs_getxattr, |
| 565 | .listxattr = cifs_listxattr, | 565 | .listxattr = cifs_listxattr, |
| 566 | .removexattr = cifs_removexattr, | 566 | .removexattr = cifs_removexattr, |
| 567 | #endif | 567 | #endif |
| 568 | }; | 568 | }; |
| 569 | 569 | ||
| 570 | struct inode_operations cifs_symlink_inode_ops = { | 570 | struct inode_operations cifs_symlink_inode_ops = { |
| 571 | .readlink = generic_readlink, | 571 | .readlink = generic_readlink, |
| 572 | .follow_link = cifs_follow_link, | 572 | .follow_link = cifs_follow_link, |
| 573 | .put_link = cifs_put_link, | 573 | .put_link = cifs_put_link, |
| 574 | .permission = cifs_permission, | 574 | .permission = cifs_permission, |
| 575 | /* BB add the following two eventually */ | 575 | /* BB add the following two eventually */ |
| 576 | /* revalidate: cifs_revalidate, | 576 | /* revalidate: cifs_revalidate, |
| 577 | setattr: cifs_notify_change, *//* BB do we need notify change */ | 577 | setattr: cifs_notify_change, *//* BB do we need notify change */ |
| 578 | #ifdef CONFIG_CIFS_XATTR | 578 | #ifdef CONFIG_CIFS_XATTR |
| 579 | .setxattr = cifs_setxattr, | 579 | .setxattr = cifs_setxattr, |
| 580 | .getxattr = cifs_getxattr, | 580 | .getxattr = cifs_getxattr, |
| 581 | .listxattr = cifs_listxattr, | 581 | .listxattr = cifs_listxattr, |
| 582 | .removexattr = cifs_removexattr, | 582 | .removexattr = cifs_removexattr, |
| 583 | #endif | 583 | #endif |
| 584 | }; | 584 | }; |
| 585 | 585 | ||
| 586 | struct file_operations cifs_file_ops = { | 586 | struct file_operations cifs_file_ops = { |
| 587 | .read = do_sync_read, | 587 | .read = do_sync_read, |
| 588 | .write = do_sync_write, | 588 | .write = do_sync_write, |
| 589 | .readv = generic_file_readv, | 589 | .readv = generic_file_readv, |
| 590 | .writev = cifs_file_writev, | 590 | .writev = cifs_file_writev, |
| 591 | .aio_read = generic_file_aio_read, | 591 | .aio_read = generic_file_aio_read, |
| 592 | .aio_write = cifs_file_aio_write, | 592 | .aio_write = cifs_file_aio_write, |
| 593 | .open = cifs_open, | 593 | .open = cifs_open, |
| 594 | .release = cifs_close, | 594 | .release = cifs_close, |
| 595 | .lock = cifs_lock, | 595 | .lock = cifs_lock, |
| 596 | .fsync = cifs_fsync, | 596 | .fsync = cifs_fsync, |
| 597 | .flush = cifs_flush, | 597 | .flush = cifs_flush, |
| 598 | .mmap = cifs_file_mmap, | 598 | .mmap = cifs_file_mmap, |
| 599 | .sendfile = generic_file_sendfile, | 599 | .sendfile = generic_file_sendfile, |
| 600 | .llseek = cifs_llseek, | 600 | .llseek = cifs_llseek, |
| 601 | #ifdef CONFIG_CIFS_POSIX | 601 | #ifdef CONFIG_CIFS_POSIX |
| 602 | .ioctl = cifs_ioctl, | 602 | .ioctl = cifs_ioctl, |
| 603 | #endif /* CONFIG_CIFS_POSIX */ | 603 | #endif /* CONFIG_CIFS_POSIX */ |
| 604 | 604 | ||
| 605 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 605 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 606 | .dir_notify = cifs_dir_notify, | 606 | .dir_notify = cifs_dir_notify, |
| 607 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 607 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 608 | }; | 608 | }; |
| 609 | 609 | ||
| 610 | struct file_operations cifs_file_direct_ops = { | 610 | struct file_operations cifs_file_direct_ops = { |
| 611 | /* no mmap, no aio, no readv - | 611 | /* no mmap, no aio, no readv - |
| 612 | BB reevaluate whether they can be done with directio, no cache */ | 612 | BB reevaluate whether they can be done with directio, no cache */ |
| 613 | .read = cifs_user_read, | 613 | .read = cifs_user_read, |
| 614 | .write = cifs_user_write, | 614 | .write = cifs_user_write, |
| 615 | .open = cifs_open, | 615 | .open = cifs_open, |
| 616 | .release = cifs_close, | 616 | .release = cifs_close, |
| 617 | .lock = cifs_lock, | 617 | .lock = cifs_lock, |
| 618 | .fsync = cifs_fsync, | 618 | .fsync = cifs_fsync, |
| 619 | .flush = cifs_flush, | 619 | .flush = cifs_flush, |
| 620 | .sendfile = generic_file_sendfile, /* BB removeme BB */ | 620 | .sendfile = generic_file_sendfile, /* BB removeme BB */ |
| 621 | #ifdef CONFIG_CIFS_POSIX | 621 | #ifdef CONFIG_CIFS_POSIX |
| 622 | .ioctl = cifs_ioctl, | 622 | .ioctl = cifs_ioctl, |
| 623 | #endif /* CONFIG_CIFS_POSIX */ | 623 | #endif /* CONFIG_CIFS_POSIX */ |
| 624 | .llseek = cifs_llseek, | 624 | .llseek = cifs_llseek, |
| 625 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 625 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 626 | .dir_notify = cifs_dir_notify, | 626 | .dir_notify = cifs_dir_notify, |
| 627 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 627 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 628 | }; | 628 | }; |
| 629 | struct file_operations cifs_file_nobrl_ops = { | 629 | struct file_operations cifs_file_nobrl_ops = { |
| 630 | .read = do_sync_read, | 630 | .read = do_sync_read, |
| 631 | .write = do_sync_write, | 631 | .write = do_sync_write, |
| 632 | .readv = generic_file_readv, | 632 | .readv = generic_file_readv, |
| 633 | .writev = cifs_file_writev, | 633 | .writev = cifs_file_writev, |
| 634 | .aio_read = generic_file_aio_read, | 634 | .aio_read = generic_file_aio_read, |
| 635 | .aio_write = cifs_file_aio_write, | 635 | .aio_write = cifs_file_aio_write, |
| 636 | .open = cifs_open, | 636 | .open = cifs_open, |
| 637 | .release = cifs_close, | 637 | .release = cifs_close, |
| 638 | .fsync = cifs_fsync, | 638 | .fsync = cifs_fsync, |
| 639 | .flush = cifs_flush, | 639 | .flush = cifs_flush, |
| 640 | .mmap = cifs_file_mmap, | 640 | .mmap = cifs_file_mmap, |
| 641 | .sendfile = generic_file_sendfile, | 641 | .sendfile = generic_file_sendfile, |
| 642 | .llseek = cifs_llseek, | 642 | .llseek = cifs_llseek, |
| 643 | #ifdef CONFIG_CIFS_POSIX | 643 | #ifdef CONFIG_CIFS_POSIX |
| 644 | .ioctl = cifs_ioctl, | 644 | .ioctl = cifs_ioctl, |
| 645 | #endif /* CONFIG_CIFS_POSIX */ | 645 | #endif /* CONFIG_CIFS_POSIX */ |
| 646 | 646 | ||
| 647 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 647 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 648 | .dir_notify = cifs_dir_notify, | 648 | .dir_notify = cifs_dir_notify, |
| 649 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 649 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 650 | }; | 650 | }; |
| 651 | 651 | ||
| 652 | struct file_operations cifs_file_direct_nobrl_ops = { | 652 | struct file_operations cifs_file_direct_nobrl_ops = { |
| 653 | /* no mmap, no aio, no readv - | 653 | /* no mmap, no aio, no readv - |
| 654 | BB reevaluate whether they can be done with directio, no cache */ | 654 | BB reevaluate whether they can be done with directio, no cache */ |
| 655 | .read = cifs_user_read, | 655 | .read = cifs_user_read, |
| 656 | .write = cifs_user_write, | 656 | .write = cifs_user_write, |
| 657 | .open = cifs_open, | 657 | .open = cifs_open, |
| 658 | .release = cifs_close, | 658 | .release = cifs_close, |
| 659 | .fsync = cifs_fsync, | 659 | .fsync = cifs_fsync, |
| 660 | .flush = cifs_flush, | 660 | .flush = cifs_flush, |
| 661 | .sendfile = generic_file_sendfile, /* BB removeme BB */ | 661 | .sendfile = generic_file_sendfile, /* BB removeme BB */ |
| 662 | #ifdef CONFIG_CIFS_POSIX | 662 | #ifdef CONFIG_CIFS_POSIX |
| 663 | .ioctl = cifs_ioctl, | 663 | .ioctl = cifs_ioctl, |
| 664 | #endif /* CONFIG_CIFS_POSIX */ | 664 | #endif /* CONFIG_CIFS_POSIX */ |
| 665 | .llseek = cifs_llseek, | 665 | .llseek = cifs_llseek, |
| 666 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 666 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 667 | .dir_notify = cifs_dir_notify, | 667 | .dir_notify = cifs_dir_notify, |
| 668 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 668 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 669 | }; | 669 | }; |
| 670 | 670 | ||
| 671 | struct file_operations cifs_dir_ops = { | 671 | struct file_operations cifs_dir_ops = { |
| 672 | .readdir = cifs_readdir, | 672 | .readdir = cifs_readdir, |
| 673 | .release = cifs_closedir, | 673 | .release = cifs_closedir, |
| 674 | .read = generic_read_dir, | 674 | .read = generic_read_dir, |
| 675 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 675 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 676 | .dir_notify = cifs_dir_notify, | 676 | .dir_notify = cifs_dir_notify, |
| 677 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ | 677 | #endif /* CONFIG_CIFS_EXPERIMENTAL */ |
| 678 | .ioctl = cifs_ioctl, | 678 | .ioctl = cifs_ioctl, |
| 679 | }; | 679 | }; |
| 680 | 680 | ||
| 681 | static void | 681 | static void |
| 682 | cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags) | 682 | cifs_init_once(void *inode, kmem_cache_t * cachep, unsigned long flags) |
| 683 | { | 683 | { |
| 684 | struct cifsInodeInfo *cifsi = inode; | 684 | struct cifsInodeInfo *cifsi = inode; |
| 685 | 685 | ||
| 686 | if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == | 686 | if ((flags & (SLAB_CTOR_VERIFY | SLAB_CTOR_CONSTRUCTOR)) == |
| 687 | SLAB_CTOR_CONSTRUCTOR) { | 687 | SLAB_CTOR_CONSTRUCTOR) { |
| 688 | inode_init_once(&cifsi->vfs_inode); | 688 | inode_init_once(&cifsi->vfs_inode); |
| 689 | INIT_LIST_HEAD(&cifsi->lockList); | 689 | INIT_LIST_HEAD(&cifsi->lockList); |
| 690 | } | 690 | } |
| 691 | } | 691 | } |
| 692 | 692 | ||
| 693 | static int | 693 | static int |
| 694 | cifs_init_inodecache(void) | 694 | cifs_init_inodecache(void) |
| 695 | { | 695 | { |
| 696 | cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", | 696 | cifs_inode_cachep = kmem_cache_create("cifs_inode_cache", |
| 697 | sizeof (struct cifsInodeInfo), | 697 | sizeof (struct cifsInodeInfo), |
| 698 | 0, SLAB_RECLAIM_ACCOUNT, | 698 | 0, SLAB_RECLAIM_ACCOUNT, |
| 699 | cifs_init_once, NULL); | 699 | cifs_init_once, NULL); |
| 700 | if (cifs_inode_cachep == NULL) | 700 | if (cifs_inode_cachep == NULL) |
| 701 | return -ENOMEM; | 701 | return -ENOMEM; |
| 702 | 702 | ||
| 703 | return 0; | 703 | return 0; |
| 704 | } | 704 | } |
| 705 | 705 | ||
| 706 | static void | 706 | static void |
| 707 | cifs_destroy_inodecache(void) | 707 | cifs_destroy_inodecache(void) |
| 708 | { | 708 | { |
| 709 | if (kmem_cache_destroy(cifs_inode_cachep)) | 709 | if (kmem_cache_destroy(cifs_inode_cachep)) |
| 710 | printk(KERN_WARNING "cifs_inode_cache: error freeing\n"); | 710 | printk(KERN_WARNING "cifs_inode_cache: error freeing\n"); |
| 711 | } | 711 | } |
| 712 | 712 | ||
| 713 | static int | 713 | static int |
| 714 | cifs_init_request_bufs(void) | 714 | cifs_init_request_bufs(void) |
| 715 | { | 715 | { |
| 716 | if(CIFSMaxBufSize < 8192) { | 716 | if(CIFSMaxBufSize < 8192) { |
| 717 | /* Buffer size can not be smaller than 2 * PATH_MAX since maximum | 717 | /* Buffer size can not be smaller than 2 * PATH_MAX since maximum |
| 718 | Unicode path name has to fit in any SMB/CIFS path based frames */ | 718 | Unicode path name has to fit in any SMB/CIFS path based frames */ |
| 719 | CIFSMaxBufSize = 8192; | 719 | CIFSMaxBufSize = 8192; |
| 720 | } else if (CIFSMaxBufSize > 1024*127) { | 720 | } else if (CIFSMaxBufSize > 1024*127) { |
| 721 | CIFSMaxBufSize = 1024 * 127; | 721 | CIFSMaxBufSize = 1024 * 127; |
| 722 | } else { | 722 | } else { |
| 723 | CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/ | 723 | CIFSMaxBufSize &= 0x1FE00; /* Round size to even 512 byte mult*/ |
| 724 | } | 724 | } |
| 725 | /* cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */ | 725 | /* cERROR(1,("CIFSMaxBufSize %d 0x%x",CIFSMaxBufSize,CIFSMaxBufSize)); */ |
| 726 | cifs_req_cachep = kmem_cache_create("cifs_request", | 726 | cifs_req_cachep = kmem_cache_create("cifs_request", |
| 727 | CIFSMaxBufSize + | 727 | CIFSMaxBufSize + |
| 728 | MAX_CIFS_HDR_SIZE, 0, | 728 | MAX_CIFS_HDR_SIZE, 0, |
| 729 | SLAB_HWCACHE_ALIGN, NULL, NULL); | 729 | SLAB_HWCACHE_ALIGN, NULL, NULL); |
| 730 | if (cifs_req_cachep == NULL) | 730 | if (cifs_req_cachep == NULL) |
| 731 | return -ENOMEM; | 731 | return -ENOMEM; |
| 732 | 732 | ||
| 733 | if(cifs_min_rcv < 1) | 733 | if(cifs_min_rcv < 1) |
| 734 | cifs_min_rcv = 1; | 734 | cifs_min_rcv = 1; |
| 735 | else if (cifs_min_rcv > 64) { | 735 | else if (cifs_min_rcv > 64) { |
| 736 | cifs_min_rcv = 64; | 736 | cifs_min_rcv = 64; |
| 737 | cERROR(1,("cifs_min_rcv set to maximum (64)")); | 737 | cERROR(1,("cifs_min_rcv set to maximum (64)")); |
| 738 | } | 738 | } |
| 739 | 739 | ||
| 740 | cifs_req_poolp = mempool_create(cifs_min_rcv, | 740 | cifs_req_poolp = mempool_create(cifs_min_rcv, |
| 741 | mempool_alloc_slab, | 741 | mempool_alloc_slab, |
| 742 | mempool_free_slab, | 742 | mempool_free_slab, |
| 743 | cifs_req_cachep); | 743 | cifs_req_cachep); |
| 744 | 744 | ||
| 745 | if(cifs_req_poolp == NULL) { | 745 | if(cifs_req_poolp == NULL) { |
| 746 | kmem_cache_destroy(cifs_req_cachep); | 746 | kmem_cache_destroy(cifs_req_cachep); |
| 747 | return -ENOMEM; | 747 | return -ENOMEM; |
| 748 | } | 748 | } |
| 749 | /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and | 749 | /* MAX_CIFS_SMALL_BUFFER_SIZE bytes is enough for most SMB responses and |
| 750 | almost all handle based requests (but not write response, nor is it | 750 | almost all handle based requests (but not write response, nor is it |
| 751 | sufficient for path based requests). A smaller size would have | 751 | sufficient for path based requests). A smaller size would have |
| 752 | been more efficient (compacting multiple slab items on one 4k page) | 752 | been more efficient (compacting multiple slab items on one 4k page) |
| 753 | for the case in which debug was on, but this larger size allows | 753 | for the case in which debug was on, but this larger size allows |
| 754 | more SMBs to use small buffer alloc and is still much more | 754 | more SMBs to use small buffer alloc and is still much more |
| 755 | efficient to alloc 1 per page off the slab compared to 17K (5page) | 755 | efficient to alloc 1 per page off the slab compared to 17K (5page) |
| 756 | alloc of large cifs buffers even when page debugging is on */ | 756 | alloc of large cifs buffers even when page debugging is on */ |
| 757 | cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", | 757 | cifs_sm_req_cachep = kmem_cache_create("cifs_small_rq", |
| 758 | MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN, | 758 | MAX_CIFS_SMALL_BUFFER_SIZE, 0, SLAB_HWCACHE_ALIGN, |
| 759 | NULL, NULL); | 759 | NULL, NULL); |
| 760 | if (cifs_sm_req_cachep == NULL) { | 760 | if (cifs_sm_req_cachep == NULL) { |
| 761 | mempool_destroy(cifs_req_poolp); | 761 | mempool_destroy(cifs_req_poolp); |
| 762 | kmem_cache_destroy(cifs_req_cachep); | 762 | kmem_cache_destroy(cifs_req_cachep); |
| 763 | return -ENOMEM; | 763 | return -ENOMEM; |
| 764 | } | 764 | } |
| 765 | 765 | ||
| 766 | if(cifs_min_small < 2) | 766 | if(cifs_min_small < 2) |
| 767 | cifs_min_small = 2; | 767 | cifs_min_small = 2; |
| 768 | else if (cifs_min_small > 256) { | 768 | else if (cifs_min_small > 256) { |
| 769 | cifs_min_small = 256; | 769 | cifs_min_small = 256; |
| 770 | cFYI(1,("cifs_min_small set to maximum (256)")); | 770 | cFYI(1,("cifs_min_small set to maximum (256)")); |
| 771 | } | 771 | } |
| 772 | 772 | ||
| 773 | cifs_sm_req_poolp = mempool_create(cifs_min_small, | 773 | cifs_sm_req_poolp = mempool_create(cifs_min_small, |
| 774 | mempool_alloc_slab, | 774 | mempool_alloc_slab, |
| 775 | mempool_free_slab, | 775 | mempool_free_slab, |
| 776 | cifs_sm_req_cachep); | 776 | cifs_sm_req_cachep); |
| 777 | 777 | ||
| 778 | if(cifs_sm_req_poolp == NULL) { | 778 | if(cifs_sm_req_poolp == NULL) { |
| 779 | mempool_destroy(cifs_req_poolp); | 779 | mempool_destroy(cifs_req_poolp); |
| 780 | kmem_cache_destroy(cifs_req_cachep); | 780 | kmem_cache_destroy(cifs_req_cachep); |
| 781 | kmem_cache_destroy(cifs_sm_req_cachep); | 781 | kmem_cache_destroy(cifs_sm_req_cachep); |
| 782 | return -ENOMEM; | 782 | return -ENOMEM; |
| 783 | } | 783 | } |
| 784 | 784 | ||
| 785 | return 0; | 785 | return 0; |
| 786 | } | 786 | } |
| 787 | 787 | ||
| 788 | static void | 788 | static void |
| 789 | cifs_destroy_request_bufs(void) | 789 | cifs_destroy_request_bufs(void) |
| 790 | { | 790 | { |
| 791 | mempool_destroy(cifs_req_poolp); | 791 | mempool_destroy(cifs_req_poolp); |
| 792 | if (kmem_cache_destroy(cifs_req_cachep)) | 792 | if (kmem_cache_destroy(cifs_req_cachep)) |
| 793 | printk(KERN_WARNING | 793 | printk(KERN_WARNING |
| 794 | "cifs_destroy_request_cache: error not all structures were freed\n"); | 794 | "cifs_destroy_request_cache: error not all structures were freed\n"); |
| 795 | mempool_destroy(cifs_sm_req_poolp); | 795 | mempool_destroy(cifs_sm_req_poolp); |
| 796 | if (kmem_cache_destroy(cifs_sm_req_cachep)) | 796 | if (kmem_cache_destroy(cifs_sm_req_cachep)) |
| 797 | printk(KERN_WARNING | 797 | printk(KERN_WARNING |
| 798 | "cifs_destroy_request_cache: cifs_small_rq free error\n"); | 798 | "cifs_destroy_request_cache: cifs_small_rq free error\n"); |
| 799 | } | 799 | } |
| 800 | 800 | ||
| 801 | static int | 801 | static int |
| 802 | cifs_init_mids(void) | 802 | cifs_init_mids(void) |
| 803 | { | 803 | { |
| 804 | cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", | 804 | cifs_mid_cachep = kmem_cache_create("cifs_mpx_ids", |
| 805 | sizeof (struct mid_q_entry), 0, | 805 | sizeof (struct mid_q_entry), 0, |
| 806 | SLAB_HWCACHE_ALIGN, NULL, NULL); | 806 | SLAB_HWCACHE_ALIGN, NULL, NULL); |
| 807 | if (cifs_mid_cachep == NULL) | 807 | if (cifs_mid_cachep == NULL) |
| 808 | return -ENOMEM; | 808 | return -ENOMEM; |
| 809 | 809 | ||
| 810 | cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */, | 810 | cifs_mid_poolp = mempool_create(3 /* a reasonable min simultan opers */, |
| 811 | mempool_alloc_slab, | 811 | mempool_alloc_slab, |
| 812 | mempool_free_slab, | 812 | mempool_free_slab, |
| 813 | cifs_mid_cachep); | 813 | cifs_mid_cachep); |
| 814 | if(cifs_mid_poolp == NULL) { | 814 | if(cifs_mid_poolp == NULL) { |
| 815 | kmem_cache_destroy(cifs_mid_cachep); | 815 | kmem_cache_destroy(cifs_mid_cachep); |
| 816 | return -ENOMEM; | 816 | return -ENOMEM; |
| 817 | } | 817 | } |
| 818 | 818 | ||
| 819 | cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", | 819 | cifs_oplock_cachep = kmem_cache_create("cifs_oplock_structs", |
| 820 | sizeof (struct oplock_q_entry), 0, | 820 | sizeof (struct oplock_q_entry), 0, |
| 821 | SLAB_HWCACHE_ALIGN, NULL, NULL); | 821 | SLAB_HWCACHE_ALIGN, NULL, NULL); |
| 822 | if (cifs_oplock_cachep == NULL) { | 822 | if (cifs_oplock_cachep == NULL) { |
| 823 | kmem_cache_destroy(cifs_mid_cachep); | 823 | kmem_cache_destroy(cifs_mid_cachep); |
| 824 | mempool_destroy(cifs_mid_poolp); | 824 | mempool_destroy(cifs_mid_poolp); |
| 825 | return -ENOMEM; | 825 | return -ENOMEM; |
| 826 | } | 826 | } |
| 827 | 827 | ||
| 828 | return 0; | 828 | return 0; |
| 829 | } | 829 | } |
| 830 | 830 | ||
| 831 | static void | 831 | static void |
| 832 | cifs_destroy_mids(void) | 832 | cifs_destroy_mids(void) |
| 833 | { | 833 | { |
| 834 | mempool_destroy(cifs_mid_poolp); | 834 | mempool_destroy(cifs_mid_poolp); |
| 835 | if (kmem_cache_destroy(cifs_mid_cachep)) | 835 | if (kmem_cache_destroy(cifs_mid_cachep)) |
| 836 | printk(KERN_WARNING | 836 | printk(KERN_WARNING |
| 837 | "cifs_destroy_mids: error not all structures were freed\n"); | 837 | "cifs_destroy_mids: error not all structures were freed\n"); |
| 838 | 838 | ||
| 839 | if (kmem_cache_destroy(cifs_oplock_cachep)) | 839 | if (kmem_cache_destroy(cifs_oplock_cachep)) |
| 840 | printk(KERN_WARNING | 840 | printk(KERN_WARNING |
| 841 | "error not all oplock structures were freed\n"); | 841 | "error not all oplock structures were freed\n"); |
| 842 | } | 842 | } |
| 843 | 843 | ||
| 844 | static int cifs_oplock_thread(void * dummyarg) | 844 | static int cifs_oplock_thread(void * dummyarg) |
| 845 | { | 845 | { |
| 846 | struct oplock_q_entry * oplock_item; | 846 | struct oplock_q_entry * oplock_item; |
| 847 | struct cifsTconInfo *pTcon; | 847 | struct cifsTconInfo *pTcon; |
| 848 | struct inode * inode; | 848 | struct inode * inode; |
| 849 | __u16 netfid; | 849 | __u16 netfid; |
| 850 | int rc; | 850 | int rc; |
| 851 | 851 | ||
| 852 | daemonize("cifsoplockd"); | 852 | daemonize("cifsoplockd"); |
| 853 | allow_signal(SIGTERM); | 853 | allow_signal(SIGTERM); |
| 854 | 854 | ||
| 855 | oplockThread = current; | 855 | oplockThread = current; |
| 856 | do { | 856 | do { |
| 857 | if (try_to_freeze()) | 857 | if (try_to_freeze()) |
| 858 | continue; | 858 | continue; |
| 859 | 859 | ||
| 860 | spin_lock(&GlobalMid_Lock); | 860 | spin_lock(&GlobalMid_Lock); |
| 861 | if(list_empty(&GlobalOplock_Q)) { | 861 | if(list_empty(&GlobalOplock_Q)) { |
| 862 | spin_unlock(&GlobalMid_Lock); | 862 | spin_unlock(&GlobalMid_Lock); |
| 863 | set_current_state(TASK_INTERRUPTIBLE); | 863 | set_current_state(TASK_INTERRUPTIBLE); |
| 864 | schedule_timeout(39*HZ); | 864 | schedule_timeout(39*HZ); |
| 865 | } else { | 865 | } else { |
| 866 | oplock_item = list_entry(GlobalOplock_Q.next, | 866 | oplock_item = list_entry(GlobalOplock_Q.next, |
| 867 | struct oplock_q_entry, qhead); | 867 | struct oplock_q_entry, qhead); |
| 868 | if(oplock_item) { | 868 | if(oplock_item) { |
| 869 | cFYI(1,("found oplock item to write out")); | 869 | cFYI(1,("found oplock item to write out")); |
| 870 | pTcon = oplock_item->tcon; | 870 | pTcon = oplock_item->tcon; |
| 871 | inode = oplock_item->pinode; | 871 | inode = oplock_item->pinode; |
| 872 | netfid = oplock_item->netfid; | 872 | netfid = oplock_item->netfid; |
| 873 | spin_unlock(&GlobalMid_Lock); | 873 | spin_unlock(&GlobalMid_Lock); |
| 874 | DeleteOplockQEntry(oplock_item); | 874 | DeleteOplockQEntry(oplock_item); |
| 875 | /* can not grab inode sem here since it would | 875 | /* can not grab inode sem here since it would |
| 876 | deadlock when oplock received on delete | 876 | deadlock when oplock received on delete |
| 877 | since vfs_unlink holds the i_mutex across | 877 | since vfs_unlink holds the i_mutex across |
| 878 | the call */ | 878 | the call */ |
| 879 | /* mutex_lock(&inode->i_mutex);*/ | 879 | /* mutex_lock(&inode->i_mutex);*/ |
| 880 | if (S_ISREG(inode->i_mode)) { | 880 | if (S_ISREG(inode->i_mode)) { |
| 881 | rc = filemap_fdatawrite(inode->i_mapping); | 881 | rc = filemap_fdatawrite(inode->i_mapping); |
| 882 | if(CIFS_I(inode)->clientCanCacheRead == 0) { | 882 | if(CIFS_I(inode)->clientCanCacheRead == 0) { |
| 883 | filemap_fdatawait(inode->i_mapping); | 883 | filemap_fdatawait(inode->i_mapping); |
| 884 | invalidate_remote_inode(inode); | 884 | invalidate_remote_inode(inode); |
| 885 | } | 885 | } |
| 886 | } else | 886 | } else |
| 887 | rc = 0; | 887 | rc = 0; |
| 888 | /* mutex_unlock(&inode->i_mutex);*/ | 888 | /* mutex_unlock(&inode->i_mutex);*/ |
| 889 | if (rc) | 889 | if (rc) |
| 890 | CIFS_I(inode)->write_behind_rc = rc; | 890 | CIFS_I(inode)->write_behind_rc = rc; |
| 891 | cFYI(1,("Oplock flush inode %p rc %d",inode,rc)); | 891 | cFYI(1,("Oplock flush inode %p rc %d",inode,rc)); |
| 892 | 892 | ||
| 893 | /* releasing a stale oplock after recent reconnection | 893 | /* releasing a stale oplock after recent reconnection |
| 894 | of smb session using a now incorrect file | 894 | of smb session using a now incorrect file |
| 895 | handle is not a data integrity issue but do | 895 | handle is not a data integrity issue but do |
| 896 | not bother sending an oplock release if session | 896 | not bother sending an oplock release if session |
| 897 | to server still is disconnected since oplock | 897 | to server still is disconnected since oplock |
| 898 | already released by the server in that case */ | 898 | already released by the server in that case */ |
| 899 | if(pTcon->tidStatus != CifsNeedReconnect) { | 899 | if(pTcon->tidStatus != CifsNeedReconnect) { |
| 900 | rc = CIFSSMBLock(0, pTcon, netfid, | 900 | rc = CIFSSMBLock(0, pTcon, netfid, |
| 901 | 0 /* len */ , 0 /* offset */, 0, | 901 | 0 /* len */ , 0 /* offset */, 0, |
| 902 | 0, LOCKING_ANDX_OPLOCK_RELEASE, | 902 | 0, LOCKING_ANDX_OPLOCK_RELEASE, |
| 903 | 0 /* wait flag */); | 903 | 0 /* wait flag */); |
| 904 | cFYI(1,("Oplock release rc = %d ",rc)); | 904 | cFYI(1,("Oplock release rc = %d ",rc)); |
| 905 | } | 905 | } |
| 906 | } else | 906 | } else |
| 907 | spin_unlock(&GlobalMid_Lock); | 907 | spin_unlock(&GlobalMid_Lock); |
| 908 | set_current_state(TASK_INTERRUPTIBLE); | 908 | set_current_state(TASK_INTERRUPTIBLE); |
| 909 | schedule_timeout(1); /* yield in case q were corrupt */ | 909 | schedule_timeout(1); /* yield in case q were corrupt */ |
| 910 | } | 910 | } |
| 911 | } while(!signal_pending(current)); | 911 | } while(!signal_pending(current)); |
| 912 | oplockThread = NULL; | 912 | oplockThread = NULL; |
| 913 | complete_and_exit (&cifs_oplock_exited, 0); | 913 | complete_and_exit (&cifs_oplock_exited, 0); |
| 914 | } | 914 | } |
| 915 | 915 | ||
| 916 | static int cifs_dnotify_thread(void * dummyarg) | 916 | static int cifs_dnotify_thread(void * dummyarg) |
| 917 | { | 917 | { |
| 918 | struct list_head *tmp; | 918 | struct list_head *tmp; |
| 919 | struct cifsSesInfo *ses; | 919 | struct cifsSesInfo *ses; |
| 920 | 920 | ||
| 921 | daemonize("cifsdnotifyd"); | 921 | daemonize("cifsdnotifyd"); |
| 922 | allow_signal(SIGTERM); | 922 | allow_signal(SIGTERM); |
| 923 | 923 | ||
| 924 | dnotifyThread = current; | 924 | dnotifyThread = current; |
| 925 | do { | 925 | do { |
| 926 | if(try_to_freeze()) | 926 | if(try_to_freeze()) |
| 927 | continue; | 927 | continue; |
| 928 | set_current_state(TASK_INTERRUPTIBLE); | 928 | set_current_state(TASK_INTERRUPTIBLE); |
| 929 | schedule_timeout(15*HZ); | 929 | schedule_timeout(15*HZ); |
| 930 | read_lock(&GlobalSMBSeslock); | 930 | read_lock(&GlobalSMBSeslock); |
| 931 | /* check if any stuck requests that need | 931 | /* check if any stuck requests that need |
| 932 | to be woken up and wakeq so the | 932 | to be woken up and wakeq so the |
| 933 | thread can wake up and error out */ | 933 | thread can wake up and error out */ |
| 934 | list_for_each(tmp, &GlobalSMBSessionList) { | 934 | list_for_each(tmp, &GlobalSMBSessionList) { |
| 935 | ses = list_entry(tmp, struct cifsSesInfo, | 935 | ses = list_entry(tmp, struct cifsSesInfo, |
| 936 | cifsSessionList); | 936 | cifsSessionList); |
| 937 | if(ses && ses->server && | 937 | if(ses && ses->server && |
| 938 | atomic_read(&ses->server->inFlight)) | 938 | atomic_read(&ses->server->inFlight)) |
| 939 | wake_up_all(&ses->server->response_q); | 939 | wake_up_all(&ses->server->response_q); |
| 940 | } | 940 | } |
| 941 | read_unlock(&GlobalSMBSeslock); | 941 | read_unlock(&GlobalSMBSeslock); |
| 942 | } while(!signal_pending(current)); | 942 | } while(!signal_pending(current)); |
| 943 | complete_and_exit (&cifs_dnotify_exited, 0); | 943 | complete_and_exit (&cifs_dnotify_exited, 0); |
| 944 | } | 944 | } |
| 945 | 945 | ||
| 946 | static int __init | 946 | static int __init |
| 947 | init_cifs(void) | 947 | init_cifs(void) |
| 948 | { | 948 | { |
| 949 | int rc = 0; | 949 | int rc = 0; |
| 950 | #ifdef CONFIG_PROC_FS | 950 | #ifdef CONFIG_PROC_FS |
| 951 | cifs_proc_init(); | 951 | cifs_proc_init(); |
| 952 | #endif | 952 | #endif |
| 953 | INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */ | 953 | INIT_LIST_HEAD(&GlobalServerList); /* BB not implemented yet */ |
| 954 | INIT_LIST_HEAD(&GlobalSMBSessionList); | 954 | INIT_LIST_HEAD(&GlobalSMBSessionList); |
| 955 | INIT_LIST_HEAD(&GlobalTreeConnectionList); | 955 | INIT_LIST_HEAD(&GlobalTreeConnectionList); |
| 956 | INIT_LIST_HEAD(&GlobalOplock_Q); | 956 | INIT_LIST_HEAD(&GlobalOplock_Q); |
| 957 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 957 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 958 | INIT_LIST_HEAD(&GlobalDnotifyReqList); | 958 | INIT_LIST_HEAD(&GlobalDnotifyReqList); |
| 959 | INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); | 959 | INIT_LIST_HEAD(&GlobalDnotifyRsp_Q); |
| 960 | #endif | 960 | #endif |
| 961 | /* | 961 | /* |
| 962 | * Initialize Global counters | 962 | * Initialize Global counters |
| 963 | */ | 963 | */ |
| 964 | atomic_set(&sesInfoAllocCount, 0); | 964 | atomic_set(&sesInfoAllocCount, 0); |
| 965 | atomic_set(&tconInfoAllocCount, 0); | 965 | atomic_set(&tconInfoAllocCount, 0); |
| 966 | atomic_set(&tcpSesAllocCount,0); | 966 | atomic_set(&tcpSesAllocCount,0); |
| 967 | atomic_set(&tcpSesReconnectCount, 0); | 967 | atomic_set(&tcpSesReconnectCount, 0); |
| 968 | atomic_set(&tconInfoReconnectCount, 0); | 968 | atomic_set(&tconInfoReconnectCount, 0); |
| 969 | 969 | ||
| 970 | atomic_set(&bufAllocCount, 0); | 970 | atomic_set(&bufAllocCount, 0); |
| 971 | atomic_set(&smBufAllocCount, 0); | 971 | atomic_set(&smBufAllocCount, 0); |
| 972 | #ifdef CONFIG_CIFS_STATS2 | 972 | #ifdef CONFIG_CIFS_STATS2 |
| 973 | atomic_set(&totBufAllocCount, 0); | 973 | atomic_set(&totBufAllocCount, 0); |
| 974 | atomic_set(&totSmBufAllocCount, 0); | 974 | atomic_set(&totSmBufAllocCount, 0); |
| 975 | #endif /* CONFIG_CIFS_STATS2 */ | 975 | #endif /* CONFIG_CIFS_STATS2 */ |
| 976 | 976 | ||
| 977 | atomic_set(&midCount, 0); | 977 | atomic_set(&midCount, 0); |
| 978 | GlobalCurrentXid = 0; | 978 | GlobalCurrentXid = 0; |
| 979 | GlobalTotalActiveXid = 0; | 979 | GlobalTotalActiveXid = 0; |
| 980 | GlobalMaxActiveXid = 0; | 980 | GlobalMaxActiveXid = 0; |
| 981 | rwlock_init(&GlobalSMBSeslock); | 981 | rwlock_init(&GlobalSMBSeslock); |
| 982 | spin_lock_init(&GlobalMid_Lock); | 982 | spin_lock_init(&GlobalMid_Lock); |
| 983 | 983 | ||
| 984 | if(cifs_max_pending < 2) { | 984 | if(cifs_max_pending < 2) { |
| 985 | cifs_max_pending = 2; | 985 | cifs_max_pending = 2; |
| 986 | cFYI(1,("cifs_max_pending set to min of 2")); | 986 | cFYI(1,("cifs_max_pending set to min of 2")); |
| 987 | } else if(cifs_max_pending > 256) { | 987 | } else if(cifs_max_pending > 256) { |
| 988 | cifs_max_pending = 256; | 988 | cifs_max_pending = 256; |
| 989 | cFYI(1,("cifs_max_pending set to max of 256")); | 989 | cFYI(1,("cifs_max_pending set to max of 256")); |
| 990 | } | 990 | } |
| 991 | 991 | ||
| 992 | rc = cifs_init_inodecache(); | 992 | rc = cifs_init_inodecache(); |
| 993 | if (!rc) { | 993 | if (!rc) { |
| 994 | rc = cifs_init_mids(); | 994 | rc = cifs_init_mids(); |
| 995 | if (!rc) { | 995 | if (!rc) { |
| 996 | rc = cifs_init_request_bufs(); | 996 | rc = cifs_init_request_bufs(); |
| 997 | if (!rc) { | 997 | if (!rc) { |
| 998 | rc = register_filesystem(&cifs_fs_type); | 998 | rc = register_filesystem(&cifs_fs_type); |
| 999 | if (!rc) { | 999 | if (!rc) { |
| 1000 | rc = (int)kernel_thread(cifs_oplock_thread, NULL, | 1000 | rc = (int)kernel_thread(cifs_oplock_thread, NULL, |
| 1001 | CLONE_FS | CLONE_FILES | CLONE_VM); | 1001 | CLONE_FS | CLONE_FILES | CLONE_VM); |
| 1002 | if(rc > 0) { | 1002 | if(rc > 0) { |
| 1003 | rc = (int)kernel_thread(cifs_dnotify_thread, NULL, | 1003 | rc = (int)kernel_thread(cifs_dnotify_thread, NULL, |
| 1004 | CLONE_FS | CLONE_FILES | CLONE_VM); | 1004 | CLONE_FS | CLONE_FILES | CLONE_VM); |
| 1005 | if(rc > 0) | 1005 | if(rc > 0) |
| 1006 | return 0; | 1006 | return 0; |
| 1007 | else | 1007 | else |
| 1008 | cERROR(1,("error %d create dnotify thread", rc)); | 1008 | cERROR(1,("error %d create dnotify thread", rc)); |
| 1009 | } else { | 1009 | } else { |
| 1010 | cERROR(1,("error %d create oplock thread",rc)); | 1010 | cERROR(1,("error %d create oplock thread",rc)); |
| 1011 | } | 1011 | } |
| 1012 | } | 1012 | } |
| 1013 | cifs_destroy_request_bufs(); | 1013 | cifs_destroy_request_bufs(); |
| 1014 | } | 1014 | } |
| 1015 | cifs_destroy_mids(); | 1015 | cifs_destroy_mids(); |
| 1016 | } | 1016 | } |
| 1017 | cifs_destroy_inodecache(); | 1017 | cifs_destroy_inodecache(); |
| 1018 | } | 1018 | } |
| 1019 | #ifdef CONFIG_PROC_FS | 1019 | #ifdef CONFIG_PROC_FS |
| 1020 | cifs_proc_clean(); | 1020 | cifs_proc_clean(); |
| 1021 | #endif | 1021 | #endif |
| 1022 | return rc; | 1022 | return rc; |
| 1023 | } | 1023 | } |
| 1024 | 1024 | ||
| 1025 | static void __exit | 1025 | static void __exit |
| 1026 | exit_cifs(void) | 1026 | exit_cifs(void) |
| 1027 | { | 1027 | { |
| 1028 | cFYI(0, ("In unregister ie exit_cifs")); | 1028 | cFYI(0, ("In unregister ie exit_cifs")); |
| 1029 | #ifdef CONFIG_PROC_FS | 1029 | #ifdef CONFIG_PROC_FS |
| 1030 | cifs_proc_clean(); | 1030 | cifs_proc_clean(); |
| 1031 | #endif | 1031 | #endif |
| 1032 | unregister_filesystem(&cifs_fs_type); | 1032 | unregister_filesystem(&cifs_fs_type); |
| 1033 | cifs_destroy_inodecache(); | 1033 | cifs_destroy_inodecache(); |
| 1034 | cifs_destroy_mids(); | 1034 | cifs_destroy_mids(); |
| 1035 | cifs_destroy_request_bufs(); | 1035 | cifs_destroy_request_bufs(); |
| 1036 | if(oplockThread) { | 1036 | if(oplockThread) { |
| 1037 | send_sig(SIGTERM, oplockThread, 1); | 1037 | send_sig(SIGTERM, oplockThread, 1); |
| 1038 | wait_for_completion(&cifs_oplock_exited); | 1038 | wait_for_completion(&cifs_oplock_exited); |
| 1039 | } | 1039 | } |
| 1040 | if(dnotifyThread) { | 1040 | if(dnotifyThread) { |
| 1041 | send_sig(SIGTERM, dnotifyThread, 1); | 1041 | send_sig(SIGTERM, dnotifyThread, 1); |
| 1042 | wait_for_completion(&cifs_dnotify_exited); | 1042 | wait_for_completion(&cifs_dnotify_exited); |
| 1043 | } | 1043 | } |
| 1044 | } | 1044 | } |
| 1045 | 1045 | ||
| 1046 | MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); | 1046 | MODULE_AUTHOR("Steve French <sfrench@us.ibm.com>"); |
| 1047 | MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */ | 1047 | MODULE_LICENSE("GPL"); /* combination of LGPL + GPL source behaves as GPL */ |
| 1048 | MODULE_DESCRIPTION | 1048 | MODULE_DESCRIPTION |
| 1049 | ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows"); | 1049 | ("VFS to access servers complying with the SNIA CIFS Specification e.g. Samba and Windows"); |
| 1050 | MODULE_VERSION(CIFS_VERSION); | 1050 | MODULE_VERSION(CIFS_VERSION); |
| 1051 | module_init(init_cifs) | 1051 | module_init(init_cifs) |
| 1052 | module_exit(exit_cifs) | 1052 | module_exit(exit_cifs) |
| 1053 | 1053 |
fs/jffs2/super.c
| 1 | /* | 1 | /* |
| 2 | * JFFS2 -- Journalling Flash File System, Version 2. | 2 | * JFFS2 -- Journalling Flash File System, Version 2. |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2001-2003 Red Hat, Inc. | 4 | * Copyright (C) 2001-2003 Red Hat, Inc. |
| 5 | * | 5 | * |
| 6 | * Created by David Woodhouse <dwmw2@infradead.org> | 6 | * Created by David Woodhouse <dwmw2@infradead.org> |
| 7 | * | 7 | * |
| 8 | * For licensing information, see the file 'LICENCE' in this directory. | 8 | * For licensing information, see the file 'LICENCE' in this directory. |
| 9 | * | 9 | * |
| 10 | * $Id: super.c,v 1.110 2005/11/07 11:14:42 gleixner Exp $ | 10 | * $Id: super.c,v 1.110 2005/11/07 11:14:42 gleixner Exp $ |
| 11 | * | 11 | * |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #include <linux/config.h> | 14 | #include <linux/config.h> |
| 15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
| 18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
| 20 | #include <linux/fs.h> | 20 | #include <linux/fs.h> |
| 21 | #include <linux/mount.h> | 21 | #include <linux/mount.h> |
| 22 | #include <linux/jffs2.h> | 22 | #include <linux/jffs2.h> |
| 23 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
| 24 | #include <linux/mtd/mtd.h> | 24 | #include <linux/mtd/mtd.h> |
| 25 | #include <linux/ctype.h> | 25 | #include <linux/ctype.h> |
| 26 | #include <linux/namei.h> | 26 | #include <linux/namei.h> |
| 27 | #include "compr.h" | 27 | #include "compr.h" |
| 28 | #include "nodelist.h" | 28 | #include "nodelist.h" |
| 29 | 29 | ||
| 30 | static void jffs2_put_super(struct super_block *); | 30 | static void jffs2_put_super(struct super_block *); |
| 31 | 31 | ||
| 32 | static kmem_cache_t *jffs2_inode_cachep; | 32 | static kmem_cache_t *jffs2_inode_cachep; |
| 33 | 33 | ||
| 34 | static struct inode *jffs2_alloc_inode(struct super_block *sb) | 34 | static struct inode *jffs2_alloc_inode(struct super_block *sb) |
| 35 | { | 35 | { |
| 36 | struct jffs2_inode_info *ei; | 36 | struct jffs2_inode_info *ei; |
| 37 | ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, SLAB_KERNEL); | 37 | ei = (struct jffs2_inode_info *)kmem_cache_alloc(jffs2_inode_cachep, SLAB_KERNEL); |
| 38 | if (!ei) | 38 | if (!ei) |
| 39 | return NULL; | 39 | return NULL; |
| 40 | return &ei->vfs_inode; | 40 | return &ei->vfs_inode; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | static void jffs2_destroy_inode(struct inode *inode) | 43 | static void jffs2_destroy_inode(struct inode *inode) |
| 44 | { | 44 | { |
| 45 | kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); | 45 | kmem_cache_free(jffs2_inode_cachep, JFFS2_INODE_INFO(inode)); |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | 48 | static void jffs2_i_init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) |
| 49 | { | 49 | { |
| 50 | struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; | 50 | struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; |
| 51 | 51 | ||
| 52 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | 52 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == |
| 53 | SLAB_CTOR_CONSTRUCTOR) { | 53 | SLAB_CTOR_CONSTRUCTOR) { |
| 54 | init_MUTEX(&ei->sem); | 54 | init_MUTEX(&ei->sem); |
| 55 | inode_init_once(&ei->vfs_inode); | 55 | inode_init_once(&ei->vfs_inode); |
| 56 | } | 56 | } |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static int jffs2_sync_fs(struct super_block *sb, int wait) | 59 | static int jffs2_sync_fs(struct super_block *sb, int wait) |
| 60 | { | 60 | { |
| 61 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 61 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
| 62 | 62 | ||
| 63 | down(&c->alloc_sem); | 63 | down(&c->alloc_sem); |
| 64 | jffs2_flush_wbuf_pad(c); | 64 | jffs2_flush_wbuf_pad(c); |
| 65 | up(&c->alloc_sem); | 65 | up(&c->alloc_sem); |
| 66 | return 0; | 66 | return 0; |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static struct super_operations jffs2_super_operations = | 69 | static struct super_operations jffs2_super_operations = |
| 70 | { | 70 | { |
| 71 | .alloc_inode = jffs2_alloc_inode, | 71 | .alloc_inode = jffs2_alloc_inode, |
| 72 | .destroy_inode =jffs2_destroy_inode, | 72 | .destroy_inode =jffs2_destroy_inode, |
| 73 | .read_inode = jffs2_read_inode, | 73 | .read_inode = jffs2_read_inode, |
| 74 | .put_super = jffs2_put_super, | 74 | .put_super = jffs2_put_super, |
| 75 | .write_super = jffs2_write_super, | 75 | .write_super = jffs2_write_super, |
| 76 | .statfs = jffs2_statfs, | 76 | .statfs = jffs2_statfs, |
| 77 | .remount_fs = jffs2_remount_fs, | 77 | .remount_fs = jffs2_remount_fs, |
| 78 | .clear_inode = jffs2_clear_inode, | 78 | .clear_inode = jffs2_clear_inode, |
| 79 | .dirty_inode = jffs2_dirty_inode, | 79 | .dirty_inode = jffs2_dirty_inode, |
| 80 | .sync_fs = jffs2_sync_fs, | 80 | .sync_fs = jffs2_sync_fs, |
| 81 | }; | 81 | }; |
| 82 | 82 | ||
| 83 | static int jffs2_sb_compare(struct super_block *sb, void *data) | 83 | static int jffs2_sb_compare(struct super_block *sb, void *data) |
| 84 | { | 84 | { |
| 85 | struct jffs2_sb_info *p = data; | 85 | struct jffs2_sb_info *p = data; |
| 86 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 86 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
| 87 | 87 | ||
| 88 | /* The superblocks are considered to be equivalent if the underlying MTD | 88 | /* The superblocks are considered to be equivalent if the underlying MTD |
| 89 | device is the same one */ | 89 | device is the same one */ |
| 90 | if (c->mtd == p->mtd) { | 90 | if (c->mtd == p->mtd) { |
| 91 | D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name)); | 91 | D1(printk(KERN_DEBUG "jffs2_sb_compare: match on device %d (\"%s\")\n", p->mtd->index, p->mtd->name)); |
| 92 | return 1; | 92 | return 1; |
| 93 | } else { | 93 | } else { |
| 94 | D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n", | 94 | D1(printk(KERN_DEBUG "jffs2_sb_compare: No match, device %d (\"%s\"), device %d (\"%s\")\n", |
| 95 | c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name)); | 95 | c->mtd->index, c->mtd->name, p->mtd->index, p->mtd->name)); |
| 96 | return 0; | 96 | return 0; |
| 97 | } | 97 | } |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | static int jffs2_sb_set(struct super_block *sb, void *data) | 100 | static int jffs2_sb_set(struct super_block *sb, void *data) |
| 101 | { | 101 | { |
| 102 | struct jffs2_sb_info *p = data; | 102 | struct jffs2_sb_info *p = data; |
| 103 | 103 | ||
| 104 | /* For persistence of NFS exports etc. we use the same s_dev | 104 | /* For persistence of NFS exports etc. we use the same s_dev |
| 105 | each time we mount the device, don't just use an anonymous | 105 | each time we mount the device, don't just use an anonymous |
| 106 | device */ | 106 | device */ |
| 107 | sb->s_fs_info = p; | 107 | sb->s_fs_info = p; |
| 108 | p->os_priv = sb; | 108 | p->os_priv = sb; |
| 109 | sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, p->mtd->index); | 109 | sb->s_dev = MKDEV(MTD_BLOCK_MAJOR, p->mtd->index); |
| 110 | 110 | ||
| 111 | return 0; | 111 | return 0; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, | 114 | static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, |
| 115 | int flags, const char *dev_name, | 115 | int flags, const char *dev_name, |
| 116 | void *data, struct mtd_info *mtd) | 116 | void *data, struct mtd_info *mtd) |
| 117 | { | 117 | { |
| 118 | struct super_block *sb; | 118 | struct super_block *sb; |
| 119 | struct jffs2_sb_info *c; | 119 | struct jffs2_sb_info *c; |
| 120 | int ret; | 120 | int ret; |
| 121 | 121 | ||
| 122 | c = kmalloc(sizeof(*c), GFP_KERNEL); | 122 | c = kmalloc(sizeof(*c), GFP_KERNEL); |
| 123 | if (!c) | 123 | if (!c) |
| 124 | return ERR_PTR(-ENOMEM); | 124 | return ERR_PTR(-ENOMEM); |
| 125 | memset(c, 0, sizeof(*c)); | 125 | memset(c, 0, sizeof(*c)); |
| 126 | c->mtd = mtd; | 126 | c->mtd = mtd; |
| 127 | 127 | ||
| 128 | sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); | 128 | sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); |
| 129 | 129 | ||
| 130 | if (IS_ERR(sb)) | 130 | if (IS_ERR(sb)) |
| 131 | goto out_put; | 131 | goto out_put; |
| 132 | 132 | ||
| 133 | if (sb->s_root) { | 133 | if (sb->s_root) { |
| 134 | /* New mountpoint for JFFS2 which is already mounted */ | 134 | /* New mountpoint for JFFS2 which is already mounted */ |
| 135 | D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", | 135 | D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", |
| 136 | mtd->index, mtd->name)); | 136 | mtd->index, mtd->name)); |
| 137 | goto out_put; | 137 | goto out_put; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", | 140 | D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): New superblock for device %d (\"%s\")\n", |
| 141 | mtd->index, mtd->name)); | 141 | mtd->index, mtd->name)); |
| 142 | 142 | ||
| 143 | /* Initialize JFFS2 superblock locks, the further initialization will be | 143 | /* Initialize JFFS2 superblock locks, the further initialization will be |
| 144 | * done later */ | 144 | * done later */ |
| 145 | init_MUTEX(&c->alloc_sem); | 145 | init_MUTEX(&c->alloc_sem); |
| 146 | init_MUTEX(&c->erase_free_sem); | 146 | init_MUTEX(&c->erase_free_sem); |
| 147 | init_waitqueue_head(&c->erase_wait); | 147 | init_waitqueue_head(&c->erase_wait); |
| 148 | init_waitqueue_head(&c->inocache_wq); | 148 | init_waitqueue_head(&c->inocache_wq); |
| 149 | spin_lock_init(&c->erase_completion_lock); | 149 | spin_lock_init(&c->erase_completion_lock); |
| 150 | spin_lock_init(&c->inocache_lock); | 150 | spin_lock_init(&c->inocache_lock); |
| 151 | 151 | ||
| 152 | sb->s_op = &jffs2_super_operations; | 152 | sb->s_op = &jffs2_super_operations; |
| 153 | sb->s_flags = flags | MS_NOATIME; | 153 | sb->s_flags = flags | MS_NOATIME; |
| 154 | 154 | ||
| 155 | ret = jffs2_do_fill_super(sb, data, (flags&MS_VERBOSE)?1:0); | 155 | ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); |
| 156 | 156 | ||
| 157 | if (ret) { | 157 | if (ret) { |
| 158 | /* Failure case... */ | 158 | /* Failure case... */ |
| 159 | up_write(&sb->s_umount); | 159 | up_write(&sb->s_umount); |
| 160 | deactivate_super(sb); | 160 | deactivate_super(sb); |
| 161 | return ERR_PTR(ret); | 161 | return ERR_PTR(ret); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | sb->s_flags |= MS_ACTIVE; | 164 | sb->s_flags |= MS_ACTIVE; |
| 165 | return sb; | 165 | return sb; |
| 166 | 166 | ||
| 167 | out_put: | 167 | out_put: |
| 168 | kfree(c); | 168 | kfree(c); |
| 169 | put_mtd_device(mtd); | 169 | put_mtd_device(mtd); |
| 170 | 170 | ||
| 171 | return sb; | 171 | return sb; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, | 174 | static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, |
| 175 | int flags, const char *dev_name, | 175 | int flags, const char *dev_name, |
| 176 | void *data, int mtdnr) | 176 | void *data, int mtdnr) |
| 177 | { | 177 | { |
| 178 | struct mtd_info *mtd; | 178 | struct mtd_info *mtd; |
| 179 | 179 | ||
| 180 | mtd = get_mtd_device(NULL, mtdnr); | 180 | mtd = get_mtd_device(NULL, mtdnr); |
| 181 | if (!mtd) { | 181 | if (!mtd) { |
| 182 | D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); | 182 | D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); |
| 183 | return ERR_PTR(-EINVAL); | 183 | return ERR_PTR(-EINVAL); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); | 186 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, | 189 | static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, |
| 190 | int flags, const char *dev_name, | 190 | int flags, const char *dev_name, |
| 191 | void *data) | 191 | void *data) |
| 192 | { | 192 | { |
| 193 | int err; | 193 | int err; |
| 194 | struct nameidata nd; | 194 | struct nameidata nd; |
| 195 | int mtdnr; | 195 | int mtdnr; |
| 196 | 196 | ||
| 197 | if (!dev_name) | 197 | if (!dev_name) |
| 198 | return ERR_PTR(-EINVAL); | 198 | return ERR_PTR(-EINVAL); |
| 199 | 199 | ||
| 200 | D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); | 200 | D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); |
| 201 | 201 | ||
| 202 | /* The preferred way of mounting in future; especially when | 202 | /* The preferred way of mounting in future; especially when |
| 203 | CONFIG_BLK_DEV is implemented - we specify the underlying | 203 | CONFIG_BLK_DEV is implemented - we specify the underlying |
| 204 | MTD device by number or by name, so that we don't require | 204 | MTD device by number or by name, so that we don't require |
| 205 | block device support to be present in the kernel. */ | 205 | block device support to be present in the kernel. */ |
| 206 | 206 | ||
| 207 | /* FIXME: How to do the root fs this way? */ | 207 | /* FIXME: How to do the root fs this way? */ |
| 208 | 208 | ||
| 209 | if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { | 209 | if (dev_name[0] == 'm' && dev_name[1] == 't' && dev_name[2] == 'd') { |
| 210 | /* Probably mounting without the blkdev crap */ | 210 | /* Probably mounting without the blkdev crap */ |
| 211 | if (dev_name[3] == ':') { | 211 | if (dev_name[3] == ':') { |
| 212 | struct mtd_info *mtd; | 212 | struct mtd_info *mtd; |
| 213 | 213 | ||
| 214 | /* Mount by MTD device name */ | 214 | /* Mount by MTD device name */ |
| 215 | D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); | 215 | D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd:%%s, name \"%s\"\n", dev_name+4)); |
| 216 | for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { | 216 | for (mtdnr = 0; mtdnr < MAX_MTD_DEVICES; mtdnr++) { |
| 217 | mtd = get_mtd_device(NULL, mtdnr); | 217 | mtd = get_mtd_device(NULL, mtdnr); |
| 218 | if (mtd) { | 218 | if (mtd) { |
| 219 | if (!strcmp(mtd->name, dev_name+4)) | 219 | if (!strcmp(mtd->name, dev_name+4)) |
| 220 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); | 220 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); |
| 221 | put_mtd_device(mtd); | 221 | put_mtd_device(mtd); |
| 222 | } | 222 | } |
| 223 | } | 223 | } |
| 224 | printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4); | 224 | printk(KERN_NOTICE "jffs2_get_sb(): MTD device with name \"%s\" not found.\n", dev_name+4); |
| 225 | } else if (isdigit(dev_name[3])) { | 225 | } else if (isdigit(dev_name[3])) { |
| 226 | /* Mount by MTD device number name */ | 226 | /* Mount by MTD device number name */ |
| 227 | char *endptr; | 227 | char *endptr; |
| 228 | 228 | ||
| 229 | mtdnr = simple_strtoul(dev_name+3, &endptr, 0); | 229 | mtdnr = simple_strtoul(dev_name+3, &endptr, 0); |
| 230 | if (!*endptr) { | 230 | if (!*endptr) { |
| 231 | /* It was a valid number */ | 231 | /* It was a valid number */ |
| 232 | D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); | 232 | D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); |
| 233 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); | 233 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); |
| 234 | } | 234 | } |
| 235 | } | 235 | } |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | /* Try the old way - the hack where we allowed users to mount | 238 | /* Try the old way - the hack where we allowed users to mount |
| 239 | /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ | 239 | /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ |
| 240 | 240 | ||
| 241 | err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); | 241 | err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); |
| 242 | 242 | ||
| 243 | D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n", | 243 | D1(printk(KERN_DEBUG "jffs2_get_sb(): path_lookup() returned %d, inode %p\n", |
| 244 | err, nd.dentry->d_inode)); | 244 | err, nd.dentry->d_inode)); |
| 245 | 245 | ||
| 246 | if (err) | 246 | if (err) |
| 247 | return ERR_PTR(err); | 247 | return ERR_PTR(err); |
| 248 | 248 | ||
| 249 | err = -EINVAL; | 249 | err = -EINVAL; |
| 250 | 250 | ||
| 251 | if (!S_ISBLK(nd.dentry->d_inode->i_mode)) | 251 | if (!S_ISBLK(nd.dentry->d_inode->i_mode)) |
| 252 | goto out; | 252 | goto out; |
| 253 | 253 | ||
| 254 | if (nd.mnt->mnt_flags & MNT_NODEV) { | 254 | if (nd.mnt->mnt_flags & MNT_NODEV) { |
| 255 | err = -EACCES; | 255 | err = -EACCES; |
| 256 | goto out; | 256 | goto out; |
| 257 | } | 257 | } |
| 258 | 258 | ||
| 259 | if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) { | 259 | if (imajor(nd.dentry->d_inode) != MTD_BLOCK_MAJOR) { |
| 260 | if (!(flags & MS_VERBOSE)) /* Yes I mean this. Strangely */ | 260 | if (!(flags & MS_SILENT)) |
| 261 | printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", | 261 | printk(KERN_NOTICE "Attempt to mount non-MTD device \"%s\" as JFFS2\n", |
| 262 | dev_name); | 262 | dev_name); |
| 263 | goto out; | 263 | goto out; |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | mtdnr = iminor(nd.dentry->d_inode); | 266 | mtdnr = iminor(nd.dentry->d_inode); |
| 267 | path_release(&nd); | 267 | path_release(&nd); |
| 268 | 268 | ||
| 269 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); | 269 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); |
| 270 | 270 | ||
| 271 | out: | 271 | out: |
| 272 | path_release(&nd); | 272 | path_release(&nd); |
| 273 | return ERR_PTR(err); | 273 | return ERR_PTR(err); |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | static void jffs2_put_super (struct super_block *sb) | 276 | static void jffs2_put_super (struct super_block *sb) |
| 277 | { | 277 | { |
| 278 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 278 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
| 279 | 279 | ||
| 280 | D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n")); | 280 | D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n")); |
| 281 | 281 | ||
| 282 | down(&c->alloc_sem); | 282 | down(&c->alloc_sem); |
| 283 | jffs2_flush_wbuf_pad(c); | 283 | jffs2_flush_wbuf_pad(c); |
| 284 | up(&c->alloc_sem); | 284 | up(&c->alloc_sem); |
| 285 | 285 | ||
| 286 | jffs2_sum_exit(c); | 286 | jffs2_sum_exit(c); |
| 287 | 287 | ||
| 288 | jffs2_free_ino_caches(c); | 288 | jffs2_free_ino_caches(c); |
| 289 | jffs2_free_raw_node_refs(c); | 289 | jffs2_free_raw_node_refs(c); |
| 290 | if (jffs2_blocks_use_vmalloc(c)) | 290 | if (jffs2_blocks_use_vmalloc(c)) |
| 291 | vfree(c->blocks); | 291 | vfree(c->blocks); |
| 292 | else | 292 | else |
| 293 | kfree(c->blocks); | 293 | kfree(c->blocks); |
| 294 | jffs2_flash_cleanup(c); | 294 | jffs2_flash_cleanup(c); |
| 295 | kfree(c->inocache_list); | 295 | kfree(c->inocache_list); |
| 296 | if (c->mtd->sync) | 296 | if (c->mtd->sync) |
| 297 | c->mtd->sync(c->mtd); | 297 | c->mtd->sync(c->mtd); |
| 298 | 298 | ||
| 299 | D1(printk(KERN_DEBUG "jffs2_put_super returning\n")); | 299 | D1(printk(KERN_DEBUG "jffs2_put_super returning\n")); |
| 300 | } | 300 | } |
| 301 | 301 | ||
| 302 | static void jffs2_kill_sb(struct super_block *sb) | 302 | static void jffs2_kill_sb(struct super_block *sb) |
| 303 | { | 303 | { |
| 304 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 304 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
| 305 | if (!(sb->s_flags & MS_RDONLY)) | 305 | if (!(sb->s_flags & MS_RDONLY)) |
| 306 | jffs2_stop_garbage_collect_thread(c); | 306 | jffs2_stop_garbage_collect_thread(c); |
| 307 | generic_shutdown_super(sb); | 307 | generic_shutdown_super(sb); |
| 308 | put_mtd_device(c->mtd); | 308 | put_mtd_device(c->mtd); |
| 309 | kfree(c); | 309 | kfree(c); |
| 310 | } | 310 | } |
| 311 | 311 | ||
| 312 | static struct file_system_type jffs2_fs_type = { | 312 | static struct file_system_type jffs2_fs_type = { |
| 313 | .owner = THIS_MODULE, | 313 | .owner = THIS_MODULE, |
| 314 | .name = "jffs2", | 314 | .name = "jffs2", |
| 315 | .get_sb = jffs2_get_sb, | 315 | .get_sb = jffs2_get_sb, |
| 316 | .kill_sb = jffs2_kill_sb, | 316 | .kill_sb = jffs2_kill_sb, |
| 317 | }; | 317 | }; |
| 318 | 318 | ||
| 319 | static int __init init_jffs2_fs(void) | 319 | static int __init init_jffs2_fs(void) |
| 320 | { | 320 | { |
| 321 | int ret; | 321 | int ret; |
| 322 | 322 | ||
| 323 | printk(KERN_INFO "JFFS2 version 2.2." | 323 | printk(KERN_INFO "JFFS2 version 2.2." |
| 324 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | 324 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER |
| 325 | " (NAND)" | 325 | " (NAND)" |
| 326 | #endif | 326 | #endif |
| 327 | #ifdef CONFIG_JFFS2_SUMMARY | 327 | #ifdef CONFIG_JFFS2_SUMMARY |
| 328 | " (SUMMARY) " | 328 | " (SUMMARY) " |
| 329 | #endif | 329 | #endif |
| 330 | " (C) 2001-2003 Red Hat, Inc.\n"); | 330 | " (C) 2001-2003 Red Hat, Inc.\n"); |
| 331 | 331 | ||
| 332 | jffs2_inode_cachep = kmem_cache_create("jffs2_i", | 332 | jffs2_inode_cachep = kmem_cache_create("jffs2_i", |
| 333 | sizeof(struct jffs2_inode_info), | 333 | sizeof(struct jffs2_inode_info), |
| 334 | 0, SLAB_RECLAIM_ACCOUNT, | 334 | 0, SLAB_RECLAIM_ACCOUNT, |
| 335 | jffs2_i_init_once, NULL); | 335 | jffs2_i_init_once, NULL); |
| 336 | if (!jffs2_inode_cachep) { | 336 | if (!jffs2_inode_cachep) { |
| 337 | printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n"); | 337 | printk(KERN_ERR "JFFS2 error: Failed to initialise inode cache\n"); |
| 338 | return -ENOMEM; | 338 | return -ENOMEM; |
| 339 | } | 339 | } |
| 340 | ret = jffs2_compressors_init(); | 340 | ret = jffs2_compressors_init(); |
| 341 | if (ret) { | 341 | if (ret) { |
| 342 | printk(KERN_ERR "JFFS2 error: Failed to initialise compressors\n"); | 342 | printk(KERN_ERR "JFFS2 error: Failed to initialise compressors\n"); |
| 343 | goto out; | 343 | goto out; |
| 344 | } | 344 | } |
| 345 | ret = jffs2_create_slab_caches(); | 345 | ret = jffs2_create_slab_caches(); |
| 346 | if (ret) { | 346 | if (ret) { |
| 347 | printk(KERN_ERR "JFFS2 error: Failed to initialise slab caches\n"); | 347 | printk(KERN_ERR "JFFS2 error: Failed to initialise slab caches\n"); |
| 348 | goto out_compressors; | 348 | goto out_compressors; |
| 349 | } | 349 | } |
| 350 | ret = register_filesystem(&jffs2_fs_type); | 350 | ret = register_filesystem(&jffs2_fs_type); |
| 351 | if (ret) { | 351 | if (ret) { |
| 352 | printk(KERN_ERR "JFFS2 error: Failed to register filesystem\n"); | 352 | printk(KERN_ERR "JFFS2 error: Failed to register filesystem\n"); |
| 353 | goto out_slab; | 353 | goto out_slab; |
| 354 | } | 354 | } |
| 355 | return 0; | 355 | return 0; |
| 356 | 356 | ||
| 357 | out_slab: | 357 | out_slab: |
| 358 | jffs2_destroy_slab_caches(); | 358 | jffs2_destroy_slab_caches(); |
| 359 | out_compressors: | 359 | out_compressors: |
| 360 | jffs2_compressors_exit(); | 360 | jffs2_compressors_exit(); |
| 361 | out: | 361 | out: |
| 362 | kmem_cache_destroy(jffs2_inode_cachep); | 362 | kmem_cache_destroy(jffs2_inode_cachep); |
| 363 | return ret; | 363 | return ret; |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | static void __exit exit_jffs2_fs(void) | 366 | static void __exit exit_jffs2_fs(void) |
| 367 | { | 367 | { |
| 368 | unregister_filesystem(&jffs2_fs_type); | 368 | unregister_filesystem(&jffs2_fs_type); |
| 369 | jffs2_destroy_slab_caches(); | 369 | jffs2_destroy_slab_caches(); |
| 370 | jffs2_compressors_exit(); | 370 | jffs2_compressors_exit(); |
| 371 | kmem_cache_destroy(jffs2_inode_cachep); | 371 | kmem_cache_destroy(jffs2_inode_cachep); |
| 372 | } | 372 | } |
| 373 | 373 | ||
| 374 | module_init(init_jffs2_fs); | 374 | module_init(init_jffs2_fs); |
| 375 | module_exit(exit_jffs2_fs); | 375 | module_exit(exit_jffs2_fs); |
| 376 | 376 | ||
| 377 | MODULE_DESCRIPTION("The Journalling Flash File System, v2"); | 377 | MODULE_DESCRIPTION("The Journalling Flash File System, v2"); |
| 378 | MODULE_AUTHOR("Red Hat, Inc."); | 378 | MODULE_AUTHOR("Red Hat, Inc."); |
| 379 | MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for | 379 | MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for |
| 380 | // the sake of this tag. It's Free Software. | 380 | // the sake of this tag. It's Free Software. |
| 381 | 381 |
fs/nfs/inode.c
| 1 | /* | 1 | /* |
| 2 | * linux/fs/nfs/inode.c | 2 | * linux/fs/nfs/inode.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1992 Rick Sladkey | 4 | * Copyright (C) 1992 Rick Sladkey |
| 5 | * | 5 | * |
| 6 | * nfs inode and superblock handling functions | 6 | * nfs inode and 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 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/config.h> | 16 | #include <linux/config.h> |
| 17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
| 18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
| 19 | 19 | ||
| 20 | #include <linux/time.h> | 20 | #include <linux/time.h> |
| 21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
| 22 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
| 23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
| 24 | #include <linux/stat.h> | 24 | #include <linux/stat.h> |
| 25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
| 26 | #include <linux/unistd.h> | 26 | #include <linux/unistd.h> |
| 27 | #include <linux/sunrpc/clnt.h> | 27 | #include <linux/sunrpc/clnt.h> |
| 28 | #include <linux/sunrpc/stats.h> | 28 | #include <linux/sunrpc/stats.h> |
| 29 | #include <linux/nfs_fs.h> | 29 | #include <linux/nfs_fs.h> |
| 30 | #include <linux/nfs_mount.h> | 30 | #include <linux/nfs_mount.h> |
| 31 | #include <linux/nfs4_mount.h> | 31 | #include <linux/nfs4_mount.h> |
| 32 | #include <linux/lockd/bind.h> | 32 | #include <linux/lockd/bind.h> |
| 33 | #include <linux/smp_lock.h> | 33 | #include <linux/smp_lock.h> |
| 34 | #include <linux/seq_file.h> | 34 | #include <linux/seq_file.h> |
| 35 | #include <linux/mount.h> | 35 | #include <linux/mount.h> |
| 36 | #include <linux/nfs_idmap.h> | 36 | #include <linux/nfs_idmap.h> |
| 37 | #include <linux/vfs.h> | 37 | #include <linux/vfs.h> |
| 38 | 38 | ||
| 39 | #include <asm/system.h> | 39 | #include <asm/system.h> |
| 40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 41 | 41 | ||
| 42 | #include "nfs4_fs.h" | 42 | #include "nfs4_fs.h" |
| 43 | #include "callback.h" | 43 | #include "callback.h" |
| 44 | #include "delegation.h" | 44 | #include "delegation.h" |
| 45 | 45 | ||
| 46 | #define NFSDBG_FACILITY NFSDBG_VFS | 46 | #define NFSDBG_FACILITY NFSDBG_VFS |
| 47 | #define NFS_PARANOIA 1 | 47 | #define NFS_PARANOIA 1 |
| 48 | 48 | ||
| 49 | /* Maximum number of readahead requests | 49 | /* Maximum number of readahead requests |
| 50 | * FIXME: this should really be a sysctl so that users may tune it to suit | 50 | * FIXME: this should really be a sysctl so that users may tune it to suit |
| 51 | * their needs. People that do NFS over a slow network, might for | 51 | * their needs. People that do NFS over a slow network, might for |
| 52 | * instance want to reduce it to something closer to 1 for improved | 52 | * instance want to reduce it to something closer to 1 for improved |
| 53 | * interactive response. | 53 | * interactive response. |
| 54 | */ | 54 | */ |
| 55 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) | 55 | #define NFS_MAX_READAHEAD (RPC_DEF_SLOT_TABLE - 1) |
| 56 | 56 | ||
| 57 | static void nfs_invalidate_inode(struct inode *); | 57 | static void nfs_invalidate_inode(struct inode *); |
| 58 | static int nfs_update_inode(struct inode *, struct nfs_fattr *); | 58 | static int nfs_update_inode(struct inode *, struct nfs_fattr *); |
| 59 | 59 | ||
| 60 | static struct inode *nfs_alloc_inode(struct super_block *sb); | 60 | static struct inode *nfs_alloc_inode(struct super_block *sb); |
| 61 | static void nfs_destroy_inode(struct inode *); | 61 | static void nfs_destroy_inode(struct inode *); |
| 62 | static int nfs_write_inode(struct inode *,int); | 62 | static int nfs_write_inode(struct inode *,int); |
| 63 | static void nfs_delete_inode(struct inode *); | 63 | static void nfs_delete_inode(struct inode *); |
| 64 | static void nfs_clear_inode(struct inode *); | 64 | static void nfs_clear_inode(struct inode *); |
| 65 | static void nfs_umount_begin(struct super_block *); | 65 | static void nfs_umount_begin(struct super_block *); |
| 66 | static int nfs_statfs(struct super_block *, struct kstatfs *); | 66 | static int nfs_statfs(struct super_block *, struct kstatfs *); |
| 67 | static int nfs_show_options(struct seq_file *, struct vfsmount *); | 67 | static int nfs_show_options(struct seq_file *, struct vfsmount *); |
| 68 | static void nfs_zap_acl_cache(struct inode *); | 68 | static void nfs_zap_acl_cache(struct inode *); |
| 69 | 69 | ||
| 70 | static struct rpc_program nfs_program; | 70 | static struct rpc_program nfs_program; |
| 71 | 71 | ||
| 72 | static struct super_operations nfs_sops = { | 72 | static struct super_operations nfs_sops = { |
| 73 | .alloc_inode = nfs_alloc_inode, | 73 | .alloc_inode = nfs_alloc_inode, |
| 74 | .destroy_inode = nfs_destroy_inode, | 74 | .destroy_inode = nfs_destroy_inode, |
| 75 | .write_inode = nfs_write_inode, | 75 | .write_inode = nfs_write_inode, |
| 76 | .delete_inode = nfs_delete_inode, | 76 | .delete_inode = nfs_delete_inode, |
| 77 | .statfs = nfs_statfs, | 77 | .statfs = nfs_statfs, |
| 78 | .clear_inode = nfs_clear_inode, | 78 | .clear_inode = nfs_clear_inode, |
| 79 | .umount_begin = nfs_umount_begin, | 79 | .umount_begin = nfs_umount_begin, |
| 80 | .show_options = nfs_show_options, | 80 | .show_options = nfs_show_options, |
| 81 | }; | 81 | }; |
| 82 | 82 | ||
| 83 | /* | 83 | /* |
| 84 | * RPC cruft for NFS | 84 | * RPC cruft for NFS |
| 85 | */ | 85 | */ |
| 86 | static struct rpc_stat nfs_rpcstat = { | 86 | static struct rpc_stat nfs_rpcstat = { |
| 87 | .program = &nfs_program | 87 | .program = &nfs_program |
| 88 | }; | 88 | }; |
| 89 | static struct rpc_version * nfs_version[] = { | 89 | static struct rpc_version * nfs_version[] = { |
| 90 | NULL, | 90 | NULL, |
| 91 | NULL, | 91 | NULL, |
| 92 | &nfs_version2, | 92 | &nfs_version2, |
| 93 | #if defined(CONFIG_NFS_V3) | 93 | #if defined(CONFIG_NFS_V3) |
| 94 | &nfs_version3, | 94 | &nfs_version3, |
| 95 | #elif defined(CONFIG_NFS_V4) | 95 | #elif defined(CONFIG_NFS_V4) |
| 96 | NULL, | 96 | NULL, |
| 97 | #endif | 97 | #endif |
| 98 | #if defined(CONFIG_NFS_V4) | 98 | #if defined(CONFIG_NFS_V4) |
| 99 | &nfs_version4, | 99 | &nfs_version4, |
| 100 | #endif | 100 | #endif |
| 101 | }; | 101 | }; |
| 102 | 102 | ||
| 103 | static struct rpc_program nfs_program = { | 103 | static struct rpc_program nfs_program = { |
| 104 | .name = "nfs", | 104 | .name = "nfs", |
| 105 | .number = NFS_PROGRAM, | 105 | .number = NFS_PROGRAM, |
| 106 | .nrvers = sizeof(nfs_version) / sizeof(nfs_version[0]), | 106 | .nrvers = sizeof(nfs_version) / sizeof(nfs_version[0]), |
| 107 | .version = nfs_version, | 107 | .version = nfs_version, |
| 108 | .stats = &nfs_rpcstat, | 108 | .stats = &nfs_rpcstat, |
| 109 | .pipe_dir_name = "/nfs", | 109 | .pipe_dir_name = "/nfs", |
| 110 | }; | 110 | }; |
| 111 | 111 | ||
| 112 | #ifdef CONFIG_NFS_V3_ACL | 112 | #ifdef CONFIG_NFS_V3_ACL |
| 113 | static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; | 113 | static struct rpc_stat nfsacl_rpcstat = { &nfsacl_program }; |
| 114 | static struct rpc_version * nfsacl_version[] = { | 114 | static struct rpc_version * nfsacl_version[] = { |
| 115 | [3] = &nfsacl_version3, | 115 | [3] = &nfsacl_version3, |
| 116 | }; | 116 | }; |
| 117 | 117 | ||
| 118 | struct rpc_program nfsacl_program = { | 118 | struct rpc_program nfsacl_program = { |
| 119 | .name = "nfsacl", | 119 | .name = "nfsacl", |
| 120 | .number = NFS_ACL_PROGRAM, | 120 | .number = NFS_ACL_PROGRAM, |
| 121 | .nrvers = sizeof(nfsacl_version) / sizeof(nfsacl_version[0]), | 121 | .nrvers = sizeof(nfsacl_version) / sizeof(nfsacl_version[0]), |
| 122 | .version = nfsacl_version, | 122 | .version = nfsacl_version, |
| 123 | .stats = &nfsacl_rpcstat, | 123 | .stats = &nfsacl_rpcstat, |
| 124 | }; | 124 | }; |
| 125 | #endif /* CONFIG_NFS_V3_ACL */ | 125 | #endif /* CONFIG_NFS_V3_ACL */ |
| 126 | 126 | ||
| 127 | static inline unsigned long | 127 | static inline unsigned long |
| 128 | nfs_fattr_to_ino_t(struct nfs_fattr *fattr) | 128 | nfs_fattr_to_ino_t(struct nfs_fattr *fattr) |
| 129 | { | 129 | { |
| 130 | return nfs_fileid_to_ino_t(fattr->fileid); | 130 | return nfs_fileid_to_ino_t(fattr->fileid); |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | static int | 133 | static int |
| 134 | nfs_write_inode(struct inode *inode, int sync) | 134 | nfs_write_inode(struct inode *inode, int sync) |
| 135 | { | 135 | { |
| 136 | int flags = sync ? FLUSH_WAIT : 0; | 136 | int flags = sync ? FLUSH_WAIT : 0; |
| 137 | int ret; | 137 | int ret; |
| 138 | 138 | ||
| 139 | ret = nfs_commit_inode(inode, flags); | 139 | ret = nfs_commit_inode(inode, flags); |
| 140 | if (ret < 0) | 140 | if (ret < 0) |
| 141 | return ret; | 141 | return ret; |
| 142 | return 0; | 142 | return 0; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | static void | 145 | static void |
| 146 | nfs_delete_inode(struct inode * inode) | 146 | nfs_delete_inode(struct inode * inode) |
| 147 | { | 147 | { |
| 148 | dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); | 148 | dprintk("NFS: delete_inode(%s/%ld)\n", inode->i_sb->s_id, inode->i_ino); |
| 149 | 149 | ||
| 150 | truncate_inode_pages(&inode->i_data, 0); | 150 | truncate_inode_pages(&inode->i_data, 0); |
| 151 | 151 | ||
| 152 | nfs_wb_all(inode); | 152 | nfs_wb_all(inode); |
| 153 | /* | 153 | /* |
| 154 | * The following should never happen... | 154 | * The following should never happen... |
| 155 | */ | 155 | */ |
| 156 | if (nfs_have_writebacks(inode)) { | 156 | if (nfs_have_writebacks(inode)) { |
| 157 | printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino); | 157 | printk(KERN_ERR "nfs_delete_inode: inode %ld has pending RPC requests\n", inode->i_ino); |
| 158 | } | 158 | } |
| 159 | 159 | ||
| 160 | clear_inode(inode); | 160 | clear_inode(inode); |
| 161 | } | 161 | } |
| 162 | 162 | ||
| 163 | static void | 163 | static void |
| 164 | nfs_clear_inode(struct inode *inode) | 164 | nfs_clear_inode(struct inode *inode) |
| 165 | { | 165 | { |
| 166 | struct nfs_inode *nfsi = NFS_I(inode); | 166 | struct nfs_inode *nfsi = NFS_I(inode); |
| 167 | struct rpc_cred *cred; | 167 | struct rpc_cred *cred; |
| 168 | 168 | ||
| 169 | nfs_wb_all(inode); | 169 | nfs_wb_all(inode); |
| 170 | BUG_ON (!list_empty(&nfsi->open_files)); | 170 | BUG_ON (!list_empty(&nfsi->open_files)); |
| 171 | nfs_zap_acl_cache(inode); | 171 | nfs_zap_acl_cache(inode); |
| 172 | cred = nfsi->cache_access.cred; | 172 | cred = nfsi->cache_access.cred; |
| 173 | if (cred) | 173 | if (cred) |
| 174 | put_rpccred(cred); | 174 | put_rpccred(cred); |
| 175 | BUG_ON(atomic_read(&nfsi->data_updates) != 0); | 175 | BUG_ON(atomic_read(&nfsi->data_updates) != 0); |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | void | 178 | void |
| 179 | nfs_umount_begin(struct super_block *sb) | 179 | nfs_umount_begin(struct super_block *sb) |
| 180 | { | 180 | { |
| 181 | struct rpc_clnt *rpc = NFS_SB(sb)->client; | 181 | struct rpc_clnt *rpc = NFS_SB(sb)->client; |
| 182 | 182 | ||
| 183 | /* -EIO all pending I/O */ | 183 | /* -EIO all pending I/O */ |
| 184 | if (!IS_ERR(rpc)) | 184 | if (!IS_ERR(rpc)) |
| 185 | rpc_killall_tasks(rpc); | 185 | rpc_killall_tasks(rpc); |
| 186 | rpc = NFS_SB(sb)->client_acl; | 186 | rpc = NFS_SB(sb)->client_acl; |
| 187 | if (!IS_ERR(rpc)) | 187 | if (!IS_ERR(rpc)) |
| 188 | rpc_killall_tasks(rpc); | 188 | rpc_killall_tasks(rpc); |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | 191 | ||
| 192 | static inline unsigned long | 192 | static inline unsigned long |
| 193 | nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp) | 193 | nfs_block_bits(unsigned long bsize, unsigned char *nrbitsp) |
| 194 | { | 194 | { |
| 195 | /* make sure blocksize is a power of two */ | 195 | /* make sure blocksize is a power of two */ |
| 196 | if ((bsize & (bsize - 1)) || nrbitsp) { | 196 | if ((bsize & (bsize - 1)) || nrbitsp) { |
| 197 | unsigned char nrbits; | 197 | unsigned char nrbits; |
| 198 | 198 | ||
| 199 | for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--) | 199 | for (nrbits = 31; nrbits && !(bsize & (1 << nrbits)); nrbits--) |
| 200 | ; | 200 | ; |
| 201 | bsize = 1 << nrbits; | 201 | bsize = 1 << nrbits; |
| 202 | if (nrbitsp) | 202 | if (nrbitsp) |
| 203 | *nrbitsp = nrbits; | 203 | *nrbitsp = nrbits; |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | return bsize; | 206 | return bsize; |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | /* | 209 | /* |
| 210 | * Calculate the number of 512byte blocks used. | 210 | * Calculate the number of 512byte blocks used. |
| 211 | */ | 211 | */ |
| 212 | static inline unsigned long | 212 | static inline unsigned long |
| 213 | nfs_calc_block_size(u64 tsize) | 213 | nfs_calc_block_size(u64 tsize) |
| 214 | { | 214 | { |
| 215 | loff_t used = (tsize + 511) >> 9; | 215 | loff_t used = (tsize + 511) >> 9; |
| 216 | return (used > ULONG_MAX) ? ULONG_MAX : used; | 216 | return (used > ULONG_MAX) ? ULONG_MAX : used; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | /* | 219 | /* |
| 220 | * Compute and set NFS server blocksize | 220 | * Compute and set NFS server blocksize |
| 221 | */ | 221 | */ |
| 222 | static inline unsigned long | 222 | static inline unsigned long |
| 223 | nfs_block_size(unsigned long bsize, unsigned char *nrbitsp) | 223 | nfs_block_size(unsigned long bsize, unsigned char *nrbitsp) |
| 224 | { | 224 | { |
| 225 | if (bsize < NFS_MIN_FILE_IO_SIZE) | 225 | if (bsize < NFS_MIN_FILE_IO_SIZE) |
| 226 | bsize = NFS_DEF_FILE_IO_SIZE; | 226 | bsize = NFS_DEF_FILE_IO_SIZE; |
| 227 | else if (bsize >= NFS_MAX_FILE_IO_SIZE) | 227 | else if (bsize >= NFS_MAX_FILE_IO_SIZE) |
| 228 | bsize = NFS_MAX_FILE_IO_SIZE; | 228 | bsize = NFS_MAX_FILE_IO_SIZE; |
| 229 | 229 | ||
| 230 | return nfs_block_bits(bsize, nrbitsp); | 230 | return nfs_block_bits(bsize, nrbitsp); |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | /* | 233 | /* |
| 234 | * Obtain the root inode of the file system. | 234 | * Obtain the root inode of the file system. |
| 235 | */ | 235 | */ |
| 236 | static struct inode * | 236 | static struct inode * |
| 237 | nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo) | 237 | nfs_get_root(struct super_block *sb, struct nfs_fh *rootfh, struct nfs_fsinfo *fsinfo) |
| 238 | { | 238 | { |
| 239 | struct nfs_server *server = NFS_SB(sb); | 239 | struct nfs_server *server = NFS_SB(sb); |
| 240 | struct inode *rooti; | 240 | struct inode *rooti; |
| 241 | int error; | 241 | int error; |
| 242 | 242 | ||
| 243 | error = server->rpc_ops->getroot(server, rootfh, fsinfo); | 243 | error = server->rpc_ops->getroot(server, rootfh, fsinfo); |
| 244 | if (error < 0) { | 244 | if (error < 0) { |
| 245 | dprintk("nfs_get_root: getattr error = %d\n", -error); | 245 | dprintk("nfs_get_root: getattr error = %d\n", -error); |
| 246 | return ERR_PTR(error); | 246 | return ERR_PTR(error); |
| 247 | } | 247 | } |
| 248 | 248 | ||
| 249 | rooti = nfs_fhget(sb, rootfh, fsinfo->fattr); | 249 | rooti = nfs_fhget(sb, rootfh, fsinfo->fattr); |
| 250 | if (!rooti) | 250 | if (!rooti) |
| 251 | return ERR_PTR(-ENOMEM); | 251 | return ERR_PTR(-ENOMEM); |
| 252 | return rooti; | 252 | return rooti; |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | /* | 255 | /* |
| 256 | * Do NFS version-independent mount processing, and sanity checking | 256 | * Do NFS version-independent mount processing, and sanity checking |
| 257 | */ | 257 | */ |
| 258 | static int | 258 | static int |
| 259 | nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor) | 259 | nfs_sb_init(struct super_block *sb, rpc_authflavor_t authflavor) |
| 260 | { | 260 | { |
| 261 | struct nfs_server *server; | 261 | struct nfs_server *server; |
| 262 | struct inode *root_inode; | 262 | struct inode *root_inode; |
| 263 | struct nfs_fattr fattr; | 263 | struct nfs_fattr fattr; |
| 264 | struct nfs_fsinfo fsinfo = { | 264 | struct nfs_fsinfo fsinfo = { |
| 265 | .fattr = &fattr, | 265 | .fattr = &fattr, |
| 266 | }; | 266 | }; |
| 267 | struct nfs_pathconf pathinfo = { | 267 | struct nfs_pathconf pathinfo = { |
| 268 | .fattr = &fattr, | 268 | .fattr = &fattr, |
| 269 | }; | 269 | }; |
| 270 | int no_root_error = 0; | 270 | int no_root_error = 0; |
| 271 | unsigned long max_rpc_payload; | 271 | unsigned long max_rpc_payload; |
| 272 | 272 | ||
| 273 | /* We probably want something more informative here */ | 273 | /* We probably want something more informative here */ |
| 274 | snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); | 274 | snprintf(sb->s_id, sizeof(sb->s_id), "%x:%x", MAJOR(sb->s_dev), MINOR(sb->s_dev)); |
| 275 | 275 | ||
| 276 | server = NFS_SB(sb); | 276 | server = NFS_SB(sb); |
| 277 | 277 | ||
| 278 | sb->s_magic = NFS_SUPER_MAGIC; | 278 | sb->s_magic = NFS_SUPER_MAGIC; |
| 279 | 279 | ||
| 280 | root_inode = nfs_get_root(sb, &server->fh, &fsinfo); | 280 | root_inode = nfs_get_root(sb, &server->fh, &fsinfo); |
| 281 | /* Did getting the root inode fail? */ | 281 | /* Did getting the root inode fail? */ |
| 282 | if (IS_ERR(root_inode)) { | 282 | if (IS_ERR(root_inode)) { |
| 283 | no_root_error = PTR_ERR(root_inode); | 283 | no_root_error = PTR_ERR(root_inode); |
| 284 | goto out_no_root; | 284 | goto out_no_root; |
| 285 | } | 285 | } |
| 286 | sb->s_root = d_alloc_root(root_inode); | 286 | sb->s_root = d_alloc_root(root_inode); |
| 287 | if (!sb->s_root) { | 287 | if (!sb->s_root) { |
| 288 | no_root_error = -ENOMEM; | 288 | no_root_error = -ENOMEM; |
| 289 | goto out_no_root; | 289 | goto out_no_root; |
| 290 | } | 290 | } |
| 291 | sb->s_root->d_op = server->rpc_ops->dentry_ops; | 291 | sb->s_root->d_op = server->rpc_ops->dentry_ops; |
| 292 | 292 | ||
| 293 | /* Get some general file system info */ | 293 | /* Get some general file system info */ |
| 294 | if (server->namelen == 0 && | 294 | if (server->namelen == 0 && |
| 295 | server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0) | 295 | server->rpc_ops->pathconf(server, &server->fh, &pathinfo) >= 0) |
| 296 | server->namelen = pathinfo.max_namelen; | 296 | server->namelen = pathinfo.max_namelen; |
| 297 | /* Work out a lot of parameters */ | 297 | /* Work out a lot of parameters */ |
| 298 | if (server->rsize == 0) | 298 | if (server->rsize == 0) |
| 299 | server->rsize = nfs_block_size(fsinfo.rtpref, NULL); | 299 | server->rsize = nfs_block_size(fsinfo.rtpref, NULL); |
| 300 | if (server->wsize == 0) | 300 | if (server->wsize == 0) |
| 301 | server->wsize = nfs_block_size(fsinfo.wtpref, NULL); | 301 | server->wsize = nfs_block_size(fsinfo.wtpref, NULL); |
| 302 | 302 | ||
| 303 | if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax) | 303 | if (fsinfo.rtmax >= 512 && server->rsize > fsinfo.rtmax) |
| 304 | server->rsize = nfs_block_size(fsinfo.rtmax, NULL); | 304 | server->rsize = nfs_block_size(fsinfo.rtmax, NULL); |
| 305 | if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax) | 305 | if (fsinfo.wtmax >= 512 && server->wsize > fsinfo.wtmax) |
| 306 | server->wsize = nfs_block_size(fsinfo.wtmax, NULL); | 306 | server->wsize = nfs_block_size(fsinfo.wtmax, NULL); |
| 307 | 307 | ||
| 308 | max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); | 308 | max_rpc_payload = nfs_block_size(rpc_max_payload(server->client), NULL); |
| 309 | if (server->rsize > max_rpc_payload) | 309 | if (server->rsize > max_rpc_payload) |
| 310 | server->rsize = max_rpc_payload; | 310 | server->rsize = max_rpc_payload; |
| 311 | if (server->rsize > NFS_MAX_FILE_IO_SIZE) | 311 | if (server->rsize > NFS_MAX_FILE_IO_SIZE) |
| 312 | server->rsize = NFS_MAX_FILE_IO_SIZE; | 312 | server->rsize = NFS_MAX_FILE_IO_SIZE; |
| 313 | server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 313 | server->rpages = (server->rsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
| 314 | 314 | ||
| 315 | if (server->wsize > max_rpc_payload) | 315 | if (server->wsize > max_rpc_payload) |
| 316 | server->wsize = max_rpc_payload; | 316 | server->wsize = max_rpc_payload; |
| 317 | if (server->wsize > NFS_MAX_FILE_IO_SIZE) | 317 | if (server->wsize > NFS_MAX_FILE_IO_SIZE) |
| 318 | server->wsize = NFS_MAX_FILE_IO_SIZE; | 318 | server->wsize = NFS_MAX_FILE_IO_SIZE; |
| 319 | server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | 319 | server->wpages = (server->wsize + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; |
| 320 | 320 | ||
| 321 | if (sb->s_blocksize == 0) | 321 | if (sb->s_blocksize == 0) |
| 322 | sb->s_blocksize = nfs_block_bits(server->wsize, | 322 | sb->s_blocksize = nfs_block_bits(server->wsize, |
| 323 | &sb->s_blocksize_bits); | 323 | &sb->s_blocksize_bits); |
| 324 | server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL); | 324 | server->wtmult = nfs_block_bits(fsinfo.wtmult, NULL); |
| 325 | 325 | ||
| 326 | server->dtsize = nfs_block_size(fsinfo.dtpref, NULL); | 326 | server->dtsize = nfs_block_size(fsinfo.dtpref, NULL); |
| 327 | if (server->dtsize > PAGE_CACHE_SIZE) | 327 | if (server->dtsize > PAGE_CACHE_SIZE) |
| 328 | server->dtsize = PAGE_CACHE_SIZE; | 328 | server->dtsize = PAGE_CACHE_SIZE; |
| 329 | if (server->dtsize > server->rsize) | 329 | if (server->dtsize > server->rsize) |
| 330 | server->dtsize = server->rsize; | 330 | server->dtsize = server->rsize; |
| 331 | 331 | ||
| 332 | if (server->flags & NFS_MOUNT_NOAC) { | 332 | if (server->flags & NFS_MOUNT_NOAC) { |
| 333 | server->acregmin = server->acregmax = 0; | 333 | server->acregmin = server->acregmax = 0; |
| 334 | server->acdirmin = server->acdirmax = 0; | 334 | server->acdirmin = server->acdirmax = 0; |
| 335 | sb->s_flags |= MS_SYNCHRONOUS; | 335 | sb->s_flags |= MS_SYNCHRONOUS; |
| 336 | } | 336 | } |
| 337 | server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; | 337 | server->backing_dev_info.ra_pages = server->rpages * NFS_MAX_READAHEAD; |
| 338 | 338 | ||
| 339 | sb->s_maxbytes = fsinfo.maxfilesize; | 339 | sb->s_maxbytes = fsinfo.maxfilesize; |
| 340 | if (sb->s_maxbytes > MAX_LFS_FILESIZE) | 340 | if (sb->s_maxbytes > MAX_LFS_FILESIZE) |
| 341 | sb->s_maxbytes = MAX_LFS_FILESIZE; | 341 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
| 342 | 342 | ||
| 343 | server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0; | 343 | server->client->cl_intr = (server->flags & NFS_MOUNT_INTR) ? 1 : 0; |
| 344 | server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0; | 344 | server->client->cl_softrtry = (server->flags & NFS_MOUNT_SOFT) ? 1 : 0; |
| 345 | 345 | ||
| 346 | /* We're airborne Set socket buffersize */ | 346 | /* We're airborne Set socket buffersize */ |
| 347 | rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); | 347 | rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); |
| 348 | return 0; | 348 | return 0; |
| 349 | /* Yargs. It didn't work out. */ | 349 | /* Yargs. It didn't work out. */ |
| 350 | out_no_root: | 350 | out_no_root: |
| 351 | dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error); | 351 | dprintk("nfs_sb_init: get root inode failed: errno %d\n", -no_root_error); |
| 352 | if (!IS_ERR(root_inode)) | 352 | if (!IS_ERR(root_inode)) |
| 353 | iput(root_inode); | 353 | iput(root_inode); |
| 354 | return no_root_error; | 354 | return no_root_error; |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans) | 357 | static void nfs_init_timeout_values(struct rpc_timeout *to, int proto, unsigned int timeo, unsigned int retrans) |
| 358 | { | 358 | { |
| 359 | to->to_initval = timeo * HZ / 10; | 359 | to->to_initval = timeo * HZ / 10; |
| 360 | to->to_retries = retrans; | 360 | to->to_retries = retrans; |
| 361 | if (!to->to_retries) | 361 | if (!to->to_retries) |
| 362 | to->to_retries = 2; | 362 | to->to_retries = 2; |
| 363 | 363 | ||
| 364 | switch (proto) { | 364 | switch (proto) { |
| 365 | case IPPROTO_TCP: | 365 | case IPPROTO_TCP: |
| 366 | if (!to->to_initval) | 366 | if (!to->to_initval) |
| 367 | to->to_initval = 60 * HZ; | 367 | to->to_initval = 60 * HZ; |
| 368 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) | 368 | if (to->to_initval > NFS_MAX_TCP_TIMEOUT) |
| 369 | to->to_initval = NFS_MAX_TCP_TIMEOUT; | 369 | to->to_initval = NFS_MAX_TCP_TIMEOUT; |
| 370 | to->to_increment = to->to_initval; | 370 | to->to_increment = to->to_initval; |
| 371 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); | 371 | to->to_maxval = to->to_initval + (to->to_increment * to->to_retries); |
| 372 | to->to_exponential = 0; | 372 | to->to_exponential = 0; |
| 373 | break; | 373 | break; |
| 374 | case IPPROTO_UDP: | 374 | case IPPROTO_UDP: |
| 375 | default: | 375 | default: |
| 376 | if (!to->to_initval) | 376 | if (!to->to_initval) |
| 377 | to->to_initval = 11 * HZ / 10; | 377 | to->to_initval = 11 * HZ / 10; |
| 378 | if (to->to_initval > NFS_MAX_UDP_TIMEOUT) | 378 | if (to->to_initval > NFS_MAX_UDP_TIMEOUT) |
| 379 | to->to_initval = NFS_MAX_UDP_TIMEOUT; | 379 | to->to_initval = NFS_MAX_UDP_TIMEOUT; |
| 380 | to->to_maxval = NFS_MAX_UDP_TIMEOUT; | 380 | to->to_maxval = NFS_MAX_UDP_TIMEOUT; |
| 381 | to->to_exponential = 1; | 381 | to->to_exponential = 1; |
| 382 | break; | 382 | break; |
| 383 | } | 383 | } |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | /* | 386 | /* |
| 387 | * Create an RPC client handle. | 387 | * Create an RPC client handle. |
| 388 | */ | 388 | */ |
| 389 | static struct rpc_clnt * | 389 | static struct rpc_clnt * |
| 390 | nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) | 390 | nfs_create_client(struct nfs_server *server, const struct nfs_mount_data *data) |
| 391 | { | 391 | { |
| 392 | struct rpc_timeout timeparms; | 392 | struct rpc_timeout timeparms; |
| 393 | struct rpc_xprt *xprt = NULL; | 393 | struct rpc_xprt *xprt = NULL; |
| 394 | struct rpc_clnt *clnt = NULL; | 394 | struct rpc_clnt *clnt = NULL; |
| 395 | int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; | 395 | int proto = (data->flags & NFS_MOUNT_TCP) ? IPPROTO_TCP : IPPROTO_UDP; |
| 396 | 396 | ||
| 397 | nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans); | 397 | nfs_init_timeout_values(&timeparms, proto, data->timeo, data->retrans); |
| 398 | 398 | ||
| 399 | /* create transport and client */ | 399 | /* create transport and client */ |
| 400 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); | 400 | xprt = xprt_create_proto(proto, &server->addr, &timeparms); |
| 401 | if (IS_ERR(xprt)) { | 401 | if (IS_ERR(xprt)) { |
| 402 | dprintk("%s: cannot create RPC transport. Error = %ld\n", | 402 | dprintk("%s: cannot create RPC transport. Error = %ld\n", |
| 403 | __FUNCTION__, PTR_ERR(xprt)); | 403 | __FUNCTION__, PTR_ERR(xprt)); |
| 404 | return (struct rpc_clnt *)xprt; | 404 | return (struct rpc_clnt *)xprt; |
| 405 | } | 405 | } |
| 406 | clnt = rpc_create_client(xprt, server->hostname, &nfs_program, | 406 | clnt = rpc_create_client(xprt, server->hostname, &nfs_program, |
| 407 | server->rpc_ops->version, data->pseudoflavor); | 407 | server->rpc_ops->version, data->pseudoflavor); |
| 408 | if (IS_ERR(clnt)) { | 408 | if (IS_ERR(clnt)) { |
| 409 | dprintk("%s: cannot create RPC client. Error = %ld\n", | 409 | dprintk("%s: cannot create RPC client. Error = %ld\n", |
| 410 | __FUNCTION__, PTR_ERR(xprt)); | 410 | __FUNCTION__, PTR_ERR(xprt)); |
| 411 | goto out_fail; | 411 | goto out_fail; |
| 412 | } | 412 | } |
| 413 | 413 | ||
| 414 | clnt->cl_intr = 1; | 414 | clnt->cl_intr = 1; |
| 415 | clnt->cl_softrtry = 1; | 415 | clnt->cl_softrtry = 1; |
| 416 | 416 | ||
| 417 | return clnt; | 417 | return clnt; |
| 418 | 418 | ||
| 419 | out_fail: | 419 | out_fail: |
| 420 | return clnt; | 420 | return clnt; |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | /* | 423 | /* |
| 424 | * The way this works is that the mount process passes a structure | 424 | * The way this works is that the mount process passes a structure |
| 425 | * in the data argument which contains the server's IP address | 425 | * in the data argument which contains the server's IP address |
| 426 | * and the root file handle obtained from the server's mount | 426 | * and the root file handle obtained from the server's mount |
| 427 | * daemon. We stash these away in the private superblock fields. | 427 | * daemon. We stash these away in the private superblock fields. |
| 428 | */ | 428 | */ |
| 429 | static int | 429 | static int |
| 430 | nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) | 430 | nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) |
| 431 | { | 431 | { |
| 432 | struct nfs_server *server; | 432 | struct nfs_server *server; |
| 433 | rpc_authflavor_t authflavor; | 433 | rpc_authflavor_t authflavor; |
| 434 | 434 | ||
| 435 | server = NFS_SB(sb); | 435 | server = NFS_SB(sb); |
| 436 | sb->s_blocksize_bits = 0; | 436 | sb->s_blocksize_bits = 0; |
| 437 | sb->s_blocksize = 0; | 437 | sb->s_blocksize = 0; |
| 438 | if (data->bsize) | 438 | if (data->bsize) |
| 439 | sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); | 439 | sb->s_blocksize = nfs_block_size(data->bsize, &sb->s_blocksize_bits); |
| 440 | if (data->rsize) | 440 | if (data->rsize) |
| 441 | server->rsize = nfs_block_size(data->rsize, NULL); | 441 | server->rsize = nfs_block_size(data->rsize, NULL); |
| 442 | if (data->wsize) | 442 | if (data->wsize) |
| 443 | server->wsize = nfs_block_size(data->wsize, NULL); | 443 | server->wsize = nfs_block_size(data->wsize, NULL); |
| 444 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; | 444 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; |
| 445 | 445 | ||
| 446 | server->acregmin = data->acregmin*HZ; | 446 | server->acregmin = data->acregmin*HZ; |
| 447 | server->acregmax = data->acregmax*HZ; | 447 | server->acregmax = data->acregmax*HZ; |
| 448 | server->acdirmin = data->acdirmin*HZ; | 448 | server->acdirmin = data->acdirmin*HZ; |
| 449 | server->acdirmax = data->acdirmax*HZ; | 449 | server->acdirmax = data->acdirmax*HZ; |
| 450 | 450 | ||
| 451 | /* Start lockd here, before we might error out */ | 451 | /* Start lockd here, before we might error out */ |
| 452 | if (!(server->flags & NFS_MOUNT_NONLM)) | 452 | if (!(server->flags & NFS_MOUNT_NONLM)) |
| 453 | lockd_up(); | 453 | lockd_up(); |
| 454 | 454 | ||
| 455 | server->namelen = data->namlen; | 455 | server->namelen = data->namlen; |
| 456 | server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL); | 456 | server->hostname = kmalloc(strlen(data->hostname) + 1, GFP_KERNEL); |
| 457 | if (!server->hostname) | 457 | if (!server->hostname) |
| 458 | return -ENOMEM; | 458 | return -ENOMEM; |
| 459 | strcpy(server->hostname, data->hostname); | 459 | strcpy(server->hostname, data->hostname); |
| 460 | 460 | ||
| 461 | /* Check NFS protocol revision and initialize RPC op vector | 461 | /* Check NFS protocol revision and initialize RPC op vector |
| 462 | * and file handle pool. */ | 462 | * and file handle pool. */ |
| 463 | #ifdef CONFIG_NFS_V3 | 463 | #ifdef CONFIG_NFS_V3 |
| 464 | if (server->flags & NFS_MOUNT_VER3) { | 464 | if (server->flags & NFS_MOUNT_VER3) { |
| 465 | server->rpc_ops = &nfs_v3_clientops; | 465 | server->rpc_ops = &nfs_v3_clientops; |
| 466 | server->caps |= NFS_CAP_READDIRPLUS; | 466 | server->caps |= NFS_CAP_READDIRPLUS; |
| 467 | } else { | 467 | } else { |
| 468 | server->rpc_ops = &nfs_v2_clientops; | 468 | server->rpc_ops = &nfs_v2_clientops; |
| 469 | } | 469 | } |
| 470 | #else | 470 | #else |
| 471 | server->rpc_ops = &nfs_v2_clientops; | 471 | server->rpc_ops = &nfs_v2_clientops; |
| 472 | #endif | 472 | #endif |
| 473 | 473 | ||
| 474 | /* Fill in pseudoflavor for mount version < 5 */ | 474 | /* Fill in pseudoflavor for mount version < 5 */ |
| 475 | if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) | 475 | if (!(data->flags & NFS_MOUNT_SECFLAVOUR)) |
| 476 | data->pseudoflavor = RPC_AUTH_UNIX; | 476 | data->pseudoflavor = RPC_AUTH_UNIX; |
| 477 | authflavor = data->pseudoflavor; /* save for sb_init() */ | 477 | authflavor = data->pseudoflavor; /* save for sb_init() */ |
| 478 | /* XXX maybe we want to add a server->pseudoflavor field */ | 478 | /* XXX maybe we want to add a server->pseudoflavor field */ |
| 479 | 479 | ||
| 480 | /* Create RPC client handles */ | 480 | /* Create RPC client handles */ |
| 481 | server->client = nfs_create_client(server, data); | 481 | server->client = nfs_create_client(server, data); |
| 482 | if (IS_ERR(server->client)) | 482 | if (IS_ERR(server->client)) |
| 483 | return PTR_ERR(server->client); | 483 | return PTR_ERR(server->client); |
| 484 | /* RFC 2623, sec 2.3.2 */ | 484 | /* RFC 2623, sec 2.3.2 */ |
| 485 | if (authflavor != RPC_AUTH_UNIX) { | 485 | if (authflavor != RPC_AUTH_UNIX) { |
| 486 | struct rpc_auth *auth; | 486 | struct rpc_auth *auth; |
| 487 | 487 | ||
| 488 | server->client_sys = rpc_clone_client(server->client); | 488 | server->client_sys = rpc_clone_client(server->client); |
| 489 | if (IS_ERR(server->client_sys)) | 489 | if (IS_ERR(server->client_sys)) |
| 490 | return PTR_ERR(server->client_sys); | 490 | return PTR_ERR(server->client_sys); |
| 491 | auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys); | 491 | auth = rpcauth_create(RPC_AUTH_UNIX, server->client_sys); |
| 492 | if (IS_ERR(auth)) | 492 | if (IS_ERR(auth)) |
| 493 | return PTR_ERR(auth); | 493 | return PTR_ERR(auth); |
| 494 | } else { | 494 | } else { |
| 495 | atomic_inc(&server->client->cl_count); | 495 | atomic_inc(&server->client->cl_count); |
| 496 | server->client_sys = server->client; | 496 | server->client_sys = server->client; |
| 497 | } | 497 | } |
| 498 | if (server->flags & NFS_MOUNT_VER3) { | 498 | if (server->flags & NFS_MOUNT_VER3) { |
| 499 | #ifdef CONFIG_NFS_V3_ACL | 499 | #ifdef CONFIG_NFS_V3_ACL |
| 500 | if (!(server->flags & NFS_MOUNT_NOACL)) { | 500 | if (!(server->flags & NFS_MOUNT_NOACL)) { |
| 501 | server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); | 501 | server->client_acl = rpc_bind_new_program(server->client, &nfsacl_program, 3); |
| 502 | /* No errors! Assume that Sun nfsacls are supported */ | 502 | /* No errors! Assume that Sun nfsacls are supported */ |
| 503 | if (!IS_ERR(server->client_acl)) | 503 | if (!IS_ERR(server->client_acl)) |
| 504 | server->caps |= NFS_CAP_ACLS; | 504 | server->caps |= NFS_CAP_ACLS; |
| 505 | } | 505 | } |
| 506 | #else | 506 | #else |
| 507 | server->flags &= ~NFS_MOUNT_NOACL; | 507 | server->flags &= ~NFS_MOUNT_NOACL; |
| 508 | #endif /* CONFIG_NFS_V3_ACL */ | 508 | #endif /* CONFIG_NFS_V3_ACL */ |
| 509 | /* | 509 | /* |
| 510 | * The VFS shouldn't apply the umask to mode bits. We will | 510 | * The VFS shouldn't apply the umask to mode bits. We will |
| 511 | * do so ourselves when necessary. | 511 | * do so ourselves when necessary. |
| 512 | */ | 512 | */ |
| 513 | sb->s_flags |= MS_POSIXACL; | 513 | sb->s_flags |= MS_POSIXACL; |
| 514 | if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) | 514 | if (server->namelen == 0 || server->namelen > NFS3_MAXNAMLEN) |
| 515 | server->namelen = NFS3_MAXNAMLEN; | 515 | server->namelen = NFS3_MAXNAMLEN; |
| 516 | sb->s_time_gran = 1; | 516 | sb->s_time_gran = 1; |
| 517 | } else { | 517 | } else { |
| 518 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) | 518 | if (server->namelen == 0 || server->namelen > NFS2_MAXNAMLEN) |
| 519 | server->namelen = NFS2_MAXNAMLEN; | 519 | server->namelen = NFS2_MAXNAMLEN; |
| 520 | } | 520 | } |
| 521 | 521 | ||
| 522 | sb->s_op = &nfs_sops; | 522 | sb->s_op = &nfs_sops; |
| 523 | return nfs_sb_init(sb, authflavor); | 523 | return nfs_sb_init(sb, authflavor); |
| 524 | } | 524 | } |
| 525 | 525 | ||
| 526 | static int | 526 | static int |
| 527 | nfs_statfs(struct super_block *sb, struct kstatfs *buf) | 527 | nfs_statfs(struct super_block *sb, struct kstatfs *buf) |
| 528 | { | 528 | { |
| 529 | struct nfs_server *server = NFS_SB(sb); | 529 | struct nfs_server *server = NFS_SB(sb); |
| 530 | unsigned char blockbits; | 530 | unsigned char blockbits; |
| 531 | unsigned long blockres; | 531 | unsigned long blockres; |
| 532 | struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode); | 532 | struct nfs_fh *rootfh = NFS_FH(sb->s_root->d_inode); |
| 533 | struct nfs_fattr fattr; | 533 | struct nfs_fattr fattr; |
| 534 | struct nfs_fsstat res = { | 534 | struct nfs_fsstat res = { |
| 535 | .fattr = &fattr, | 535 | .fattr = &fattr, |
| 536 | }; | 536 | }; |
| 537 | int error; | 537 | int error; |
| 538 | 538 | ||
| 539 | lock_kernel(); | 539 | lock_kernel(); |
| 540 | 540 | ||
| 541 | error = server->rpc_ops->statfs(server, rootfh, &res); | 541 | error = server->rpc_ops->statfs(server, rootfh, &res); |
| 542 | buf->f_type = NFS_SUPER_MAGIC; | 542 | buf->f_type = NFS_SUPER_MAGIC; |
| 543 | if (error < 0) | 543 | if (error < 0) |
| 544 | goto out_err; | 544 | goto out_err; |
| 545 | 545 | ||
| 546 | /* | 546 | /* |
| 547 | * Current versions of glibc do not correctly handle the | 547 | * Current versions of glibc do not correctly handle the |
| 548 | * case where f_frsize != f_bsize. Eventually we want to | 548 | * case where f_frsize != f_bsize. Eventually we want to |
| 549 | * report the value of wtmult in this field. | 549 | * report the value of wtmult in this field. |
| 550 | */ | 550 | */ |
| 551 | buf->f_frsize = sb->s_blocksize; | 551 | buf->f_frsize = sb->s_blocksize; |
| 552 | 552 | ||
| 553 | /* | 553 | /* |
| 554 | * On most *nix systems, f_blocks, f_bfree, and f_bavail | 554 | * On most *nix systems, f_blocks, f_bfree, and f_bavail |
| 555 | * are reported in units of f_frsize. Linux hasn't had | 555 | * are reported in units of f_frsize. Linux hasn't had |
| 556 | * an f_frsize field in its statfs struct until recently, | 556 | * an f_frsize field in its statfs struct until recently, |
| 557 | * thus historically Linux's sys_statfs reports these | 557 | * thus historically Linux's sys_statfs reports these |
| 558 | * fields in units of f_bsize. | 558 | * fields in units of f_bsize. |
| 559 | */ | 559 | */ |
| 560 | buf->f_bsize = sb->s_blocksize; | 560 | buf->f_bsize = sb->s_blocksize; |
| 561 | blockbits = sb->s_blocksize_bits; | 561 | blockbits = sb->s_blocksize_bits; |
| 562 | blockres = (1 << blockbits) - 1; | 562 | blockres = (1 << blockbits) - 1; |
| 563 | buf->f_blocks = (res.tbytes + blockres) >> blockbits; | 563 | buf->f_blocks = (res.tbytes + blockres) >> blockbits; |
| 564 | buf->f_bfree = (res.fbytes + blockres) >> blockbits; | 564 | buf->f_bfree = (res.fbytes + blockres) >> blockbits; |
| 565 | buf->f_bavail = (res.abytes + blockres) >> blockbits; | 565 | buf->f_bavail = (res.abytes + blockres) >> blockbits; |
| 566 | 566 | ||
| 567 | buf->f_files = res.tfiles; | 567 | buf->f_files = res.tfiles; |
| 568 | buf->f_ffree = res.afiles; | 568 | buf->f_ffree = res.afiles; |
| 569 | 569 | ||
| 570 | buf->f_namelen = server->namelen; | 570 | buf->f_namelen = server->namelen; |
| 571 | out: | 571 | out: |
| 572 | unlock_kernel(); | 572 | unlock_kernel(); |
| 573 | return 0; | 573 | return 0; |
| 574 | 574 | ||
| 575 | out_err: | 575 | out_err: |
| 576 | dprintk("%s: statfs error = %d\n", __FUNCTION__, -error); | 576 | dprintk("%s: statfs error = %d\n", __FUNCTION__, -error); |
| 577 | buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; | 577 | buf->f_bsize = buf->f_blocks = buf->f_bfree = buf->f_bavail = -1; |
| 578 | goto out; | 578 | goto out; |
| 579 | 579 | ||
| 580 | } | 580 | } |
| 581 | 581 | ||
| 582 | static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) | 582 | static int nfs_show_options(struct seq_file *m, struct vfsmount *mnt) |
| 583 | { | 583 | { |
| 584 | static struct proc_nfs_info { | 584 | static struct proc_nfs_info { |
| 585 | int flag; | 585 | int flag; |
| 586 | char *str; | 586 | char *str; |
| 587 | char *nostr; | 587 | char *nostr; |
| 588 | } nfs_info[] = { | 588 | } nfs_info[] = { |
| 589 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, | 589 | { NFS_MOUNT_SOFT, ",soft", ",hard" }, |
| 590 | { NFS_MOUNT_INTR, ",intr", "" }, | 590 | { NFS_MOUNT_INTR, ",intr", "" }, |
| 591 | { NFS_MOUNT_POSIX, ",posix", "" }, | 591 | { NFS_MOUNT_POSIX, ",posix", "" }, |
| 592 | { NFS_MOUNT_NOCTO, ",nocto", "" }, | 592 | { NFS_MOUNT_NOCTO, ",nocto", "" }, |
| 593 | { NFS_MOUNT_NOAC, ",noac", "" }, | 593 | { NFS_MOUNT_NOAC, ",noac", "" }, |
| 594 | { NFS_MOUNT_NONLM, ",nolock", ",lock" }, | 594 | { NFS_MOUNT_NONLM, ",nolock", ",lock" }, |
| 595 | { NFS_MOUNT_NOACL, ",noacl", "" }, | 595 | { NFS_MOUNT_NOACL, ",noacl", "" }, |
| 596 | { 0, NULL, NULL } | 596 | { 0, NULL, NULL } |
| 597 | }; | 597 | }; |
| 598 | struct proc_nfs_info *nfs_infop; | 598 | struct proc_nfs_info *nfs_infop; |
| 599 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); | 599 | struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); |
| 600 | char buf[12]; | 600 | char buf[12]; |
| 601 | char *proto; | 601 | char *proto; |
| 602 | 602 | ||
| 603 | seq_printf(m, ",v%d", nfss->rpc_ops->version); | 603 | seq_printf(m, ",v%d", nfss->rpc_ops->version); |
| 604 | seq_printf(m, ",rsize=%d", nfss->rsize); | 604 | seq_printf(m, ",rsize=%d", nfss->rsize); |
| 605 | seq_printf(m, ",wsize=%d", nfss->wsize); | 605 | seq_printf(m, ",wsize=%d", nfss->wsize); |
| 606 | if (nfss->acregmin != 3*HZ) | 606 | if (nfss->acregmin != 3*HZ) |
| 607 | seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ); | 607 | seq_printf(m, ",acregmin=%d", nfss->acregmin/HZ); |
| 608 | if (nfss->acregmax != 60*HZ) | 608 | if (nfss->acregmax != 60*HZ) |
| 609 | seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ); | 609 | seq_printf(m, ",acregmax=%d", nfss->acregmax/HZ); |
| 610 | if (nfss->acdirmin != 30*HZ) | 610 | if (nfss->acdirmin != 30*HZ) |
| 611 | seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ); | 611 | seq_printf(m, ",acdirmin=%d", nfss->acdirmin/HZ); |
| 612 | if (nfss->acdirmax != 60*HZ) | 612 | if (nfss->acdirmax != 60*HZ) |
| 613 | seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ); | 613 | seq_printf(m, ",acdirmax=%d", nfss->acdirmax/HZ); |
| 614 | for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) { | 614 | for (nfs_infop = nfs_info; nfs_infop->flag; nfs_infop++) { |
| 615 | if (nfss->flags & nfs_infop->flag) | 615 | if (nfss->flags & nfs_infop->flag) |
| 616 | seq_puts(m, nfs_infop->str); | 616 | seq_puts(m, nfs_infop->str); |
| 617 | else | 617 | else |
| 618 | seq_puts(m, nfs_infop->nostr); | 618 | seq_puts(m, nfs_infop->nostr); |
| 619 | } | 619 | } |
| 620 | switch (nfss->client->cl_xprt->prot) { | 620 | switch (nfss->client->cl_xprt->prot) { |
| 621 | case IPPROTO_TCP: | 621 | case IPPROTO_TCP: |
| 622 | proto = "tcp"; | 622 | proto = "tcp"; |
| 623 | break; | 623 | break; |
| 624 | case IPPROTO_UDP: | 624 | case IPPROTO_UDP: |
| 625 | proto = "udp"; | 625 | proto = "udp"; |
| 626 | break; | 626 | break; |
| 627 | default: | 627 | default: |
| 628 | snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot); | 628 | snprintf(buf, sizeof(buf), "%u", nfss->client->cl_xprt->prot); |
| 629 | proto = buf; | 629 | proto = buf; |
| 630 | } | 630 | } |
| 631 | seq_printf(m, ",proto=%s", proto); | 631 | seq_printf(m, ",proto=%s", proto); |
| 632 | seq_puts(m, ",addr="); | 632 | seq_puts(m, ",addr="); |
| 633 | seq_escape(m, nfss->hostname, " \t\n\\"); | 633 | seq_escape(m, nfss->hostname, " \t\n\\"); |
| 634 | return 0; | 634 | return 0; |
| 635 | } | 635 | } |
| 636 | 636 | ||
| 637 | /** | 637 | /** |
| 638 | * nfs_sync_mapping - helper to flush all mmapped dirty data to disk | 638 | * nfs_sync_mapping - helper to flush all mmapped dirty data to disk |
| 639 | */ | 639 | */ |
| 640 | int nfs_sync_mapping(struct address_space *mapping) | 640 | int nfs_sync_mapping(struct address_space *mapping) |
| 641 | { | 641 | { |
| 642 | int ret; | 642 | int ret; |
| 643 | 643 | ||
| 644 | if (mapping->nrpages == 0) | 644 | if (mapping->nrpages == 0) |
| 645 | return 0; | 645 | return 0; |
| 646 | unmap_mapping_range(mapping, 0, 0, 0); | 646 | unmap_mapping_range(mapping, 0, 0, 0); |
| 647 | ret = filemap_write_and_wait(mapping); | 647 | ret = filemap_write_and_wait(mapping); |
| 648 | if (ret != 0) | 648 | if (ret != 0) |
| 649 | goto out; | 649 | goto out; |
| 650 | ret = nfs_wb_all(mapping->host); | 650 | ret = nfs_wb_all(mapping->host); |
| 651 | out: | 651 | out: |
| 652 | return ret; | 652 | return ret; |
| 653 | } | 653 | } |
| 654 | 654 | ||
| 655 | /* | 655 | /* |
| 656 | * Invalidate the local caches | 656 | * Invalidate the local caches |
| 657 | */ | 657 | */ |
| 658 | static void nfs_zap_caches_locked(struct inode *inode) | 658 | static void nfs_zap_caches_locked(struct inode *inode) |
| 659 | { | 659 | { |
| 660 | struct nfs_inode *nfsi = NFS_I(inode); | 660 | struct nfs_inode *nfsi = NFS_I(inode); |
| 661 | int mode = inode->i_mode; | 661 | int mode = inode->i_mode; |
| 662 | 662 | ||
| 663 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); | 663 | NFS_ATTRTIMEO(inode) = NFS_MINATTRTIMEO(inode); |
| 664 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; | 664 | NFS_ATTRTIMEO_UPDATE(inode) = jiffies; |
| 665 | 665 | ||
| 666 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); | 666 | memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); |
| 667 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) | 667 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) |
| 668 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 668 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; |
| 669 | else | 669 | else |
| 670 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 670 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; |
| 671 | } | 671 | } |
| 672 | 672 | ||
| 673 | void nfs_zap_caches(struct inode *inode) | 673 | void nfs_zap_caches(struct inode *inode) |
| 674 | { | 674 | { |
| 675 | spin_lock(&inode->i_lock); | 675 | spin_lock(&inode->i_lock); |
| 676 | nfs_zap_caches_locked(inode); | 676 | nfs_zap_caches_locked(inode); |
| 677 | spin_unlock(&inode->i_lock); | 677 | spin_unlock(&inode->i_lock); |
| 678 | } | 678 | } |
| 679 | 679 | ||
| 680 | static void nfs_zap_acl_cache(struct inode *inode) | 680 | static void nfs_zap_acl_cache(struct inode *inode) |
| 681 | { | 681 | { |
| 682 | void (*clear_acl_cache)(struct inode *); | 682 | void (*clear_acl_cache)(struct inode *); |
| 683 | 683 | ||
| 684 | clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache; | 684 | clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache; |
| 685 | if (clear_acl_cache != NULL) | 685 | if (clear_acl_cache != NULL) |
| 686 | clear_acl_cache(inode); | 686 | clear_acl_cache(inode); |
| 687 | spin_lock(&inode->i_lock); | 687 | spin_lock(&inode->i_lock); |
| 688 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL; | 688 | NFS_I(inode)->cache_validity &= ~NFS_INO_INVALID_ACL; |
| 689 | spin_unlock(&inode->i_lock); | 689 | spin_unlock(&inode->i_lock); |
| 690 | } | 690 | } |
| 691 | 691 | ||
| 692 | /* | 692 | /* |
| 693 | * Invalidate, but do not unhash, the inode. | 693 | * Invalidate, but do not unhash, the inode. |
| 694 | * NB: must be called with inode->i_lock held! | 694 | * NB: must be called with inode->i_lock held! |
| 695 | */ | 695 | */ |
| 696 | static void nfs_invalidate_inode(struct inode *inode) | 696 | static void nfs_invalidate_inode(struct inode *inode) |
| 697 | { | 697 | { |
| 698 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); | 698 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
| 699 | nfs_zap_caches_locked(inode); | 699 | nfs_zap_caches_locked(inode); |
| 700 | } | 700 | } |
| 701 | 701 | ||
| 702 | struct nfs_find_desc { | 702 | struct nfs_find_desc { |
| 703 | struct nfs_fh *fh; | 703 | struct nfs_fh *fh; |
| 704 | struct nfs_fattr *fattr; | 704 | struct nfs_fattr *fattr; |
| 705 | }; | 705 | }; |
| 706 | 706 | ||
| 707 | /* | 707 | /* |
| 708 | * In NFSv3 we can have 64bit inode numbers. In order to support | 708 | * In NFSv3 we can have 64bit inode numbers. In order to support |
| 709 | * this, and re-exported directories (also seen in NFSv2) | 709 | * this, and re-exported directories (also seen in NFSv2) |
| 710 | * we are forced to allow 2 different inodes to have the same | 710 | * we are forced to allow 2 different inodes to have the same |
| 711 | * i_ino. | 711 | * i_ino. |
| 712 | */ | 712 | */ |
| 713 | static int | 713 | static int |
| 714 | nfs_find_actor(struct inode *inode, void *opaque) | 714 | nfs_find_actor(struct inode *inode, void *opaque) |
| 715 | { | 715 | { |
| 716 | struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; | 716 | struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; |
| 717 | struct nfs_fh *fh = desc->fh; | 717 | struct nfs_fh *fh = desc->fh; |
| 718 | struct nfs_fattr *fattr = desc->fattr; | 718 | struct nfs_fattr *fattr = desc->fattr; |
| 719 | 719 | ||
| 720 | if (NFS_FILEID(inode) != fattr->fileid) | 720 | if (NFS_FILEID(inode) != fattr->fileid) |
| 721 | return 0; | 721 | return 0; |
| 722 | if (nfs_compare_fh(NFS_FH(inode), fh)) | 722 | if (nfs_compare_fh(NFS_FH(inode), fh)) |
| 723 | return 0; | 723 | return 0; |
| 724 | if (is_bad_inode(inode) || NFS_STALE(inode)) | 724 | if (is_bad_inode(inode) || NFS_STALE(inode)) |
| 725 | return 0; | 725 | return 0; |
| 726 | return 1; | 726 | return 1; |
| 727 | } | 727 | } |
| 728 | 728 | ||
| 729 | static int | 729 | static int |
| 730 | nfs_init_locked(struct inode *inode, void *opaque) | 730 | nfs_init_locked(struct inode *inode, void *opaque) |
| 731 | { | 731 | { |
| 732 | struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; | 732 | struct nfs_find_desc *desc = (struct nfs_find_desc *)opaque; |
| 733 | struct nfs_fattr *fattr = desc->fattr; | 733 | struct nfs_fattr *fattr = desc->fattr; |
| 734 | 734 | ||
| 735 | NFS_FILEID(inode) = fattr->fileid; | 735 | NFS_FILEID(inode) = fattr->fileid; |
| 736 | nfs_copy_fh(NFS_FH(inode), desc->fh); | 736 | nfs_copy_fh(NFS_FH(inode), desc->fh); |
| 737 | return 0; | 737 | return 0; |
| 738 | } | 738 | } |
| 739 | 739 | ||
| 740 | /* Don't use READDIRPLUS on directories that we believe are too large */ | 740 | /* Don't use READDIRPLUS on directories that we believe are too large */ |
| 741 | #define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE) | 741 | #define NFS_LIMIT_READDIRPLUS (8*PAGE_SIZE) |
| 742 | 742 | ||
| 743 | /* | 743 | /* |
| 744 | * This is our front-end to iget that looks up inodes by file handle | 744 | * This is our front-end to iget that looks up inodes by file handle |
| 745 | * instead of inode number. | 745 | * instead of inode number. |
| 746 | */ | 746 | */ |
| 747 | struct inode * | 747 | struct inode * |
| 748 | nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | 748 | nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) |
| 749 | { | 749 | { |
| 750 | struct nfs_find_desc desc = { | 750 | struct nfs_find_desc desc = { |
| 751 | .fh = fh, | 751 | .fh = fh, |
| 752 | .fattr = fattr | 752 | .fattr = fattr |
| 753 | }; | 753 | }; |
| 754 | struct inode *inode = NULL; | 754 | struct inode *inode = NULL; |
| 755 | unsigned long hash; | 755 | unsigned long hash; |
| 756 | 756 | ||
| 757 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 757 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) |
| 758 | goto out_no_inode; | 758 | goto out_no_inode; |
| 759 | 759 | ||
| 760 | if (!fattr->nlink) { | 760 | if (!fattr->nlink) { |
| 761 | printk("NFS: Buggy server - nlink == 0!\n"); | 761 | printk("NFS: Buggy server - nlink == 0!\n"); |
| 762 | goto out_no_inode; | 762 | goto out_no_inode; |
| 763 | } | 763 | } |
| 764 | 764 | ||
| 765 | hash = nfs_fattr_to_ino_t(fattr); | 765 | hash = nfs_fattr_to_ino_t(fattr); |
| 766 | 766 | ||
| 767 | if (!(inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc))) | 767 | if (!(inode = iget5_locked(sb, hash, nfs_find_actor, nfs_init_locked, &desc))) |
| 768 | goto out_no_inode; | 768 | goto out_no_inode; |
| 769 | 769 | ||
| 770 | if (inode->i_state & I_NEW) { | 770 | if (inode->i_state & I_NEW) { |
| 771 | struct nfs_inode *nfsi = NFS_I(inode); | 771 | struct nfs_inode *nfsi = NFS_I(inode); |
| 772 | 772 | ||
| 773 | /* We set i_ino for the few things that still rely on it, | 773 | /* We set i_ino for the few things that still rely on it, |
| 774 | * such as stat(2) */ | 774 | * such as stat(2) */ |
| 775 | inode->i_ino = hash; | 775 | inode->i_ino = hash; |
| 776 | 776 | ||
| 777 | /* We can't support update_atime(), since the server will reset it */ | 777 | /* We can't support update_atime(), since the server will reset it */ |
| 778 | inode->i_flags |= S_NOATIME|S_NOCMTIME; | 778 | inode->i_flags |= S_NOATIME|S_NOCMTIME; |
| 779 | inode->i_mode = fattr->mode; | 779 | inode->i_mode = fattr->mode; |
| 780 | /* Why so? Because we want revalidate for devices/FIFOs, and | 780 | /* Why so? Because we want revalidate for devices/FIFOs, and |
| 781 | * that's precisely what we have in nfs_file_inode_operations. | 781 | * that's precisely what we have in nfs_file_inode_operations. |
| 782 | */ | 782 | */ |
| 783 | inode->i_op = NFS_SB(sb)->rpc_ops->file_inode_ops; | 783 | inode->i_op = NFS_SB(sb)->rpc_ops->file_inode_ops; |
| 784 | if (S_ISREG(inode->i_mode)) { | 784 | if (S_ISREG(inode->i_mode)) { |
| 785 | inode->i_fop = &nfs_file_operations; | 785 | inode->i_fop = &nfs_file_operations; |
| 786 | inode->i_data.a_ops = &nfs_file_aops; | 786 | inode->i_data.a_ops = &nfs_file_aops; |
| 787 | inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info; | 787 | inode->i_data.backing_dev_info = &NFS_SB(sb)->backing_dev_info; |
| 788 | } else if (S_ISDIR(inode->i_mode)) { | 788 | } else if (S_ISDIR(inode->i_mode)) { |
| 789 | inode->i_op = NFS_SB(sb)->rpc_ops->dir_inode_ops; | 789 | inode->i_op = NFS_SB(sb)->rpc_ops->dir_inode_ops; |
| 790 | inode->i_fop = &nfs_dir_operations; | 790 | inode->i_fop = &nfs_dir_operations; |
| 791 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) | 791 | if (nfs_server_capable(inode, NFS_CAP_READDIRPLUS) |
| 792 | && fattr->size <= NFS_LIMIT_READDIRPLUS) | 792 | && fattr->size <= NFS_LIMIT_READDIRPLUS) |
| 793 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); | 793 | set_bit(NFS_INO_ADVISE_RDPLUS, &NFS_FLAGS(inode)); |
| 794 | } else if (S_ISLNK(inode->i_mode)) | 794 | } else if (S_ISLNK(inode->i_mode)) |
| 795 | inode->i_op = &nfs_symlink_inode_operations; | 795 | inode->i_op = &nfs_symlink_inode_operations; |
| 796 | else | 796 | else |
| 797 | init_special_inode(inode, inode->i_mode, fattr->rdev); | 797 | init_special_inode(inode, inode->i_mode, fattr->rdev); |
| 798 | 798 | ||
| 799 | nfsi->read_cache_jiffies = fattr->time_start; | 799 | nfsi->read_cache_jiffies = fattr->time_start; |
| 800 | nfsi->last_updated = jiffies; | 800 | nfsi->last_updated = jiffies; |
| 801 | inode->i_atime = fattr->atime; | 801 | inode->i_atime = fattr->atime; |
| 802 | inode->i_mtime = fattr->mtime; | 802 | inode->i_mtime = fattr->mtime; |
| 803 | inode->i_ctime = fattr->ctime; | 803 | inode->i_ctime = fattr->ctime; |
| 804 | if (fattr->valid & NFS_ATTR_FATTR_V4) | 804 | if (fattr->valid & NFS_ATTR_FATTR_V4) |
| 805 | nfsi->change_attr = fattr->change_attr; | 805 | nfsi->change_attr = fattr->change_attr; |
| 806 | inode->i_size = nfs_size_to_loff_t(fattr->size); | 806 | inode->i_size = nfs_size_to_loff_t(fattr->size); |
| 807 | inode->i_nlink = fattr->nlink; | 807 | inode->i_nlink = fattr->nlink; |
| 808 | inode->i_uid = fattr->uid; | 808 | inode->i_uid = fattr->uid; |
| 809 | inode->i_gid = fattr->gid; | 809 | inode->i_gid = fattr->gid; |
| 810 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 810 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { |
| 811 | /* | 811 | /* |
| 812 | * report the blocks in 512byte units | 812 | * report the blocks in 512byte units |
| 813 | */ | 813 | */ |
| 814 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 814 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
| 815 | inode->i_blksize = inode->i_sb->s_blocksize; | 815 | inode->i_blksize = inode->i_sb->s_blocksize; |
| 816 | } else { | 816 | } else { |
| 817 | inode->i_blocks = fattr->du.nfs2.blocks; | 817 | inode->i_blocks = fattr->du.nfs2.blocks; |
| 818 | inode->i_blksize = fattr->du.nfs2.blocksize; | 818 | inode->i_blksize = fattr->du.nfs2.blocksize; |
| 819 | } | 819 | } |
| 820 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 820 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 821 | nfsi->attrtimeo_timestamp = jiffies; | 821 | nfsi->attrtimeo_timestamp = jiffies; |
| 822 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 822 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
| 823 | nfsi->cache_access.cred = NULL; | 823 | nfsi->cache_access.cred = NULL; |
| 824 | 824 | ||
| 825 | unlock_new_inode(inode); | 825 | unlock_new_inode(inode); |
| 826 | } else | 826 | } else |
| 827 | nfs_refresh_inode(inode, fattr); | 827 | nfs_refresh_inode(inode, fattr); |
| 828 | dprintk("NFS: nfs_fhget(%s/%Ld ct=%d)\n", | 828 | dprintk("NFS: nfs_fhget(%s/%Ld ct=%d)\n", |
| 829 | inode->i_sb->s_id, | 829 | inode->i_sb->s_id, |
| 830 | (long long)NFS_FILEID(inode), | 830 | (long long)NFS_FILEID(inode), |
| 831 | atomic_read(&inode->i_count)); | 831 | atomic_read(&inode->i_count)); |
| 832 | 832 | ||
| 833 | out: | 833 | out: |
| 834 | return inode; | 834 | return inode; |
| 835 | 835 | ||
| 836 | out_no_inode: | 836 | out_no_inode: |
| 837 | printk("nfs_fhget: iget failed\n"); | 837 | printk("nfs_fhget: iget failed\n"); |
| 838 | goto out; | 838 | goto out; |
| 839 | } | 839 | } |
| 840 | 840 | ||
| 841 | #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET) | 841 | #define NFS_VALID_ATTRS (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE|ATTR_ATIME|ATTR_ATIME_SET|ATTR_MTIME|ATTR_MTIME_SET) |
| 842 | 842 | ||
| 843 | int | 843 | int |
| 844 | nfs_setattr(struct dentry *dentry, struct iattr *attr) | 844 | nfs_setattr(struct dentry *dentry, struct iattr *attr) |
| 845 | { | 845 | { |
| 846 | struct inode *inode = dentry->d_inode; | 846 | struct inode *inode = dentry->d_inode; |
| 847 | struct nfs_fattr fattr; | 847 | struct nfs_fattr fattr; |
| 848 | int error; | 848 | int error; |
| 849 | 849 | ||
| 850 | if (attr->ia_valid & ATTR_SIZE) { | 850 | if (attr->ia_valid & ATTR_SIZE) { |
| 851 | if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode)) | 851 | if (!S_ISREG(inode->i_mode) || attr->ia_size == i_size_read(inode)) |
| 852 | attr->ia_valid &= ~ATTR_SIZE; | 852 | attr->ia_valid &= ~ATTR_SIZE; |
| 853 | } | 853 | } |
| 854 | 854 | ||
| 855 | /* Optimization: if the end result is no change, don't RPC */ | 855 | /* Optimization: if the end result is no change, don't RPC */ |
| 856 | attr->ia_valid &= NFS_VALID_ATTRS; | 856 | attr->ia_valid &= NFS_VALID_ATTRS; |
| 857 | if (attr->ia_valid == 0) | 857 | if (attr->ia_valid == 0) |
| 858 | return 0; | 858 | return 0; |
| 859 | 859 | ||
| 860 | lock_kernel(); | 860 | lock_kernel(); |
| 861 | nfs_begin_data_update(inode); | 861 | nfs_begin_data_update(inode); |
| 862 | /* Write all dirty data if we're changing file permissions or size */ | 862 | /* Write all dirty data if we're changing file permissions or size */ |
| 863 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE)) != 0) { | 863 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_SIZE)) != 0) { |
| 864 | filemap_write_and_wait(inode->i_mapping); | 864 | filemap_write_and_wait(inode->i_mapping); |
| 865 | nfs_wb_all(inode); | 865 | nfs_wb_all(inode); |
| 866 | } | 866 | } |
| 867 | /* | 867 | /* |
| 868 | * Return any delegations if we're going to change ACLs | 868 | * Return any delegations if we're going to change ACLs |
| 869 | */ | 869 | */ |
| 870 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) | 870 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) |
| 871 | nfs_inode_return_delegation(inode); | 871 | nfs_inode_return_delegation(inode); |
| 872 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); | 872 | error = NFS_PROTO(inode)->setattr(dentry, &fattr, attr); |
| 873 | if (error == 0) | 873 | if (error == 0) |
| 874 | nfs_refresh_inode(inode, &fattr); | 874 | nfs_refresh_inode(inode, &fattr); |
| 875 | nfs_end_data_update(inode); | 875 | nfs_end_data_update(inode); |
| 876 | unlock_kernel(); | 876 | unlock_kernel(); |
| 877 | return error; | 877 | return error; |
| 878 | } | 878 | } |
| 879 | 879 | ||
| 880 | /** | 880 | /** |
| 881 | * nfs_setattr_update_inode - Update inode metadata after a setattr call. | 881 | * nfs_setattr_update_inode - Update inode metadata after a setattr call. |
| 882 | * @inode: pointer to struct inode | 882 | * @inode: pointer to struct inode |
| 883 | * @attr: pointer to struct iattr | 883 | * @attr: pointer to struct iattr |
| 884 | * | 884 | * |
| 885 | * Note: we do this in the *proc.c in order to ensure that | 885 | * Note: we do this in the *proc.c in order to ensure that |
| 886 | * it works for things like exclusive creates too. | 886 | * it works for things like exclusive creates too. |
| 887 | */ | 887 | */ |
| 888 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) | 888 | void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr) |
| 889 | { | 889 | { |
| 890 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { | 890 | if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) { |
| 891 | if ((attr->ia_valid & ATTR_MODE) != 0) { | 891 | if ((attr->ia_valid & ATTR_MODE) != 0) { |
| 892 | int mode = attr->ia_mode & S_IALLUGO; | 892 | int mode = attr->ia_mode & S_IALLUGO; |
| 893 | mode |= inode->i_mode & ~S_IALLUGO; | 893 | mode |= inode->i_mode & ~S_IALLUGO; |
| 894 | inode->i_mode = mode; | 894 | inode->i_mode = mode; |
| 895 | } | 895 | } |
| 896 | if ((attr->ia_valid & ATTR_UID) != 0) | 896 | if ((attr->ia_valid & ATTR_UID) != 0) |
| 897 | inode->i_uid = attr->ia_uid; | 897 | inode->i_uid = attr->ia_uid; |
| 898 | if ((attr->ia_valid & ATTR_GID) != 0) | 898 | if ((attr->ia_valid & ATTR_GID) != 0) |
| 899 | inode->i_gid = attr->ia_gid; | 899 | inode->i_gid = attr->ia_gid; |
| 900 | spin_lock(&inode->i_lock); | 900 | spin_lock(&inode->i_lock); |
| 901 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 901 | NFS_I(inode)->cache_validity |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
| 902 | spin_unlock(&inode->i_lock); | 902 | spin_unlock(&inode->i_lock); |
| 903 | } | 903 | } |
| 904 | if ((attr->ia_valid & ATTR_SIZE) != 0) { | 904 | if ((attr->ia_valid & ATTR_SIZE) != 0) { |
| 905 | inode->i_size = attr->ia_size; | 905 | inode->i_size = attr->ia_size; |
| 906 | vmtruncate(inode, attr->ia_size); | 906 | vmtruncate(inode, attr->ia_size); |
| 907 | } | 907 | } |
| 908 | } | 908 | } |
| 909 | 909 | ||
| 910 | static int nfs_wait_schedule(void *word) | 910 | static int nfs_wait_schedule(void *word) |
| 911 | { | 911 | { |
| 912 | if (signal_pending(current)) | 912 | if (signal_pending(current)) |
| 913 | return -ERESTARTSYS; | 913 | return -ERESTARTSYS; |
| 914 | schedule(); | 914 | schedule(); |
| 915 | return 0; | 915 | return 0; |
| 916 | } | 916 | } |
| 917 | 917 | ||
| 918 | /* | 918 | /* |
| 919 | * Wait for the inode to get unlocked. | 919 | * Wait for the inode to get unlocked. |
| 920 | */ | 920 | */ |
| 921 | static int nfs_wait_on_inode(struct inode *inode) | 921 | static int nfs_wait_on_inode(struct inode *inode) |
| 922 | { | 922 | { |
| 923 | struct rpc_clnt *clnt = NFS_CLIENT(inode); | 923 | struct rpc_clnt *clnt = NFS_CLIENT(inode); |
| 924 | struct nfs_inode *nfsi = NFS_I(inode); | 924 | struct nfs_inode *nfsi = NFS_I(inode); |
| 925 | sigset_t oldmask; | 925 | sigset_t oldmask; |
| 926 | int error; | 926 | int error; |
| 927 | 927 | ||
| 928 | rpc_clnt_sigmask(clnt, &oldmask); | 928 | rpc_clnt_sigmask(clnt, &oldmask); |
| 929 | error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, | 929 | error = wait_on_bit_lock(&nfsi->flags, NFS_INO_REVALIDATING, |
| 930 | nfs_wait_schedule, TASK_INTERRUPTIBLE); | 930 | nfs_wait_schedule, TASK_INTERRUPTIBLE); |
| 931 | rpc_clnt_sigunmask(clnt, &oldmask); | 931 | rpc_clnt_sigunmask(clnt, &oldmask); |
| 932 | 932 | ||
| 933 | return error; | 933 | return error; |
| 934 | } | 934 | } |
| 935 | 935 | ||
| 936 | static void nfs_wake_up_inode(struct inode *inode) | 936 | static void nfs_wake_up_inode(struct inode *inode) |
| 937 | { | 937 | { |
| 938 | struct nfs_inode *nfsi = NFS_I(inode); | 938 | struct nfs_inode *nfsi = NFS_I(inode); |
| 939 | 939 | ||
| 940 | clear_bit(NFS_INO_REVALIDATING, &nfsi->flags); | 940 | clear_bit(NFS_INO_REVALIDATING, &nfsi->flags); |
| 941 | smp_mb__after_clear_bit(); | 941 | smp_mb__after_clear_bit(); |
| 942 | wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING); | 942 | wake_up_bit(&nfsi->flags, NFS_INO_REVALIDATING); |
| 943 | } | 943 | } |
| 944 | 944 | ||
| 945 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) | 945 | int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) |
| 946 | { | 946 | { |
| 947 | struct inode *inode = dentry->d_inode; | 947 | struct inode *inode = dentry->d_inode; |
| 948 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; | 948 | int need_atime = NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATIME; |
| 949 | int err; | 949 | int err; |
| 950 | 950 | ||
| 951 | /* Flush out writes to the server in order to update c/mtime */ | 951 | /* Flush out writes to the server in order to update c/mtime */ |
| 952 | nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT); | 952 | nfs_sync_inode(inode, 0, 0, FLUSH_WAIT|FLUSH_NOCOMMIT); |
| 953 | 953 | ||
| 954 | /* | 954 | /* |
| 955 | * We may force a getattr if the user cares about atime. | 955 | * We may force a getattr if the user cares about atime. |
| 956 | * | 956 | * |
| 957 | * Note that we only have to check the vfsmount flags here: | 957 | * Note that we only have to check the vfsmount flags here: |
| 958 | * - NFS always sets S_NOATIME by so checking it would give a | 958 | * - NFS always sets S_NOATIME by so checking it would give a |
| 959 | * bogus result | 959 | * bogus result |
| 960 | * - NFS never sets MS_NOATIME or MS_NODIRATIME so there is | 960 | * - NFS never sets MS_NOATIME or MS_NODIRATIME so there is |
| 961 | * no point in checking those. | 961 | * no point in checking those. |
| 962 | */ | 962 | */ |
| 963 | if ((mnt->mnt_flags & MNT_NOATIME) || | 963 | if ((mnt->mnt_flags & MNT_NOATIME) || |
| 964 | ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))) | 964 | ((mnt->mnt_flags & MNT_NODIRATIME) && S_ISDIR(inode->i_mode))) |
| 965 | need_atime = 0; | 965 | need_atime = 0; |
| 966 | 966 | ||
| 967 | if (need_atime) | 967 | if (need_atime) |
| 968 | err = __nfs_revalidate_inode(NFS_SERVER(inode), inode); | 968 | err = __nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 969 | else | 969 | else |
| 970 | err = nfs_revalidate_inode(NFS_SERVER(inode), inode); | 970 | err = nfs_revalidate_inode(NFS_SERVER(inode), inode); |
| 971 | if (!err) | 971 | if (!err) |
| 972 | generic_fillattr(inode, stat); | 972 | generic_fillattr(inode, stat); |
| 973 | return err; | 973 | return err; |
| 974 | } | 974 | } |
| 975 | 975 | ||
| 976 | struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred) | 976 | struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, struct rpc_cred *cred) |
| 977 | { | 977 | { |
| 978 | struct nfs_open_context *ctx; | 978 | struct nfs_open_context *ctx; |
| 979 | 979 | ||
| 980 | ctx = (struct nfs_open_context *)kmalloc(sizeof(*ctx), GFP_KERNEL); | 980 | ctx = (struct nfs_open_context *)kmalloc(sizeof(*ctx), GFP_KERNEL); |
| 981 | if (ctx != NULL) { | 981 | if (ctx != NULL) { |
| 982 | atomic_set(&ctx->count, 1); | 982 | atomic_set(&ctx->count, 1); |
| 983 | ctx->dentry = dget(dentry); | 983 | ctx->dentry = dget(dentry); |
| 984 | ctx->cred = get_rpccred(cred); | 984 | ctx->cred = get_rpccred(cred); |
| 985 | ctx->state = NULL; | 985 | ctx->state = NULL; |
| 986 | ctx->lockowner = current->files; | 986 | ctx->lockowner = current->files; |
| 987 | ctx->error = 0; | 987 | ctx->error = 0; |
| 988 | ctx->dir_cookie = 0; | 988 | ctx->dir_cookie = 0; |
| 989 | } | 989 | } |
| 990 | return ctx; | 990 | return ctx; |
| 991 | } | 991 | } |
| 992 | 992 | ||
| 993 | struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) | 993 | struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx) |
| 994 | { | 994 | { |
| 995 | if (ctx != NULL) | 995 | if (ctx != NULL) |
| 996 | atomic_inc(&ctx->count); | 996 | atomic_inc(&ctx->count); |
| 997 | return ctx; | 997 | return ctx; |
| 998 | } | 998 | } |
| 999 | 999 | ||
| 1000 | void put_nfs_open_context(struct nfs_open_context *ctx) | 1000 | void put_nfs_open_context(struct nfs_open_context *ctx) |
| 1001 | { | 1001 | { |
| 1002 | if (atomic_dec_and_test(&ctx->count)) { | 1002 | if (atomic_dec_and_test(&ctx->count)) { |
| 1003 | if (!list_empty(&ctx->list)) { | 1003 | if (!list_empty(&ctx->list)) { |
| 1004 | struct inode *inode = ctx->dentry->d_inode; | 1004 | struct inode *inode = ctx->dentry->d_inode; |
| 1005 | spin_lock(&inode->i_lock); | 1005 | spin_lock(&inode->i_lock); |
| 1006 | list_del(&ctx->list); | 1006 | list_del(&ctx->list); |
| 1007 | spin_unlock(&inode->i_lock); | 1007 | spin_unlock(&inode->i_lock); |
| 1008 | } | 1008 | } |
| 1009 | if (ctx->state != NULL) | 1009 | if (ctx->state != NULL) |
| 1010 | nfs4_close_state(ctx->state, ctx->mode); | 1010 | nfs4_close_state(ctx->state, ctx->mode); |
| 1011 | if (ctx->cred != NULL) | 1011 | if (ctx->cred != NULL) |
| 1012 | put_rpccred(ctx->cred); | 1012 | put_rpccred(ctx->cred); |
| 1013 | dput(ctx->dentry); | 1013 | dput(ctx->dentry); |
| 1014 | kfree(ctx); | 1014 | kfree(ctx); |
| 1015 | } | 1015 | } |
| 1016 | } | 1016 | } |
| 1017 | 1017 | ||
| 1018 | /* | 1018 | /* |
| 1019 | * Ensure that mmap has a recent RPC credential for use when writing out | 1019 | * Ensure that mmap has a recent RPC credential for use when writing out |
| 1020 | * shared pages | 1020 | * shared pages |
| 1021 | */ | 1021 | */ |
| 1022 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) | 1022 | void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) |
| 1023 | { | 1023 | { |
| 1024 | struct inode *inode = filp->f_dentry->d_inode; | 1024 | struct inode *inode = filp->f_dentry->d_inode; |
| 1025 | struct nfs_inode *nfsi = NFS_I(inode); | 1025 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1026 | 1026 | ||
| 1027 | filp->private_data = get_nfs_open_context(ctx); | 1027 | filp->private_data = get_nfs_open_context(ctx); |
| 1028 | spin_lock(&inode->i_lock); | 1028 | spin_lock(&inode->i_lock); |
| 1029 | list_add(&ctx->list, &nfsi->open_files); | 1029 | list_add(&ctx->list, &nfsi->open_files); |
| 1030 | spin_unlock(&inode->i_lock); | 1030 | spin_unlock(&inode->i_lock); |
| 1031 | } | 1031 | } |
| 1032 | 1032 | ||
| 1033 | /* | 1033 | /* |
| 1034 | * Given an inode, search for an open context with the desired characteristics | 1034 | * Given an inode, search for an open context with the desired characteristics |
| 1035 | */ | 1035 | */ |
| 1036 | struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode) | 1036 | struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode) |
| 1037 | { | 1037 | { |
| 1038 | struct nfs_inode *nfsi = NFS_I(inode); | 1038 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1039 | struct nfs_open_context *pos, *ctx = NULL; | 1039 | struct nfs_open_context *pos, *ctx = NULL; |
| 1040 | 1040 | ||
| 1041 | spin_lock(&inode->i_lock); | 1041 | spin_lock(&inode->i_lock); |
| 1042 | list_for_each_entry(pos, &nfsi->open_files, list) { | 1042 | list_for_each_entry(pos, &nfsi->open_files, list) { |
| 1043 | if (cred != NULL && pos->cred != cred) | 1043 | if (cred != NULL && pos->cred != cred) |
| 1044 | continue; | 1044 | continue; |
| 1045 | if ((pos->mode & mode) == mode) { | 1045 | if ((pos->mode & mode) == mode) { |
| 1046 | ctx = get_nfs_open_context(pos); | 1046 | ctx = get_nfs_open_context(pos); |
| 1047 | break; | 1047 | break; |
| 1048 | } | 1048 | } |
| 1049 | } | 1049 | } |
| 1050 | spin_unlock(&inode->i_lock); | 1050 | spin_unlock(&inode->i_lock); |
| 1051 | return ctx; | 1051 | return ctx; |
| 1052 | } | 1052 | } |
| 1053 | 1053 | ||
| 1054 | void nfs_file_clear_open_context(struct file *filp) | 1054 | void nfs_file_clear_open_context(struct file *filp) |
| 1055 | { | 1055 | { |
| 1056 | struct inode *inode = filp->f_dentry->d_inode; | 1056 | struct inode *inode = filp->f_dentry->d_inode; |
| 1057 | struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data; | 1057 | struct nfs_open_context *ctx = (struct nfs_open_context *)filp->private_data; |
| 1058 | 1058 | ||
| 1059 | if (ctx) { | 1059 | if (ctx) { |
| 1060 | filp->private_data = NULL; | 1060 | filp->private_data = NULL; |
| 1061 | spin_lock(&inode->i_lock); | 1061 | spin_lock(&inode->i_lock); |
| 1062 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); | 1062 | list_move_tail(&ctx->list, &NFS_I(inode)->open_files); |
| 1063 | spin_unlock(&inode->i_lock); | 1063 | spin_unlock(&inode->i_lock); |
| 1064 | put_nfs_open_context(ctx); | 1064 | put_nfs_open_context(ctx); |
| 1065 | } | 1065 | } |
| 1066 | } | 1066 | } |
| 1067 | 1067 | ||
| 1068 | /* | 1068 | /* |
| 1069 | * These allocate and release file read/write context information. | 1069 | * These allocate and release file read/write context information. |
| 1070 | */ | 1070 | */ |
| 1071 | int nfs_open(struct inode *inode, struct file *filp) | 1071 | int nfs_open(struct inode *inode, struct file *filp) |
| 1072 | { | 1072 | { |
| 1073 | struct nfs_open_context *ctx; | 1073 | struct nfs_open_context *ctx; |
| 1074 | struct rpc_cred *cred; | 1074 | struct rpc_cred *cred; |
| 1075 | 1075 | ||
| 1076 | cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0); | 1076 | cred = rpcauth_lookupcred(NFS_CLIENT(inode)->cl_auth, 0); |
| 1077 | if (IS_ERR(cred)) | 1077 | if (IS_ERR(cred)) |
| 1078 | return PTR_ERR(cred); | 1078 | return PTR_ERR(cred); |
| 1079 | ctx = alloc_nfs_open_context(filp->f_dentry, cred); | 1079 | ctx = alloc_nfs_open_context(filp->f_dentry, cred); |
| 1080 | put_rpccred(cred); | 1080 | put_rpccred(cred); |
| 1081 | if (ctx == NULL) | 1081 | if (ctx == NULL) |
| 1082 | return -ENOMEM; | 1082 | return -ENOMEM; |
| 1083 | ctx->mode = filp->f_mode; | 1083 | ctx->mode = filp->f_mode; |
| 1084 | nfs_file_set_open_context(filp, ctx); | 1084 | nfs_file_set_open_context(filp, ctx); |
| 1085 | put_nfs_open_context(ctx); | 1085 | put_nfs_open_context(ctx); |
| 1086 | return 0; | 1086 | return 0; |
| 1087 | } | 1087 | } |
| 1088 | 1088 | ||
| 1089 | int nfs_release(struct inode *inode, struct file *filp) | 1089 | int nfs_release(struct inode *inode, struct file *filp) |
| 1090 | { | 1090 | { |
| 1091 | nfs_file_clear_open_context(filp); | 1091 | nfs_file_clear_open_context(filp); |
| 1092 | return 0; | 1092 | return 0; |
| 1093 | } | 1093 | } |
| 1094 | 1094 | ||
| 1095 | /* | 1095 | /* |
| 1096 | * This function is called whenever some part of NFS notices that | 1096 | * This function is called whenever some part of NFS notices that |
| 1097 | * the cached attributes have to be refreshed. | 1097 | * the cached attributes have to be refreshed. |
| 1098 | */ | 1098 | */ |
| 1099 | int | 1099 | int |
| 1100 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 1100 | __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
| 1101 | { | 1101 | { |
| 1102 | int status = -ESTALE; | 1102 | int status = -ESTALE; |
| 1103 | struct nfs_fattr fattr; | 1103 | struct nfs_fattr fattr; |
| 1104 | struct nfs_inode *nfsi = NFS_I(inode); | 1104 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1105 | 1105 | ||
| 1106 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", | 1106 | dfprintk(PAGECACHE, "NFS: revalidating (%s/%Ld)\n", |
| 1107 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); | 1107 | inode->i_sb->s_id, (long long)NFS_FILEID(inode)); |
| 1108 | 1108 | ||
| 1109 | lock_kernel(); | 1109 | lock_kernel(); |
| 1110 | if (!inode || is_bad_inode(inode)) | 1110 | if (!inode || is_bad_inode(inode)) |
| 1111 | goto out_nowait; | 1111 | goto out_nowait; |
| 1112 | if (NFS_STALE(inode)) | 1112 | if (NFS_STALE(inode)) |
| 1113 | goto out_nowait; | 1113 | goto out_nowait; |
| 1114 | 1114 | ||
| 1115 | status = nfs_wait_on_inode(inode); | 1115 | status = nfs_wait_on_inode(inode); |
| 1116 | if (status < 0) | 1116 | if (status < 0) |
| 1117 | goto out; | 1117 | goto out; |
| 1118 | if (NFS_STALE(inode)) { | 1118 | if (NFS_STALE(inode)) { |
| 1119 | status = -ESTALE; | 1119 | status = -ESTALE; |
| 1120 | /* Do we trust the cached ESTALE? */ | 1120 | /* Do we trust the cached ESTALE? */ |
| 1121 | if (NFS_ATTRTIMEO(inode) != 0) { | 1121 | if (NFS_ATTRTIMEO(inode) != 0) { |
| 1122 | if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) { | 1122 | if (nfsi->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ATIME)) { |
| 1123 | /* no */ | 1123 | /* no */ |
| 1124 | } else | 1124 | } else |
| 1125 | goto out; | 1125 | goto out; |
| 1126 | } | 1126 | } |
| 1127 | } | 1127 | } |
| 1128 | 1128 | ||
| 1129 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); | 1129 | status = NFS_PROTO(inode)->getattr(server, NFS_FH(inode), &fattr); |
| 1130 | if (status != 0) { | 1130 | if (status != 0) { |
| 1131 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", | 1131 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) getattr failed, error=%d\n", |
| 1132 | inode->i_sb->s_id, | 1132 | inode->i_sb->s_id, |
| 1133 | (long long)NFS_FILEID(inode), status); | 1133 | (long long)NFS_FILEID(inode), status); |
| 1134 | if (status == -ESTALE) { | 1134 | if (status == -ESTALE) { |
| 1135 | nfs_zap_caches(inode); | 1135 | nfs_zap_caches(inode); |
| 1136 | if (!S_ISDIR(inode->i_mode)) | 1136 | if (!S_ISDIR(inode->i_mode)) |
| 1137 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); | 1137 | set_bit(NFS_INO_STALE, &NFS_FLAGS(inode)); |
| 1138 | } | 1138 | } |
| 1139 | goto out; | 1139 | goto out; |
| 1140 | } | 1140 | } |
| 1141 | 1141 | ||
| 1142 | spin_lock(&inode->i_lock); | 1142 | spin_lock(&inode->i_lock); |
| 1143 | status = nfs_update_inode(inode, &fattr); | 1143 | status = nfs_update_inode(inode, &fattr); |
| 1144 | if (status) { | 1144 | if (status) { |
| 1145 | spin_unlock(&inode->i_lock); | 1145 | spin_unlock(&inode->i_lock); |
| 1146 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", | 1146 | dfprintk(PAGECACHE, "nfs_revalidate_inode: (%s/%Ld) refresh failed, error=%d\n", |
| 1147 | inode->i_sb->s_id, | 1147 | inode->i_sb->s_id, |
| 1148 | (long long)NFS_FILEID(inode), status); | 1148 | (long long)NFS_FILEID(inode), status); |
| 1149 | goto out; | 1149 | goto out; |
| 1150 | } | 1150 | } |
| 1151 | spin_unlock(&inode->i_lock); | 1151 | spin_unlock(&inode->i_lock); |
| 1152 | 1152 | ||
| 1153 | nfs_revalidate_mapping(inode, inode->i_mapping); | 1153 | nfs_revalidate_mapping(inode, inode->i_mapping); |
| 1154 | 1154 | ||
| 1155 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) | 1155 | if (nfsi->cache_validity & NFS_INO_INVALID_ACL) |
| 1156 | nfs_zap_acl_cache(inode); | 1156 | nfs_zap_acl_cache(inode); |
| 1157 | 1157 | ||
| 1158 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", | 1158 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", |
| 1159 | inode->i_sb->s_id, | 1159 | inode->i_sb->s_id, |
| 1160 | (long long)NFS_FILEID(inode)); | 1160 | (long long)NFS_FILEID(inode)); |
| 1161 | 1161 | ||
| 1162 | out: | 1162 | out: |
| 1163 | nfs_wake_up_inode(inode); | 1163 | nfs_wake_up_inode(inode); |
| 1164 | 1164 | ||
| 1165 | out_nowait: | 1165 | out_nowait: |
| 1166 | unlock_kernel(); | 1166 | unlock_kernel(); |
| 1167 | return status; | 1167 | return status; |
| 1168 | } | 1168 | } |
| 1169 | 1169 | ||
| 1170 | int nfs_attribute_timeout(struct inode *inode) | 1170 | int nfs_attribute_timeout(struct inode *inode) |
| 1171 | { | 1171 | { |
| 1172 | struct nfs_inode *nfsi = NFS_I(inode); | 1172 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1173 | 1173 | ||
| 1174 | if (nfs_have_delegation(inode, FMODE_READ)) | 1174 | if (nfs_have_delegation(inode, FMODE_READ)) |
| 1175 | return 0; | 1175 | return 0; |
| 1176 | return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo); | 1176 | return time_after(jiffies, nfsi->read_cache_jiffies+nfsi->attrtimeo); |
| 1177 | } | 1177 | } |
| 1178 | 1178 | ||
| 1179 | /** | 1179 | /** |
| 1180 | * nfs_revalidate_inode - Revalidate the inode attributes | 1180 | * nfs_revalidate_inode - Revalidate the inode attributes |
| 1181 | * @server - pointer to nfs_server struct | 1181 | * @server - pointer to nfs_server struct |
| 1182 | * @inode - pointer to inode struct | 1182 | * @inode - pointer to inode struct |
| 1183 | * | 1183 | * |
| 1184 | * Updates inode attribute information by retrieving the data from the server. | 1184 | * Updates inode attribute information by retrieving the data from the server. |
| 1185 | */ | 1185 | */ |
| 1186 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 1186 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
| 1187 | { | 1187 | { |
| 1188 | if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) | 1188 | if (!(NFS_I(inode)->cache_validity & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA)) |
| 1189 | && !nfs_attribute_timeout(inode)) | 1189 | && !nfs_attribute_timeout(inode)) |
| 1190 | return NFS_STALE(inode) ? -ESTALE : 0; | 1190 | return NFS_STALE(inode) ? -ESTALE : 0; |
| 1191 | return __nfs_revalidate_inode(server, inode); | 1191 | return __nfs_revalidate_inode(server, inode); |
| 1192 | } | 1192 | } |
| 1193 | 1193 | ||
| 1194 | /** | 1194 | /** |
| 1195 | * nfs_revalidate_mapping - Revalidate the pagecache | 1195 | * nfs_revalidate_mapping - Revalidate the pagecache |
| 1196 | * @inode - pointer to host inode | 1196 | * @inode - pointer to host inode |
| 1197 | * @mapping - pointer to mapping | 1197 | * @mapping - pointer to mapping |
| 1198 | */ | 1198 | */ |
| 1199 | void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) | 1199 | void nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping) |
| 1200 | { | 1200 | { |
| 1201 | struct nfs_inode *nfsi = NFS_I(inode); | 1201 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1202 | 1202 | ||
| 1203 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { | 1203 | if (nfsi->cache_validity & NFS_INO_INVALID_DATA) { |
| 1204 | if (S_ISREG(inode->i_mode)) | 1204 | if (S_ISREG(inode->i_mode)) |
| 1205 | nfs_sync_mapping(mapping); | 1205 | nfs_sync_mapping(mapping); |
| 1206 | invalidate_inode_pages2(mapping); | 1206 | invalidate_inode_pages2(mapping); |
| 1207 | 1207 | ||
| 1208 | spin_lock(&inode->i_lock); | 1208 | spin_lock(&inode->i_lock); |
| 1209 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; | 1209 | nfsi->cache_validity &= ~NFS_INO_INVALID_DATA; |
| 1210 | if (S_ISDIR(inode->i_mode)) { | 1210 | if (S_ISDIR(inode->i_mode)) { |
| 1211 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); | 1211 | memset(nfsi->cookieverf, 0, sizeof(nfsi->cookieverf)); |
| 1212 | /* This ensures we revalidate child dentries */ | 1212 | /* This ensures we revalidate child dentries */ |
| 1213 | nfsi->cache_change_attribute = jiffies; | 1213 | nfsi->cache_change_attribute = jiffies; |
| 1214 | } | 1214 | } |
| 1215 | spin_unlock(&inode->i_lock); | 1215 | spin_unlock(&inode->i_lock); |
| 1216 | 1216 | ||
| 1217 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", | 1217 | dfprintk(PAGECACHE, "NFS: (%s/%Ld) data cache invalidated\n", |
| 1218 | inode->i_sb->s_id, | 1218 | inode->i_sb->s_id, |
| 1219 | (long long)NFS_FILEID(inode)); | 1219 | (long long)NFS_FILEID(inode)); |
| 1220 | } | 1220 | } |
| 1221 | } | 1221 | } |
| 1222 | 1222 | ||
| 1223 | /** | 1223 | /** |
| 1224 | * nfs_begin_data_update | 1224 | * nfs_begin_data_update |
| 1225 | * @inode - pointer to inode | 1225 | * @inode - pointer to inode |
| 1226 | * Declare that a set of operations will update file data on the server | 1226 | * Declare that a set of operations will update file data on the server |
| 1227 | */ | 1227 | */ |
| 1228 | void nfs_begin_data_update(struct inode *inode) | 1228 | void nfs_begin_data_update(struct inode *inode) |
| 1229 | { | 1229 | { |
| 1230 | atomic_inc(&NFS_I(inode)->data_updates); | 1230 | atomic_inc(&NFS_I(inode)->data_updates); |
| 1231 | } | 1231 | } |
| 1232 | 1232 | ||
| 1233 | /** | 1233 | /** |
| 1234 | * nfs_end_data_update | 1234 | * nfs_end_data_update |
| 1235 | * @inode - pointer to inode | 1235 | * @inode - pointer to inode |
| 1236 | * Declare end of the operations that will update file data | 1236 | * Declare end of the operations that will update file data |
| 1237 | * This will mark the inode as immediately needing revalidation | 1237 | * This will mark the inode as immediately needing revalidation |
| 1238 | * of its attribute cache. | 1238 | * of its attribute cache. |
| 1239 | */ | 1239 | */ |
| 1240 | void nfs_end_data_update(struct inode *inode) | 1240 | void nfs_end_data_update(struct inode *inode) |
| 1241 | { | 1241 | { |
| 1242 | struct nfs_inode *nfsi = NFS_I(inode); | 1242 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1243 | 1243 | ||
| 1244 | if (!nfs_have_delegation(inode, FMODE_READ)) { | 1244 | if (!nfs_have_delegation(inode, FMODE_READ)) { |
| 1245 | /* Directories and symlinks: invalidate page cache */ | 1245 | /* Directories and symlinks: invalidate page cache */ |
| 1246 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { | 1246 | if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) { |
| 1247 | spin_lock(&inode->i_lock); | 1247 | spin_lock(&inode->i_lock); |
| 1248 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; | 1248 | nfsi->cache_validity |= NFS_INO_INVALID_DATA; |
| 1249 | spin_unlock(&inode->i_lock); | 1249 | spin_unlock(&inode->i_lock); |
| 1250 | } | 1250 | } |
| 1251 | } | 1251 | } |
| 1252 | nfsi->cache_change_attribute = jiffies; | 1252 | nfsi->cache_change_attribute = jiffies; |
| 1253 | atomic_dec(&nfsi->data_updates); | 1253 | atomic_dec(&nfsi->data_updates); |
| 1254 | } | 1254 | } |
| 1255 | 1255 | ||
| 1256 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 1256 | static void nfs_wcc_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 1257 | { | 1257 | { |
| 1258 | struct nfs_inode *nfsi = NFS_I(inode); | 1258 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1259 | 1259 | ||
| 1260 | if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0 | 1260 | if ((fattr->valid & NFS_ATTR_PRE_CHANGE) != 0 |
| 1261 | && nfsi->change_attr == fattr->pre_change_attr) { | 1261 | && nfsi->change_attr == fattr->pre_change_attr) { |
| 1262 | nfsi->change_attr = fattr->change_attr; | 1262 | nfsi->change_attr = fattr->change_attr; |
| 1263 | nfsi->cache_change_attribute = jiffies; | 1263 | nfsi->cache_change_attribute = jiffies; |
| 1264 | } | 1264 | } |
| 1265 | 1265 | ||
| 1266 | /* If we have atomic WCC data, we may update some attributes */ | 1266 | /* If we have atomic WCC data, we may update some attributes */ |
| 1267 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { | 1267 | if ((fattr->valid & NFS_ATTR_WCC) != 0) { |
| 1268 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { | 1268 | if (timespec_equal(&inode->i_ctime, &fattr->pre_ctime)) { |
| 1269 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1269 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
| 1270 | nfsi->cache_change_attribute = jiffies; | 1270 | nfsi->cache_change_attribute = jiffies; |
| 1271 | } | 1271 | } |
| 1272 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { | 1272 | if (timespec_equal(&inode->i_mtime, &fattr->pre_mtime)) { |
| 1273 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1273 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
| 1274 | nfsi->cache_change_attribute = jiffies; | 1274 | nfsi->cache_change_attribute = jiffies; |
| 1275 | } | 1275 | } |
| 1276 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) { | 1276 | if (inode->i_size == fattr->pre_size && nfsi->npages == 0) { |
| 1277 | inode->i_size = fattr->size; | 1277 | inode->i_size = fattr->size; |
| 1278 | nfsi->cache_change_attribute = jiffies; | 1278 | nfsi->cache_change_attribute = jiffies; |
| 1279 | } | 1279 | } |
| 1280 | } | 1280 | } |
| 1281 | } | 1281 | } |
| 1282 | 1282 | ||
| 1283 | /** | 1283 | /** |
| 1284 | * nfs_check_inode_attributes - verify consistency of the inode attribute cache | 1284 | * nfs_check_inode_attributes - verify consistency of the inode attribute cache |
| 1285 | * @inode - pointer to inode | 1285 | * @inode - pointer to inode |
| 1286 | * @fattr - updated attributes | 1286 | * @fattr - updated attributes |
| 1287 | * | 1287 | * |
| 1288 | * Verifies the attribute cache. If we have just changed the attributes, | 1288 | * Verifies the attribute cache. If we have just changed the attributes, |
| 1289 | * so that fattr carries weak cache consistency data, then it may | 1289 | * so that fattr carries weak cache consistency data, then it may |
| 1290 | * also update the ctime/mtime/change_attribute. | 1290 | * also update the ctime/mtime/change_attribute. |
| 1291 | */ | 1291 | */ |
| 1292 | static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr) | 1292 | static int nfs_check_inode_attributes(struct inode *inode, struct nfs_fattr *fattr) |
| 1293 | { | 1293 | { |
| 1294 | struct nfs_inode *nfsi = NFS_I(inode); | 1294 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1295 | loff_t cur_size, new_isize; | 1295 | loff_t cur_size, new_isize; |
| 1296 | int data_unstable; | 1296 | int data_unstable; |
| 1297 | 1297 | ||
| 1298 | 1298 | ||
| 1299 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 1299 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) |
| 1300 | return 0; | 1300 | return 0; |
| 1301 | 1301 | ||
| 1302 | /* Are we in the process of updating data on the server? */ | 1302 | /* Are we in the process of updating data on the server? */ |
| 1303 | data_unstable = nfs_caches_unstable(inode); | 1303 | data_unstable = nfs_caches_unstable(inode); |
| 1304 | 1304 | ||
| 1305 | /* Do atomic weak cache consistency updates */ | 1305 | /* Do atomic weak cache consistency updates */ |
| 1306 | nfs_wcc_update_inode(inode, fattr); | 1306 | nfs_wcc_update_inode(inode, fattr); |
| 1307 | 1307 | ||
| 1308 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && | 1308 | if ((fattr->valid & NFS_ATTR_FATTR_V4) != 0 && |
| 1309 | nfsi->change_attr != fattr->change_attr) { | 1309 | nfsi->change_attr != fattr->change_attr) { |
| 1310 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 1310 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
| 1311 | if (!data_unstable) | 1311 | if (!data_unstable) |
| 1312 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; | 1312 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; |
| 1313 | } | 1313 | } |
| 1314 | 1314 | ||
| 1315 | /* Has the inode gone and changed behind our back? */ | 1315 | /* Has the inode gone and changed behind our back? */ |
| 1316 | if (nfsi->fileid != fattr->fileid | 1316 | if (nfsi->fileid != fattr->fileid |
| 1317 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { | 1317 | || (inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) { |
| 1318 | return -EIO; | 1318 | return -EIO; |
| 1319 | } | 1319 | } |
| 1320 | 1320 | ||
| 1321 | cur_size = i_size_read(inode); | 1321 | cur_size = i_size_read(inode); |
| 1322 | new_isize = nfs_size_to_loff_t(fattr->size); | 1322 | new_isize = nfs_size_to_loff_t(fattr->size); |
| 1323 | 1323 | ||
| 1324 | /* Verify a few of the more important attributes */ | 1324 | /* Verify a few of the more important attributes */ |
| 1325 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | 1325 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { |
| 1326 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 1326 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
| 1327 | if (!data_unstable) | 1327 | if (!data_unstable) |
| 1328 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; | 1328 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; |
| 1329 | } | 1329 | } |
| 1330 | if (cur_size != new_isize) { | 1330 | if (cur_size != new_isize) { |
| 1331 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 1331 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
| 1332 | if (nfsi->npages == 0) | 1332 | if (nfsi->npages == 0) |
| 1333 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; | 1333 | nfsi->cache_validity |= NFS_INO_REVAL_PAGECACHE; |
| 1334 | } | 1334 | } |
| 1335 | 1335 | ||
| 1336 | /* Have any file permissions changed? */ | 1336 | /* Have any file permissions changed? */ |
| 1337 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) | 1337 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) |
| 1338 | || inode->i_uid != fattr->uid | 1338 | || inode->i_uid != fattr->uid |
| 1339 | || inode->i_gid != fattr->gid) | 1339 | || inode->i_gid != fattr->gid) |
| 1340 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; | 1340 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL; |
| 1341 | 1341 | ||
| 1342 | /* Has the link count changed? */ | 1342 | /* Has the link count changed? */ |
| 1343 | if (inode->i_nlink != fattr->nlink) | 1343 | if (inode->i_nlink != fattr->nlink) |
| 1344 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; | 1344 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR; |
| 1345 | 1345 | ||
| 1346 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) | 1346 | if (!timespec_equal(&inode->i_atime, &fattr->atime)) |
| 1347 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; | 1347 | nfsi->cache_validity |= NFS_INO_INVALID_ATIME; |
| 1348 | 1348 | ||
| 1349 | nfsi->read_cache_jiffies = fattr->time_start; | 1349 | nfsi->read_cache_jiffies = fattr->time_start; |
| 1350 | return 0; | 1350 | return 0; |
| 1351 | } | 1351 | } |
| 1352 | 1352 | ||
| 1353 | /** | 1353 | /** |
| 1354 | * nfs_refresh_inode - try to update the inode attribute cache | 1354 | * nfs_refresh_inode - try to update the inode attribute cache |
| 1355 | * @inode - pointer to inode | 1355 | * @inode - pointer to inode |
| 1356 | * @fattr - updated attributes | 1356 | * @fattr - updated attributes |
| 1357 | * | 1357 | * |
| 1358 | * Check that an RPC call that returned attributes has not overlapped with | 1358 | * Check that an RPC call that returned attributes has not overlapped with |
| 1359 | * other recent updates of the inode metadata, then decide whether it is | 1359 | * other recent updates of the inode metadata, then decide whether it is |
| 1360 | * safe to do a full update of the inode attributes, or whether just to | 1360 | * safe to do a full update of the inode attributes, or whether just to |
| 1361 | * call nfs_check_inode_attributes. | 1361 | * call nfs_check_inode_attributes. |
| 1362 | */ | 1362 | */ |
| 1363 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) | 1363 | int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 1364 | { | 1364 | { |
| 1365 | struct nfs_inode *nfsi = NFS_I(inode); | 1365 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1366 | int status; | 1366 | int status; |
| 1367 | 1367 | ||
| 1368 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 1368 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) |
| 1369 | return 0; | 1369 | return 0; |
| 1370 | spin_lock(&inode->i_lock); | 1370 | spin_lock(&inode->i_lock); |
| 1371 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; | 1371 | nfsi->cache_validity &= ~NFS_INO_REVAL_PAGECACHE; |
| 1372 | if (time_after(fattr->time_start, nfsi->last_updated)) | 1372 | if (time_after(fattr->time_start, nfsi->last_updated)) |
| 1373 | status = nfs_update_inode(inode, fattr); | 1373 | status = nfs_update_inode(inode, fattr); |
| 1374 | else | 1374 | else |
| 1375 | status = nfs_check_inode_attributes(inode, fattr); | 1375 | status = nfs_check_inode_attributes(inode, fattr); |
| 1376 | 1376 | ||
| 1377 | spin_unlock(&inode->i_lock); | 1377 | spin_unlock(&inode->i_lock); |
| 1378 | return status; | 1378 | return status; |
| 1379 | } | 1379 | } |
| 1380 | 1380 | ||
| 1381 | /** | 1381 | /** |
| 1382 | * nfs_post_op_update_inode - try to update the inode attribute cache | 1382 | * nfs_post_op_update_inode - try to update the inode attribute cache |
| 1383 | * @inode - pointer to inode | 1383 | * @inode - pointer to inode |
| 1384 | * @fattr - updated attributes | 1384 | * @fattr - updated attributes |
| 1385 | * | 1385 | * |
| 1386 | * After an operation that has changed the inode metadata, mark the | 1386 | * After an operation that has changed the inode metadata, mark the |
| 1387 | * attribute cache as being invalid, then try to update it. | 1387 | * attribute cache as being invalid, then try to update it. |
| 1388 | */ | 1388 | */ |
| 1389 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 1389 | int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 1390 | { | 1390 | { |
| 1391 | struct nfs_inode *nfsi = NFS_I(inode); | 1391 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1392 | int status = 0; | 1392 | int status = 0; |
| 1393 | 1393 | ||
| 1394 | spin_lock(&inode->i_lock); | 1394 | spin_lock(&inode->i_lock); |
| 1395 | if (unlikely((fattr->valid & NFS_ATTR_FATTR) == 0)) { | 1395 | if (unlikely((fattr->valid & NFS_ATTR_FATTR) == 0)) { |
| 1396 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; | 1396 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; |
| 1397 | goto out; | 1397 | goto out; |
| 1398 | } | 1398 | } |
| 1399 | status = nfs_update_inode(inode, fattr); | 1399 | status = nfs_update_inode(inode, fattr); |
| 1400 | out: | 1400 | out: |
| 1401 | spin_unlock(&inode->i_lock); | 1401 | spin_unlock(&inode->i_lock); |
| 1402 | return status; | 1402 | return status; |
| 1403 | } | 1403 | } |
| 1404 | 1404 | ||
| 1405 | /* | 1405 | /* |
| 1406 | * Many nfs protocol calls return the new file attributes after | 1406 | * Many nfs protocol calls return the new file attributes after |
| 1407 | * an operation. Here we update the inode to reflect the state | 1407 | * an operation. Here we update the inode to reflect the state |
| 1408 | * of the server's inode. | 1408 | * of the server's inode. |
| 1409 | * | 1409 | * |
| 1410 | * This is a bit tricky because we have to make sure all dirty pages | 1410 | * This is a bit tricky because we have to make sure all dirty pages |
| 1411 | * have been sent off to the server before calling invalidate_inode_pages. | 1411 | * have been sent off to the server before calling invalidate_inode_pages. |
| 1412 | * To make sure no other process adds more write requests while we try | 1412 | * To make sure no other process adds more write requests while we try |
| 1413 | * our best to flush them, we make them sleep during the attribute refresh. | 1413 | * our best to flush them, we make them sleep during the attribute refresh. |
| 1414 | * | 1414 | * |
| 1415 | * A very similar scenario holds for the dir cache. | 1415 | * A very similar scenario holds for the dir cache. |
| 1416 | */ | 1416 | */ |
| 1417 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | 1417 | static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) |
| 1418 | { | 1418 | { |
| 1419 | struct nfs_inode *nfsi = NFS_I(inode); | 1419 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1420 | loff_t cur_isize, new_isize; | 1420 | loff_t cur_isize, new_isize; |
| 1421 | unsigned int invalid = 0; | 1421 | unsigned int invalid = 0; |
| 1422 | int data_stable; | 1422 | int data_stable; |
| 1423 | 1423 | ||
| 1424 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", | 1424 | dfprintk(VFS, "NFS: %s(%s/%ld ct=%d info=0x%x)\n", |
| 1425 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, | 1425 | __FUNCTION__, inode->i_sb->s_id, inode->i_ino, |
| 1426 | atomic_read(&inode->i_count), fattr->valid); | 1426 | atomic_read(&inode->i_count), fattr->valid); |
| 1427 | 1427 | ||
| 1428 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) | 1428 | if ((fattr->valid & NFS_ATTR_FATTR) == 0) |
| 1429 | return 0; | 1429 | return 0; |
| 1430 | 1430 | ||
| 1431 | if (nfsi->fileid != fattr->fileid) | 1431 | if (nfsi->fileid != fattr->fileid) |
| 1432 | goto out_fileid; | 1432 | goto out_fileid; |
| 1433 | 1433 | ||
| 1434 | /* | 1434 | /* |
| 1435 | * Make sure the inode's type hasn't changed. | 1435 | * Make sure the inode's type hasn't changed. |
| 1436 | */ | 1436 | */ |
| 1437 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) | 1437 | if ((inode->i_mode & S_IFMT) != (fattr->mode & S_IFMT)) |
| 1438 | goto out_changed; | 1438 | goto out_changed; |
| 1439 | 1439 | ||
| 1440 | /* | 1440 | /* |
| 1441 | * Update the read time so we don't revalidate too often. | 1441 | * Update the read time so we don't revalidate too often. |
| 1442 | */ | 1442 | */ |
| 1443 | nfsi->read_cache_jiffies = fattr->time_start; | 1443 | nfsi->read_cache_jiffies = fattr->time_start; |
| 1444 | nfsi->last_updated = jiffies; | 1444 | nfsi->last_updated = jiffies; |
| 1445 | 1445 | ||
| 1446 | /* Are we racing with known updates of the metadata on the server? */ | 1446 | /* Are we racing with known updates of the metadata on the server? */ |
| 1447 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); | 1447 | data_stable = nfs_verify_change_attribute(inode, fattr->time_start); |
| 1448 | if (data_stable) | 1448 | if (data_stable) |
| 1449 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); | 1449 | nfsi->cache_validity &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME); |
| 1450 | 1450 | ||
| 1451 | /* Do atomic weak cache consistency updates */ | 1451 | /* Do atomic weak cache consistency updates */ |
| 1452 | nfs_wcc_update_inode(inode, fattr); | 1452 | nfs_wcc_update_inode(inode, fattr); |
| 1453 | 1453 | ||
| 1454 | /* Check if our cached file size is stale */ | 1454 | /* Check if our cached file size is stale */ |
| 1455 | new_isize = nfs_size_to_loff_t(fattr->size); | 1455 | new_isize = nfs_size_to_loff_t(fattr->size); |
| 1456 | cur_isize = i_size_read(inode); | 1456 | cur_isize = i_size_read(inode); |
| 1457 | if (new_isize != cur_isize) { | 1457 | if (new_isize != cur_isize) { |
| 1458 | /* Do we perhaps have any outstanding writes? */ | 1458 | /* Do we perhaps have any outstanding writes? */ |
| 1459 | if (nfsi->npages == 0) { | 1459 | if (nfsi->npages == 0) { |
| 1460 | /* No, but did we race with nfs_end_data_update()? */ | 1460 | /* No, but did we race with nfs_end_data_update()? */ |
| 1461 | if (data_stable) { | 1461 | if (data_stable) { |
| 1462 | inode->i_size = new_isize; | 1462 | inode->i_size = new_isize; |
| 1463 | invalid |= NFS_INO_INVALID_DATA; | 1463 | invalid |= NFS_INO_INVALID_DATA; |
| 1464 | } | 1464 | } |
| 1465 | invalid |= NFS_INO_INVALID_ATTR; | 1465 | invalid |= NFS_INO_INVALID_ATTR; |
| 1466 | } else if (new_isize > cur_isize) { | 1466 | } else if (new_isize > cur_isize) { |
| 1467 | inode->i_size = new_isize; | 1467 | inode->i_size = new_isize; |
| 1468 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1468 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
| 1469 | } | 1469 | } |
| 1470 | nfsi->cache_change_attribute = jiffies; | 1470 | nfsi->cache_change_attribute = jiffies; |
| 1471 | dprintk("NFS: isize change on server for file %s/%ld\n", | 1471 | dprintk("NFS: isize change on server for file %s/%ld\n", |
| 1472 | inode->i_sb->s_id, inode->i_ino); | 1472 | inode->i_sb->s_id, inode->i_ino); |
| 1473 | } | 1473 | } |
| 1474 | 1474 | ||
| 1475 | /* Check if the mtime agrees */ | 1475 | /* Check if the mtime agrees */ |
| 1476 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { | 1476 | if (!timespec_equal(&inode->i_mtime, &fattr->mtime)) { |
| 1477 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); | 1477 | memcpy(&inode->i_mtime, &fattr->mtime, sizeof(inode->i_mtime)); |
| 1478 | dprintk("NFS: mtime change on server for file %s/%ld\n", | 1478 | dprintk("NFS: mtime change on server for file %s/%ld\n", |
| 1479 | inode->i_sb->s_id, inode->i_ino); | 1479 | inode->i_sb->s_id, inode->i_ino); |
| 1480 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1480 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
| 1481 | nfsi->cache_change_attribute = jiffies; | 1481 | nfsi->cache_change_attribute = jiffies; |
| 1482 | } | 1482 | } |
| 1483 | 1483 | ||
| 1484 | if ((fattr->valid & NFS_ATTR_FATTR_V4) | 1484 | if ((fattr->valid & NFS_ATTR_FATTR_V4) |
| 1485 | && nfsi->change_attr != fattr->change_attr) { | 1485 | && nfsi->change_attr != fattr->change_attr) { |
| 1486 | dprintk("NFS: change_attr change on server for file %s/%ld\n", | 1486 | dprintk("NFS: change_attr change on server for file %s/%ld\n", |
| 1487 | inode->i_sb->s_id, inode->i_ino); | 1487 | inode->i_sb->s_id, inode->i_ino); |
| 1488 | nfsi->change_attr = fattr->change_attr; | 1488 | nfsi->change_attr = fattr->change_attr; |
| 1489 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1489 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
| 1490 | nfsi->cache_change_attribute = jiffies; | 1490 | nfsi->cache_change_attribute = jiffies; |
| 1491 | } | 1491 | } |
| 1492 | 1492 | ||
| 1493 | /* If ctime has changed we should definitely clear access+acl caches */ | 1493 | /* If ctime has changed we should definitely clear access+acl caches */ |
| 1494 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { | 1494 | if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) { |
| 1495 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1495 | invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
| 1496 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); | 1496 | memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); |
| 1497 | nfsi->cache_change_attribute = jiffies; | 1497 | nfsi->cache_change_attribute = jiffies; |
| 1498 | } | 1498 | } |
| 1499 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); | 1499 | memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); |
| 1500 | 1500 | ||
| 1501 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || | 1501 | if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || |
| 1502 | inode->i_uid != fattr->uid || | 1502 | inode->i_uid != fattr->uid || |
| 1503 | inode->i_gid != fattr->gid) | 1503 | inode->i_gid != fattr->gid) |
| 1504 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; | 1504 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL; |
| 1505 | 1505 | ||
| 1506 | inode->i_mode = fattr->mode; | 1506 | inode->i_mode = fattr->mode; |
| 1507 | inode->i_nlink = fattr->nlink; | 1507 | inode->i_nlink = fattr->nlink; |
| 1508 | inode->i_uid = fattr->uid; | 1508 | inode->i_uid = fattr->uid; |
| 1509 | inode->i_gid = fattr->gid; | 1509 | inode->i_gid = fattr->gid; |
| 1510 | 1510 | ||
| 1511 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { | 1511 | if (fattr->valid & (NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4)) { |
| 1512 | /* | 1512 | /* |
| 1513 | * report the blocks in 512byte units | 1513 | * report the blocks in 512byte units |
| 1514 | */ | 1514 | */ |
| 1515 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 1515 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
| 1516 | inode->i_blksize = inode->i_sb->s_blocksize; | 1516 | inode->i_blksize = inode->i_sb->s_blocksize; |
| 1517 | } else { | 1517 | } else { |
| 1518 | inode->i_blocks = fattr->du.nfs2.blocks; | 1518 | inode->i_blocks = fattr->du.nfs2.blocks; |
| 1519 | inode->i_blksize = fattr->du.nfs2.blocksize; | 1519 | inode->i_blksize = fattr->du.nfs2.blocksize; |
| 1520 | } | 1520 | } |
| 1521 | 1521 | ||
| 1522 | /* Update attrtimeo value if we're out of the unstable period */ | 1522 | /* Update attrtimeo value if we're out of the unstable period */ |
| 1523 | if (invalid & NFS_INO_INVALID_ATTR) { | 1523 | if (invalid & NFS_INO_INVALID_ATTR) { |
| 1524 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1524 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
| 1525 | nfsi->attrtimeo_timestamp = jiffies; | 1525 | nfsi->attrtimeo_timestamp = jiffies; |
| 1526 | } else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { | 1526 | } else if (time_after(jiffies, nfsi->attrtimeo_timestamp+nfsi->attrtimeo)) { |
| 1527 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) | 1527 | if ((nfsi->attrtimeo <<= 1) > NFS_MAXATTRTIMEO(inode)) |
| 1528 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); | 1528 | nfsi->attrtimeo = NFS_MAXATTRTIMEO(inode); |
| 1529 | nfsi->attrtimeo_timestamp = jiffies; | 1529 | nfsi->attrtimeo_timestamp = jiffies; |
| 1530 | } | 1530 | } |
| 1531 | /* Don't invalidate the data if we were to blame */ | 1531 | /* Don't invalidate the data if we were to blame */ |
| 1532 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1532 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
| 1533 | || S_ISLNK(inode->i_mode))) | 1533 | || S_ISLNK(inode->i_mode))) |
| 1534 | invalid &= ~NFS_INO_INVALID_DATA; | 1534 | invalid &= ~NFS_INO_INVALID_DATA; |
| 1535 | if (data_stable) | 1535 | if (data_stable) |
| 1536 | invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); | 1536 | invalid &= ~(NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ATIME|NFS_INO_REVAL_PAGECACHE); |
| 1537 | if (!nfs_have_delegation(inode, FMODE_READ)) | 1537 | if (!nfs_have_delegation(inode, FMODE_READ)) |
| 1538 | nfsi->cache_validity |= invalid; | 1538 | nfsi->cache_validity |= invalid; |
| 1539 | 1539 | ||
| 1540 | return 0; | 1540 | return 0; |
| 1541 | out_changed: | 1541 | out_changed: |
| 1542 | /* | 1542 | /* |
| 1543 | * Big trouble! The inode has become a different object. | 1543 | * Big trouble! The inode has become a different object. |
| 1544 | */ | 1544 | */ |
| 1545 | #ifdef NFS_PARANOIA | 1545 | #ifdef NFS_PARANOIA |
| 1546 | printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n", | 1546 | printk(KERN_DEBUG "%s: inode %ld mode changed, %07o to %07o\n", |
| 1547 | __FUNCTION__, inode->i_ino, inode->i_mode, fattr->mode); | 1547 | __FUNCTION__, inode->i_ino, inode->i_mode, fattr->mode); |
| 1548 | #endif | 1548 | #endif |
| 1549 | out_err: | 1549 | out_err: |
| 1550 | /* | 1550 | /* |
| 1551 | * No need to worry about unhashing the dentry, as the | 1551 | * No need to worry about unhashing the dentry, as the |
| 1552 | * lookup validation will know that the inode is bad. | 1552 | * lookup validation will know that the inode is bad. |
| 1553 | * (But we fall through to invalidate the caches.) | 1553 | * (But we fall through to invalidate the caches.) |
| 1554 | */ | 1554 | */ |
| 1555 | nfs_invalidate_inode(inode); | 1555 | nfs_invalidate_inode(inode); |
| 1556 | return -ESTALE; | 1556 | return -ESTALE; |
| 1557 | 1557 | ||
| 1558 | out_fileid: | 1558 | out_fileid: |
| 1559 | printk(KERN_ERR "NFS: server %s error: fileid changed\n" | 1559 | printk(KERN_ERR "NFS: server %s error: fileid changed\n" |
| 1560 | "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", | 1560 | "fsid %s: expected fileid 0x%Lx, got 0x%Lx\n", |
| 1561 | NFS_SERVER(inode)->hostname, inode->i_sb->s_id, | 1561 | NFS_SERVER(inode)->hostname, inode->i_sb->s_id, |
| 1562 | (long long)nfsi->fileid, (long long)fattr->fileid); | 1562 | (long long)nfsi->fileid, (long long)fattr->fileid); |
| 1563 | goto out_err; | 1563 | goto out_err; |
| 1564 | } | 1564 | } |
| 1565 | 1565 | ||
| 1566 | /* | 1566 | /* |
| 1567 | * File system information | 1567 | * File system information |
| 1568 | */ | 1568 | */ |
| 1569 | 1569 | ||
| 1570 | static int nfs_set_super(struct super_block *s, void *data) | 1570 | static int nfs_set_super(struct super_block *s, void *data) |
| 1571 | { | 1571 | { |
| 1572 | s->s_fs_info = data; | 1572 | s->s_fs_info = data; |
| 1573 | return set_anon_super(s, data); | 1573 | return set_anon_super(s, data); |
| 1574 | } | 1574 | } |
| 1575 | 1575 | ||
| 1576 | static int nfs_compare_super(struct super_block *sb, void *data) | 1576 | static int nfs_compare_super(struct super_block *sb, void *data) |
| 1577 | { | 1577 | { |
| 1578 | struct nfs_server *server = data; | 1578 | struct nfs_server *server = data; |
| 1579 | struct nfs_server *old = NFS_SB(sb); | 1579 | struct nfs_server *old = NFS_SB(sb); |
| 1580 | 1580 | ||
| 1581 | if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr) | 1581 | if (old->addr.sin_addr.s_addr != server->addr.sin_addr.s_addr) |
| 1582 | return 0; | 1582 | return 0; |
| 1583 | if (old->addr.sin_port != server->addr.sin_port) | 1583 | if (old->addr.sin_port != server->addr.sin_port) |
| 1584 | return 0; | 1584 | return 0; |
| 1585 | return !nfs_compare_fh(&old->fh, &server->fh); | 1585 | return !nfs_compare_fh(&old->fh, &server->fh); |
| 1586 | } | 1586 | } |
| 1587 | 1587 | ||
| 1588 | static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | 1588 | static struct super_block *nfs_get_sb(struct file_system_type *fs_type, |
| 1589 | int flags, const char *dev_name, void *raw_data) | 1589 | int flags, const char *dev_name, void *raw_data) |
| 1590 | { | 1590 | { |
| 1591 | int error; | 1591 | int error; |
| 1592 | struct nfs_server *server = NULL; | 1592 | struct nfs_server *server = NULL; |
| 1593 | struct super_block *s; | 1593 | struct super_block *s; |
| 1594 | struct nfs_fh *root; | 1594 | struct nfs_fh *root; |
| 1595 | struct nfs_mount_data *data = raw_data; | 1595 | struct nfs_mount_data *data = raw_data; |
| 1596 | 1596 | ||
| 1597 | s = ERR_PTR(-EINVAL); | 1597 | s = ERR_PTR(-EINVAL); |
| 1598 | if (data == NULL) { | 1598 | if (data == NULL) { |
| 1599 | dprintk("%s: missing data argument\n", __FUNCTION__); | 1599 | dprintk("%s: missing data argument\n", __FUNCTION__); |
| 1600 | goto out_err; | 1600 | goto out_err; |
| 1601 | } | 1601 | } |
| 1602 | if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { | 1602 | if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { |
| 1603 | dprintk("%s: bad mount version\n", __FUNCTION__); | 1603 | dprintk("%s: bad mount version\n", __FUNCTION__); |
| 1604 | goto out_err; | 1604 | goto out_err; |
| 1605 | } | 1605 | } |
| 1606 | switch (data->version) { | 1606 | switch (data->version) { |
| 1607 | case 1: | 1607 | case 1: |
| 1608 | data->namlen = 0; | 1608 | data->namlen = 0; |
| 1609 | case 2: | 1609 | case 2: |
| 1610 | data->bsize = 0; | 1610 | data->bsize = 0; |
| 1611 | case 3: | 1611 | case 3: |
| 1612 | if (data->flags & NFS_MOUNT_VER3) { | 1612 | if (data->flags & NFS_MOUNT_VER3) { |
| 1613 | dprintk("%s: mount structure version %d does not support NFSv3\n", | 1613 | dprintk("%s: mount structure version %d does not support NFSv3\n", |
| 1614 | __FUNCTION__, | 1614 | __FUNCTION__, |
| 1615 | data->version); | 1615 | data->version); |
| 1616 | goto out_err; | 1616 | goto out_err; |
| 1617 | } | 1617 | } |
| 1618 | data->root.size = NFS2_FHSIZE; | 1618 | data->root.size = NFS2_FHSIZE; |
| 1619 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); | 1619 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); |
| 1620 | case 4: | 1620 | case 4: |
| 1621 | if (data->flags & NFS_MOUNT_SECFLAVOUR) { | 1621 | if (data->flags & NFS_MOUNT_SECFLAVOUR) { |
| 1622 | dprintk("%s: mount structure version %d does not support strong security\n", | 1622 | dprintk("%s: mount structure version %d does not support strong security\n", |
| 1623 | __FUNCTION__, | 1623 | __FUNCTION__, |
| 1624 | data->version); | 1624 | data->version); |
| 1625 | goto out_err; | 1625 | goto out_err; |
| 1626 | } | 1626 | } |
| 1627 | case 5: | 1627 | case 5: |
| 1628 | memset(data->context, 0, sizeof(data->context)); | 1628 | memset(data->context, 0, sizeof(data->context)); |
| 1629 | } | 1629 | } |
| 1630 | #ifndef CONFIG_NFS_V3 | 1630 | #ifndef CONFIG_NFS_V3 |
| 1631 | /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ | 1631 | /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ |
| 1632 | s = ERR_PTR(-EPROTONOSUPPORT); | 1632 | s = ERR_PTR(-EPROTONOSUPPORT); |
| 1633 | if (data->flags & NFS_MOUNT_VER3) { | 1633 | if (data->flags & NFS_MOUNT_VER3) { |
| 1634 | dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); | 1634 | dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); |
| 1635 | goto out_err; | 1635 | goto out_err; |
| 1636 | } | 1636 | } |
| 1637 | #endif /* CONFIG_NFS_V3 */ | 1637 | #endif /* CONFIG_NFS_V3 */ |
| 1638 | 1638 | ||
| 1639 | s = ERR_PTR(-ENOMEM); | 1639 | s = ERR_PTR(-ENOMEM); |
| 1640 | server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); | 1640 | server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); |
| 1641 | if (!server) | 1641 | if (!server) |
| 1642 | goto out_err; | 1642 | goto out_err; |
| 1643 | memset(server, 0, sizeof(struct nfs_server)); | 1643 | memset(server, 0, sizeof(struct nfs_server)); |
| 1644 | /* Zero out the NFS state stuff */ | 1644 | /* Zero out the NFS state stuff */ |
| 1645 | init_nfsv4_state(server); | 1645 | init_nfsv4_state(server); |
| 1646 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | 1646 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); |
| 1647 | 1647 | ||
| 1648 | root = &server->fh; | 1648 | root = &server->fh; |
| 1649 | if (data->flags & NFS_MOUNT_VER3) | 1649 | if (data->flags & NFS_MOUNT_VER3) |
| 1650 | root->size = data->root.size; | 1650 | root->size = data->root.size; |
| 1651 | else | 1651 | else |
| 1652 | root->size = NFS2_FHSIZE; | 1652 | root->size = NFS2_FHSIZE; |
| 1653 | s = ERR_PTR(-EINVAL); | 1653 | s = ERR_PTR(-EINVAL); |
| 1654 | if (root->size > sizeof(root->data)) { | 1654 | if (root->size > sizeof(root->data)) { |
| 1655 | dprintk("%s: invalid root filehandle\n", __FUNCTION__); | 1655 | dprintk("%s: invalid root filehandle\n", __FUNCTION__); |
| 1656 | goto out_err; | 1656 | goto out_err; |
| 1657 | } | 1657 | } |
| 1658 | memcpy(root->data, data->root.data, root->size); | 1658 | memcpy(root->data, data->root.data, root->size); |
| 1659 | 1659 | ||
| 1660 | /* We now require that the mount process passes the remote address */ | 1660 | /* We now require that the mount process passes the remote address */ |
| 1661 | memcpy(&server->addr, &data->addr, sizeof(server->addr)); | 1661 | memcpy(&server->addr, &data->addr, sizeof(server->addr)); |
| 1662 | if (server->addr.sin_addr.s_addr == INADDR_ANY) { | 1662 | if (server->addr.sin_addr.s_addr == INADDR_ANY) { |
| 1663 | dprintk("%s: mount program didn't pass remote address!\n", | 1663 | dprintk("%s: mount program didn't pass remote address!\n", |
| 1664 | __FUNCTION__); | 1664 | __FUNCTION__); |
| 1665 | goto out_err; | 1665 | goto out_err; |
| 1666 | } | 1666 | } |
| 1667 | 1667 | ||
| 1668 | /* Fire up rpciod if not yet running */ | 1668 | /* Fire up rpciod if not yet running */ |
| 1669 | s = ERR_PTR(rpciod_up()); | 1669 | s = ERR_PTR(rpciod_up()); |
| 1670 | if (IS_ERR(s)) { | 1670 | if (IS_ERR(s)) { |
| 1671 | dprintk("%s: couldn't start rpciod! Error = %ld\n", | 1671 | dprintk("%s: couldn't start rpciod! Error = %ld\n", |
| 1672 | __FUNCTION__, PTR_ERR(s)); | 1672 | __FUNCTION__, PTR_ERR(s)); |
| 1673 | goto out_err; | 1673 | goto out_err; |
| 1674 | } | 1674 | } |
| 1675 | 1675 | ||
| 1676 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); | 1676 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); |
| 1677 | if (IS_ERR(s) || s->s_root) | 1677 | if (IS_ERR(s) || s->s_root) |
| 1678 | goto out_rpciod_down; | 1678 | goto out_rpciod_down; |
| 1679 | 1679 | ||
| 1680 | s->s_flags = flags; | 1680 | s->s_flags = flags; |
| 1681 | 1681 | ||
| 1682 | error = nfs_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); | 1682 | error = nfs_fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
| 1683 | if (error) { | 1683 | if (error) { |
| 1684 | up_write(&s->s_umount); | 1684 | up_write(&s->s_umount); |
| 1685 | deactivate_super(s); | 1685 | deactivate_super(s); |
| 1686 | return ERR_PTR(error); | 1686 | return ERR_PTR(error); |
| 1687 | } | 1687 | } |
| 1688 | s->s_flags |= MS_ACTIVE; | 1688 | s->s_flags |= MS_ACTIVE; |
| 1689 | return s; | 1689 | return s; |
| 1690 | out_rpciod_down: | 1690 | out_rpciod_down: |
| 1691 | rpciod_down(); | 1691 | rpciod_down(); |
| 1692 | out_err: | 1692 | out_err: |
| 1693 | kfree(server); | 1693 | kfree(server); |
| 1694 | return s; | 1694 | return s; |
| 1695 | } | 1695 | } |
| 1696 | 1696 | ||
| 1697 | static void nfs_kill_super(struct super_block *s) | 1697 | static void nfs_kill_super(struct super_block *s) |
| 1698 | { | 1698 | { |
| 1699 | struct nfs_server *server = NFS_SB(s); | 1699 | struct nfs_server *server = NFS_SB(s); |
| 1700 | 1700 | ||
| 1701 | kill_anon_super(s); | 1701 | kill_anon_super(s); |
| 1702 | 1702 | ||
| 1703 | if (!IS_ERR(server->client)) | 1703 | if (!IS_ERR(server->client)) |
| 1704 | rpc_shutdown_client(server->client); | 1704 | rpc_shutdown_client(server->client); |
| 1705 | if (!IS_ERR(server->client_sys)) | 1705 | if (!IS_ERR(server->client_sys)) |
| 1706 | rpc_shutdown_client(server->client_sys); | 1706 | rpc_shutdown_client(server->client_sys); |
| 1707 | if (!IS_ERR(server->client_acl)) | 1707 | if (!IS_ERR(server->client_acl)) |
| 1708 | rpc_shutdown_client(server->client_acl); | 1708 | rpc_shutdown_client(server->client_acl); |
| 1709 | 1709 | ||
| 1710 | if (!(server->flags & NFS_MOUNT_NONLM)) | 1710 | if (!(server->flags & NFS_MOUNT_NONLM)) |
| 1711 | lockd_down(); /* release rpc.lockd */ | 1711 | lockd_down(); /* release rpc.lockd */ |
| 1712 | 1712 | ||
| 1713 | rpciod_down(); /* release rpciod */ | 1713 | rpciod_down(); /* release rpciod */ |
| 1714 | 1714 | ||
| 1715 | kfree(server->hostname); | 1715 | kfree(server->hostname); |
| 1716 | kfree(server); | 1716 | kfree(server); |
| 1717 | } | 1717 | } |
| 1718 | 1718 | ||
| 1719 | static struct file_system_type nfs_fs_type = { | 1719 | static struct file_system_type nfs_fs_type = { |
| 1720 | .owner = THIS_MODULE, | 1720 | .owner = THIS_MODULE, |
| 1721 | .name = "nfs", | 1721 | .name = "nfs", |
| 1722 | .get_sb = nfs_get_sb, | 1722 | .get_sb = nfs_get_sb, |
| 1723 | .kill_sb = nfs_kill_super, | 1723 | .kill_sb = nfs_kill_super, |
| 1724 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 1724 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
| 1725 | }; | 1725 | }; |
| 1726 | 1726 | ||
| 1727 | #ifdef CONFIG_NFS_V4 | 1727 | #ifdef CONFIG_NFS_V4 |
| 1728 | 1728 | ||
| 1729 | static void nfs4_clear_inode(struct inode *); | 1729 | static void nfs4_clear_inode(struct inode *); |
| 1730 | 1730 | ||
| 1731 | 1731 | ||
| 1732 | static struct super_operations nfs4_sops = { | 1732 | static struct super_operations nfs4_sops = { |
| 1733 | .alloc_inode = nfs_alloc_inode, | 1733 | .alloc_inode = nfs_alloc_inode, |
| 1734 | .destroy_inode = nfs_destroy_inode, | 1734 | .destroy_inode = nfs_destroy_inode, |
| 1735 | .write_inode = nfs_write_inode, | 1735 | .write_inode = nfs_write_inode, |
| 1736 | .delete_inode = nfs_delete_inode, | 1736 | .delete_inode = nfs_delete_inode, |
| 1737 | .statfs = nfs_statfs, | 1737 | .statfs = nfs_statfs, |
| 1738 | .clear_inode = nfs4_clear_inode, | 1738 | .clear_inode = nfs4_clear_inode, |
| 1739 | .umount_begin = nfs_umount_begin, | 1739 | .umount_begin = nfs_umount_begin, |
| 1740 | .show_options = nfs_show_options, | 1740 | .show_options = nfs_show_options, |
| 1741 | }; | 1741 | }; |
| 1742 | 1742 | ||
| 1743 | /* | 1743 | /* |
| 1744 | * Clean out any remaining NFSv4 state that might be left over due | 1744 | * Clean out any remaining NFSv4 state that might be left over due |
| 1745 | * to open() calls that passed nfs_atomic_lookup, but failed to call | 1745 | * to open() calls that passed nfs_atomic_lookup, but failed to call |
| 1746 | * nfs_open(). | 1746 | * nfs_open(). |
| 1747 | */ | 1747 | */ |
| 1748 | static void nfs4_clear_inode(struct inode *inode) | 1748 | static void nfs4_clear_inode(struct inode *inode) |
| 1749 | { | 1749 | { |
| 1750 | struct nfs_inode *nfsi = NFS_I(inode); | 1750 | struct nfs_inode *nfsi = NFS_I(inode); |
| 1751 | 1751 | ||
| 1752 | /* If we are holding a delegation, return it! */ | 1752 | /* If we are holding a delegation, return it! */ |
| 1753 | nfs_inode_return_delegation(inode); | 1753 | nfs_inode_return_delegation(inode); |
| 1754 | /* First call standard NFS clear_inode() code */ | 1754 | /* First call standard NFS clear_inode() code */ |
| 1755 | nfs_clear_inode(inode); | 1755 | nfs_clear_inode(inode); |
| 1756 | /* Now clear out any remaining state */ | 1756 | /* Now clear out any remaining state */ |
| 1757 | while (!list_empty(&nfsi->open_states)) { | 1757 | while (!list_empty(&nfsi->open_states)) { |
| 1758 | struct nfs4_state *state; | 1758 | struct nfs4_state *state; |
| 1759 | 1759 | ||
| 1760 | state = list_entry(nfsi->open_states.next, | 1760 | state = list_entry(nfsi->open_states.next, |
| 1761 | struct nfs4_state, | 1761 | struct nfs4_state, |
| 1762 | inode_states); | 1762 | inode_states); |
| 1763 | dprintk("%s(%s/%Ld): found unclaimed NFSv4 state %p\n", | 1763 | dprintk("%s(%s/%Ld): found unclaimed NFSv4 state %p\n", |
| 1764 | __FUNCTION__, | 1764 | __FUNCTION__, |
| 1765 | inode->i_sb->s_id, | 1765 | inode->i_sb->s_id, |
| 1766 | (long long)NFS_FILEID(inode), | 1766 | (long long)NFS_FILEID(inode), |
| 1767 | state); | 1767 | state); |
| 1768 | BUG_ON(atomic_read(&state->count) != 1); | 1768 | BUG_ON(atomic_read(&state->count) != 1); |
| 1769 | nfs4_close_state(state, state->state); | 1769 | nfs4_close_state(state, state->state); |
| 1770 | } | 1770 | } |
| 1771 | } | 1771 | } |
| 1772 | 1772 | ||
| 1773 | 1773 | ||
| 1774 | static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent) | 1774 | static int nfs4_fill_super(struct super_block *sb, struct nfs4_mount_data *data, int silent) |
| 1775 | { | 1775 | { |
| 1776 | struct nfs_server *server; | 1776 | struct nfs_server *server; |
| 1777 | struct nfs4_client *clp = NULL; | 1777 | struct nfs4_client *clp = NULL; |
| 1778 | struct rpc_xprt *xprt = NULL; | 1778 | struct rpc_xprt *xprt = NULL; |
| 1779 | struct rpc_clnt *clnt = NULL; | 1779 | struct rpc_clnt *clnt = NULL; |
| 1780 | struct rpc_timeout timeparms; | 1780 | struct rpc_timeout timeparms; |
| 1781 | rpc_authflavor_t authflavour; | 1781 | rpc_authflavor_t authflavour; |
| 1782 | int err = -EIO; | 1782 | int err = -EIO; |
| 1783 | 1783 | ||
| 1784 | sb->s_blocksize_bits = 0; | 1784 | sb->s_blocksize_bits = 0; |
| 1785 | sb->s_blocksize = 0; | 1785 | sb->s_blocksize = 0; |
| 1786 | server = NFS_SB(sb); | 1786 | server = NFS_SB(sb); |
| 1787 | if (data->rsize != 0) | 1787 | if (data->rsize != 0) |
| 1788 | server->rsize = nfs_block_size(data->rsize, NULL); | 1788 | server->rsize = nfs_block_size(data->rsize, NULL); |
| 1789 | if (data->wsize != 0) | 1789 | if (data->wsize != 0) |
| 1790 | server->wsize = nfs_block_size(data->wsize, NULL); | 1790 | server->wsize = nfs_block_size(data->wsize, NULL); |
| 1791 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; | 1791 | server->flags = data->flags & NFS_MOUNT_FLAGMASK; |
| 1792 | server->caps = NFS_CAP_ATOMIC_OPEN; | 1792 | server->caps = NFS_CAP_ATOMIC_OPEN; |
| 1793 | 1793 | ||
| 1794 | server->acregmin = data->acregmin*HZ; | 1794 | server->acregmin = data->acregmin*HZ; |
| 1795 | server->acregmax = data->acregmax*HZ; | 1795 | server->acregmax = data->acregmax*HZ; |
| 1796 | server->acdirmin = data->acdirmin*HZ; | 1796 | server->acdirmin = data->acdirmin*HZ; |
| 1797 | server->acdirmax = data->acdirmax*HZ; | 1797 | server->acdirmax = data->acdirmax*HZ; |
| 1798 | 1798 | ||
| 1799 | server->rpc_ops = &nfs_v4_clientops; | 1799 | server->rpc_ops = &nfs_v4_clientops; |
| 1800 | 1800 | ||
| 1801 | nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans); | 1801 | nfs_init_timeout_values(&timeparms, data->proto, data->timeo, data->retrans); |
| 1802 | 1802 | ||
| 1803 | clp = nfs4_get_client(&server->addr.sin_addr); | 1803 | clp = nfs4_get_client(&server->addr.sin_addr); |
| 1804 | if (!clp) { | 1804 | if (!clp) { |
| 1805 | dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__); | 1805 | dprintk("%s: failed to create NFS4 client.\n", __FUNCTION__); |
| 1806 | return -EIO; | 1806 | return -EIO; |
| 1807 | } | 1807 | } |
| 1808 | 1808 | ||
| 1809 | /* Now create transport and client */ | 1809 | /* Now create transport and client */ |
| 1810 | authflavour = RPC_AUTH_UNIX; | 1810 | authflavour = RPC_AUTH_UNIX; |
| 1811 | if (data->auth_flavourlen != 0) { | 1811 | if (data->auth_flavourlen != 0) { |
| 1812 | if (data->auth_flavourlen != 1) { | 1812 | if (data->auth_flavourlen != 1) { |
| 1813 | dprintk("%s: Invalid number of RPC auth flavours %d.\n", | 1813 | dprintk("%s: Invalid number of RPC auth flavours %d.\n", |
| 1814 | __FUNCTION__, data->auth_flavourlen); | 1814 | __FUNCTION__, data->auth_flavourlen); |
| 1815 | err = -EINVAL; | 1815 | err = -EINVAL; |
| 1816 | goto out_fail; | 1816 | goto out_fail; |
| 1817 | } | 1817 | } |
| 1818 | if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { | 1818 | if (copy_from_user(&authflavour, data->auth_flavours, sizeof(authflavour))) { |
| 1819 | err = -EFAULT; | 1819 | err = -EFAULT; |
| 1820 | goto out_fail; | 1820 | goto out_fail; |
| 1821 | } | 1821 | } |
| 1822 | } | 1822 | } |
| 1823 | 1823 | ||
| 1824 | down_write(&clp->cl_sem); | 1824 | down_write(&clp->cl_sem); |
| 1825 | if (IS_ERR(clp->cl_rpcclient)) { | 1825 | if (IS_ERR(clp->cl_rpcclient)) { |
| 1826 | xprt = xprt_create_proto(data->proto, &server->addr, &timeparms); | 1826 | xprt = xprt_create_proto(data->proto, &server->addr, &timeparms); |
| 1827 | if (IS_ERR(xprt)) { | 1827 | if (IS_ERR(xprt)) { |
| 1828 | up_write(&clp->cl_sem); | 1828 | up_write(&clp->cl_sem); |
| 1829 | err = PTR_ERR(xprt); | 1829 | err = PTR_ERR(xprt); |
| 1830 | dprintk("%s: cannot create RPC transport. Error = %d\n", | 1830 | dprintk("%s: cannot create RPC transport. Error = %d\n", |
| 1831 | __FUNCTION__, err); | 1831 | __FUNCTION__, err); |
| 1832 | goto out_fail; | 1832 | goto out_fail; |
| 1833 | } | 1833 | } |
| 1834 | clnt = rpc_create_client(xprt, server->hostname, &nfs_program, | 1834 | clnt = rpc_create_client(xprt, server->hostname, &nfs_program, |
| 1835 | server->rpc_ops->version, authflavour); | 1835 | server->rpc_ops->version, authflavour); |
| 1836 | if (IS_ERR(clnt)) { | 1836 | if (IS_ERR(clnt)) { |
| 1837 | up_write(&clp->cl_sem); | 1837 | up_write(&clp->cl_sem); |
| 1838 | err = PTR_ERR(clnt); | 1838 | err = PTR_ERR(clnt); |
| 1839 | dprintk("%s: cannot create RPC client. Error = %d\n", | 1839 | dprintk("%s: cannot create RPC client. Error = %d\n", |
| 1840 | __FUNCTION__, err); | 1840 | __FUNCTION__, err); |
| 1841 | goto out_fail; | 1841 | goto out_fail; |
| 1842 | } | 1842 | } |
| 1843 | clnt->cl_intr = 1; | 1843 | clnt->cl_intr = 1; |
| 1844 | clnt->cl_softrtry = 1; | 1844 | clnt->cl_softrtry = 1; |
| 1845 | clp->cl_rpcclient = clnt; | 1845 | clp->cl_rpcclient = clnt; |
| 1846 | memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr)); | 1846 | memcpy(clp->cl_ipaddr, server->ip_addr, sizeof(clp->cl_ipaddr)); |
| 1847 | nfs_idmap_new(clp); | 1847 | nfs_idmap_new(clp); |
| 1848 | } | 1848 | } |
| 1849 | list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); | 1849 | list_add_tail(&server->nfs4_siblings, &clp->cl_superblocks); |
| 1850 | clnt = rpc_clone_client(clp->cl_rpcclient); | 1850 | clnt = rpc_clone_client(clp->cl_rpcclient); |
| 1851 | if (!IS_ERR(clnt)) | 1851 | if (!IS_ERR(clnt)) |
| 1852 | server->nfs4_state = clp; | 1852 | server->nfs4_state = clp; |
| 1853 | up_write(&clp->cl_sem); | 1853 | up_write(&clp->cl_sem); |
| 1854 | clp = NULL; | 1854 | clp = NULL; |
| 1855 | 1855 | ||
| 1856 | if (IS_ERR(clnt)) { | 1856 | if (IS_ERR(clnt)) { |
| 1857 | err = PTR_ERR(clnt); | 1857 | err = PTR_ERR(clnt); |
| 1858 | dprintk("%s: cannot create RPC client. Error = %d\n", | 1858 | dprintk("%s: cannot create RPC client. Error = %d\n", |
| 1859 | __FUNCTION__, err); | 1859 | __FUNCTION__, err); |
| 1860 | return err; | 1860 | return err; |
| 1861 | } | 1861 | } |
| 1862 | 1862 | ||
| 1863 | server->client = clnt; | 1863 | server->client = clnt; |
| 1864 | 1864 | ||
| 1865 | if (server->nfs4_state->cl_idmap == NULL) { | 1865 | if (server->nfs4_state->cl_idmap == NULL) { |
| 1866 | dprintk("%s: failed to create idmapper.\n", __FUNCTION__); | 1866 | dprintk("%s: failed to create idmapper.\n", __FUNCTION__); |
| 1867 | return -ENOMEM; | 1867 | return -ENOMEM; |
| 1868 | } | 1868 | } |
| 1869 | 1869 | ||
| 1870 | if (clnt->cl_auth->au_flavor != authflavour) { | 1870 | if (clnt->cl_auth->au_flavor != authflavour) { |
| 1871 | struct rpc_auth *auth; | 1871 | struct rpc_auth *auth; |
| 1872 | 1872 | ||
| 1873 | auth = rpcauth_create(authflavour, clnt); | 1873 | auth = rpcauth_create(authflavour, clnt); |
| 1874 | if (IS_ERR(auth)) { | 1874 | if (IS_ERR(auth)) { |
| 1875 | dprintk("%s: couldn't create credcache!\n", __FUNCTION__); | 1875 | dprintk("%s: couldn't create credcache!\n", __FUNCTION__); |
| 1876 | return PTR_ERR(auth); | 1876 | return PTR_ERR(auth); |
| 1877 | } | 1877 | } |
| 1878 | } | 1878 | } |
| 1879 | 1879 | ||
| 1880 | sb->s_time_gran = 1; | 1880 | sb->s_time_gran = 1; |
| 1881 | 1881 | ||
| 1882 | sb->s_op = &nfs4_sops; | 1882 | sb->s_op = &nfs4_sops; |
| 1883 | err = nfs_sb_init(sb, authflavour); | 1883 | err = nfs_sb_init(sb, authflavour); |
| 1884 | if (err == 0) | 1884 | if (err == 0) |
| 1885 | return 0; | 1885 | return 0; |
| 1886 | out_fail: | 1886 | out_fail: |
| 1887 | if (clp) | 1887 | if (clp) |
| 1888 | nfs4_put_client(clp); | 1888 | nfs4_put_client(clp); |
| 1889 | return err; | 1889 | return err; |
| 1890 | } | 1890 | } |
| 1891 | 1891 | ||
| 1892 | static int nfs4_compare_super(struct super_block *sb, void *data) | 1892 | static int nfs4_compare_super(struct super_block *sb, void *data) |
| 1893 | { | 1893 | { |
| 1894 | struct nfs_server *server = data; | 1894 | struct nfs_server *server = data; |
| 1895 | struct nfs_server *old = NFS_SB(sb); | 1895 | struct nfs_server *old = NFS_SB(sb); |
| 1896 | 1896 | ||
| 1897 | if (strcmp(server->hostname, old->hostname) != 0) | 1897 | if (strcmp(server->hostname, old->hostname) != 0) |
| 1898 | return 0; | 1898 | return 0; |
| 1899 | if (strcmp(server->mnt_path, old->mnt_path) != 0) | 1899 | if (strcmp(server->mnt_path, old->mnt_path) != 0) |
| 1900 | return 0; | 1900 | return 0; |
| 1901 | return 1; | 1901 | return 1; |
| 1902 | } | 1902 | } |
| 1903 | 1903 | ||
| 1904 | static void * | 1904 | static void * |
| 1905 | nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) | 1905 | nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) |
| 1906 | { | 1906 | { |
| 1907 | void *p = NULL; | 1907 | void *p = NULL; |
| 1908 | 1908 | ||
| 1909 | if (!src->len) | 1909 | if (!src->len) |
| 1910 | return ERR_PTR(-EINVAL); | 1910 | return ERR_PTR(-EINVAL); |
| 1911 | if (src->len < maxlen) | 1911 | if (src->len < maxlen) |
| 1912 | maxlen = src->len; | 1912 | maxlen = src->len; |
| 1913 | if (dst == NULL) { | 1913 | if (dst == NULL) { |
| 1914 | p = dst = kmalloc(maxlen + 1, GFP_KERNEL); | 1914 | p = dst = kmalloc(maxlen + 1, GFP_KERNEL); |
| 1915 | if (p == NULL) | 1915 | if (p == NULL) |
| 1916 | return ERR_PTR(-ENOMEM); | 1916 | return ERR_PTR(-ENOMEM); |
| 1917 | } | 1917 | } |
| 1918 | if (copy_from_user(dst, src->data, maxlen)) { | 1918 | if (copy_from_user(dst, src->data, maxlen)) { |
| 1919 | kfree(p); | 1919 | kfree(p); |
| 1920 | return ERR_PTR(-EFAULT); | 1920 | return ERR_PTR(-EFAULT); |
| 1921 | } | 1921 | } |
| 1922 | dst[maxlen] = '\0'; | 1922 | dst[maxlen] = '\0'; |
| 1923 | return dst; | 1923 | return dst; |
| 1924 | } | 1924 | } |
| 1925 | 1925 | ||
| 1926 | static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | 1926 | static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, |
| 1927 | int flags, const char *dev_name, void *raw_data) | 1927 | int flags, const char *dev_name, void *raw_data) |
| 1928 | { | 1928 | { |
| 1929 | int error; | 1929 | int error; |
| 1930 | struct nfs_server *server; | 1930 | struct nfs_server *server; |
| 1931 | struct super_block *s; | 1931 | struct super_block *s; |
| 1932 | struct nfs4_mount_data *data = raw_data; | 1932 | struct nfs4_mount_data *data = raw_data; |
| 1933 | void *p; | 1933 | void *p; |
| 1934 | 1934 | ||
| 1935 | if (data == NULL) { | 1935 | if (data == NULL) { |
| 1936 | dprintk("%s: missing data argument\n", __FUNCTION__); | 1936 | dprintk("%s: missing data argument\n", __FUNCTION__); |
| 1937 | return ERR_PTR(-EINVAL); | 1937 | return ERR_PTR(-EINVAL); |
| 1938 | } | 1938 | } |
| 1939 | if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { | 1939 | if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { |
| 1940 | dprintk("%s: bad mount version\n", __FUNCTION__); | 1940 | dprintk("%s: bad mount version\n", __FUNCTION__); |
| 1941 | return ERR_PTR(-EINVAL); | 1941 | return ERR_PTR(-EINVAL); |
| 1942 | } | 1942 | } |
| 1943 | 1943 | ||
| 1944 | server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); | 1944 | server = kmalloc(sizeof(struct nfs_server), GFP_KERNEL); |
| 1945 | if (!server) | 1945 | if (!server) |
| 1946 | return ERR_PTR(-ENOMEM); | 1946 | return ERR_PTR(-ENOMEM); |
| 1947 | memset(server, 0, sizeof(struct nfs_server)); | 1947 | memset(server, 0, sizeof(struct nfs_server)); |
| 1948 | /* Zero out the NFS state stuff */ | 1948 | /* Zero out the NFS state stuff */ |
| 1949 | init_nfsv4_state(server); | 1949 | init_nfsv4_state(server); |
| 1950 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | 1950 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); |
| 1951 | 1951 | ||
| 1952 | p = nfs_copy_user_string(NULL, &data->hostname, 256); | 1952 | p = nfs_copy_user_string(NULL, &data->hostname, 256); |
| 1953 | if (IS_ERR(p)) | 1953 | if (IS_ERR(p)) |
| 1954 | goto out_err; | 1954 | goto out_err; |
| 1955 | server->hostname = p; | 1955 | server->hostname = p; |
| 1956 | 1956 | ||
| 1957 | p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); | 1957 | p = nfs_copy_user_string(NULL, &data->mnt_path, 1024); |
| 1958 | if (IS_ERR(p)) | 1958 | if (IS_ERR(p)) |
| 1959 | goto out_err; | 1959 | goto out_err; |
| 1960 | server->mnt_path = p; | 1960 | server->mnt_path = p; |
| 1961 | 1961 | ||
| 1962 | p = nfs_copy_user_string(server->ip_addr, &data->client_addr, | 1962 | p = nfs_copy_user_string(server->ip_addr, &data->client_addr, |
| 1963 | sizeof(server->ip_addr) - 1); | 1963 | sizeof(server->ip_addr) - 1); |
| 1964 | if (IS_ERR(p)) | 1964 | if (IS_ERR(p)) |
| 1965 | goto out_err; | 1965 | goto out_err; |
| 1966 | 1966 | ||
| 1967 | /* We now require that the mount process passes the remote address */ | 1967 | /* We now require that the mount process passes the remote address */ |
| 1968 | if (data->host_addrlen != sizeof(server->addr)) { | 1968 | if (data->host_addrlen != sizeof(server->addr)) { |
| 1969 | s = ERR_PTR(-EINVAL); | 1969 | s = ERR_PTR(-EINVAL); |
| 1970 | goto out_free; | 1970 | goto out_free; |
| 1971 | } | 1971 | } |
| 1972 | if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { | 1972 | if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { |
| 1973 | s = ERR_PTR(-EFAULT); | 1973 | s = ERR_PTR(-EFAULT); |
| 1974 | goto out_free; | 1974 | goto out_free; |
| 1975 | } | 1975 | } |
| 1976 | if (server->addr.sin_family != AF_INET || | 1976 | if (server->addr.sin_family != AF_INET || |
| 1977 | server->addr.sin_addr.s_addr == INADDR_ANY) { | 1977 | server->addr.sin_addr.s_addr == INADDR_ANY) { |
| 1978 | dprintk("%s: mount program didn't pass remote IP address!\n", | 1978 | dprintk("%s: mount program didn't pass remote IP address!\n", |
| 1979 | __FUNCTION__); | 1979 | __FUNCTION__); |
| 1980 | s = ERR_PTR(-EINVAL); | 1980 | s = ERR_PTR(-EINVAL); |
| 1981 | goto out_free; | 1981 | goto out_free; |
| 1982 | } | 1982 | } |
| 1983 | 1983 | ||
| 1984 | /* Fire up rpciod if not yet running */ | 1984 | /* Fire up rpciod if not yet running */ |
| 1985 | s = ERR_PTR(rpciod_up()); | 1985 | s = ERR_PTR(rpciod_up()); |
| 1986 | if (IS_ERR(s)) { | 1986 | if (IS_ERR(s)) { |
| 1987 | dprintk("%s: couldn't start rpciod! Error = %ld\n", | 1987 | dprintk("%s: couldn't start rpciod! Error = %ld\n", |
| 1988 | __FUNCTION__, PTR_ERR(s)); | 1988 | __FUNCTION__, PTR_ERR(s)); |
| 1989 | goto out_free; | 1989 | goto out_free; |
| 1990 | } | 1990 | } |
| 1991 | 1991 | ||
| 1992 | s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); | 1992 | s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); |
| 1993 | 1993 | ||
| 1994 | if (IS_ERR(s) || s->s_root) | 1994 | if (IS_ERR(s) || s->s_root) |
| 1995 | goto out_free; | 1995 | goto out_free; |
| 1996 | 1996 | ||
| 1997 | s->s_flags = flags; | 1997 | s->s_flags = flags; |
| 1998 | 1998 | ||
| 1999 | error = nfs4_fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); | 1999 | error = nfs4_fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
| 2000 | if (error) { | 2000 | if (error) { |
| 2001 | up_write(&s->s_umount); | 2001 | up_write(&s->s_umount); |
| 2002 | deactivate_super(s); | 2002 | deactivate_super(s); |
| 2003 | return ERR_PTR(error); | 2003 | return ERR_PTR(error); |
| 2004 | } | 2004 | } |
| 2005 | s->s_flags |= MS_ACTIVE; | 2005 | s->s_flags |= MS_ACTIVE; |
| 2006 | return s; | 2006 | return s; |
| 2007 | out_err: | 2007 | out_err: |
| 2008 | s = (struct super_block *)p; | 2008 | s = (struct super_block *)p; |
| 2009 | out_free: | 2009 | out_free: |
| 2010 | kfree(server->mnt_path); | 2010 | kfree(server->mnt_path); |
| 2011 | kfree(server->hostname); | 2011 | kfree(server->hostname); |
| 2012 | kfree(server); | 2012 | kfree(server); |
| 2013 | return s; | 2013 | return s; |
| 2014 | } | 2014 | } |
| 2015 | 2015 | ||
| 2016 | static void nfs4_kill_super(struct super_block *sb) | 2016 | static void nfs4_kill_super(struct super_block *sb) |
| 2017 | { | 2017 | { |
| 2018 | struct nfs_server *server = NFS_SB(sb); | 2018 | struct nfs_server *server = NFS_SB(sb); |
| 2019 | 2019 | ||
| 2020 | nfs_return_all_delegations(sb); | 2020 | nfs_return_all_delegations(sb); |
| 2021 | kill_anon_super(sb); | 2021 | kill_anon_super(sb); |
| 2022 | 2022 | ||
| 2023 | nfs4_renewd_prepare_shutdown(server); | 2023 | nfs4_renewd_prepare_shutdown(server); |
| 2024 | 2024 | ||
| 2025 | if (server->client != NULL && !IS_ERR(server->client)) | 2025 | if (server->client != NULL && !IS_ERR(server->client)) |
| 2026 | rpc_shutdown_client(server->client); | 2026 | rpc_shutdown_client(server->client); |
| 2027 | rpciod_down(); /* release rpciod */ | 2027 | rpciod_down(); /* release rpciod */ |
| 2028 | 2028 | ||
| 2029 | destroy_nfsv4_state(server); | 2029 | destroy_nfsv4_state(server); |
| 2030 | 2030 | ||
| 2031 | kfree(server->hostname); | 2031 | kfree(server->hostname); |
| 2032 | kfree(server); | 2032 | kfree(server); |
| 2033 | } | 2033 | } |
| 2034 | 2034 | ||
| 2035 | static struct file_system_type nfs4_fs_type = { | 2035 | static struct file_system_type nfs4_fs_type = { |
| 2036 | .owner = THIS_MODULE, | 2036 | .owner = THIS_MODULE, |
| 2037 | .name = "nfs4", | 2037 | .name = "nfs4", |
| 2038 | .get_sb = nfs4_get_sb, | 2038 | .get_sb = nfs4_get_sb, |
| 2039 | .kill_sb = nfs4_kill_super, | 2039 | .kill_sb = nfs4_kill_super, |
| 2040 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, | 2040 | .fs_flags = FS_ODD_RENAME|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, |
| 2041 | }; | 2041 | }; |
| 2042 | 2042 | ||
| 2043 | static const int nfs_set_port_min = 0; | 2043 | static const int nfs_set_port_min = 0; |
| 2044 | static const int nfs_set_port_max = 65535; | 2044 | static const int nfs_set_port_max = 65535; |
| 2045 | static int param_set_port(const char *val, struct kernel_param *kp) | 2045 | static int param_set_port(const char *val, struct kernel_param *kp) |
| 2046 | { | 2046 | { |
| 2047 | char *endp; | 2047 | char *endp; |
| 2048 | int num = simple_strtol(val, &endp, 0); | 2048 | int num = simple_strtol(val, &endp, 0); |
| 2049 | if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max) | 2049 | if (endp == val || *endp || num < nfs_set_port_min || num > nfs_set_port_max) |
| 2050 | return -EINVAL; | 2050 | return -EINVAL; |
| 2051 | *((int *)kp->arg) = num; | 2051 | *((int *)kp->arg) = num; |
| 2052 | return 0; | 2052 | return 0; |
| 2053 | } | 2053 | } |
| 2054 | 2054 | ||
| 2055 | module_param_call(callback_tcpport, param_set_port, param_get_int, | 2055 | module_param_call(callback_tcpport, param_set_port, param_get_int, |
| 2056 | &nfs_callback_set_tcpport, 0644); | 2056 | &nfs_callback_set_tcpport, 0644); |
| 2057 | 2057 | ||
| 2058 | static int param_set_idmap_timeout(const char *val, struct kernel_param *kp) | 2058 | static int param_set_idmap_timeout(const char *val, struct kernel_param *kp) |
| 2059 | { | 2059 | { |
| 2060 | char *endp; | 2060 | char *endp; |
| 2061 | int num = simple_strtol(val, &endp, 0); | 2061 | int num = simple_strtol(val, &endp, 0); |
| 2062 | int jif = num * HZ; | 2062 | int jif = num * HZ; |
| 2063 | if (endp == val || *endp || num < 0 || jif < num) | 2063 | if (endp == val || *endp || num < 0 || jif < num) |
| 2064 | return -EINVAL; | 2064 | return -EINVAL; |
| 2065 | *((int *)kp->arg) = jif; | 2065 | *((int *)kp->arg) = jif; |
| 2066 | return 0; | 2066 | return 0; |
| 2067 | } | 2067 | } |
| 2068 | 2068 | ||
| 2069 | module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, | 2069 | module_param_call(idmap_cache_timeout, param_set_idmap_timeout, param_get_int, |
| 2070 | &nfs_idmap_cache_timeout, 0644); | 2070 | &nfs_idmap_cache_timeout, 0644); |
| 2071 | 2071 | ||
| 2072 | #define nfs4_init_once(nfsi) \ | 2072 | #define nfs4_init_once(nfsi) \ |
| 2073 | do { \ | 2073 | do { \ |
| 2074 | INIT_LIST_HEAD(&(nfsi)->open_states); \ | 2074 | INIT_LIST_HEAD(&(nfsi)->open_states); \ |
| 2075 | nfsi->delegation = NULL; \ | 2075 | nfsi->delegation = NULL; \ |
| 2076 | nfsi->delegation_state = 0; \ | 2076 | nfsi->delegation_state = 0; \ |
| 2077 | init_rwsem(&nfsi->rwsem); \ | 2077 | init_rwsem(&nfsi->rwsem); \ |
| 2078 | } while(0) | 2078 | } while(0) |
| 2079 | 2079 | ||
| 2080 | static inline int register_nfs4fs(void) | 2080 | static inline int register_nfs4fs(void) |
| 2081 | { | 2081 | { |
| 2082 | int ret; | 2082 | int ret; |
| 2083 | 2083 | ||
| 2084 | ret = nfs_register_sysctl(); | 2084 | ret = nfs_register_sysctl(); |
| 2085 | if (ret != 0) | 2085 | if (ret != 0) |
| 2086 | return ret; | 2086 | return ret; |
| 2087 | ret = register_filesystem(&nfs4_fs_type); | 2087 | ret = register_filesystem(&nfs4_fs_type); |
| 2088 | if (ret != 0) | 2088 | if (ret != 0) |
| 2089 | nfs_unregister_sysctl(); | 2089 | nfs_unregister_sysctl(); |
| 2090 | return ret; | 2090 | return ret; |
| 2091 | } | 2091 | } |
| 2092 | 2092 | ||
| 2093 | static inline void unregister_nfs4fs(void) | 2093 | static inline void unregister_nfs4fs(void) |
| 2094 | { | 2094 | { |
| 2095 | unregister_filesystem(&nfs4_fs_type); | 2095 | unregister_filesystem(&nfs4_fs_type); |
| 2096 | nfs_unregister_sysctl(); | 2096 | nfs_unregister_sysctl(); |
| 2097 | } | 2097 | } |
| 2098 | #else | 2098 | #else |
| 2099 | #define nfs4_init_once(nfsi) \ | 2099 | #define nfs4_init_once(nfsi) \ |
| 2100 | do { } while (0) | 2100 | do { } while (0) |
| 2101 | #define register_nfs4fs() (0) | 2101 | #define register_nfs4fs() (0) |
| 2102 | #define unregister_nfs4fs() | 2102 | #define unregister_nfs4fs() |
| 2103 | #endif | 2103 | #endif |
| 2104 | 2104 | ||
| 2105 | extern int nfs_init_nfspagecache(void); | 2105 | extern int nfs_init_nfspagecache(void); |
| 2106 | extern void nfs_destroy_nfspagecache(void); | 2106 | extern void nfs_destroy_nfspagecache(void); |
| 2107 | extern int nfs_init_readpagecache(void); | 2107 | extern int nfs_init_readpagecache(void); |
| 2108 | extern void nfs_destroy_readpagecache(void); | 2108 | extern void nfs_destroy_readpagecache(void); |
| 2109 | extern int nfs_init_writepagecache(void); | 2109 | extern int nfs_init_writepagecache(void); |
| 2110 | extern void nfs_destroy_writepagecache(void); | 2110 | extern void nfs_destroy_writepagecache(void); |
| 2111 | #ifdef CONFIG_NFS_DIRECTIO | 2111 | #ifdef CONFIG_NFS_DIRECTIO |
| 2112 | extern int nfs_init_directcache(void); | 2112 | extern int nfs_init_directcache(void); |
| 2113 | extern void nfs_destroy_directcache(void); | 2113 | extern void nfs_destroy_directcache(void); |
| 2114 | #endif | 2114 | #endif |
| 2115 | 2115 | ||
| 2116 | static kmem_cache_t * nfs_inode_cachep; | 2116 | static kmem_cache_t * nfs_inode_cachep; |
| 2117 | 2117 | ||
| 2118 | static struct inode *nfs_alloc_inode(struct super_block *sb) | 2118 | static struct inode *nfs_alloc_inode(struct super_block *sb) |
| 2119 | { | 2119 | { |
| 2120 | struct nfs_inode *nfsi; | 2120 | struct nfs_inode *nfsi; |
| 2121 | nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL); | 2121 | nfsi = (struct nfs_inode *)kmem_cache_alloc(nfs_inode_cachep, SLAB_KERNEL); |
| 2122 | if (!nfsi) | 2122 | if (!nfsi) |
| 2123 | return NULL; | 2123 | return NULL; |
| 2124 | nfsi->flags = 0UL; | 2124 | nfsi->flags = 0UL; |
| 2125 | nfsi->cache_validity = 0UL; | 2125 | nfsi->cache_validity = 0UL; |
| 2126 | nfsi->cache_change_attribute = jiffies; | 2126 | nfsi->cache_change_attribute = jiffies; |
| 2127 | #ifdef CONFIG_NFS_V3_ACL | 2127 | #ifdef CONFIG_NFS_V3_ACL |
| 2128 | nfsi->acl_access = ERR_PTR(-EAGAIN); | 2128 | nfsi->acl_access = ERR_PTR(-EAGAIN); |
| 2129 | nfsi->acl_default = ERR_PTR(-EAGAIN); | 2129 | nfsi->acl_default = ERR_PTR(-EAGAIN); |
| 2130 | #endif | 2130 | #endif |
| 2131 | #ifdef CONFIG_NFS_V4 | 2131 | #ifdef CONFIG_NFS_V4 |
| 2132 | nfsi->nfs4_acl = NULL; | 2132 | nfsi->nfs4_acl = NULL; |
| 2133 | #endif /* CONFIG_NFS_V4 */ | 2133 | #endif /* CONFIG_NFS_V4 */ |
| 2134 | return &nfsi->vfs_inode; | 2134 | return &nfsi->vfs_inode; |
| 2135 | } | 2135 | } |
| 2136 | 2136 | ||
| 2137 | static void nfs_destroy_inode(struct inode *inode) | 2137 | static void nfs_destroy_inode(struct inode *inode) |
| 2138 | { | 2138 | { |
| 2139 | kmem_cache_free(nfs_inode_cachep, NFS_I(inode)); | 2139 | kmem_cache_free(nfs_inode_cachep, NFS_I(inode)); |
| 2140 | } | 2140 | } |
| 2141 | 2141 | ||
| 2142 | static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) | 2142 | static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) |
| 2143 | { | 2143 | { |
| 2144 | struct nfs_inode *nfsi = (struct nfs_inode *) foo; | 2144 | struct nfs_inode *nfsi = (struct nfs_inode *) foo; |
| 2145 | 2145 | ||
| 2146 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | 2146 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == |
| 2147 | SLAB_CTOR_CONSTRUCTOR) { | 2147 | SLAB_CTOR_CONSTRUCTOR) { |
| 2148 | inode_init_once(&nfsi->vfs_inode); | 2148 | inode_init_once(&nfsi->vfs_inode); |
| 2149 | spin_lock_init(&nfsi->req_lock); | 2149 | spin_lock_init(&nfsi->req_lock); |
| 2150 | INIT_LIST_HEAD(&nfsi->dirty); | 2150 | INIT_LIST_HEAD(&nfsi->dirty); |
| 2151 | INIT_LIST_HEAD(&nfsi->commit); | 2151 | INIT_LIST_HEAD(&nfsi->commit); |
| 2152 | INIT_LIST_HEAD(&nfsi->open_files); | 2152 | INIT_LIST_HEAD(&nfsi->open_files); |
| 2153 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); | 2153 | INIT_RADIX_TREE(&nfsi->nfs_page_tree, GFP_ATOMIC); |
| 2154 | atomic_set(&nfsi->data_updates, 0); | 2154 | atomic_set(&nfsi->data_updates, 0); |
| 2155 | nfsi->ndirty = 0; | 2155 | nfsi->ndirty = 0; |
| 2156 | nfsi->ncommit = 0; | 2156 | nfsi->ncommit = 0; |
| 2157 | nfsi->npages = 0; | 2157 | nfsi->npages = 0; |
| 2158 | nfs4_init_once(nfsi); | 2158 | nfs4_init_once(nfsi); |
| 2159 | } | 2159 | } |
| 2160 | } | 2160 | } |
| 2161 | 2161 | ||
| 2162 | static int nfs_init_inodecache(void) | 2162 | static int nfs_init_inodecache(void) |
| 2163 | { | 2163 | { |
| 2164 | nfs_inode_cachep = kmem_cache_create("nfs_inode_cache", | 2164 | nfs_inode_cachep = kmem_cache_create("nfs_inode_cache", |
| 2165 | sizeof(struct nfs_inode), | 2165 | sizeof(struct nfs_inode), |
| 2166 | 0, SLAB_RECLAIM_ACCOUNT, | 2166 | 0, SLAB_RECLAIM_ACCOUNT, |
| 2167 | init_once, NULL); | 2167 | init_once, NULL); |
| 2168 | if (nfs_inode_cachep == NULL) | 2168 | if (nfs_inode_cachep == NULL) |
| 2169 | return -ENOMEM; | 2169 | return -ENOMEM; |
| 2170 | 2170 | ||
| 2171 | return 0; | 2171 | return 0; |
| 2172 | } | 2172 | } |
| 2173 | 2173 | ||
| 2174 | static void nfs_destroy_inodecache(void) | 2174 | static void nfs_destroy_inodecache(void) |
| 2175 | { | 2175 | { |
| 2176 | if (kmem_cache_destroy(nfs_inode_cachep)) | 2176 | if (kmem_cache_destroy(nfs_inode_cachep)) |
| 2177 | printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n"); | 2177 | printk(KERN_INFO "nfs_inode_cache: not all structures were freed\n"); |
| 2178 | } | 2178 | } |
| 2179 | 2179 | ||
| 2180 | /* | 2180 | /* |
| 2181 | * Initialize NFS | 2181 | * Initialize NFS |
| 2182 | */ | 2182 | */ |
| 2183 | static int __init init_nfs_fs(void) | 2183 | static int __init init_nfs_fs(void) |
| 2184 | { | 2184 | { |
| 2185 | int err; | 2185 | int err; |
| 2186 | 2186 | ||
| 2187 | err = nfs_init_nfspagecache(); | 2187 | err = nfs_init_nfspagecache(); |
| 2188 | if (err) | 2188 | if (err) |
| 2189 | goto out4; | 2189 | goto out4; |
| 2190 | 2190 | ||
| 2191 | err = nfs_init_inodecache(); | 2191 | err = nfs_init_inodecache(); |
| 2192 | if (err) | 2192 | if (err) |
| 2193 | goto out3; | 2193 | goto out3; |
| 2194 | 2194 | ||
| 2195 | err = nfs_init_readpagecache(); | 2195 | err = nfs_init_readpagecache(); |
| 2196 | if (err) | 2196 | if (err) |
| 2197 | goto out2; | 2197 | goto out2; |
| 2198 | 2198 | ||
| 2199 | err = nfs_init_writepagecache(); | 2199 | err = nfs_init_writepagecache(); |
| 2200 | if (err) | 2200 | if (err) |
| 2201 | goto out1; | 2201 | goto out1; |
| 2202 | 2202 | ||
| 2203 | #ifdef CONFIG_NFS_DIRECTIO | 2203 | #ifdef CONFIG_NFS_DIRECTIO |
| 2204 | err = nfs_init_directcache(); | 2204 | err = nfs_init_directcache(); |
| 2205 | if (err) | 2205 | if (err) |
| 2206 | goto out0; | 2206 | goto out0; |
| 2207 | #endif | 2207 | #endif |
| 2208 | 2208 | ||
| 2209 | #ifdef CONFIG_PROC_FS | 2209 | #ifdef CONFIG_PROC_FS |
| 2210 | rpc_proc_register(&nfs_rpcstat); | 2210 | rpc_proc_register(&nfs_rpcstat); |
| 2211 | #endif | 2211 | #endif |
| 2212 | err = register_filesystem(&nfs_fs_type); | 2212 | err = register_filesystem(&nfs_fs_type); |
| 2213 | if (err) | 2213 | if (err) |
| 2214 | goto out; | 2214 | goto out; |
| 2215 | if ((err = register_nfs4fs()) != 0) | 2215 | if ((err = register_nfs4fs()) != 0) |
| 2216 | goto out; | 2216 | goto out; |
| 2217 | return 0; | 2217 | return 0; |
| 2218 | out: | 2218 | out: |
| 2219 | #ifdef CONFIG_PROC_FS | 2219 | #ifdef CONFIG_PROC_FS |
| 2220 | rpc_proc_unregister("nfs"); | 2220 | rpc_proc_unregister("nfs"); |
| 2221 | #endif | 2221 | #endif |
| 2222 | #ifdef CONFIG_NFS_DIRECTIO | 2222 | #ifdef CONFIG_NFS_DIRECTIO |
| 2223 | nfs_destroy_directcache(); | 2223 | nfs_destroy_directcache(); |
| 2224 | out0: | 2224 | out0: |
| 2225 | #endif | 2225 | #endif |
| 2226 | nfs_destroy_writepagecache(); | 2226 | nfs_destroy_writepagecache(); |
| 2227 | out1: | 2227 | out1: |
| 2228 | nfs_destroy_readpagecache(); | 2228 | nfs_destroy_readpagecache(); |
| 2229 | out2: | 2229 | out2: |
| 2230 | nfs_destroy_inodecache(); | 2230 | nfs_destroy_inodecache(); |
| 2231 | out3: | 2231 | out3: |
| 2232 | nfs_destroy_nfspagecache(); | 2232 | nfs_destroy_nfspagecache(); |
| 2233 | out4: | 2233 | out4: |
| 2234 | return err; | 2234 | return err; |
| 2235 | } | 2235 | } |
| 2236 | 2236 | ||
| 2237 | static void __exit exit_nfs_fs(void) | 2237 | static void __exit exit_nfs_fs(void) |
| 2238 | { | 2238 | { |
| 2239 | #ifdef CONFIG_NFS_DIRECTIO | 2239 | #ifdef CONFIG_NFS_DIRECTIO |
| 2240 | nfs_destroy_directcache(); | 2240 | nfs_destroy_directcache(); |
| 2241 | #endif | 2241 | #endif |
| 2242 | nfs_destroy_writepagecache(); | 2242 | nfs_destroy_writepagecache(); |
| 2243 | nfs_destroy_readpagecache(); | 2243 | nfs_destroy_readpagecache(); |
| 2244 | nfs_destroy_inodecache(); | 2244 | nfs_destroy_inodecache(); |
| 2245 | nfs_destroy_nfspagecache(); | 2245 | nfs_destroy_nfspagecache(); |
| 2246 | #ifdef CONFIG_PROC_FS | 2246 | #ifdef CONFIG_PROC_FS |
| 2247 | rpc_proc_unregister("nfs"); | 2247 | rpc_proc_unregister("nfs"); |
| 2248 | #endif | 2248 | #endif |
| 2249 | unregister_filesystem(&nfs_fs_type); | 2249 | unregister_filesystem(&nfs_fs_type); |
| 2250 | unregister_nfs4fs(); | 2250 | unregister_nfs4fs(); |
| 2251 | } | 2251 | } |
| 2252 | 2252 | ||
| 2253 | /* Not quite true; I just maintain it */ | 2253 | /* Not quite true; I just maintain it */ |
| 2254 | MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); | 2254 | MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>"); |
| 2255 | MODULE_LICENSE("GPL"); | 2255 | MODULE_LICENSE("GPL"); |
| 2256 | 2256 | ||
| 2257 | module_init(init_nfs_fs) | 2257 | module_init(init_nfs_fs) |
| 2258 | module_exit(exit_nfs_fs) | 2258 | module_exit(exit_nfs_fs) |
| 2259 | 2259 |
fs/super.c
| 1 | /* | 1 | /* |
| 2 | * linux/fs/super.c | 2 | * linux/fs/super.c |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 1991, 1992 Linus Torvalds | 4 | * Copyright (C) 1991, 1992 Linus Torvalds |
| 5 | * | 5 | * |
| 6 | * super.c contains code to handle: - mount structures | 6 | * super.c contains code to handle: - mount structures |
| 7 | * - super-block tables | 7 | * - super-block tables |
| 8 | * - filesystem drivers list | 8 | * - filesystem drivers list |
| 9 | * - mount system call | 9 | * - mount system call |
| 10 | * - umount system call | 10 | * - umount system call |
| 11 | * - ustat system call | 11 | * - ustat system call |
| 12 | * | 12 | * |
| 13 | * GK 2/5/95 - Changed to support mounting the root fs via NFS | 13 | * GK 2/5/95 - Changed to support mounting the root fs via NFS |
| 14 | * | 14 | * |
| 15 | * Added kerneld support: Jacques Gelinas and Bjorn Ekwall | 15 | * Added kerneld support: Jacques Gelinas and Bjorn Ekwall |
| 16 | * Added change_root: Werner Almesberger & Hans Lermen, Feb '96 | 16 | * Added change_root: Werner Almesberger & Hans Lermen, Feb '96 |
| 17 | * Added options to /proc/mounts: | 17 | * Added options to /proc/mounts: |
| 18 | * Torbjรถrn Lindh (torbjorn.lindh@gopta.se), April 14, 1996. | 18 | * Torbjรถrn Lindh (torbjorn.lindh@gopta.se), April 14, 1996. |
| 19 | * Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998 | 19 | * Added devfs support: Richard Gooch <rgooch@atnf.csiro.au>, 13-JAN-1998 |
| 20 | * Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000 | 20 | * Heavily rewritten for 'one fs - one tree' dcache architecture. AV, Mar 2000 |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | #include <linux/config.h> | 23 | #include <linux/config.h> |
| 24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
| 25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
| 26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
| 27 | #include <linux/smp_lock.h> | 27 | #include <linux/smp_lock.h> |
| 28 | #include <linux/acct.h> | 28 | #include <linux/acct.h> |
| 29 | #include <linux/blkdev.h> | 29 | #include <linux/blkdev.h> |
| 30 | #include <linux/quotaops.h> | 30 | #include <linux/quotaops.h> |
| 31 | #include <linux/namei.h> | 31 | #include <linux/namei.h> |
| 32 | #include <linux/buffer_head.h> /* for fsync_super() */ | 32 | #include <linux/buffer_head.h> /* for fsync_super() */ |
| 33 | #include <linux/mount.h> | 33 | #include <linux/mount.h> |
| 34 | #include <linux/security.h> | 34 | #include <linux/security.h> |
| 35 | #include <linux/syscalls.h> | 35 | #include <linux/syscalls.h> |
| 36 | #include <linux/vfs.h> | 36 | #include <linux/vfs.h> |
| 37 | #include <linux/writeback.h> /* for the emergency remount stuff */ | 37 | #include <linux/writeback.h> /* for the emergency remount stuff */ |
| 38 | #include <linux/idr.h> | 38 | #include <linux/idr.h> |
| 39 | #include <linux/kobject.h> | 39 | #include <linux/kobject.h> |
| 40 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 41 | 41 | ||
| 42 | 42 | ||
| 43 | void get_filesystem(struct file_system_type *fs); | 43 | void get_filesystem(struct file_system_type *fs); |
| 44 | void put_filesystem(struct file_system_type *fs); | 44 | void put_filesystem(struct file_system_type *fs); |
| 45 | struct file_system_type *get_fs_type(const char *name); | 45 | struct file_system_type *get_fs_type(const char *name); |
| 46 | 46 | ||
| 47 | LIST_HEAD(super_blocks); | 47 | LIST_HEAD(super_blocks); |
| 48 | DEFINE_SPINLOCK(sb_lock); | 48 | DEFINE_SPINLOCK(sb_lock); |
| 49 | 49 | ||
| 50 | /** | 50 | /** |
| 51 | * alloc_super - create new superblock | 51 | * alloc_super - create new superblock |
| 52 | * | 52 | * |
| 53 | * Allocates and initializes a new &struct super_block. alloc_super() | 53 | * Allocates and initializes a new &struct super_block. alloc_super() |
| 54 | * returns a pointer new superblock or %NULL if allocation had failed. | 54 | * returns a pointer new superblock or %NULL if allocation had failed. |
| 55 | */ | 55 | */ |
| 56 | static struct super_block *alloc_super(void) | 56 | static struct super_block *alloc_super(void) |
| 57 | { | 57 | { |
| 58 | struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER); | 58 | struct super_block *s = kmalloc(sizeof(struct super_block), GFP_USER); |
| 59 | static struct super_operations default_op; | 59 | static struct super_operations default_op; |
| 60 | 60 | ||
| 61 | if (s) { | 61 | if (s) { |
| 62 | memset(s, 0, sizeof(struct super_block)); | 62 | memset(s, 0, sizeof(struct super_block)); |
| 63 | if (security_sb_alloc(s)) { | 63 | if (security_sb_alloc(s)) { |
| 64 | kfree(s); | 64 | kfree(s); |
| 65 | s = NULL; | 65 | s = NULL; |
| 66 | goto out; | 66 | goto out; |
| 67 | } | 67 | } |
| 68 | INIT_LIST_HEAD(&s->s_dirty); | 68 | INIT_LIST_HEAD(&s->s_dirty); |
| 69 | INIT_LIST_HEAD(&s->s_io); | 69 | INIT_LIST_HEAD(&s->s_io); |
| 70 | INIT_LIST_HEAD(&s->s_files); | 70 | INIT_LIST_HEAD(&s->s_files); |
| 71 | INIT_LIST_HEAD(&s->s_instances); | 71 | INIT_LIST_HEAD(&s->s_instances); |
| 72 | INIT_HLIST_HEAD(&s->s_anon); | 72 | INIT_HLIST_HEAD(&s->s_anon); |
| 73 | INIT_LIST_HEAD(&s->s_inodes); | 73 | INIT_LIST_HEAD(&s->s_inodes); |
| 74 | init_rwsem(&s->s_umount); | 74 | init_rwsem(&s->s_umount); |
| 75 | mutex_init(&s->s_lock); | 75 | mutex_init(&s->s_lock); |
| 76 | down_write(&s->s_umount); | 76 | down_write(&s->s_umount); |
| 77 | s->s_count = S_BIAS; | 77 | s->s_count = S_BIAS; |
| 78 | atomic_set(&s->s_active, 1); | 78 | atomic_set(&s->s_active, 1); |
| 79 | mutex_init(&s->s_vfs_rename_mutex); | 79 | mutex_init(&s->s_vfs_rename_mutex); |
| 80 | mutex_init(&s->s_dquot.dqio_mutex); | 80 | mutex_init(&s->s_dquot.dqio_mutex); |
| 81 | mutex_init(&s->s_dquot.dqonoff_mutex); | 81 | mutex_init(&s->s_dquot.dqonoff_mutex); |
| 82 | init_rwsem(&s->s_dquot.dqptr_sem); | 82 | init_rwsem(&s->s_dquot.dqptr_sem); |
| 83 | init_waitqueue_head(&s->s_wait_unfrozen); | 83 | init_waitqueue_head(&s->s_wait_unfrozen); |
| 84 | s->s_maxbytes = MAX_NON_LFS; | 84 | s->s_maxbytes = MAX_NON_LFS; |
| 85 | s->dq_op = sb_dquot_ops; | 85 | s->dq_op = sb_dquot_ops; |
| 86 | s->s_qcop = sb_quotactl_ops; | 86 | s->s_qcop = sb_quotactl_ops; |
| 87 | s->s_op = &default_op; | 87 | s->s_op = &default_op; |
| 88 | s->s_time_gran = 1000000000; | 88 | s->s_time_gran = 1000000000; |
| 89 | } | 89 | } |
| 90 | out: | 90 | out: |
| 91 | return s; | 91 | return s; |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | /** | 94 | /** |
| 95 | * destroy_super - frees a superblock | 95 | * destroy_super - frees a superblock |
| 96 | * @s: superblock to free | 96 | * @s: superblock to free |
| 97 | * | 97 | * |
| 98 | * Frees a superblock. | 98 | * Frees a superblock. |
| 99 | */ | 99 | */ |
| 100 | static inline void destroy_super(struct super_block *s) | 100 | static inline void destroy_super(struct super_block *s) |
| 101 | { | 101 | { |
| 102 | security_sb_free(s); | 102 | security_sb_free(s); |
| 103 | kfree(s); | 103 | kfree(s); |
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | /* Superblock refcounting */ | 106 | /* Superblock refcounting */ |
| 107 | 107 | ||
| 108 | /* | 108 | /* |
| 109 | * Drop a superblock's refcount. Returns non-zero if the superblock was | 109 | * Drop a superblock's refcount. Returns non-zero if the superblock was |
| 110 | * destroyed. The caller must hold sb_lock. | 110 | * destroyed. The caller must hold sb_lock. |
| 111 | */ | 111 | */ |
| 112 | int __put_super(struct super_block *sb) | 112 | int __put_super(struct super_block *sb) |
| 113 | { | 113 | { |
| 114 | int ret = 0; | 114 | int ret = 0; |
| 115 | 115 | ||
| 116 | if (!--sb->s_count) { | 116 | if (!--sb->s_count) { |
| 117 | destroy_super(sb); | 117 | destroy_super(sb); |
| 118 | ret = 1; | 118 | ret = 1; |
| 119 | } | 119 | } |
| 120 | return ret; | 120 | return ret; |
| 121 | } | 121 | } |
| 122 | 122 | ||
| 123 | /* | 123 | /* |
| 124 | * Drop a superblock's refcount. | 124 | * Drop a superblock's refcount. |
| 125 | * Returns non-zero if the superblock is about to be destroyed and | 125 | * Returns non-zero if the superblock is about to be destroyed and |
| 126 | * at least is already removed from super_blocks list, so if we are | 126 | * at least is already removed from super_blocks list, so if we are |
| 127 | * making a loop through super blocks then we need to restart. | 127 | * making a loop through super blocks then we need to restart. |
| 128 | * The caller must hold sb_lock. | 128 | * The caller must hold sb_lock. |
| 129 | */ | 129 | */ |
| 130 | int __put_super_and_need_restart(struct super_block *sb) | 130 | int __put_super_and_need_restart(struct super_block *sb) |
| 131 | { | 131 | { |
| 132 | /* check for race with generic_shutdown_super() */ | 132 | /* check for race with generic_shutdown_super() */ |
| 133 | if (list_empty(&sb->s_list)) { | 133 | if (list_empty(&sb->s_list)) { |
| 134 | /* super block is removed, need to restart... */ | 134 | /* super block is removed, need to restart... */ |
| 135 | __put_super(sb); | 135 | __put_super(sb); |
| 136 | return 1; | 136 | return 1; |
| 137 | } | 137 | } |
| 138 | /* can't be the last, since s_list is still in use */ | 138 | /* can't be the last, since s_list is still in use */ |
| 139 | sb->s_count--; | 139 | sb->s_count--; |
| 140 | BUG_ON(sb->s_count == 0); | 140 | BUG_ON(sb->s_count == 0); |
| 141 | return 0; | 141 | return 0; |
| 142 | } | 142 | } |
| 143 | 143 | ||
| 144 | /** | 144 | /** |
| 145 | * put_super - drop a temporary reference to superblock | 145 | * put_super - drop a temporary reference to superblock |
| 146 | * @sb: superblock in question | 146 | * @sb: superblock in question |
| 147 | * | 147 | * |
| 148 | * Drops a temporary reference, frees superblock if there's no | 148 | * Drops a temporary reference, frees superblock if there's no |
| 149 | * references left. | 149 | * references left. |
| 150 | */ | 150 | */ |
| 151 | static void put_super(struct super_block *sb) | 151 | static void put_super(struct super_block *sb) |
| 152 | { | 152 | { |
| 153 | spin_lock(&sb_lock); | 153 | spin_lock(&sb_lock); |
| 154 | __put_super(sb); | 154 | __put_super(sb); |
| 155 | spin_unlock(&sb_lock); | 155 | spin_unlock(&sb_lock); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | 158 | ||
| 159 | /** | 159 | /** |
| 160 | * deactivate_super - drop an active reference to superblock | 160 | * deactivate_super - drop an active reference to superblock |
| 161 | * @s: superblock to deactivate | 161 | * @s: superblock to deactivate |
| 162 | * | 162 | * |
| 163 | * Drops an active reference to superblock, acquiring a temprory one if | 163 | * Drops an active reference to superblock, acquiring a temprory one if |
| 164 | * there is no active references left. In that case we lock superblock, | 164 | * there is no active references left. In that case we lock superblock, |
| 165 | * tell fs driver to shut it down and drop the temporary reference we | 165 | * tell fs driver to shut it down and drop the temporary reference we |
| 166 | * had just acquired. | 166 | * had just acquired. |
| 167 | */ | 167 | */ |
| 168 | void deactivate_super(struct super_block *s) | 168 | void deactivate_super(struct super_block *s) |
| 169 | { | 169 | { |
| 170 | struct file_system_type *fs = s->s_type; | 170 | struct file_system_type *fs = s->s_type; |
| 171 | if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { | 171 | if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { |
| 172 | s->s_count -= S_BIAS-1; | 172 | s->s_count -= S_BIAS-1; |
| 173 | spin_unlock(&sb_lock); | 173 | spin_unlock(&sb_lock); |
| 174 | DQUOT_OFF(s); | 174 | DQUOT_OFF(s); |
| 175 | down_write(&s->s_umount); | 175 | down_write(&s->s_umount); |
| 176 | fs->kill_sb(s); | 176 | fs->kill_sb(s); |
| 177 | put_filesystem(fs); | 177 | put_filesystem(fs); |
| 178 | put_super(s); | 178 | put_super(s); |
| 179 | } | 179 | } |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | EXPORT_SYMBOL(deactivate_super); | 182 | EXPORT_SYMBOL(deactivate_super); |
| 183 | 183 | ||
| 184 | /** | 184 | /** |
| 185 | * grab_super - acquire an active reference | 185 | * grab_super - acquire an active reference |
| 186 | * @s: reference we are trying to make active | 186 | * @s: reference we are trying to make active |
| 187 | * | 187 | * |
| 188 | * Tries to acquire an active reference. grab_super() is used when we | 188 | * Tries to acquire an active reference. grab_super() is used when we |
| 189 | * had just found a superblock in super_blocks or fs_type->fs_supers | 189 | * had just found a superblock in super_blocks or fs_type->fs_supers |
| 190 | * and want to turn it into a full-blown active reference. grab_super() | 190 | * and want to turn it into a full-blown active reference. grab_super() |
| 191 | * is called with sb_lock held and drops it. Returns 1 in case of | 191 | * is called with sb_lock held and drops it. Returns 1 in case of |
| 192 | * success, 0 if we had failed (superblock contents was already dead or | 192 | * success, 0 if we had failed (superblock contents was already dead or |
| 193 | * dying when grab_super() had been called). | 193 | * dying when grab_super() had been called). |
| 194 | */ | 194 | */ |
| 195 | static int grab_super(struct super_block *s) | 195 | static int grab_super(struct super_block *s) |
| 196 | { | 196 | { |
| 197 | s->s_count++; | 197 | s->s_count++; |
| 198 | spin_unlock(&sb_lock); | 198 | spin_unlock(&sb_lock); |
| 199 | down_write(&s->s_umount); | 199 | down_write(&s->s_umount); |
| 200 | if (s->s_root) { | 200 | if (s->s_root) { |
| 201 | spin_lock(&sb_lock); | 201 | spin_lock(&sb_lock); |
| 202 | if (s->s_count > S_BIAS) { | 202 | if (s->s_count > S_BIAS) { |
| 203 | atomic_inc(&s->s_active); | 203 | atomic_inc(&s->s_active); |
| 204 | s->s_count--; | 204 | s->s_count--; |
| 205 | spin_unlock(&sb_lock); | 205 | spin_unlock(&sb_lock); |
| 206 | return 1; | 206 | return 1; |
| 207 | } | 207 | } |
| 208 | spin_unlock(&sb_lock); | 208 | spin_unlock(&sb_lock); |
| 209 | } | 209 | } |
| 210 | up_write(&s->s_umount); | 210 | up_write(&s->s_umount); |
| 211 | put_super(s); | 211 | put_super(s); |
| 212 | yield(); | 212 | yield(); |
| 213 | return 0; | 213 | return 0; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | /** | 216 | /** |
| 217 | * generic_shutdown_super - common helper for ->kill_sb() | 217 | * generic_shutdown_super - common helper for ->kill_sb() |
| 218 | * @sb: superblock to kill | 218 | * @sb: superblock to kill |
| 219 | * | 219 | * |
| 220 | * generic_shutdown_super() does all fs-independent work on superblock | 220 | * generic_shutdown_super() does all fs-independent work on superblock |
| 221 | * shutdown. Typical ->kill_sb() should pick all fs-specific objects | 221 | * shutdown. Typical ->kill_sb() should pick all fs-specific objects |
| 222 | * that need destruction out of superblock, call generic_shutdown_super() | 222 | * that need destruction out of superblock, call generic_shutdown_super() |
| 223 | * and release aforementioned objects. Note: dentries and inodes _are_ | 223 | * and release aforementioned objects. Note: dentries and inodes _are_ |
| 224 | * taken care of and do not need specific handling. | 224 | * taken care of and do not need specific handling. |
| 225 | */ | 225 | */ |
| 226 | void generic_shutdown_super(struct super_block *sb) | 226 | void generic_shutdown_super(struct super_block *sb) |
| 227 | { | 227 | { |
| 228 | struct dentry *root = sb->s_root; | 228 | struct dentry *root = sb->s_root; |
| 229 | struct super_operations *sop = sb->s_op; | 229 | struct super_operations *sop = sb->s_op; |
| 230 | 230 | ||
| 231 | if (root) { | 231 | if (root) { |
| 232 | sb->s_root = NULL; | 232 | sb->s_root = NULL; |
| 233 | shrink_dcache_parent(root); | 233 | shrink_dcache_parent(root); |
| 234 | shrink_dcache_anon(&sb->s_anon); | 234 | shrink_dcache_anon(&sb->s_anon); |
| 235 | dput(root); | 235 | dput(root); |
| 236 | fsync_super(sb); | 236 | fsync_super(sb); |
| 237 | lock_super(sb); | 237 | lock_super(sb); |
| 238 | sb->s_flags &= ~MS_ACTIVE; | 238 | sb->s_flags &= ~MS_ACTIVE; |
| 239 | /* bad name - it should be evict_inodes() */ | 239 | /* bad name - it should be evict_inodes() */ |
| 240 | invalidate_inodes(sb); | 240 | invalidate_inodes(sb); |
| 241 | lock_kernel(); | 241 | lock_kernel(); |
| 242 | 242 | ||
| 243 | if (sop->write_super && sb->s_dirt) | 243 | if (sop->write_super && sb->s_dirt) |
| 244 | sop->write_super(sb); | 244 | sop->write_super(sb); |
| 245 | if (sop->put_super) | 245 | if (sop->put_super) |
| 246 | sop->put_super(sb); | 246 | sop->put_super(sb); |
| 247 | 247 | ||
| 248 | /* Forget any remaining inodes */ | 248 | /* Forget any remaining inodes */ |
| 249 | if (invalidate_inodes(sb)) { | 249 | if (invalidate_inodes(sb)) { |
| 250 | printk("VFS: Busy inodes after unmount of %s. " | 250 | printk("VFS: Busy inodes after unmount of %s. " |
| 251 | "Self-destruct in 5 seconds. Have a nice day...\n", | 251 | "Self-destruct in 5 seconds. Have a nice day...\n", |
| 252 | sb->s_id); | 252 | sb->s_id); |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | unlock_kernel(); | 255 | unlock_kernel(); |
| 256 | unlock_super(sb); | 256 | unlock_super(sb); |
| 257 | } | 257 | } |
| 258 | spin_lock(&sb_lock); | 258 | spin_lock(&sb_lock); |
| 259 | /* should be initialized for __put_super_and_need_restart() */ | 259 | /* should be initialized for __put_super_and_need_restart() */ |
| 260 | list_del_init(&sb->s_list); | 260 | list_del_init(&sb->s_list); |
| 261 | list_del(&sb->s_instances); | 261 | list_del(&sb->s_instances); |
| 262 | spin_unlock(&sb_lock); | 262 | spin_unlock(&sb_lock); |
| 263 | up_write(&sb->s_umount); | 263 | up_write(&sb->s_umount); |
| 264 | } | 264 | } |
| 265 | 265 | ||
| 266 | EXPORT_SYMBOL(generic_shutdown_super); | 266 | EXPORT_SYMBOL(generic_shutdown_super); |
| 267 | 267 | ||
| 268 | /** | 268 | /** |
| 269 | * sget - find or create a superblock | 269 | * sget - find or create a superblock |
| 270 | * @type: filesystem type superblock should belong to | 270 | * @type: filesystem type superblock should belong to |
| 271 | * @test: comparison callback | 271 | * @test: comparison callback |
| 272 | * @set: setup callback | 272 | * @set: setup callback |
| 273 | * @data: argument to each of them | 273 | * @data: argument to each of them |
| 274 | */ | 274 | */ |
| 275 | struct super_block *sget(struct file_system_type *type, | 275 | struct super_block *sget(struct file_system_type *type, |
| 276 | int (*test)(struct super_block *,void *), | 276 | int (*test)(struct super_block *,void *), |
| 277 | int (*set)(struct super_block *,void *), | 277 | int (*set)(struct super_block *,void *), |
| 278 | void *data) | 278 | void *data) |
| 279 | { | 279 | { |
| 280 | struct super_block *s = NULL; | 280 | struct super_block *s = NULL; |
| 281 | struct list_head *p; | 281 | struct list_head *p; |
| 282 | int err; | 282 | int err; |
| 283 | 283 | ||
| 284 | retry: | 284 | retry: |
| 285 | spin_lock(&sb_lock); | 285 | spin_lock(&sb_lock); |
| 286 | if (test) list_for_each(p, &type->fs_supers) { | 286 | if (test) list_for_each(p, &type->fs_supers) { |
| 287 | struct super_block *old; | 287 | struct super_block *old; |
| 288 | old = list_entry(p, struct super_block, s_instances); | 288 | old = list_entry(p, struct super_block, s_instances); |
| 289 | if (!test(old, data)) | 289 | if (!test(old, data)) |
| 290 | continue; | 290 | continue; |
| 291 | if (!grab_super(old)) | 291 | if (!grab_super(old)) |
| 292 | goto retry; | 292 | goto retry; |
| 293 | if (s) | 293 | if (s) |
| 294 | destroy_super(s); | 294 | destroy_super(s); |
| 295 | return old; | 295 | return old; |
| 296 | } | 296 | } |
| 297 | if (!s) { | 297 | if (!s) { |
| 298 | spin_unlock(&sb_lock); | 298 | spin_unlock(&sb_lock); |
| 299 | s = alloc_super(); | 299 | s = alloc_super(); |
| 300 | if (!s) | 300 | if (!s) |
| 301 | return ERR_PTR(-ENOMEM); | 301 | return ERR_PTR(-ENOMEM); |
| 302 | goto retry; | 302 | goto retry; |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | err = set(s, data); | 305 | err = set(s, data); |
| 306 | if (err) { | 306 | if (err) { |
| 307 | spin_unlock(&sb_lock); | 307 | spin_unlock(&sb_lock); |
| 308 | destroy_super(s); | 308 | destroy_super(s); |
| 309 | return ERR_PTR(err); | 309 | return ERR_PTR(err); |
| 310 | } | 310 | } |
| 311 | s->s_type = type; | 311 | s->s_type = type; |
| 312 | strlcpy(s->s_id, type->name, sizeof(s->s_id)); | 312 | strlcpy(s->s_id, type->name, sizeof(s->s_id)); |
| 313 | list_add_tail(&s->s_list, &super_blocks); | 313 | list_add_tail(&s->s_list, &super_blocks); |
| 314 | list_add(&s->s_instances, &type->fs_supers); | 314 | list_add(&s->s_instances, &type->fs_supers); |
| 315 | spin_unlock(&sb_lock); | 315 | spin_unlock(&sb_lock); |
| 316 | get_filesystem(type); | 316 | get_filesystem(type); |
| 317 | return s; | 317 | return s; |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | EXPORT_SYMBOL(sget); | 320 | EXPORT_SYMBOL(sget); |
| 321 | 321 | ||
| 322 | void drop_super(struct super_block *sb) | 322 | void drop_super(struct super_block *sb) |
| 323 | { | 323 | { |
| 324 | up_read(&sb->s_umount); | 324 | up_read(&sb->s_umount); |
| 325 | put_super(sb); | 325 | put_super(sb); |
| 326 | } | 326 | } |
| 327 | 327 | ||
| 328 | EXPORT_SYMBOL(drop_super); | 328 | EXPORT_SYMBOL(drop_super); |
| 329 | 329 | ||
| 330 | static inline void write_super(struct super_block *sb) | 330 | static inline void write_super(struct super_block *sb) |
| 331 | { | 331 | { |
| 332 | lock_super(sb); | 332 | lock_super(sb); |
| 333 | if (sb->s_root && sb->s_dirt) | 333 | if (sb->s_root && sb->s_dirt) |
| 334 | if (sb->s_op->write_super) | 334 | if (sb->s_op->write_super) |
| 335 | sb->s_op->write_super(sb); | 335 | sb->s_op->write_super(sb); |
| 336 | unlock_super(sb); | 336 | unlock_super(sb); |
| 337 | } | 337 | } |
| 338 | 338 | ||
| 339 | /* | 339 | /* |
| 340 | * Note: check the dirty flag before waiting, so we don't | 340 | * Note: check the dirty flag before waiting, so we don't |
| 341 | * hold up the sync while mounting a device. (The newly | 341 | * hold up the sync while mounting a device. (The newly |
| 342 | * mounted device won't need syncing.) | 342 | * mounted device won't need syncing.) |
| 343 | */ | 343 | */ |
| 344 | void sync_supers(void) | 344 | void sync_supers(void) |
| 345 | { | 345 | { |
| 346 | struct super_block *sb; | 346 | struct super_block *sb; |
| 347 | 347 | ||
| 348 | spin_lock(&sb_lock); | 348 | spin_lock(&sb_lock); |
| 349 | restart: | 349 | restart: |
| 350 | list_for_each_entry(sb, &super_blocks, s_list) { | 350 | list_for_each_entry(sb, &super_blocks, s_list) { |
| 351 | if (sb->s_dirt) { | 351 | if (sb->s_dirt) { |
| 352 | sb->s_count++; | 352 | sb->s_count++; |
| 353 | spin_unlock(&sb_lock); | 353 | spin_unlock(&sb_lock); |
| 354 | down_read(&sb->s_umount); | 354 | down_read(&sb->s_umount); |
| 355 | write_super(sb); | 355 | write_super(sb); |
| 356 | up_read(&sb->s_umount); | 356 | up_read(&sb->s_umount); |
| 357 | spin_lock(&sb_lock); | 357 | spin_lock(&sb_lock); |
| 358 | if (__put_super_and_need_restart(sb)) | 358 | if (__put_super_and_need_restart(sb)) |
| 359 | goto restart; | 359 | goto restart; |
| 360 | } | 360 | } |
| 361 | } | 361 | } |
| 362 | spin_unlock(&sb_lock); | 362 | spin_unlock(&sb_lock); |
| 363 | } | 363 | } |
| 364 | 364 | ||
| 365 | /* | 365 | /* |
| 366 | * Call the ->sync_fs super_op against all filesytems which are r/w and | 366 | * Call the ->sync_fs super_op against all filesytems which are r/w and |
| 367 | * which implement it. | 367 | * which implement it. |
| 368 | * | 368 | * |
| 369 | * This operation is careful to avoid the livelock which could easily happen | 369 | * This operation is careful to avoid the livelock which could easily happen |
| 370 | * if two or more filesystems are being continuously dirtied. s_need_sync_fs | 370 | * if two or more filesystems are being continuously dirtied. s_need_sync_fs |
| 371 | * is used only here. We set it against all filesystems and then clear it as | 371 | * is used only here. We set it against all filesystems and then clear it as |
| 372 | * we sync them. So redirtied filesystems are skipped. | 372 | * we sync them. So redirtied filesystems are skipped. |
| 373 | * | 373 | * |
| 374 | * But if process A is currently running sync_filesytems and then process B | 374 | * But if process A is currently running sync_filesytems and then process B |
| 375 | * calls sync_filesystems as well, process B will set all the s_need_sync_fs | 375 | * calls sync_filesystems as well, process B will set all the s_need_sync_fs |
| 376 | * flags again, which will cause process A to resync everything. Fix that with | 376 | * flags again, which will cause process A to resync everything. Fix that with |
| 377 | * a local mutex. | 377 | * a local mutex. |
| 378 | * | 378 | * |
| 379 | * (Fabian) Avoid sync_fs with clean fs & wait mode 0 | 379 | * (Fabian) Avoid sync_fs with clean fs & wait mode 0 |
| 380 | */ | 380 | */ |
| 381 | void sync_filesystems(int wait) | 381 | void sync_filesystems(int wait) |
| 382 | { | 382 | { |
| 383 | struct super_block *sb; | 383 | struct super_block *sb; |
| 384 | static DECLARE_MUTEX(mutex); | 384 | static DECLARE_MUTEX(mutex); |
| 385 | 385 | ||
| 386 | down(&mutex); /* Could be down_interruptible */ | 386 | down(&mutex); /* Could be down_interruptible */ |
| 387 | spin_lock(&sb_lock); | 387 | spin_lock(&sb_lock); |
| 388 | list_for_each_entry(sb, &super_blocks, s_list) { | 388 | list_for_each_entry(sb, &super_blocks, s_list) { |
| 389 | if (!sb->s_op->sync_fs) | 389 | if (!sb->s_op->sync_fs) |
| 390 | continue; | 390 | continue; |
| 391 | if (sb->s_flags & MS_RDONLY) | 391 | if (sb->s_flags & MS_RDONLY) |
| 392 | continue; | 392 | continue; |
| 393 | sb->s_need_sync_fs = 1; | 393 | sb->s_need_sync_fs = 1; |
| 394 | } | 394 | } |
| 395 | 395 | ||
| 396 | restart: | 396 | restart: |
| 397 | list_for_each_entry(sb, &super_blocks, s_list) { | 397 | list_for_each_entry(sb, &super_blocks, s_list) { |
| 398 | if (!sb->s_need_sync_fs) | 398 | if (!sb->s_need_sync_fs) |
| 399 | continue; | 399 | continue; |
| 400 | sb->s_need_sync_fs = 0; | 400 | sb->s_need_sync_fs = 0; |
| 401 | if (sb->s_flags & MS_RDONLY) | 401 | if (sb->s_flags & MS_RDONLY) |
| 402 | continue; /* hm. Was remounted r/o meanwhile */ | 402 | continue; /* hm. Was remounted r/o meanwhile */ |
| 403 | sb->s_count++; | 403 | sb->s_count++; |
| 404 | spin_unlock(&sb_lock); | 404 | spin_unlock(&sb_lock); |
| 405 | down_read(&sb->s_umount); | 405 | down_read(&sb->s_umount); |
| 406 | if (sb->s_root && (wait || sb->s_dirt)) | 406 | if (sb->s_root && (wait || sb->s_dirt)) |
| 407 | sb->s_op->sync_fs(sb, wait); | 407 | sb->s_op->sync_fs(sb, wait); |
| 408 | up_read(&sb->s_umount); | 408 | up_read(&sb->s_umount); |
| 409 | /* restart only when sb is no longer on the list */ | 409 | /* restart only when sb is no longer on the list */ |
| 410 | spin_lock(&sb_lock); | 410 | spin_lock(&sb_lock); |
| 411 | if (__put_super_and_need_restart(sb)) | 411 | if (__put_super_and_need_restart(sb)) |
| 412 | goto restart; | 412 | goto restart; |
| 413 | } | 413 | } |
| 414 | spin_unlock(&sb_lock); | 414 | spin_unlock(&sb_lock); |
| 415 | up(&mutex); | 415 | up(&mutex); |
| 416 | } | 416 | } |
| 417 | 417 | ||
| 418 | /** | 418 | /** |
| 419 | * get_super - get the superblock of a device | 419 | * get_super - get the superblock of a device |
| 420 | * @bdev: device to get the superblock for | 420 | * @bdev: device to get the superblock for |
| 421 | * | 421 | * |
| 422 | * Scans the superblock list and finds the superblock of the file system | 422 | * Scans the superblock list and finds the superblock of the file system |
| 423 | * mounted on the device given. %NULL is returned if no match is found. | 423 | * mounted on the device given. %NULL is returned if no match is found. |
| 424 | */ | 424 | */ |
| 425 | 425 | ||
| 426 | struct super_block * get_super(struct block_device *bdev) | 426 | struct super_block * get_super(struct block_device *bdev) |
| 427 | { | 427 | { |
| 428 | struct super_block *sb; | 428 | struct super_block *sb; |
| 429 | 429 | ||
| 430 | if (!bdev) | 430 | if (!bdev) |
| 431 | return NULL; | 431 | return NULL; |
| 432 | 432 | ||
| 433 | spin_lock(&sb_lock); | 433 | spin_lock(&sb_lock); |
| 434 | rescan: | 434 | rescan: |
| 435 | list_for_each_entry(sb, &super_blocks, s_list) { | 435 | list_for_each_entry(sb, &super_blocks, s_list) { |
| 436 | if (sb->s_bdev == bdev) { | 436 | if (sb->s_bdev == bdev) { |
| 437 | sb->s_count++; | 437 | sb->s_count++; |
| 438 | spin_unlock(&sb_lock); | 438 | spin_unlock(&sb_lock); |
| 439 | down_read(&sb->s_umount); | 439 | down_read(&sb->s_umount); |
| 440 | if (sb->s_root) | 440 | if (sb->s_root) |
| 441 | return sb; | 441 | return sb; |
| 442 | up_read(&sb->s_umount); | 442 | up_read(&sb->s_umount); |
| 443 | /* restart only when sb is no longer on the list */ | 443 | /* restart only when sb is no longer on the list */ |
| 444 | spin_lock(&sb_lock); | 444 | spin_lock(&sb_lock); |
| 445 | if (__put_super_and_need_restart(sb)) | 445 | if (__put_super_and_need_restart(sb)) |
| 446 | goto rescan; | 446 | goto rescan; |
| 447 | } | 447 | } |
| 448 | } | 448 | } |
| 449 | spin_unlock(&sb_lock); | 449 | spin_unlock(&sb_lock); |
| 450 | return NULL; | 450 | return NULL; |
| 451 | } | 451 | } |
| 452 | 452 | ||
| 453 | EXPORT_SYMBOL(get_super); | 453 | EXPORT_SYMBOL(get_super); |
| 454 | 454 | ||
| 455 | struct super_block * user_get_super(dev_t dev) | 455 | struct super_block * user_get_super(dev_t dev) |
| 456 | { | 456 | { |
| 457 | struct super_block *sb; | 457 | struct super_block *sb; |
| 458 | 458 | ||
| 459 | spin_lock(&sb_lock); | 459 | spin_lock(&sb_lock); |
| 460 | rescan: | 460 | rescan: |
| 461 | list_for_each_entry(sb, &super_blocks, s_list) { | 461 | list_for_each_entry(sb, &super_blocks, s_list) { |
| 462 | if (sb->s_dev == dev) { | 462 | if (sb->s_dev == dev) { |
| 463 | sb->s_count++; | 463 | sb->s_count++; |
| 464 | spin_unlock(&sb_lock); | 464 | spin_unlock(&sb_lock); |
| 465 | down_read(&sb->s_umount); | 465 | down_read(&sb->s_umount); |
| 466 | if (sb->s_root) | 466 | if (sb->s_root) |
| 467 | return sb; | 467 | return sb; |
| 468 | up_read(&sb->s_umount); | 468 | up_read(&sb->s_umount); |
| 469 | /* restart only when sb is no longer on the list */ | 469 | /* restart only when sb is no longer on the list */ |
| 470 | spin_lock(&sb_lock); | 470 | spin_lock(&sb_lock); |
| 471 | if (__put_super_and_need_restart(sb)) | 471 | if (__put_super_and_need_restart(sb)) |
| 472 | goto rescan; | 472 | goto rescan; |
| 473 | } | 473 | } |
| 474 | } | 474 | } |
| 475 | spin_unlock(&sb_lock); | 475 | spin_unlock(&sb_lock); |
| 476 | return NULL; | 476 | return NULL; |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf) | 479 | asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf) |
| 480 | { | 480 | { |
| 481 | struct super_block *s; | 481 | struct super_block *s; |
| 482 | struct ustat tmp; | 482 | struct ustat tmp; |
| 483 | struct kstatfs sbuf; | 483 | struct kstatfs sbuf; |
| 484 | int err = -EINVAL; | 484 | int err = -EINVAL; |
| 485 | 485 | ||
| 486 | s = user_get_super(new_decode_dev(dev)); | 486 | s = user_get_super(new_decode_dev(dev)); |
| 487 | if (s == NULL) | 487 | if (s == NULL) |
| 488 | goto out; | 488 | goto out; |
| 489 | err = vfs_statfs(s, &sbuf); | 489 | err = vfs_statfs(s, &sbuf); |
| 490 | drop_super(s); | 490 | drop_super(s); |
| 491 | if (err) | 491 | if (err) |
| 492 | goto out; | 492 | goto out; |
| 493 | 493 | ||
| 494 | memset(&tmp,0,sizeof(struct ustat)); | 494 | memset(&tmp,0,sizeof(struct ustat)); |
| 495 | tmp.f_tfree = sbuf.f_bfree; | 495 | tmp.f_tfree = sbuf.f_bfree; |
| 496 | tmp.f_tinode = sbuf.f_ffree; | 496 | tmp.f_tinode = sbuf.f_ffree; |
| 497 | 497 | ||
| 498 | err = copy_to_user(ubuf,&tmp,sizeof(struct ustat)) ? -EFAULT : 0; | 498 | err = copy_to_user(ubuf,&tmp,sizeof(struct ustat)) ? -EFAULT : 0; |
| 499 | out: | 499 | out: |
| 500 | return err; | 500 | return err; |
| 501 | } | 501 | } |
| 502 | 502 | ||
| 503 | /** | 503 | /** |
| 504 | * mark_files_ro | 504 | * mark_files_ro |
| 505 | * @sb: superblock in question | 505 | * @sb: superblock in question |
| 506 | * | 506 | * |
| 507 | * All files are marked read/only. We don't care about pending | 507 | * All files are marked read/only. We don't care about pending |
| 508 | * delete files so this should be used in 'force' mode only | 508 | * delete files so this should be used in 'force' mode only |
| 509 | */ | 509 | */ |
| 510 | 510 | ||
| 511 | static void mark_files_ro(struct super_block *sb) | 511 | static void mark_files_ro(struct super_block *sb) |
| 512 | { | 512 | { |
| 513 | struct file *f; | 513 | struct file *f; |
| 514 | 514 | ||
| 515 | file_list_lock(); | 515 | file_list_lock(); |
| 516 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { | 516 | list_for_each_entry(f, &sb->s_files, f_u.fu_list) { |
| 517 | if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f)) | 517 | if (S_ISREG(f->f_dentry->d_inode->i_mode) && file_count(f)) |
| 518 | f->f_mode &= ~FMODE_WRITE; | 518 | f->f_mode &= ~FMODE_WRITE; |
| 519 | } | 519 | } |
| 520 | file_list_unlock(); | 520 | file_list_unlock(); |
| 521 | } | 521 | } |
| 522 | 522 | ||
| 523 | /** | 523 | /** |
| 524 | * do_remount_sb - asks filesystem to change mount options. | 524 | * do_remount_sb - asks filesystem to change mount options. |
| 525 | * @sb: superblock in question | 525 | * @sb: superblock in question |
| 526 | * @flags: numeric part of options | 526 | * @flags: numeric part of options |
| 527 | * @data: the rest of options | 527 | * @data: the rest of options |
| 528 | * @force: whether or not to force the change | 528 | * @force: whether or not to force the change |
| 529 | * | 529 | * |
| 530 | * Alters the mount options of a mounted file system. | 530 | * Alters the mount options of a mounted file system. |
| 531 | */ | 531 | */ |
| 532 | int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | 532 | int do_remount_sb(struct super_block *sb, int flags, void *data, int force) |
| 533 | { | 533 | { |
| 534 | int retval; | 534 | int retval; |
| 535 | 535 | ||
| 536 | if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev)) | 536 | if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev)) |
| 537 | return -EACCES; | 537 | return -EACCES; |
| 538 | if (flags & MS_RDONLY) | 538 | if (flags & MS_RDONLY) |
| 539 | acct_auto_close(sb); | 539 | acct_auto_close(sb); |
| 540 | shrink_dcache_sb(sb); | 540 | shrink_dcache_sb(sb); |
| 541 | fsync_super(sb); | 541 | fsync_super(sb); |
| 542 | 542 | ||
| 543 | /* If we are remounting RDONLY and current sb is read/write, | 543 | /* If we are remounting RDONLY and current sb is read/write, |
| 544 | make sure there are no rw files opened */ | 544 | make sure there are no rw files opened */ |
| 545 | if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) { | 545 | if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) { |
| 546 | if (force) | 546 | if (force) |
| 547 | mark_files_ro(sb); | 547 | mark_files_ro(sb); |
| 548 | else if (!fs_may_remount_ro(sb)) | 548 | else if (!fs_may_remount_ro(sb)) |
| 549 | return -EBUSY; | 549 | return -EBUSY; |
| 550 | } | 550 | } |
| 551 | 551 | ||
| 552 | if (sb->s_op->remount_fs) { | 552 | if (sb->s_op->remount_fs) { |
| 553 | lock_super(sb); | 553 | lock_super(sb); |
| 554 | retval = sb->s_op->remount_fs(sb, &flags, data); | 554 | retval = sb->s_op->remount_fs(sb, &flags, data); |
| 555 | unlock_super(sb); | 555 | unlock_super(sb); |
| 556 | if (retval) | 556 | if (retval) |
| 557 | return retval; | 557 | return retval; |
| 558 | } | 558 | } |
| 559 | sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); | 559 | sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); |
| 560 | return 0; | 560 | return 0; |
| 561 | } | 561 | } |
| 562 | 562 | ||
| 563 | static void do_emergency_remount(unsigned long foo) | 563 | static void do_emergency_remount(unsigned long foo) |
| 564 | { | 564 | { |
| 565 | struct super_block *sb; | 565 | struct super_block *sb; |
| 566 | 566 | ||
| 567 | spin_lock(&sb_lock); | 567 | spin_lock(&sb_lock); |
| 568 | list_for_each_entry(sb, &super_blocks, s_list) { | 568 | list_for_each_entry(sb, &super_blocks, s_list) { |
| 569 | sb->s_count++; | 569 | sb->s_count++; |
| 570 | spin_unlock(&sb_lock); | 570 | spin_unlock(&sb_lock); |
| 571 | down_read(&sb->s_umount); | 571 | down_read(&sb->s_umount); |
| 572 | if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) { | 572 | if (sb->s_root && sb->s_bdev && !(sb->s_flags & MS_RDONLY)) { |
| 573 | /* | 573 | /* |
| 574 | * ->remount_fs needs lock_kernel(). | 574 | * ->remount_fs needs lock_kernel(). |
| 575 | * | 575 | * |
| 576 | * What lock protects sb->s_flags?? | 576 | * What lock protects sb->s_flags?? |
| 577 | */ | 577 | */ |
| 578 | lock_kernel(); | 578 | lock_kernel(); |
| 579 | do_remount_sb(sb, MS_RDONLY, NULL, 1); | 579 | do_remount_sb(sb, MS_RDONLY, NULL, 1); |
| 580 | unlock_kernel(); | 580 | unlock_kernel(); |
| 581 | } | 581 | } |
| 582 | drop_super(sb); | 582 | drop_super(sb); |
| 583 | spin_lock(&sb_lock); | 583 | spin_lock(&sb_lock); |
| 584 | } | 584 | } |
| 585 | spin_unlock(&sb_lock); | 585 | spin_unlock(&sb_lock); |
| 586 | printk("Emergency Remount complete\n"); | 586 | printk("Emergency Remount complete\n"); |
| 587 | } | 587 | } |
| 588 | 588 | ||
| 589 | void emergency_remount(void) | 589 | void emergency_remount(void) |
| 590 | { | 590 | { |
| 591 | pdflush_operation(do_emergency_remount, 0); | 591 | pdflush_operation(do_emergency_remount, 0); |
| 592 | } | 592 | } |
| 593 | 593 | ||
| 594 | /* | 594 | /* |
| 595 | * Unnamed block devices are dummy devices used by virtual | 595 | * Unnamed block devices are dummy devices used by virtual |
| 596 | * filesystems which don't use real block-devices. -- jrs | 596 | * filesystems which don't use real block-devices. -- jrs |
| 597 | */ | 597 | */ |
| 598 | 598 | ||
| 599 | static struct idr unnamed_dev_idr; | 599 | static struct idr unnamed_dev_idr; |
| 600 | static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */ | 600 | static DEFINE_SPINLOCK(unnamed_dev_lock);/* protects the above */ |
| 601 | 601 | ||
| 602 | int set_anon_super(struct super_block *s, void *data) | 602 | int set_anon_super(struct super_block *s, void *data) |
| 603 | { | 603 | { |
| 604 | int dev; | 604 | int dev; |
| 605 | int error; | 605 | int error; |
| 606 | 606 | ||
| 607 | retry: | 607 | retry: |
| 608 | if (idr_pre_get(&unnamed_dev_idr, GFP_ATOMIC) == 0) | 608 | if (idr_pre_get(&unnamed_dev_idr, GFP_ATOMIC) == 0) |
| 609 | return -ENOMEM; | 609 | return -ENOMEM; |
| 610 | spin_lock(&unnamed_dev_lock); | 610 | spin_lock(&unnamed_dev_lock); |
| 611 | error = idr_get_new(&unnamed_dev_idr, NULL, &dev); | 611 | error = idr_get_new(&unnamed_dev_idr, NULL, &dev); |
| 612 | spin_unlock(&unnamed_dev_lock); | 612 | spin_unlock(&unnamed_dev_lock); |
| 613 | if (error == -EAGAIN) | 613 | if (error == -EAGAIN) |
| 614 | /* We raced and lost with another CPU. */ | 614 | /* We raced and lost with another CPU. */ |
| 615 | goto retry; | 615 | goto retry; |
| 616 | else if (error) | 616 | else if (error) |
| 617 | return -EAGAIN; | 617 | return -EAGAIN; |
| 618 | 618 | ||
| 619 | if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) { | 619 | if ((dev & MAX_ID_MASK) == (1 << MINORBITS)) { |
| 620 | spin_lock(&unnamed_dev_lock); | 620 | spin_lock(&unnamed_dev_lock); |
| 621 | idr_remove(&unnamed_dev_idr, dev); | 621 | idr_remove(&unnamed_dev_idr, dev); |
| 622 | spin_unlock(&unnamed_dev_lock); | 622 | spin_unlock(&unnamed_dev_lock); |
| 623 | return -EMFILE; | 623 | return -EMFILE; |
| 624 | } | 624 | } |
| 625 | s->s_dev = MKDEV(0, dev & MINORMASK); | 625 | s->s_dev = MKDEV(0, dev & MINORMASK); |
| 626 | return 0; | 626 | return 0; |
| 627 | } | 627 | } |
| 628 | 628 | ||
| 629 | EXPORT_SYMBOL(set_anon_super); | 629 | EXPORT_SYMBOL(set_anon_super); |
| 630 | 630 | ||
| 631 | void kill_anon_super(struct super_block *sb) | 631 | void kill_anon_super(struct super_block *sb) |
| 632 | { | 632 | { |
| 633 | int slot = MINOR(sb->s_dev); | 633 | int slot = MINOR(sb->s_dev); |
| 634 | 634 | ||
| 635 | generic_shutdown_super(sb); | 635 | generic_shutdown_super(sb); |
| 636 | spin_lock(&unnamed_dev_lock); | 636 | spin_lock(&unnamed_dev_lock); |
| 637 | idr_remove(&unnamed_dev_idr, slot); | 637 | idr_remove(&unnamed_dev_idr, slot); |
| 638 | spin_unlock(&unnamed_dev_lock); | 638 | spin_unlock(&unnamed_dev_lock); |
| 639 | } | 639 | } |
| 640 | 640 | ||
| 641 | EXPORT_SYMBOL(kill_anon_super); | 641 | EXPORT_SYMBOL(kill_anon_super); |
| 642 | 642 | ||
| 643 | void __init unnamed_dev_init(void) | 643 | void __init unnamed_dev_init(void) |
| 644 | { | 644 | { |
| 645 | idr_init(&unnamed_dev_idr); | 645 | idr_init(&unnamed_dev_idr); |
| 646 | } | 646 | } |
| 647 | 647 | ||
| 648 | void kill_litter_super(struct super_block *sb) | 648 | void kill_litter_super(struct super_block *sb) |
| 649 | { | 649 | { |
| 650 | if (sb->s_root) | 650 | if (sb->s_root) |
| 651 | d_genocide(sb->s_root); | 651 | d_genocide(sb->s_root); |
| 652 | kill_anon_super(sb); | 652 | kill_anon_super(sb); |
| 653 | } | 653 | } |
| 654 | 654 | ||
| 655 | EXPORT_SYMBOL(kill_litter_super); | 655 | EXPORT_SYMBOL(kill_litter_super); |
| 656 | 656 | ||
| 657 | static int set_bdev_super(struct super_block *s, void *data) | 657 | static int set_bdev_super(struct super_block *s, void *data) |
| 658 | { | 658 | { |
| 659 | s->s_bdev = data; | 659 | s->s_bdev = data; |
| 660 | s->s_dev = s->s_bdev->bd_dev; | 660 | s->s_dev = s->s_bdev->bd_dev; |
| 661 | return 0; | 661 | return 0; |
| 662 | } | 662 | } |
| 663 | 663 | ||
| 664 | static int test_bdev_super(struct super_block *s, void *data) | 664 | static int test_bdev_super(struct super_block *s, void *data) |
| 665 | { | 665 | { |
| 666 | return (void *)s->s_bdev == data; | 666 | return (void *)s->s_bdev == data; |
| 667 | } | 667 | } |
| 668 | 668 | ||
| 669 | static void bdev_uevent(struct block_device *bdev, enum kobject_action action) | 669 | static void bdev_uevent(struct block_device *bdev, enum kobject_action action) |
| 670 | { | 670 | { |
| 671 | if (bdev->bd_disk) { | 671 | if (bdev->bd_disk) { |
| 672 | if (bdev->bd_part) | 672 | if (bdev->bd_part) |
| 673 | kobject_uevent(&bdev->bd_part->kobj, action); | 673 | kobject_uevent(&bdev->bd_part->kobj, action); |
| 674 | else | 674 | else |
| 675 | kobject_uevent(&bdev->bd_disk->kobj, action); | 675 | kobject_uevent(&bdev->bd_disk->kobj, action); |
| 676 | } | 676 | } |
| 677 | } | 677 | } |
| 678 | 678 | ||
| 679 | struct super_block *get_sb_bdev(struct file_system_type *fs_type, | 679 | struct super_block *get_sb_bdev(struct file_system_type *fs_type, |
| 680 | int flags, const char *dev_name, void *data, | 680 | int flags, const char *dev_name, void *data, |
| 681 | int (*fill_super)(struct super_block *, void *, int)) | 681 | int (*fill_super)(struct super_block *, void *, int)) |
| 682 | { | 682 | { |
| 683 | struct block_device *bdev; | 683 | struct block_device *bdev; |
| 684 | struct super_block *s; | 684 | struct super_block *s; |
| 685 | int error = 0; | 685 | int error = 0; |
| 686 | 686 | ||
| 687 | bdev = open_bdev_excl(dev_name, flags, fs_type); | 687 | bdev = open_bdev_excl(dev_name, flags, fs_type); |
| 688 | if (IS_ERR(bdev)) | 688 | if (IS_ERR(bdev)) |
| 689 | return (struct super_block *)bdev; | 689 | return (struct super_block *)bdev; |
| 690 | 690 | ||
| 691 | /* | 691 | /* |
| 692 | * once the super is inserted into the list by sget, s_umount | 692 | * once the super is inserted into the list by sget, s_umount |
| 693 | * will protect the lockfs code from trying to start a snapshot | 693 | * will protect the lockfs code from trying to start a snapshot |
| 694 | * while we are mounting | 694 | * while we are mounting |
| 695 | */ | 695 | */ |
| 696 | mutex_lock(&bdev->bd_mount_mutex); | 696 | mutex_lock(&bdev->bd_mount_mutex); |
| 697 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); | 697 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); |
| 698 | mutex_unlock(&bdev->bd_mount_mutex); | 698 | mutex_unlock(&bdev->bd_mount_mutex); |
| 699 | if (IS_ERR(s)) | 699 | if (IS_ERR(s)) |
| 700 | goto out; | 700 | goto out; |
| 701 | 701 | ||
| 702 | if (s->s_root) { | 702 | if (s->s_root) { |
| 703 | if ((flags ^ s->s_flags) & MS_RDONLY) { | 703 | if ((flags ^ s->s_flags) & MS_RDONLY) { |
| 704 | up_write(&s->s_umount); | 704 | up_write(&s->s_umount); |
| 705 | deactivate_super(s); | 705 | deactivate_super(s); |
| 706 | s = ERR_PTR(-EBUSY); | 706 | s = ERR_PTR(-EBUSY); |
| 707 | } | 707 | } |
| 708 | goto out; | 708 | goto out; |
| 709 | } else { | 709 | } else { |
| 710 | char b[BDEVNAME_SIZE]; | 710 | char b[BDEVNAME_SIZE]; |
| 711 | 711 | ||
| 712 | s->s_flags = flags; | 712 | s->s_flags = flags; |
| 713 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); | 713 | strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id)); |
| 714 | sb_set_blocksize(s, block_size(bdev)); | 714 | sb_set_blocksize(s, block_size(bdev)); |
| 715 | error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); | 715 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
| 716 | if (error) { | 716 | if (error) { |
| 717 | up_write(&s->s_umount); | 717 | up_write(&s->s_umount); |
| 718 | deactivate_super(s); | 718 | deactivate_super(s); |
| 719 | s = ERR_PTR(error); | 719 | s = ERR_PTR(error); |
| 720 | } else { | 720 | } else { |
| 721 | s->s_flags |= MS_ACTIVE; | 721 | s->s_flags |= MS_ACTIVE; |
| 722 | bdev_uevent(bdev, KOBJ_MOUNT); | 722 | bdev_uevent(bdev, KOBJ_MOUNT); |
| 723 | } | 723 | } |
| 724 | } | 724 | } |
| 725 | 725 | ||
| 726 | return s; | 726 | return s; |
| 727 | 727 | ||
| 728 | out: | 728 | out: |
| 729 | close_bdev_excl(bdev); | 729 | close_bdev_excl(bdev); |
| 730 | return s; | 730 | return s; |
| 731 | } | 731 | } |
| 732 | 732 | ||
| 733 | EXPORT_SYMBOL(get_sb_bdev); | 733 | EXPORT_SYMBOL(get_sb_bdev); |
| 734 | 734 | ||
| 735 | void kill_block_super(struct super_block *sb) | 735 | void kill_block_super(struct super_block *sb) |
| 736 | { | 736 | { |
| 737 | struct block_device *bdev = sb->s_bdev; | 737 | struct block_device *bdev = sb->s_bdev; |
| 738 | 738 | ||
| 739 | bdev_uevent(bdev, KOBJ_UMOUNT); | 739 | bdev_uevent(bdev, KOBJ_UMOUNT); |
| 740 | generic_shutdown_super(sb); | 740 | generic_shutdown_super(sb); |
| 741 | sync_blockdev(bdev); | 741 | sync_blockdev(bdev); |
| 742 | close_bdev_excl(bdev); | 742 | close_bdev_excl(bdev); |
| 743 | } | 743 | } |
| 744 | 744 | ||
| 745 | EXPORT_SYMBOL(kill_block_super); | 745 | EXPORT_SYMBOL(kill_block_super); |
| 746 | 746 | ||
| 747 | struct super_block *get_sb_nodev(struct file_system_type *fs_type, | 747 | struct super_block *get_sb_nodev(struct file_system_type *fs_type, |
| 748 | int flags, void *data, | 748 | int flags, void *data, |
| 749 | int (*fill_super)(struct super_block *, void *, int)) | 749 | int (*fill_super)(struct super_block *, void *, int)) |
| 750 | { | 750 | { |
| 751 | int error; | 751 | int error; |
| 752 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); | 752 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); |
| 753 | 753 | ||
| 754 | if (IS_ERR(s)) | 754 | if (IS_ERR(s)) |
| 755 | return s; | 755 | return s; |
| 756 | 756 | ||
| 757 | s->s_flags = flags; | 757 | s->s_flags = flags; |
| 758 | 758 | ||
| 759 | error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); | 759 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
| 760 | if (error) { | 760 | if (error) { |
| 761 | up_write(&s->s_umount); | 761 | up_write(&s->s_umount); |
| 762 | deactivate_super(s); | 762 | deactivate_super(s); |
| 763 | return ERR_PTR(error); | 763 | return ERR_PTR(error); |
| 764 | } | 764 | } |
| 765 | s->s_flags |= MS_ACTIVE; | 765 | s->s_flags |= MS_ACTIVE; |
| 766 | return s; | 766 | return s; |
| 767 | } | 767 | } |
| 768 | 768 | ||
| 769 | EXPORT_SYMBOL(get_sb_nodev); | 769 | EXPORT_SYMBOL(get_sb_nodev); |
| 770 | 770 | ||
| 771 | static int compare_single(struct super_block *s, void *p) | 771 | static int compare_single(struct super_block *s, void *p) |
| 772 | { | 772 | { |
| 773 | return 1; | 773 | return 1; |
| 774 | } | 774 | } |
| 775 | 775 | ||
| 776 | struct super_block *get_sb_single(struct file_system_type *fs_type, | 776 | struct super_block *get_sb_single(struct file_system_type *fs_type, |
| 777 | int flags, void *data, | 777 | int flags, void *data, |
| 778 | int (*fill_super)(struct super_block *, void *, int)) | 778 | int (*fill_super)(struct super_block *, void *, int)) |
| 779 | { | 779 | { |
| 780 | struct super_block *s; | 780 | struct super_block *s; |
| 781 | int error; | 781 | int error; |
| 782 | 782 | ||
| 783 | s = sget(fs_type, compare_single, set_anon_super, NULL); | 783 | s = sget(fs_type, compare_single, set_anon_super, NULL); |
| 784 | if (IS_ERR(s)) | 784 | if (IS_ERR(s)) |
| 785 | return s; | 785 | return s; |
| 786 | if (!s->s_root) { | 786 | if (!s->s_root) { |
| 787 | s->s_flags = flags; | 787 | s->s_flags = flags; |
| 788 | error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); | 788 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
| 789 | if (error) { | 789 | if (error) { |
| 790 | up_write(&s->s_umount); | 790 | up_write(&s->s_umount); |
| 791 | deactivate_super(s); | 791 | deactivate_super(s); |
| 792 | return ERR_PTR(error); | 792 | return ERR_PTR(error); |
| 793 | } | 793 | } |
| 794 | s->s_flags |= MS_ACTIVE; | 794 | s->s_flags |= MS_ACTIVE; |
| 795 | } | 795 | } |
| 796 | do_remount_sb(s, flags, data, 0); | 796 | do_remount_sb(s, flags, data, 0); |
| 797 | return s; | 797 | return s; |
| 798 | } | 798 | } |
| 799 | 799 | ||
| 800 | EXPORT_SYMBOL(get_sb_single); | 800 | EXPORT_SYMBOL(get_sb_single); |
| 801 | 801 | ||
| 802 | struct vfsmount * | 802 | struct vfsmount * |
| 803 | do_kern_mount(const char *fstype, int flags, const char *name, void *data) | 803 | do_kern_mount(const char *fstype, int flags, const char *name, void *data) |
| 804 | { | 804 | { |
| 805 | struct file_system_type *type = get_fs_type(fstype); | 805 | struct file_system_type *type = get_fs_type(fstype); |
| 806 | struct super_block *sb = ERR_PTR(-ENOMEM); | 806 | struct super_block *sb = ERR_PTR(-ENOMEM); |
| 807 | struct vfsmount *mnt; | 807 | struct vfsmount *mnt; |
| 808 | int error; | 808 | int error; |
| 809 | char *secdata = NULL; | 809 | char *secdata = NULL; |
| 810 | 810 | ||
| 811 | if (!type) | 811 | if (!type) |
| 812 | return ERR_PTR(-ENODEV); | 812 | return ERR_PTR(-ENODEV); |
| 813 | 813 | ||
| 814 | mnt = alloc_vfsmnt(name); | 814 | mnt = alloc_vfsmnt(name); |
| 815 | if (!mnt) | 815 | if (!mnt) |
| 816 | goto out; | 816 | goto out; |
| 817 | 817 | ||
| 818 | if (data) { | 818 | if (data) { |
| 819 | secdata = alloc_secdata(); | 819 | secdata = alloc_secdata(); |
| 820 | if (!secdata) { | 820 | if (!secdata) { |
| 821 | sb = ERR_PTR(-ENOMEM); | 821 | sb = ERR_PTR(-ENOMEM); |
| 822 | goto out_mnt; | 822 | goto out_mnt; |
| 823 | } | 823 | } |
| 824 | 824 | ||
| 825 | error = security_sb_copy_data(type, data, secdata); | 825 | error = security_sb_copy_data(type, data, secdata); |
| 826 | if (error) { | 826 | if (error) { |
| 827 | sb = ERR_PTR(error); | 827 | sb = ERR_PTR(error); |
| 828 | goto out_free_secdata; | 828 | goto out_free_secdata; |
| 829 | } | 829 | } |
| 830 | } | 830 | } |
| 831 | 831 | ||
| 832 | sb = type->get_sb(type, flags, name, data); | 832 | sb = type->get_sb(type, flags, name, data); |
| 833 | if (IS_ERR(sb)) | 833 | if (IS_ERR(sb)) |
| 834 | goto out_free_secdata; | 834 | goto out_free_secdata; |
| 835 | error = security_sb_kern_mount(sb, secdata); | 835 | error = security_sb_kern_mount(sb, secdata); |
| 836 | if (error) | 836 | if (error) |
| 837 | goto out_sb; | 837 | goto out_sb; |
| 838 | mnt->mnt_sb = sb; | 838 | mnt->mnt_sb = sb; |
| 839 | mnt->mnt_root = dget(sb->s_root); | 839 | mnt->mnt_root = dget(sb->s_root); |
| 840 | mnt->mnt_mountpoint = sb->s_root; | 840 | mnt->mnt_mountpoint = sb->s_root; |
| 841 | mnt->mnt_parent = mnt; | 841 | mnt->mnt_parent = mnt; |
| 842 | up_write(&sb->s_umount); | 842 | up_write(&sb->s_umount); |
| 843 | free_secdata(secdata); | 843 | free_secdata(secdata); |
| 844 | put_filesystem(type); | 844 | put_filesystem(type); |
| 845 | return mnt; | 845 | return mnt; |
| 846 | out_sb: | 846 | out_sb: |
| 847 | up_write(&sb->s_umount); | 847 | up_write(&sb->s_umount); |
| 848 | deactivate_super(sb); | 848 | deactivate_super(sb); |
| 849 | sb = ERR_PTR(error); | 849 | sb = ERR_PTR(error); |
| 850 | out_free_secdata: | 850 | out_free_secdata: |
| 851 | free_secdata(secdata); | 851 | free_secdata(secdata); |
| 852 | out_mnt: | 852 | out_mnt: |
| 853 | free_vfsmnt(mnt); | 853 | free_vfsmnt(mnt); |
| 854 | out: | 854 | out: |
| 855 | put_filesystem(type); | 855 | put_filesystem(type); |
| 856 | return (struct vfsmount *)sb; | 856 | return (struct vfsmount *)sb; |
| 857 | } | 857 | } |
| 858 | 858 | ||
| 859 | EXPORT_SYMBOL_GPL(do_kern_mount); | 859 | EXPORT_SYMBOL_GPL(do_kern_mount); |
| 860 | 860 | ||
| 861 | struct vfsmount *kern_mount(struct file_system_type *type) | 861 | struct vfsmount *kern_mount(struct file_system_type *type) |
| 862 | { | 862 | { |
| 863 | return do_kern_mount(type->name, 0, type->name, NULL); | 863 | return do_kern_mount(type->name, 0, type->name, NULL); |
| 864 | } | 864 | } |
| 865 | 865 | ||
| 866 | EXPORT_SYMBOL(kern_mount); | 866 | EXPORT_SYMBOL(kern_mount); |
| 867 | 867 |
include/linux/fs.h
| 1 | #ifndef _LINUX_FS_H | 1 | #ifndef _LINUX_FS_H |
| 2 | #define _LINUX_FS_H | 2 | #define _LINUX_FS_H |
| 3 | 3 | ||
| 4 | /* | 4 | /* |
| 5 | * This file has definitions for some important file table | 5 | * This file has definitions for some important file table |
| 6 | * structures etc. | 6 | * structures etc. |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| 9 | #include <linux/config.h> | 9 | #include <linux/config.h> |
| 10 | #include <linux/limits.h> | 10 | #include <linux/limits.h> |
| 11 | #include <linux/ioctl.h> | 11 | #include <linux/ioctl.h> |
| 12 | 12 | ||
| 13 | /* | 13 | /* |
| 14 | * It's silly to have NR_OPEN bigger than NR_FILE, but you can change | 14 | * It's silly to have NR_OPEN bigger than NR_FILE, but you can change |
| 15 | * the file limit at runtime and only root can increase the per-process | 15 | * the file limit at runtime and only root can increase the per-process |
| 16 | * nr_file rlimit, so it's safe to set up a ridiculously high absolute | 16 | * nr_file rlimit, so it's safe to set up a ridiculously high absolute |
| 17 | * upper limit on files-per-process. | 17 | * upper limit on files-per-process. |
| 18 | * | 18 | * |
| 19 | * Some programs (notably those using select()) may have to be | 19 | * Some programs (notably those using select()) may have to be |
| 20 | * recompiled to take full advantage of the new limits.. | 20 | * recompiled to take full advantage of the new limits.. |
| 21 | */ | 21 | */ |
| 22 | 22 | ||
| 23 | /* Fixed constants first: */ | 23 | /* Fixed constants first: */ |
| 24 | #undef NR_OPEN | 24 | #undef NR_OPEN |
| 25 | #define NR_OPEN (1024*1024) /* Absolute upper limit on fd num */ | 25 | #define NR_OPEN (1024*1024) /* Absolute upper limit on fd num */ |
| 26 | #define INR_OPEN 1024 /* Initial setting for nfile rlimits */ | 26 | #define INR_OPEN 1024 /* Initial setting for nfile rlimits */ |
| 27 | 27 | ||
| 28 | #define BLOCK_SIZE_BITS 10 | 28 | #define BLOCK_SIZE_BITS 10 |
| 29 | #define BLOCK_SIZE (1<<BLOCK_SIZE_BITS) | 29 | #define BLOCK_SIZE (1<<BLOCK_SIZE_BITS) |
| 30 | 30 | ||
| 31 | /* And dynamically-tunable limits and defaults: */ | 31 | /* And dynamically-tunable limits and defaults: */ |
| 32 | struct files_stat_struct { | 32 | struct files_stat_struct { |
| 33 | int nr_files; /* read only */ | 33 | int nr_files; /* read only */ |
| 34 | int nr_free_files; /* read only */ | 34 | int nr_free_files; /* read only */ |
| 35 | int max_files; /* tunable */ | 35 | int max_files; /* tunable */ |
| 36 | }; | 36 | }; |
| 37 | extern struct files_stat_struct files_stat; | 37 | extern struct files_stat_struct files_stat; |
| 38 | extern int get_max_files(void); | 38 | extern int get_max_files(void); |
| 39 | 39 | ||
| 40 | struct inodes_stat_t { | 40 | struct inodes_stat_t { |
| 41 | int nr_inodes; | 41 | int nr_inodes; |
| 42 | int nr_unused; | 42 | int nr_unused; |
| 43 | int dummy[5]; | 43 | int dummy[5]; |
| 44 | }; | 44 | }; |
| 45 | extern struct inodes_stat_t inodes_stat; | 45 | extern struct inodes_stat_t inodes_stat; |
| 46 | 46 | ||
| 47 | extern int leases_enable, lease_break_time; | 47 | extern int leases_enable, lease_break_time; |
| 48 | 48 | ||
| 49 | #ifdef CONFIG_DNOTIFY | 49 | #ifdef CONFIG_DNOTIFY |
| 50 | extern int dir_notify_enable; | 50 | extern int dir_notify_enable; |
| 51 | #endif | 51 | #endif |
| 52 | 52 | ||
| 53 | #define NR_FILE 8192 /* this can well be larger on a larger system */ | 53 | #define NR_FILE 8192 /* this can well be larger on a larger system */ |
| 54 | 54 | ||
| 55 | #define MAY_EXEC 1 | 55 | #define MAY_EXEC 1 |
| 56 | #define MAY_WRITE 2 | 56 | #define MAY_WRITE 2 |
| 57 | #define MAY_READ 4 | 57 | #define MAY_READ 4 |
| 58 | #define MAY_APPEND 8 | 58 | #define MAY_APPEND 8 |
| 59 | 59 | ||
| 60 | #define FMODE_READ 1 | 60 | #define FMODE_READ 1 |
| 61 | #define FMODE_WRITE 2 | 61 | #define FMODE_WRITE 2 |
| 62 | 62 | ||
| 63 | /* Internal kernel extensions */ | 63 | /* Internal kernel extensions */ |
| 64 | #define FMODE_LSEEK 4 | 64 | #define FMODE_LSEEK 4 |
| 65 | #define FMODE_PREAD 8 | 65 | #define FMODE_PREAD 8 |
| 66 | #define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */ | 66 | #define FMODE_PWRITE FMODE_PREAD /* These go hand in hand */ |
| 67 | 67 | ||
| 68 | #define RW_MASK 1 | 68 | #define RW_MASK 1 |
| 69 | #define RWA_MASK 2 | 69 | #define RWA_MASK 2 |
| 70 | #define READ 0 | 70 | #define READ 0 |
| 71 | #define WRITE 1 | 71 | #define WRITE 1 |
| 72 | #define READA 2 /* read-ahead - don't block if no resources */ | 72 | #define READA 2 /* read-ahead - don't block if no resources */ |
| 73 | #define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */ | 73 | #define SWRITE 3 /* for ll_rw_block() - wait for buffer lock */ |
| 74 | #define SPECIAL 4 /* For non-blockdevice requests in request queue */ | 74 | #define SPECIAL 4 /* For non-blockdevice requests in request queue */ |
| 75 | #define READ_SYNC (READ | (1 << BIO_RW_SYNC)) | 75 | #define READ_SYNC (READ | (1 << BIO_RW_SYNC)) |
| 76 | #define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNC)) | 76 | #define WRITE_SYNC (WRITE | (1 << BIO_RW_SYNC)) |
| 77 | #define WRITE_BARRIER ((1 << BIO_RW) | (1 << BIO_RW_BARRIER)) | 77 | #define WRITE_BARRIER ((1 << BIO_RW) | (1 << BIO_RW_BARRIER)) |
| 78 | 78 | ||
| 79 | #define SEL_IN 1 | 79 | #define SEL_IN 1 |
| 80 | #define SEL_OUT 2 | 80 | #define SEL_OUT 2 |
| 81 | #define SEL_EX 4 | 81 | #define SEL_EX 4 |
| 82 | 82 | ||
| 83 | /* public flags for file_system_type */ | 83 | /* public flags for file_system_type */ |
| 84 | #define FS_REQUIRES_DEV 1 | 84 | #define FS_REQUIRES_DEV 1 |
| 85 | #define FS_BINARY_MOUNTDATA 2 | 85 | #define FS_BINARY_MOUNTDATA 2 |
| 86 | #define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */ | 86 | #define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */ |
| 87 | #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon | 87 | #define FS_ODD_RENAME 32768 /* Temporary stuff; will go away as soon |
| 88 | * as nfs_rename() will be cleaned up | 88 | * as nfs_rename() will be cleaned up |
| 89 | */ | 89 | */ |
| 90 | /* | 90 | /* |
| 91 | * These are the fs-independent mount-flags: up to 32 flags are supported | 91 | * These are the fs-independent mount-flags: up to 32 flags are supported |
| 92 | */ | 92 | */ |
| 93 | #define MS_RDONLY 1 /* Mount read-only */ | 93 | #define MS_RDONLY 1 /* Mount read-only */ |
| 94 | #define MS_NOSUID 2 /* Ignore suid and sgid bits */ | 94 | #define MS_NOSUID 2 /* Ignore suid and sgid bits */ |
| 95 | #define MS_NODEV 4 /* Disallow access to device special files */ | 95 | #define MS_NODEV 4 /* Disallow access to device special files */ |
| 96 | #define MS_NOEXEC 8 /* Disallow program execution */ | 96 | #define MS_NOEXEC 8 /* Disallow program execution */ |
| 97 | #define MS_SYNCHRONOUS 16 /* Writes are synced at once */ | 97 | #define MS_SYNCHRONOUS 16 /* Writes are synced at once */ |
| 98 | #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ | 98 | #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ |
| 99 | #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ | 99 | #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ |
| 100 | #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ | 100 | #define MS_DIRSYNC 128 /* Directory modifications are synchronous */ |
| 101 | #define MS_NOATIME 1024 /* Do not update access times. */ | 101 | #define MS_NOATIME 1024 /* Do not update access times. */ |
| 102 | #define MS_NODIRATIME 2048 /* Do not update directory access times */ | 102 | #define MS_NODIRATIME 2048 /* Do not update directory access times */ |
| 103 | #define MS_BIND 4096 | 103 | #define MS_BIND 4096 |
| 104 | #define MS_MOVE 8192 | 104 | #define MS_MOVE 8192 |
| 105 | #define MS_REC 16384 | 105 | #define MS_REC 16384 |
| 106 | #define MS_VERBOSE 32768 | 106 | #define MS_VERBOSE 32768 /* War is peace. Verbosity is silence. |
| 107 | MS_VERBOSE is deprecated. */ | ||
| 108 | #define MS_SILENT 32768 | ||
| 107 | #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ | 109 | #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ |
| 108 | #define MS_UNBINDABLE (1<<17) /* change to unbindable */ | 110 | #define MS_UNBINDABLE (1<<17) /* change to unbindable */ |
| 109 | #define MS_PRIVATE (1<<18) /* change to private */ | 111 | #define MS_PRIVATE (1<<18) /* change to private */ |
| 110 | #define MS_SLAVE (1<<19) /* change to slave */ | 112 | #define MS_SLAVE (1<<19) /* change to slave */ |
| 111 | #define MS_SHARED (1<<20) /* change to shared */ | 113 | #define MS_SHARED (1<<20) /* change to shared */ |
| 112 | #define MS_ACTIVE (1<<30) | 114 | #define MS_ACTIVE (1<<30) |
| 113 | #define MS_NOUSER (1<<31) | 115 | #define MS_NOUSER (1<<31) |
| 114 | 116 | ||
| 115 | /* | 117 | /* |
| 116 | * Superblock flags that can be altered by MS_REMOUNT | 118 | * Superblock flags that can be altered by MS_REMOUNT |
| 117 | */ | 119 | */ |
| 118 | #define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK) | 120 | #define MS_RMT_MASK (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK) |
| 119 | 121 | ||
| 120 | /* | 122 | /* |
| 121 | * Old magic mount flag and mask | 123 | * Old magic mount flag and mask |
| 122 | */ | 124 | */ |
| 123 | #define MS_MGC_VAL 0xC0ED0000 | 125 | #define MS_MGC_VAL 0xC0ED0000 |
| 124 | #define MS_MGC_MSK 0xffff0000 | 126 | #define MS_MGC_MSK 0xffff0000 |
| 125 | 127 | ||
| 126 | /* Inode flags - they have nothing to superblock flags now */ | 128 | /* Inode flags - they have nothing to superblock flags now */ |
| 127 | 129 | ||
| 128 | #define S_SYNC 1 /* Writes are synced at once */ | 130 | #define S_SYNC 1 /* Writes are synced at once */ |
| 129 | #define S_NOATIME 2 /* Do not update access times */ | 131 | #define S_NOATIME 2 /* Do not update access times */ |
| 130 | #define S_APPEND 4 /* Append-only file */ | 132 | #define S_APPEND 4 /* Append-only file */ |
| 131 | #define S_IMMUTABLE 8 /* Immutable file */ | 133 | #define S_IMMUTABLE 8 /* Immutable file */ |
| 132 | #define S_DEAD 16 /* removed, but still open directory */ | 134 | #define S_DEAD 16 /* removed, but still open directory */ |
| 133 | #define S_NOQUOTA 32 /* Inode is not counted to quota */ | 135 | #define S_NOQUOTA 32 /* Inode is not counted to quota */ |
| 134 | #define S_DIRSYNC 64 /* Directory modifications are synchronous */ | 136 | #define S_DIRSYNC 64 /* Directory modifications are synchronous */ |
| 135 | #define S_NOCMTIME 128 /* Do not update file c/mtime */ | 137 | #define S_NOCMTIME 128 /* Do not update file c/mtime */ |
| 136 | #define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */ | 138 | #define S_SWAPFILE 256 /* Do not truncate: swapon got its bmaps */ |
| 137 | #define S_PRIVATE 512 /* Inode is fs-internal */ | 139 | #define S_PRIVATE 512 /* Inode is fs-internal */ |
| 138 | 140 | ||
| 139 | /* | 141 | /* |
| 140 | * Note that nosuid etc flags are inode-specific: setting some file-system | 142 | * Note that nosuid etc flags are inode-specific: setting some file-system |
| 141 | * flags just means all the inodes inherit those flags by default. It might be | 143 | * flags just means all the inodes inherit those flags by default. It might be |
| 142 | * possible to override it selectively if you really wanted to with some | 144 | * possible to override it selectively if you really wanted to with some |
| 143 | * ioctl() that is not currently implemented. | 145 | * ioctl() that is not currently implemented. |
| 144 | * | 146 | * |
| 145 | * Exception: MS_RDONLY is always applied to the entire file system. | 147 | * Exception: MS_RDONLY is always applied to the entire file system. |
| 146 | * | 148 | * |
| 147 | * Unfortunately, it is possible to change a filesystems flags with it mounted | 149 | * Unfortunately, it is possible to change a filesystems flags with it mounted |
| 148 | * with files in use. This means that all of the inodes will not have their | 150 | * with files in use. This means that all of the inodes will not have their |
| 149 | * i_flags updated. Hence, i_flags no longer inherit the superblock mount | 151 | * i_flags updated. Hence, i_flags no longer inherit the superblock mount |
| 150 | * flags, so these have to be checked separately. -- rmk@arm.uk.linux.org | 152 | * flags, so these have to be checked separately. -- rmk@arm.uk.linux.org |
| 151 | */ | 153 | */ |
| 152 | #define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg)) | 154 | #define __IS_FLG(inode,flg) ((inode)->i_sb->s_flags & (flg)) |
| 153 | 155 | ||
| 154 | #define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY) | 156 | #define IS_RDONLY(inode) ((inode)->i_sb->s_flags & MS_RDONLY) |
| 155 | #define IS_SYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS) || \ | 157 | #define IS_SYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS) || \ |
| 156 | ((inode)->i_flags & S_SYNC)) | 158 | ((inode)->i_flags & S_SYNC)) |
| 157 | #define IS_DIRSYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \ | 159 | #define IS_DIRSYNC(inode) (__IS_FLG(inode, MS_SYNCHRONOUS|MS_DIRSYNC) || \ |
| 158 | ((inode)->i_flags & (S_SYNC|S_DIRSYNC))) | 160 | ((inode)->i_flags & (S_SYNC|S_DIRSYNC))) |
| 159 | #define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK) | 161 | #define IS_MANDLOCK(inode) __IS_FLG(inode, MS_MANDLOCK) |
| 160 | 162 | ||
| 161 | #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) | 163 | #define IS_NOQUOTA(inode) ((inode)->i_flags & S_NOQUOTA) |
| 162 | #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) | 164 | #define IS_APPEND(inode) ((inode)->i_flags & S_APPEND) |
| 163 | #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) | 165 | #define IS_IMMUTABLE(inode) ((inode)->i_flags & S_IMMUTABLE) |
| 164 | #define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL) | 166 | #define IS_POSIXACL(inode) __IS_FLG(inode, MS_POSIXACL) |
| 165 | 167 | ||
| 166 | #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD) | 168 | #define IS_DEADDIR(inode) ((inode)->i_flags & S_DEAD) |
| 167 | #define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME) | 169 | #define IS_NOCMTIME(inode) ((inode)->i_flags & S_NOCMTIME) |
| 168 | #define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE) | 170 | #define IS_SWAPFILE(inode) ((inode)->i_flags & S_SWAPFILE) |
| 169 | #define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE) | 171 | #define IS_PRIVATE(inode) ((inode)->i_flags & S_PRIVATE) |
| 170 | 172 | ||
| 171 | /* the read-only stuff doesn't really belong here, but any other place is | 173 | /* the read-only stuff doesn't really belong here, but any other place is |
| 172 | probably as bad and I don't want to create yet another include file. */ | 174 | probably as bad and I don't want to create yet another include file. */ |
| 173 | 175 | ||
| 174 | #define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */ | 176 | #define BLKROSET _IO(0x12,93) /* set device read-only (0 = read-write) */ |
| 175 | #define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */ | 177 | #define BLKROGET _IO(0x12,94) /* get read-only status (0 = read_write) */ |
| 176 | #define BLKRRPART _IO(0x12,95) /* re-read partition table */ | 178 | #define BLKRRPART _IO(0x12,95) /* re-read partition table */ |
| 177 | #define BLKGETSIZE _IO(0x12,96) /* return device size /512 (long *arg) */ | 179 | #define BLKGETSIZE _IO(0x12,96) /* return device size /512 (long *arg) */ |
| 178 | #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ | 180 | #define BLKFLSBUF _IO(0x12,97) /* flush buffer cache */ |
| 179 | #define BLKRASET _IO(0x12,98) /* set read ahead for block device */ | 181 | #define BLKRASET _IO(0x12,98) /* set read ahead for block device */ |
| 180 | #define BLKRAGET _IO(0x12,99) /* get current read ahead setting */ | 182 | #define BLKRAGET _IO(0x12,99) /* get current read ahead setting */ |
| 181 | #define BLKFRASET _IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */ | 183 | #define BLKFRASET _IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */ |
| 182 | #define BLKFRAGET _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */ | 184 | #define BLKFRAGET _IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */ |
| 183 | #define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */ | 185 | #define BLKSECTSET _IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */ |
| 184 | #define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */ | 186 | #define BLKSECTGET _IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */ |
| 185 | #define BLKSSZGET _IO(0x12,104)/* get block device sector size */ | 187 | #define BLKSSZGET _IO(0x12,104)/* get block device sector size */ |
| 186 | #if 0 | 188 | #if 0 |
| 187 | #define BLKPG _IO(0x12,105)/* See blkpg.h */ | 189 | #define BLKPG _IO(0x12,105)/* See blkpg.h */ |
| 188 | 190 | ||
| 189 | /* Some people are morons. Do not use sizeof! */ | 191 | /* Some people are morons. Do not use sizeof! */ |
| 190 | 192 | ||
| 191 | #define BLKELVGET _IOR(0x12,106,size_t)/* elevator get */ | 193 | #define BLKELVGET _IOR(0x12,106,size_t)/* elevator get */ |
| 192 | #define BLKELVSET _IOW(0x12,107,size_t)/* elevator set */ | 194 | #define BLKELVSET _IOW(0x12,107,size_t)/* elevator set */ |
| 193 | /* This was here just to show that the number is taken - | 195 | /* This was here just to show that the number is taken - |
| 194 | probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */ | 196 | probably all these _IO(0x12,*) ioctls should be moved to blkpg.h. */ |
| 195 | #endif | 197 | #endif |
| 196 | /* A jump here: 108-111 have been used for various private purposes. */ | 198 | /* A jump here: 108-111 have been used for various private purposes. */ |
| 197 | #define BLKBSZGET _IOR(0x12,112,size_t) | 199 | #define BLKBSZGET _IOR(0x12,112,size_t) |
| 198 | #define BLKBSZSET _IOW(0x12,113,size_t) | 200 | #define BLKBSZSET _IOW(0x12,113,size_t) |
| 199 | #define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ | 201 | #define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */ |
| 200 | #define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup) | 202 | #define BLKTRACESETUP _IOWR(0x12,115,struct blk_user_trace_setup) |
| 201 | #define BLKTRACESTART _IO(0x12,116) | 203 | #define BLKTRACESTART _IO(0x12,116) |
| 202 | #define BLKTRACESTOP _IO(0x12,117) | 204 | #define BLKTRACESTOP _IO(0x12,117) |
| 203 | #define BLKTRACETEARDOWN _IO(0x12,118) | 205 | #define BLKTRACETEARDOWN _IO(0x12,118) |
| 204 | 206 | ||
| 205 | #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ | 207 | #define BMAP_IOCTL 1 /* obsolete - kept for compatibility */ |
| 206 | #define FIBMAP _IO(0x00,1) /* bmap access */ | 208 | #define FIBMAP _IO(0x00,1) /* bmap access */ |
| 207 | #define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ | 209 | #define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ |
| 208 | 210 | ||
| 209 | #ifdef __KERNEL__ | 211 | #ifdef __KERNEL__ |
| 210 | 212 | ||
| 211 | #include <linux/linkage.h> | 213 | #include <linux/linkage.h> |
| 212 | #include <linux/wait.h> | 214 | #include <linux/wait.h> |
| 213 | #include <linux/types.h> | 215 | #include <linux/types.h> |
| 214 | #include <linux/kdev_t.h> | 216 | #include <linux/kdev_t.h> |
| 215 | #include <linux/dcache.h> | 217 | #include <linux/dcache.h> |
| 216 | #include <linux/stat.h> | 218 | #include <linux/stat.h> |
| 217 | #include <linux/cache.h> | 219 | #include <linux/cache.h> |
| 218 | #include <linux/kobject.h> | 220 | #include <linux/kobject.h> |
| 219 | #include <linux/list.h> | 221 | #include <linux/list.h> |
| 220 | #include <linux/radix-tree.h> | 222 | #include <linux/radix-tree.h> |
| 221 | #include <linux/prio_tree.h> | 223 | #include <linux/prio_tree.h> |
| 222 | #include <linux/init.h> | 224 | #include <linux/init.h> |
| 223 | #include <linux/sched.h> | 225 | #include <linux/sched.h> |
| 224 | #include <linux/mutex.h> | 226 | #include <linux/mutex.h> |
| 225 | 227 | ||
| 226 | #include <asm/atomic.h> | 228 | #include <asm/atomic.h> |
| 227 | #include <asm/semaphore.h> | 229 | #include <asm/semaphore.h> |
| 228 | #include <asm/byteorder.h> | 230 | #include <asm/byteorder.h> |
| 229 | 231 | ||
| 230 | struct hd_geometry; | 232 | struct hd_geometry; |
| 231 | struct iovec; | 233 | struct iovec; |
| 232 | struct nameidata; | 234 | struct nameidata; |
| 233 | struct kiocb; | 235 | struct kiocb; |
| 234 | struct pipe_inode_info; | 236 | struct pipe_inode_info; |
| 235 | struct poll_table_struct; | 237 | struct poll_table_struct; |
| 236 | struct kstatfs; | 238 | struct kstatfs; |
| 237 | struct vm_area_struct; | 239 | struct vm_area_struct; |
| 238 | struct vfsmount; | 240 | struct vfsmount; |
| 239 | 241 | ||
| 240 | extern void __init inode_init(unsigned long); | 242 | extern void __init inode_init(unsigned long); |
| 241 | extern void __init inode_init_early(void); | 243 | extern void __init inode_init_early(void); |
| 242 | extern void __init mnt_init(unsigned long); | 244 | extern void __init mnt_init(unsigned long); |
| 243 | extern void __init files_init(unsigned long); | 245 | extern void __init files_init(unsigned long); |
| 244 | 246 | ||
| 245 | struct buffer_head; | 247 | struct buffer_head; |
| 246 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, | 248 | typedef int (get_block_t)(struct inode *inode, sector_t iblock, |
| 247 | struct buffer_head *bh_result, int create); | 249 | struct buffer_head *bh_result, int create); |
| 248 | typedef int (get_blocks_t)(struct inode *inode, sector_t iblock, | 250 | typedef int (get_blocks_t)(struct inode *inode, sector_t iblock, |
| 249 | unsigned long max_blocks, | 251 | unsigned long max_blocks, |
| 250 | struct buffer_head *bh_result, int create); | 252 | struct buffer_head *bh_result, int create); |
| 251 | typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, | 253 | typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, |
| 252 | ssize_t bytes, void *private); | 254 | ssize_t bytes, void *private); |
| 253 | 255 | ||
| 254 | /* | 256 | /* |
| 255 | * Attribute flags. These should be or-ed together to figure out what | 257 | * Attribute flags. These should be or-ed together to figure out what |
| 256 | * has been changed! | 258 | * has been changed! |
| 257 | */ | 259 | */ |
| 258 | #define ATTR_MODE 1 | 260 | #define ATTR_MODE 1 |
| 259 | #define ATTR_UID 2 | 261 | #define ATTR_UID 2 |
| 260 | #define ATTR_GID 4 | 262 | #define ATTR_GID 4 |
| 261 | #define ATTR_SIZE 8 | 263 | #define ATTR_SIZE 8 |
| 262 | #define ATTR_ATIME 16 | 264 | #define ATTR_ATIME 16 |
| 263 | #define ATTR_MTIME 32 | 265 | #define ATTR_MTIME 32 |
| 264 | #define ATTR_CTIME 64 | 266 | #define ATTR_CTIME 64 |
| 265 | #define ATTR_ATIME_SET 128 | 267 | #define ATTR_ATIME_SET 128 |
| 266 | #define ATTR_MTIME_SET 256 | 268 | #define ATTR_MTIME_SET 256 |
| 267 | #define ATTR_FORCE 512 /* Not a change, but a change it */ | 269 | #define ATTR_FORCE 512 /* Not a change, but a change it */ |
| 268 | #define ATTR_ATTR_FLAG 1024 | 270 | #define ATTR_ATTR_FLAG 1024 |
| 269 | #define ATTR_KILL_SUID 2048 | 271 | #define ATTR_KILL_SUID 2048 |
| 270 | #define ATTR_KILL_SGID 4096 | 272 | #define ATTR_KILL_SGID 4096 |
| 271 | #define ATTR_FILE 8192 | 273 | #define ATTR_FILE 8192 |
| 272 | 274 | ||
| 273 | /* | 275 | /* |
| 274 | * This is the Inode Attributes structure, used for notify_change(). It | 276 | * This is the Inode Attributes structure, used for notify_change(). It |
| 275 | * uses the above definitions as flags, to know which values have changed. | 277 | * uses the above definitions as flags, to know which values have changed. |
| 276 | * Also, in this manner, a Filesystem can look at only the values it cares | 278 | * Also, in this manner, a Filesystem can look at only the values it cares |
| 277 | * about. Basically, these are the attributes that the VFS layer can | 279 | * about. Basically, these are the attributes that the VFS layer can |
| 278 | * request to change from the FS layer. | 280 | * request to change from the FS layer. |
| 279 | * | 281 | * |
| 280 | * Derek Atkins <warlord@MIT.EDU> 94-10-20 | 282 | * Derek Atkins <warlord@MIT.EDU> 94-10-20 |
| 281 | */ | 283 | */ |
| 282 | struct iattr { | 284 | struct iattr { |
| 283 | unsigned int ia_valid; | 285 | unsigned int ia_valid; |
| 284 | umode_t ia_mode; | 286 | umode_t ia_mode; |
| 285 | uid_t ia_uid; | 287 | uid_t ia_uid; |
| 286 | gid_t ia_gid; | 288 | gid_t ia_gid; |
| 287 | loff_t ia_size; | 289 | loff_t ia_size; |
| 288 | struct timespec ia_atime; | 290 | struct timespec ia_atime; |
| 289 | struct timespec ia_mtime; | 291 | struct timespec ia_mtime; |
| 290 | struct timespec ia_ctime; | 292 | struct timespec ia_ctime; |
| 291 | 293 | ||
| 292 | /* | 294 | /* |
| 293 | * Not an attribute, but an auxilary info for filesystems wanting to | 295 | * Not an attribute, but an auxilary info for filesystems wanting to |
| 294 | * implement an ftruncate() like method. NOTE: filesystem should | 296 | * implement an ftruncate() like method. NOTE: filesystem should |
| 295 | * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL). | 297 | * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL). |
| 296 | */ | 298 | */ |
| 297 | struct file *ia_file; | 299 | struct file *ia_file; |
| 298 | }; | 300 | }; |
| 299 | 301 | ||
| 300 | /* | 302 | /* |
| 301 | * Includes for diskquotas. | 303 | * Includes for diskquotas. |
| 302 | */ | 304 | */ |
| 303 | #include <linux/quota.h> | 305 | #include <linux/quota.h> |
| 304 | 306 | ||
| 305 | /** | 307 | /** |
| 306 | * enum positive_aop_returns - aop return codes with specific semantics | 308 | * enum positive_aop_returns - aop return codes with specific semantics |
| 307 | * | 309 | * |
| 308 | * @AOP_WRITEPAGE_ACTIVATE: Informs the caller that page writeback has | 310 | * @AOP_WRITEPAGE_ACTIVATE: Informs the caller that page writeback has |
| 309 | * completed, that the page is still locked, and | 311 | * completed, that the page is still locked, and |
| 310 | * should be considered active. The VM uses this hint | 312 | * should be considered active. The VM uses this hint |
| 311 | * to return the page to the active list -- it won't | 313 | * to return the page to the active list -- it won't |
| 312 | * be a candidate for writeback again in the near | 314 | * be a candidate for writeback again in the near |
| 313 | * future. Other callers must be careful to unlock | 315 | * future. Other callers must be careful to unlock |
| 314 | * the page if they get this return. Returned by | 316 | * the page if they get this return. Returned by |
| 315 | * writepage(); | 317 | * writepage(); |
| 316 | * | 318 | * |
| 317 | * @AOP_TRUNCATED_PAGE: The AOP method that was handed a locked page has | 319 | * @AOP_TRUNCATED_PAGE: The AOP method that was handed a locked page has |
| 318 | * unlocked it and the page might have been truncated. | 320 | * unlocked it and the page might have been truncated. |
| 319 | * The caller should back up to acquiring a new page and | 321 | * The caller should back up to acquiring a new page and |
| 320 | * trying again. The aop will be taking reasonable | 322 | * trying again. The aop will be taking reasonable |
| 321 | * precautions not to livelock. If the caller held a page | 323 | * precautions not to livelock. If the caller held a page |
| 322 | * reference, it should drop it before retrying. Returned | 324 | * reference, it should drop it before retrying. Returned |
| 323 | * by readpage(), prepare_write(), and commit_write(). | 325 | * by readpage(), prepare_write(), and commit_write(). |
| 324 | * | 326 | * |
| 325 | * address_space_operation functions return these large constants to indicate | 327 | * address_space_operation functions return these large constants to indicate |
| 326 | * special semantics to the caller. These are much larger than the bytes in a | 328 | * special semantics to the caller. These are much larger than the bytes in a |
| 327 | * page to allow for functions that return the number of bytes operated on in a | 329 | * page to allow for functions that return the number of bytes operated on in a |
| 328 | * given page. | 330 | * given page. |
| 329 | */ | 331 | */ |
| 330 | 332 | ||
| 331 | enum positive_aop_returns { | 333 | enum positive_aop_returns { |
| 332 | AOP_WRITEPAGE_ACTIVATE = 0x80000, | 334 | AOP_WRITEPAGE_ACTIVATE = 0x80000, |
| 333 | AOP_TRUNCATED_PAGE = 0x80001, | 335 | AOP_TRUNCATED_PAGE = 0x80001, |
| 334 | }; | 336 | }; |
| 335 | 337 | ||
| 336 | /* | 338 | /* |
| 337 | * oh the beauties of C type declarations. | 339 | * oh the beauties of C type declarations. |
| 338 | */ | 340 | */ |
| 339 | struct page; | 341 | struct page; |
| 340 | struct address_space; | 342 | struct address_space; |
| 341 | struct writeback_control; | 343 | struct writeback_control; |
| 342 | 344 | ||
| 343 | struct address_space_operations { | 345 | struct address_space_operations { |
| 344 | int (*writepage)(struct page *page, struct writeback_control *wbc); | 346 | int (*writepage)(struct page *page, struct writeback_control *wbc); |
| 345 | int (*readpage)(struct file *, struct page *); | 347 | int (*readpage)(struct file *, struct page *); |
| 346 | int (*sync_page)(struct page *); | 348 | int (*sync_page)(struct page *); |
| 347 | 349 | ||
| 348 | /* Write back some dirty pages from this mapping. */ | 350 | /* Write back some dirty pages from this mapping. */ |
| 349 | int (*writepages)(struct address_space *, struct writeback_control *); | 351 | int (*writepages)(struct address_space *, struct writeback_control *); |
| 350 | 352 | ||
| 351 | /* Set a page dirty */ | 353 | /* Set a page dirty */ |
| 352 | int (*set_page_dirty)(struct page *page); | 354 | int (*set_page_dirty)(struct page *page); |
| 353 | 355 | ||
| 354 | int (*readpages)(struct file *filp, struct address_space *mapping, | 356 | int (*readpages)(struct file *filp, struct address_space *mapping, |
| 355 | struct list_head *pages, unsigned nr_pages); | 357 | struct list_head *pages, unsigned nr_pages); |
| 356 | 358 | ||
| 357 | /* | 359 | /* |
| 358 | * ext3 requires that a successful prepare_write() call be followed | 360 | * ext3 requires that a successful prepare_write() call be followed |
| 359 | * by a commit_write() call - they must be balanced | 361 | * by a commit_write() call - they must be balanced |
| 360 | */ | 362 | */ |
| 361 | int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); | 363 | int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); |
| 362 | int (*commit_write)(struct file *, struct page *, unsigned, unsigned); | 364 | int (*commit_write)(struct file *, struct page *, unsigned, unsigned); |
| 363 | /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ | 365 | /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ |
| 364 | sector_t (*bmap)(struct address_space *, sector_t); | 366 | sector_t (*bmap)(struct address_space *, sector_t); |
| 365 | int (*invalidatepage) (struct page *, unsigned long); | 367 | int (*invalidatepage) (struct page *, unsigned long); |
| 366 | int (*releasepage) (struct page *, gfp_t); | 368 | int (*releasepage) (struct page *, gfp_t); |
| 367 | ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov, | 369 | ssize_t (*direct_IO)(int, struct kiocb *, const struct iovec *iov, |
| 368 | loff_t offset, unsigned long nr_segs); | 370 | loff_t offset, unsigned long nr_segs); |
| 369 | struct page* (*get_xip_page)(struct address_space *, sector_t, | 371 | struct page* (*get_xip_page)(struct address_space *, sector_t, |
| 370 | int); | 372 | int); |
| 371 | /* migrate the contents of a page to the specified target */ | 373 | /* migrate the contents of a page to the specified target */ |
| 372 | int (*migratepage) (struct page *, struct page *); | 374 | int (*migratepage) (struct page *, struct page *); |
| 373 | }; | 375 | }; |
| 374 | 376 | ||
| 375 | struct backing_dev_info; | 377 | struct backing_dev_info; |
| 376 | struct address_space { | 378 | struct address_space { |
| 377 | struct inode *host; /* owner: inode, block_device */ | 379 | struct inode *host; /* owner: inode, block_device */ |
| 378 | struct radix_tree_root page_tree; /* radix tree of all pages */ | 380 | struct radix_tree_root page_tree; /* radix tree of all pages */ |
| 379 | rwlock_t tree_lock; /* and rwlock protecting it */ | 381 | rwlock_t tree_lock; /* and rwlock protecting it */ |
| 380 | unsigned int i_mmap_writable;/* count VM_SHARED mappings */ | 382 | unsigned int i_mmap_writable;/* count VM_SHARED mappings */ |
| 381 | struct prio_tree_root i_mmap; /* tree of private and shared mappings */ | 383 | struct prio_tree_root i_mmap; /* tree of private and shared mappings */ |
| 382 | struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */ | 384 | struct list_head i_mmap_nonlinear;/*list VM_NONLINEAR mappings */ |
| 383 | spinlock_t i_mmap_lock; /* protect tree, count, list */ | 385 | spinlock_t i_mmap_lock; /* protect tree, count, list */ |
| 384 | unsigned int truncate_count; /* Cover race condition with truncate */ | 386 | unsigned int truncate_count; /* Cover race condition with truncate */ |
| 385 | unsigned long nrpages; /* number of total pages */ | 387 | unsigned long nrpages; /* number of total pages */ |
| 386 | pgoff_t writeback_index;/* writeback starts here */ | 388 | pgoff_t writeback_index;/* writeback starts here */ |
| 387 | struct address_space_operations *a_ops; /* methods */ | 389 | struct address_space_operations *a_ops; /* methods */ |
| 388 | unsigned long flags; /* error bits/gfp mask */ | 390 | unsigned long flags; /* error bits/gfp mask */ |
| 389 | struct backing_dev_info *backing_dev_info; /* device readahead, etc */ | 391 | struct backing_dev_info *backing_dev_info; /* device readahead, etc */ |
| 390 | spinlock_t private_lock; /* for use by the address_space */ | 392 | spinlock_t private_lock; /* for use by the address_space */ |
| 391 | struct list_head private_list; /* ditto */ | 393 | struct list_head private_list; /* ditto */ |
| 392 | struct address_space *assoc_mapping; /* ditto */ | 394 | struct address_space *assoc_mapping; /* ditto */ |
| 393 | } __attribute__((aligned(sizeof(long)))); | 395 | } __attribute__((aligned(sizeof(long)))); |
| 394 | /* | 396 | /* |
| 395 | * On most architectures that alignment is already the case; but | 397 | * On most architectures that alignment is already the case; but |
| 396 | * must be enforced here for CRIS, to let the least signficant bit | 398 | * must be enforced here for CRIS, to let the least signficant bit |
| 397 | * of struct page's "mapping" pointer be used for PAGE_MAPPING_ANON. | 399 | * of struct page's "mapping" pointer be used for PAGE_MAPPING_ANON. |
| 398 | */ | 400 | */ |
| 399 | 401 | ||
| 400 | struct block_device { | 402 | struct block_device { |
| 401 | dev_t bd_dev; /* not a kdev_t - it's a search key */ | 403 | dev_t bd_dev; /* not a kdev_t - it's a search key */ |
| 402 | struct inode * bd_inode; /* will die */ | 404 | struct inode * bd_inode; /* will die */ |
| 403 | int bd_openers; | 405 | int bd_openers; |
| 404 | struct mutex bd_mutex; /* open/close mutex */ | 406 | struct mutex bd_mutex; /* open/close mutex */ |
| 405 | struct mutex bd_mount_mutex; /* mount mutex */ | 407 | struct mutex bd_mount_mutex; /* mount mutex */ |
| 406 | struct list_head bd_inodes; | 408 | struct list_head bd_inodes; |
| 407 | void * bd_holder; | 409 | void * bd_holder; |
| 408 | int bd_holders; | 410 | int bd_holders; |
| 409 | struct block_device * bd_contains; | 411 | struct block_device * bd_contains; |
| 410 | unsigned bd_block_size; | 412 | unsigned bd_block_size; |
| 411 | struct hd_struct * bd_part; | 413 | struct hd_struct * bd_part; |
| 412 | /* number of times partitions within this device have been opened. */ | 414 | /* number of times partitions within this device have been opened. */ |
| 413 | unsigned bd_part_count; | 415 | unsigned bd_part_count; |
| 414 | int bd_invalidated; | 416 | int bd_invalidated; |
| 415 | struct gendisk * bd_disk; | 417 | struct gendisk * bd_disk; |
| 416 | struct list_head bd_list; | 418 | struct list_head bd_list; |
| 417 | struct backing_dev_info *bd_inode_backing_dev_info; | 419 | struct backing_dev_info *bd_inode_backing_dev_info; |
| 418 | /* | 420 | /* |
| 419 | * Private data. You must have bd_claim'ed the block_device | 421 | * Private data. You must have bd_claim'ed the block_device |
| 420 | * to use this. NOTE: bd_claim allows an owner to claim | 422 | * to use this. NOTE: bd_claim allows an owner to claim |
| 421 | * the same device multiple times, the owner must take special | 423 | * the same device multiple times, the owner must take special |
| 422 | * care to not mess up bd_private for that case. | 424 | * care to not mess up bd_private for that case. |
| 423 | */ | 425 | */ |
| 424 | unsigned long bd_private; | 426 | unsigned long bd_private; |
| 425 | }; | 427 | }; |
| 426 | 428 | ||
| 427 | /* | 429 | /* |
| 428 | * Radix-tree tags, for tagging dirty and writeback pages within the pagecache | 430 | * Radix-tree tags, for tagging dirty and writeback pages within the pagecache |
| 429 | * radix trees | 431 | * radix trees |
| 430 | */ | 432 | */ |
| 431 | #define PAGECACHE_TAG_DIRTY 0 | 433 | #define PAGECACHE_TAG_DIRTY 0 |
| 432 | #define PAGECACHE_TAG_WRITEBACK 1 | 434 | #define PAGECACHE_TAG_WRITEBACK 1 |
| 433 | 435 | ||
| 434 | int mapping_tagged(struct address_space *mapping, int tag); | 436 | int mapping_tagged(struct address_space *mapping, int tag); |
| 435 | 437 | ||
| 436 | /* | 438 | /* |
| 437 | * Might pages of this file be mapped into userspace? | 439 | * Might pages of this file be mapped into userspace? |
| 438 | */ | 440 | */ |
| 439 | static inline int mapping_mapped(struct address_space *mapping) | 441 | static inline int mapping_mapped(struct address_space *mapping) |
| 440 | { | 442 | { |
| 441 | return !prio_tree_empty(&mapping->i_mmap) || | 443 | return !prio_tree_empty(&mapping->i_mmap) || |
| 442 | !list_empty(&mapping->i_mmap_nonlinear); | 444 | !list_empty(&mapping->i_mmap_nonlinear); |
| 443 | } | 445 | } |
| 444 | 446 | ||
| 445 | /* | 447 | /* |
| 446 | * Might pages of this file have been modified in userspace? | 448 | * Might pages of this file have been modified in userspace? |
| 447 | * Note that i_mmap_writable counts all VM_SHARED vmas: do_mmap_pgoff | 449 | * Note that i_mmap_writable counts all VM_SHARED vmas: do_mmap_pgoff |
| 448 | * marks vma as VM_SHARED if it is shared, and the file was opened for | 450 | * marks vma as VM_SHARED if it is shared, and the file was opened for |
| 449 | * writing i.e. vma may be mprotected writable even if now readonly. | 451 | * writing i.e. vma may be mprotected writable even if now readonly. |
| 450 | */ | 452 | */ |
| 451 | static inline int mapping_writably_mapped(struct address_space *mapping) | 453 | static inline int mapping_writably_mapped(struct address_space *mapping) |
| 452 | { | 454 | { |
| 453 | return mapping->i_mmap_writable != 0; | 455 | return mapping->i_mmap_writable != 0; |
| 454 | } | 456 | } |
| 455 | 457 | ||
| 456 | /* | 458 | /* |
| 457 | * Use sequence counter to get consistent i_size on 32-bit processors. | 459 | * Use sequence counter to get consistent i_size on 32-bit processors. |
| 458 | */ | 460 | */ |
| 459 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | 461 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) |
| 460 | #include <linux/seqlock.h> | 462 | #include <linux/seqlock.h> |
| 461 | #define __NEED_I_SIZE_ORDERED | 463 | #define __NEED_I_SIZE_ORDERED |
| 462 | #define i_size_ordered_init(inode) seqcount_init(&inode->i_size_seqcount) | 464 | #define i_size_ordered_init(inode) seqcount_init(&inode->i_size_seqcount) |
| 463 | #else | 465 | #else |
| 464 | #define i_size_ordered_init(inode) do { } while (0) | 466 | #define i_size_ordered_init(inode) do { } while (0) |
| 465 | #endif | 467 | #endif |
| 466 | 468 | ||
| 467 | struct inode { | 469 | struct inode { |
| 468 | struct hlist_node i_hash; | 470 | struct hlist_node i_hash; |
| 469 | struct list_head i_list; | 471 | struct list_head i_list; |
| 470 | struct list_head i_sb_list; | 472 | struct list_head i_sb_list; |
| 471 | struct list_head i_dentry; | 473 | struct list_head i_dentry; |
| 472 | unsigned long i_ino; | 474 | unsigned long i_ino; |
| 473 | atomic_t i_count; | 475 | atomic_t i_count; |
| 474 | umode_t i_mode; | 476 | umode_t i_mode; |
| 475 | unsigned int i_nlink; | 477 | unsigned int i_nlink; |
| 476 | uid_t i_uid; | 478 | uid_t i_uid; |
| 477 | gid_t i_gid; | 479 | gid_t i_gid; |
| 478 | dev_t i_rdev; | 480 | dev_t i_rdev; |
| 479 | loff_t i_size; | 481 | loff_t i_size; |
| 480 | struct timespec i_atime; | 482 | struct timespec i_atime; |
| 481 | struct timespec i_mtime; | 483 | struct timespec i_mtime; |
| 482 | struct timespec i_ctime; | 484 | struct timespec i_ctime; |
| 483 | unsigned int i_blkbits; | 485 | unsigned int i_blkbits; |
| 484 | unsigned long i_blksize; | 486 | unsigned long i_blksize; |
| 485 | unsigned long i_version; | 487 | unsigned long i_version; |
| 486 | unsigned long i_blocks; | 488 | unsigned long i_blocks; |
| 487 | unsigned short i_bytes; | 489 | unsigned short i_bytes; |
| 488 | spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ | 490 | spinlock_t i_lock; /* i_blocks, i_bytes, maybe i_size */ |
| 489 | struct mutex i_mutex; | 491 | struct mutex i_mutex; |
| 490 | struct rw_semaphore i_alloc_sem; | 492 | struct rw_semaphore i_alloc_sem; |
| 491 | struct inode_operations *i_op; | 493 | struct inode_operations *i_op; |
| 492 | struct file_operations *i_fop; /* former ->i_op->default_file_ops */ | 494 | struct file_operations *i_fop; /* former ->i_op->default_file_ops */ |
| 493 | struct super_block *i_sb; | 495 | struct super_block *i_sb; |
| 494 | struct file_lock *i_flock; | 496 | struct file_lock *i_flock; |
| 495 | struct address_space *i_mapping; | 497 | struct address_space *i_mapping; |
| 496 | struct address_space i_data; | 498 | struct address_space i_data; |
| 497 | #ifdef CONFIG_QUOTA | 499 | #ifdef CONFIG_QUOTA |
| 498 | struct dquot *i_dquot[MAXQUOTAS]; | 500 | struct dquot *i_dquot[MAXQUOTAS]; |
| 499 | #endif | 501 | #endif |
| 500 | /* These three should probably be a union */ | 502 | /* These three should probably be a union */ |
| 501 | struct list_head i_devices; | 503 | struct list_head i_devices; |
| 502 | struct pipe_inode_info *i_pipe; | 504 | struct pipe_inode_info *i_pipe; |
| 503 | struct block_device *i_bdev; | 505 | struct block_device *i_bdev; |
| 504 | struct cdev *i_cdev; | 506 | struct cdev *i_cdev; |
| 505 | int i_cindex; | 507 | int i_cindex; |
| 506 | 508 | ||
| 507 | __u32 i_generation; | 509 | __u32 i_generation; |
| 508 | 510 | ||
| 509 | #ifdef CONFIG_DNOTIFY | 511 | #ifdef CONFIG_DNOTIFY |
| 510 | unsigned long i_dnotify_mask; /* Directory notify events */ | 512 | unsigned long i_dnotify_mask; /* Directory notify events */ |
| 511 | struct dnotify_struct *i_dnotify; /* for directory notifications */ | 513 | struct dnotify_struct *i_dnotify; /* for directory notifications */ |
| 512 | #endif | 514 | #endif |
| 513 | 515 | ||
| 514 | #ifdef CONFIG_INOTIFY | 516 | #ifdef CONFIG_INOTIFY |
| 515 | struct list_head inotify_watches; /* watches on this inode */ | 517 | struct list_head inotify_watches; /* watches on this inode */ |
| 516 | struct mutex inotify_mutex; /* protects the watches list */ | 518 | struct mutex inotify_mutex; /* protects the watches list */ |
| 517 | #endif | 519 | #endif |
| 518 | 520 | ||
| 519 | unsigned long i_state; | 521 | unsigned long i_state; |
| 520 | unsigned long dirtied_when; /* jiffies of first dirtying */ | 522 | unsigned long dirtied_when; /* jiffies of first dirtying */ |
| 521 | 523 | ||
| 522 | unsigned int i_flags; | 524 | unsigned int i_flags; |
| 523 | 525 | ||
| 524 | atomic_t i_writecount; | 526 | atomic_t i_writecount; |
| 525 | void *i_security; | 527 | void *i_security; |
| 526 | union { | 528 | union { |
| 527 | void *generic_ip; | 529 | void *generic_ip; |
| 528 | } u; | 530 | } u; |
| 529 | #ifdef __NEED_I_SIZE_ORDERED | 531 | #ifdef __NEED_I_SIZE_ORDERED |
| 530 | seqcount_t i_size_seqcount; | 532 | seqcount_t i_size_seqcount; |
| 531 | #endif | 533 | #endif |
| 532 | }; | 534 | }; |
| 533 | 535 | ||
| 534 | /* | 536 | /* |
| 535 | * NOTE: in a 32bit arch with a preemptable kernel and | 537 | * NOTE: in a 32bit arch with a preemptable kernel and |
| 536 | * an UP compile the i_size_read/write must be atomic | 538 | * an UP compile the i_size_read/write must be atomic |
| 537 | * with respect to the local cpu (unlike with preempt disabled), | 539 | * with respect to the local cpu (unlike with preempt disabled), |
| 538 | * but they don't need to be atomic with respect to other cpus like in | 540 | * but they don't need to be atomic with respect to other cpus like in |
| 539 | * true SMP (so they need either to either locally disable irq around | 541 | * true SMP (so they need either to either locally disable irq around |
| 540 | * the read or for example on x86 they can be still implemented as a | 542 | * the read or for example on x86 they can be still implemented as a |
| 541 | * cmpxchg8b without the need of the lock prefix). For SMP compiles | 543 | * cmpxchg8b without the need of the lock prefix). For SMP compiles |
| 542 | * and 64bit archs it makes no difference if preempt is enabled or not. | 544 | * and 64bit archs it makes no difference if preempt is enabled or not. |
| 543 | */ | 545 | */ |
| 544 | static inline loff_t i_size_read(struct inode *inode) | 546 | static inline loff_t i_size_read(struct inode *inode) |
| 545 | { | 547 | { |
| 546 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | 548 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) |
| 547 | loff_t i_size; | 549 | loff_t i_size; |
| 548 | unsigned int seq; | 550 | unsigned int seq; |
| 549 | 551 | ||
| 550 | do { | 552 | do { |
| 551 | seq = read_seqcount_begin(&inode->i_size_seqcount); | 553 | seq = read_seqcount_begin(&inode->i_size_seqcount); |
| 552 | i_size = inode->i_size; | 554 | i_size = inode->i_size; |
| 553 | } while (read_seqcount_retry(&inode->i_size_seqcount, seq)); | 555 | } while (read_seqcount_retry(&inode->i_size_seqcount, seq)); |
| 554 | return i_size; | 556 | return i_size; |
| 555 | #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT) | 557 | #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT) |
| 556 | loff_t i_size; | 558 | loff_t i_size; |
| 557 | 559 | ||
| 558 | preempt_disable(); | 560 | preempt_disable(); |
| 559 | i_size = inode->i_size; | 561 | i_size = inode->i_size; |
| 560 | preempt_enable(); | 562 | preempt_enable(); |
| 561 | return i_size; | 563 | return i_size; |
| 562 | #else | 564 | #else |
| 563 | return inode->i_size; | 565 | return inode->i_size; |
| 564 | #endif | 566 | #endif |
| 565 | } | 567 | } |
| 566 | 568 | ||
| 567 | 569 | ||
| 568 | static inline void i_size_write(struct inode *inode, loff_t i_size) | 570 | static inline void i_size_write(struct inode *inode, loff_t i_size) |
| 569 | { | 571 | { |
| 570 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) | 572 | #if BITS_PER_LONG==32 && defined(CONFIG_SMP) |
| 571 | write_seqcount_begin(&inode->i_size_seqcount); | 573 | write_seqcount_begin(&inode->i_size_seqcount); |
| 572 | inode->i_size = i_size; | 574 | inode->i_size = i_size; |
| 573 | write_seqcount_end(&inode->i_size_seqcount); | 575 | write_seqcount_end(&inode->i_size_seqcount); |
| 574 | #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT) | 576 | #elif BITS_PER_LONG==32 && defined(CONFIG_PREEMPT) |
| 575 | preempt_disable(); | 577 | preempt_disable(); |
| 576 | inode->i_size = i_size; | 578 | inode->i_size = i_size; |
| 577 | preempt_enable(); | 579 | preempt_enable(); |
| 578 | #else | 580 | #else |
| 579 | inode->i_size = i_size; | 581 | inode->i_size = i_size; |
| 580 | #endif | 582 | #endif |
| 581 | } | 583 | } |
| 582 | 584 | ||
| 583 | static inline unsigned iminor(struct inode *inode) | 585 | static inline unsigned iminor(struct inode *inode) |
| 584 | { | 586 | { |
| 585 | return MINOR(inode->i_rdev); | 587 | return MINOR(inode->i_rdev); |
| 586 | } | 588 | } |
| 587 | 589 | ||
| 588 | static inline unsigned imajor(struct inode *inode) | 590 | static inline unsigned imajor(struct inode *inode) |
| 589 | { | 591 | { |
| 590 | return MAJOR(inode->i_rdev); | 592 | return MAJOR(inode->i_rdev); |
| 591 | } | 593 | } |
| 592 | 594 | ||
| 593 | extern struct block_device *I_BDEV(struct inode *inode); | 595 | extern struct block_device *I_BDEV(struct inode *inode); |
| 594 | 596 | ||
| 595 | struct fown_struct { | 597 | struct fown_struct { |
| 596 | rwlock_t lock; /* protects pid, uid, euid fields */ | 598 | rwlock_t lock; /* protects pid, uid, euid fields */ |
| 597 | int pid; /* pid or -pgrp where SIGIO should be sent */ | 599 | int pid; /* pid or -pgrp where SIGIO should be sent */ |
| 598 | uid_t uid, euid; /* uid/euid of process setting the owner */ | 600 | uid_t uid, euid; /* uid/euid of process setting the owner */ |
| 599 | void *security; | 601 | void *security; |
| 600 | int signum; /* posix.1b rt signal to be delivered on IO */ | 602 | int signum; /* posix.1b rt signal to be delivered on IO */ |
| 601 | }; | 603 | }; |
| 602 | 604 | ||
| 603 | /* | 605 | /* |
| 604 | * Track a single file's readahead state | 606 | * Track a single file's readahead state |
| 605 | */ | 607 | */ |
| 606 | struct file_ra_state { | 608 | struct file_ra_state { |
| 607 | unsigned long start; /* Current window */ | 609 | unsigned long start; /* Current window */ |
| 608 | unsigned long size; | 610 | unsigned long size; |
| 609 | unsigned long flags; /* ra flags RA_FLAG_xxx*/ | 611 | unsigned long flags; /* ra flags RA_FLAG_xxx*/ |
| 610 | unsigned long cache_hit; /* cache hit count*/ | 612 | unsigned long cache_hit; /* cache hit count*/ |
| 611 | unsigned long prev_page; /* Cache last read() position */ | 613 | unsigned long prev_page; /* Cache last read() position */ |
| 612 | unsigned long ahead_start; /* Ahead window */ | 614 | unsigned long ahead_start; /* Ahead window */ |
| 613 | unsigned long ahead_size; | 615 | unsigned long ahead_size; |
| 614 | unsigned long ra_pages; /* Maximum readahead window */ | 616 | unsigned long ra_pages; /* Maximum readahead window */ |
| 615 | unsigned long mmap_hit; /* Cache hit stat for mmap accesses */ | 617 | unsigned long mmap_hit; /* Cache hit stat for mmap accesses */ |
| 616 | unsigned long mmap_miss; /* Cache miss stat for mmap accesses */ | 618 | unsigned long mmap_miss; /* Cache miss stat for mmap accesses */ |
| 617 | }; | 619 | }; |
| 618 | #define RA_FLAG_MISS 0x01 /* a cache miss occured against this file */ | 620 | #define RA_FLAG_MISS 0x01 /* a cache miss occured against this file */ |
| 619 | #define RA_FLAG_INCACHE 0x02 /* file is already in cache */ | 621 | #define RA_FLAG_INCACHE 0x02 /* file is already in cache */ |
| 620 | 622 | ||
| 621 | struct file { | 623 | struct file { |
| 622 | /* | 624 | /* |
| 623 | * fu_list becomes invalid after file_free is called and queued via | 625 | * fu_list becomes invalid after file_free is called and queued via |
| 624 | * fu_rcuhead for RCU freeing | 626 | * fu_rcuhead for RCU freeing |
| 625 | */ | 627 | */ |
| 626 | union { | 628 | union { |
| 627 | struct list_head fu_list; | 629 | struct list_head fu_list; |
| 628 | struct rcu_head fu_rcuhead; | 630 | struct rcu_head fu_rcuhead; |
| 629 | } f_u; | 631 | } f_u; |
| 630 | struct dentry *f_dentry; | 632 | struct dentry *f_dentry; |
| 631 | struct vfsmount *f_vfsmnt; | 633 | struct vfsmount *f_vfsmnt; |
| 632 | struct file_operations *f_op; | 634 | struct file_operations *f_op; |
| 633 | atomic_t f_count; | 635 | atomic_t f_count; |
| 634 | unsigned int f_flags; | 636 | unsigned int f_flags; |
| 635 | mode_t f_mode; | 637 | mode_t f_mode; |
| 636 | loff_t f_pos; | 638 | loff_t f_pos; |
| 637 | struct fown_struct f_owner; | 639 | struct fown_struct f_owner; |
| 638 | unsigned int f_uid, f_gid; | 640 | unsigned int f_uid, f_gid; |
| 639 | struct file_ra_state f_ra; | 641 | struct file_ra_state f_ra; |
| 640 | 642 | ||
| 641 | unsigned long f_version; | 643 | unsigned long f_version; |
| 642 | void *f_security; | 644 | void *f_security; |
| 643 | 645 | ||
| 644 | /* needed for tty driver, and maybe others */ | 646 | /* needed for tty driver, and maybe others */ |
| 645 | void *private_data; | 647 | void *private_data; |
| 646 | 648 | ||
| 647 | #ifdef CONFIG_EPOLL | 649 | #ifdef CONFIG_EPOLL |
| 648 | /* Used by fs/eventpoll.c to link all the hooks to this file */ | 650 | /* Used by fs/eventpoll.c to link all the hooks to this file */ |
| 649 | struct list_head f_ep_links; | 651 | struct list_head f_ep_links; |
| 650 | spinlock_t f_ep_lock; | 652 | spinlock_t f_ep_lock; |
| 651 | #endif /* #ifdef CONFIG_EPOLL */ | 653 | #endif /* #ifdef CONFIG_EPOLL */ |
| 652 | struct address_space *f_mapping; | 654 | struct address_space *f_mapping; |
| 653 | }; | 655 | }; |
| 654 | extern spinlock_t files_lock; | 656 | extern spinlock_t files_lock; |
| 655 | #define file_list_lock() spin_lock(&files_lock); | 657 | #define file_list_lock() spin_lock(&files_lock); |
| 656 | #define file_list_unlock() spin_unlock(&files_lock); | 658 | #define file_list_unlock() spin_unlock(&files_lock); |
| 657 | 659 | ||
| 658 | #define get_file(x) atomic_inc(&(x)->f_count) | 660 | #define get_file(x) atomic_inc(&(x)->f_count) |
| 659 | #define file_count(x) atomic_read(&(x)->f_count) | 661 | #define file_count(x) atomic_read(&(x)->f_count) |
| 660 | 662 | ||
| 661 | #define MAX_NON_LFS ((1UL<<31) - 1) | 663 | #define MAX_NON_LFS ((1UL<<31) - 1) |
| 662 | 664 | ||
| 663 | /* Page cache limit. The filesystems should put that into their s_maxbytes | 665 | /* Page cache limit. The filesystems should put that into their s_maxbytes |
| 664 | limits, otherwise bad things can happen in VM. */ | 666 | limits, otherwise bad things can happen in VM. */ |
| 665 | #if BITS_PER_LONG==32 | 667 | #if BITS_PER_LONG==32 |
| 666 | #define MAX_LFS_FILESIZE (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) | 668 | #define MAX_LFS_FILESIZE (((u64)PAGE_CACHE_SIZE << (BITS_PER_LONG-1))-1) |
| 667 | #elif BITS_PER_LONG==64 | 669 | #elif BITS_PER_LONG==64 |
| 668 | #define MAX_LFS_FILESIZE 0x7fffffffffffffffUL | 670 | #define MAX_LFS_FILESIZE 0x7fffffffffffffffUL |
| 669 | #endif | 671 | #endif |
| 670 | 672 | ||
| 671 | #define FL_POSIX 1 | 673 | #define FL_POSIX 1 |
| 672 | #define FL_FLOCK 2 | 674 | #define FL_FLOCK 2 |
| 673 | #define FL_ACCESS 8 /* not trying to lock, just looking */ | 675 | #define FL_ACCESS 8 /* not trying to lock, just looking */ |
| 674 | #define FL_LOCKD 16 /* lock held by rpc.lockd */ | 676 | #define FL_LOCKD 16 /* lock held by rpc.lockd */ |
| 675 | #define FL_LEASE 32 /* lease held on this file */ | 677 | #define FL_LEASE 32 /* lease held on this file */ |
| 676 | #define FL_SLEEP 128 /* A blocking lock */ | 678 | #define FL_SLEEP 128 /* A blocking lock */ |
| 677 | 679 | ||
| 678 | /* | 680 | /* |
| 679 | * The POSIX file lock owner is determined by | 681 | * The POSIX file lock owner is determined by |
| 680 | * the "struct files_struct" in the thread group | 682 | * the "struct files_struct" in the thread group |
| 681 | * (or NULL for no owner - BSD locks). | 683 | * (or NULL for no owner - BSD locks). |
| 682 | * | 684 | * |
| 683 | * Lockd stuffs a "host" pointer into this. | 685 | * Lockd stuffs a "host" pointer into this. |
| 684 | */ | 686 | */ |
| 685 | typedef struct files_struct *fl_owner_t; | 687 | typedef struct files_struct *fl_owner_t; |
| 686 | 688 | ||
| 687 | struct file_lock_operations { | 689 | struct file_lock_operations { |
| 688 | void (*fl_insert)(struct file_lock *); /* lock insertion callback */ | 690 | void (*fl_insert)(struct file_lock *); /* lock insertion callback */ |
| 689 | void (*fl_remove)(struct file_lock *); /* lock removal callback */ | 691 | void (*fl_remove)(struct file_lock *); /* lock removal callback */ |
| 690 | void (*fl_copy_lock)(struct file_lock *, struct file_lock *); | 692 | void (*fl_copy_lock)(struct file_lock *, struct file_lock *); |
| 691 | void (*fl_release_private)(struct file_lock *); | 693 | void (*fl_release_private)(struct file_lock *); |
| 692 | }; | 694 | }; |
| 693 | 695 | ||
| 694 | struct lock_manager_operations { | 696 | struct lock_manager_operations { |
| 695 | int (*fl_compare_owner)(struct file_lock *, struct file_lock *); | 697 | int (*fl_compare_owner)(struct file_lock *, struct file_lock *); |
| 696 | void (*fl_notify)(struct file_lock *); /* unblock callback */ | 698 | void (*fl_notify)(struct file_lock *); /* unblock callback */ |
| 697 | void (*fl_copy_lock)(struct file_lock *, struct file_lock *); | 699 | void (*fl_copy_lock)(struct file_lock *, struct file_lock *); |
| 698 | void (*fl_release_private)(struct file_lock *); | 700 | void (*fl_release_private)(struct file_lock *); |
| 699 | void (*fl_break)(struct file_lock *); | 701 | void (*fl_break)(struct file_lock *); |
| 700 | int (*fl_mylease)(struct file_lock *, struct file_lock *); | 702 | int (*fl_mylease)(struct file_lock *, struct file_lock *); |
| 701 | int (*fl_change)(struct file_lock **, int); | 703 | int (*fl_change)(struct file_lock **, int); |
| 702 | }; | 704 | }; |
| 703 | 705 | ||
| 704 | /* that will die - we need it for nfs_lock_info */ | 706 | /* that will die - we need it for nfs_lock_info */ |
| 705 | #include <linux/nfs_fs_i.h> | 707 | #include <linux/nfs_fs_i.h> |
| 706 | 708 | ||
| 707 | struct file_lock { | 709 | struct file_lock { |
| 708 | struct file_lock *fl_next; /* singly linked list for this inode */ | 710 | struct file_lock *fl_next; /* singly linked list for this inode */ |
| 709 | struct list_head fl_link; /* doubly linked list of all locks */ | 711 | struct list_head fl_link; /* doubly linked list of all locks */ |
| 710 | struct list_head fl_block; /* circular list of blocked processes */ | 712 | struct list_head fl_block; /* circular list of blocked processes */ |
| 711 | fl_owner_t fl_owner; | 713 | fl_owner_t fl_owner; |
| 712 | unsigned int fl_pid; | 714 | unsigned int fl_pid; |
| 713 | wait_queue_head_t fl_wait; | 715 | wait_queue_head_t fl_wait; |
| 714 | struct file *fl_file; | 716 | struct file *fl_file; |
| 715 | unsigned char fl_flags; | 717 | unsigned char fl_flags; |
| 716 | unsigned char fl_type; | 718 | unsigned char fl_type; |
| 717 | loff_t fl_start; | 719 | loff_t fl_start; |
| 718 | loff_t fl_end; | 720 | loff_t fl_end; |
| 719 | 721 | ||
| 720 | struct fasync_struct * fl_fasync; /* for lease break notifications */ | 722 | struct fasync_struct * fl_fasync; /* for lease break notifications */ |
| 721 | unsigned long fl_break_time; /* for nonblocking lease breaks */ | 723 | unsigned long fl_break_time; /* for nonblocking lease breaks */ |
| 722 | 724 | ||
| 723 | struct file_lock_operations *fl_ops; /* Callbacks for filesystems */ | 725 | struct file_lock_operations *fl_ops; /* Callbacks for filesystems */ |
| 724 | struct lock_manager_operations *fl_lmops; /* Callbacks for lockmanagers */ | 726 | struct lock_manager_operations *fl_lmops; /* Callbacks for lockmanagers */ |
| 725 | union { | 727 | union { |
| 726 | struct nfs_lock_info nfs_fl; | 728 | struct nfs_lock_info nfs_fl; |
| 727 | struct nfs4_lock_info nfs4_fl; | 729 | struct nfs4_lock_info nfs4_fl; |
| 728 | } fl_u; | 730 | } fl_u; |
| 729 | }; | 731 | }; |
| 730 | 732 | ||
| 731 | /* The following constant reflects the upper bound of the file/locking space */ | 733 | /* The following constant reflects the upper bound of the file/locking space */ |
| 732 | #ifndef OFFSET_MAX | 734 | #ifndef OFFSET_MAX |
| 733 | #define INT_LIMIT(x) (~((x)1 << (sizeof(x)*8 - 1))) | 735 | #define INT_LIMIT(x) (~((x)1 << (sizeof(x)*8 - 1))) |
| 734 | #define OFFSET_MAX INT_LIMIT(loff_t) | 736 | #define OFFSET_MAX INT_LIMIT(loff_t) |
| 735 | #define OFFT_OFFSET_MAX INT_LIMIT(off_t) | 737 | #define OFFT_OFFSET_MAX INT_LIMIT(off_t) |
| 736 | #endif | 738 | #endif |
| 737 | 739 | ||
| 738 | extern struct list_head file_lock_list; | 740 | extern struct list_head file_lock_list; |
| 739 | 741 | ||
| 740 | #include <linux/fcntl.h> | 742 | #include <linux/fcntl.h> |
| 741 | 743 | ||
| 742 | extern int fcntl_getlk(struct file *, struct flock __user *); | 744 | extern int fcntl_getlk(struct file *, struct flock __user *); |
| 743 | extern int fcntl_setlk(unsigned int, struct file *, unsigned int, | 745 | extern int fcntl_setlk(unsigned int, struct file *, unsigned int, |
| 744 | struct flock __user *); | 746 | struct flock __user *); |
| 745 | 747 | ||
| 746 | #if BITS_PER_LONG == 32 | 748 | #if BITS_PER_LONG == 32 |
| 747 | extern int fcntl_getlk64(struct file *, struct flock64 __user *); | 749 | extern int fcntl_getlk64(struct file *, struct flock64 __user *); |
| 748 | extern int fcntl_setlk64(unsigned int, struct file *, unsigned int, | 750 | extern int fcntl_setlk64(unsigned int, struct file *, unsigned int, |
| 749 | struct flock64 __user *); | 751 | struct flock64 __user *); |
| 750 | #endif | 752 | #endif |
| 751 | 753 | ||
| 752 | extern void send_sigio(struct fown_struct *fown, int fd, int band); | 754 | extern void send_sigio(struct fown_struct *fown, int fd, int band); |
| 753 | extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg); | 755 | extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg); |
| 754 | extern int fcntl_getlease(struct file *filp); | 756 | extern int fcntl_getlease(struct file *filp); |
| 755 | 757 | ||
| 756 | /* fs/locks.c */ | 758 | /* fs/locks.c */ |
| 757 | extern void locks_init_lock(struct file_lock *); | 759 | extern void locks_init_lock(struct file_lock *); |
| 758 | extern void locks_copy_lock(struct file_lock *, struct file_lock *); | 760 | extern void locks_copy_lock(struct file_lock *, struct file_lock *); |
| 759 | extern void locks_remove_posix(struct file *, fl_owner_t); | 761 | extern void locks_remove_posix(struct file *, fl_owner_t); |
| 760 | extern void locks_remove_flock(struct file *); | 762 | extern void locks_remove_flock(struct file *); |
| 761 | extern struct file_lock *posix_test_lock(struct file *, struct file_lock *); | 763 | extern struct file_lock *posix_test_lock(struct file *, struct file_lock *); |
| 762 | extern int posix_lock_file(struct file *, struct file_lock *); | 764 | extern int posix_lock_file(struct file *, struct file_lock *); |
| 763 | extern int posix_lock_file_wait(struct file *, struct file_lock *); | 765 | extern int posix_lock_file_wait(struct file *, struct file_lock *); |
| 764 | extern void posix_block_lock(struct file_lock *, struct file_lock *); | 766 | extern void posix_block_lock(struct file_lock *, struct file_lock *); |
| 765 | extern int posix_unblock_lock(struct file *, struct file_lock *); | 767 | extern int posix_unblock_lock(struct file *, struct file_lock *); |
| 766 | extern int posix_locks_deadlock(struct file_lock *, struct file_lock *); | 768 | extern int posix_locks_deadlock(struct file_lock *, struct file_lock *); |
| 767 | extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); | 769 | extern int flock_lock_file_wait(struct file *filp, struct file_lock *fl); |
| 768 | extern int __break_lease(struct inode *inode, unsigned int flags); | 770 | extern int __break_lease(struct inode *inode, unsigned int flags); |
| 769 | extern void lease_get_mtime(struct inode *, struct timespec *time); | 771 | extern void lease_get_mtime(struct inode *, struct timespec *time); |
| 770 | extern int setlease(struct file *, long, struct file_lock **); | 772 | extern int setlease(struct file *, long, struct file_lock **); |
| 771 | extern int lease_modify(struct file_lock **, int); | 773 | extern int lease_modify(struct file_lock **, int); |
| 772 | extern int lock_may_read(struct inode *, loff_t start, unsigned long count); | 774 | extern int lock_may_read(struct inode *, loff_t start, unsigned long count); |
| 773 | extern int lock_may_write(struct inode *, loff_t start, unsigned long count); | 775 | extern int lock_may_write(struct inode *, loff_t start, unsigned long count); |
| 774 | extern void steal_locks(fl_owner_t from); | 776 | extern void steal_locks(fl_owner_t from); |
| 775 | 777 | ||
| 776 | struct fasync_struct { | 778 | struct fasync_struct { |
| 777 | int magic; | 779 | int magic; |
| 778 | int fa_fd; | 780 | int fa_fd; |
| 779 | struct fasync_struct *fa_next; /* singly linked list */ | 781 | struct fasync_struct *fa_next; /* singly linked list */ |
| 780 | struct file *fa_file; | 782 | struct file *fa_file; |
| 781 | }; | 783 | }; |
| 782 | 784 | ||
| 783 | #define FASYNC_MAGIC 0x4601 | 785 | #define FASYNC_MAGIC 0x4601 |
| 784 | 786 | ||
| 785 | /* SMP safe fasync helpers: */ | 787 | /* SMP safe fasync helpers: */ |
| 786 | extern int fasync_helper(int, struct file *, int, struct fasync_struct **); | 788 | extern int fasync_helper(int, struct file *, int, struct fasync_struct **); |
| 787 | /* can be called from interrupts */ | 789 | /* can be called from interrupts */ |
| 788 | extern void kill_fasync(struct fasync_struct **, int, int); | 790 | extern void kill_fasync(struct fasync_struct **, int, int); |
| 789 | /* only for net: no internal synchronization */ | 791 | /* only for net: no internal synchronization */ |
| 790 | extern void __kill_fasync(struct fasync_struct *, int, int); | 792 | extern void __kill_fasync(struct fasync_struct *, int, int); |
| 791 | 793 | ||
| 792 | extern int f_setown(struct file *filp, unsigned long arg, int force); | 794 | extern int f_setown(struct file *filp, unsigned long arg, int force); |
| 793 | extern void f_delown(struct file *filp); | 795 | extern void f_delown(struct file *filp); |
| 794 | extern int send_sigurg(struct fown_struct *fown); | 796 | extern int send_sigurg(struct fown_struct *fown); |
| 795 | 797 | ||
| 796 | /* | 798 | /* |
| 797 | * Umount options | 799 | * Umount options |
| 798 | */ | 800 | */ |
| 799 | 801 | ||
| 800 | #define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */ | 802 | #define MNT_FORCE 0x00000001 /* Attempt to forcibily umount */ |
| 801 | #define MNT_DETACH 0x00000002 /* Just detach from the tree */ | 803 | #define MNT_DETACH 0x00000002 /* Just detach from the tree */ |
| 802 | #define MNT_EXPIRE 0x00000004 /* Mark for expiry */ | 804 | #define MNT_EXPIRE 0x00000004 /* Mark for expiry */ |
| 803 | 805 | ||
| 804 | extern struct list_head super_blocks; | 806 | extern struct list_head super_blocks; |
| 805 | extern spinlock_t sb_lock; | 807 | extern spinlock_t sb_lock; |
| 806 | 808 | ||
| 807 | #define sb_entry(list) list_entry((list), struct super_block, s_list) | 809 | #define sb_entry(list) list_entry((list), struct super_block, s_list) |
| 808 | #define S_BIAS (1<<30) | 810 | #define S_BIAS (1<<30) |
| 809 | struct super_block { | 811 | struct super_block { |
| 810 | struct list_head s_list; /* Keep this first */ | 812 | struct list_head s_list; /* Keep this first */ |
| 811 | dev_t s_dev; /* search index; _not_ kdev_t */ | 813 | dev_t s_dev; /* search index; _not_ kdev_t */ |
| 812 | unsigned long s_blocksize; | 814 | unsigned long s_blocksize; |
| 813 | unsigned char s_blocksize_bits; | 815 | unsigned char s_blocksize_bits; |
| 814 | unsigned char s_dirt; | 816 | unsigned char s_dirt; |
| 815 | unsigned long long s_maxbytes; /* Max file size */ | 817 | unsigned long long s_maxbytes; /* Max file size */ |
| 816 | struct file_system_type *s_type; | 818 | struct file_system_type *s_type; |
| 817 | struct super_operations *s_op; | 819 | struct super_operations *s_op; |
| 818 | struct dquot_operations *dq_op; | 820 | struct dquot_operations *dq_op; |
| 819 | struct quotactl_ops *s_qcop; | 821 | struct quotactl_ops *s_qcop; |
| 820 | struct export_operations *s_export_op; | 822 | struct export_operations *s_export_op; |
| 821 | unsigned long s_flags; | 823 | unsigned long s_flags; |
| 822 | unsigned long s_magic; | 824 | unsigned long s_magic; |
| 823 | struct dentry *s_root; | 825 | struct dentry *s_root; |
| 824 | struct rw_semaphore s_umount; | 826 | struct rw_semaphore s_umount; |
| 825 | struct mutex s_lock; | 827 | struct mutex s_lock; |
| 826 | int s_count; | 828 | int s_count; |
| 827 | int s_syncing; | 829 | int s_syncing; |
| 828 | int s_need_sync_fs; | 830 | int s_need_sync_fs; |
| 829 | atomic_t s_active; | 831 | atomic_t s_active; |
| 830 | void *s_security; | 832 | void *s_security; |
| 831 | struct xattr_handler **s_xattr; | 833 | struct xattr_handler **s_xattr; |
| 832 | 834 | ||
| 833 | struct list_head s_inodes; /* all inodes */ | 835 | struct list_head s_inodes; /* all inodes */ |
| 834 | struct list_head s_dirty; /* dirty inodes */ | 836 | struct list_head s_dirty; /* dirty inodes */ |
| 835 | struct list_head s_io; /* parked for writeback */ | 837 | struct list_head s_io; /* parked for writeback */ |
| 836 | struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ | 838 | struct hlist_head s_anon; /* anonymous dentries for (nfs) exporting */ |
| 837 | struct list_head s_files; | 839 | struct list_head s_files; |
| 838 | 840 | ||
| 839 | struct block_device *s_bdev; | 841 | struct block_device *s_bdev; |
| 840 | struct list_head s_instances; | 842 | struct list_head s_instances; |
| 841 | struct quota_info s_dquot; /* Diskquota specific options */ | 843 | struct quota_info s_dquot; /* Diskquota specific options */ |
| 842 | 844 | ||
| 843 | int s_frozen; | 845 | int s_frozen; |
| 844 | wait_queue_head_t s_wait_unfrozen; | 846 | wait_queue_head_t s_wait_unfrozen; |
| 845 | 847 | ||
| 846 | char s_id[32]; /* Informational name */ | 848 | char s_id[32]; /* Informational name */ |
| 847 | 849 | ||
| 848 | void *s_fs_info; /* Filesystem private info */ | 850 | void *s_fs_info; /* Filesystem private info */ |
| 849 | 851 | ||
| 850 | /* | 852 | /* |
| 851 | * The next field is for VFS *only*. No filesystems have any business | 853 | * The next field is for VFS *only*. No filesystems have any business |
| 852 | * even looking at it. You had been warned. | 854 | * even looking at it. You had been warned. |
| 853 | */ | 855 | */ |
| 854 | struct mutex s_vfs_rename_mutex; /* Kludge */ | 856 | struct mutex s_vfs_rename_mutex; /* Kludge */ |
| 855 | 857 | ||
| 856 | /* Granuality of c/m/atime in ns. | 858 | /* Granuality of c/m/atime in ns. |
| 857 | Cannot be worse than a second */ | 859 | Cannot be worse than a second */ |
| 858 | u32 s_time_gran; | 860 | u32 s_time_gran; |
| 859 | }; | 861 | }; |
| 860 | 862 | ||
| 861 | extern struct timespec current_fs_time(struct super_block *sb); | 863 | extern struct timespec current_fs_time(struct super_block *sb); |
| 862 | 864 | ||
| 863 | /* | 865 | /* |
| 864 | * Snapshotting support. | 866 | * Snapshotting support. |
| 865 | */ | 867 | */ |
| 866 | enum { | 868 | enum { |
| 867 | SB_UNFROZEN = 0, | 869 | SB_UNFROZEN = 0, |
| 868 | SB_FREEZE_WRITE = 1, | 870 | SB_FREEZE_WRITE = 1, |
| 869 | SB_FREEZE_TRANS = 2, | 871 | SB_FREEZE_TRANS = 2, |
| 870 | }; | 872 | }; |
| 871 | 873 | ||
| 872 | #define vfs_check_frozen(sb, level) \ | 874 | #define vfs_check_frozen(sb, level) \ |
| 873 | wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) | 875 | wait_event((sb)->s_wait_unfrozen, ((sb)->s_frozen < (level))) |
| 874 | 876 | ||
| 875 | static inline void get_fs_excl(void) | 877 | static inline void get_fs_excl(void) |
| 876 | { | 878 | { |
| 877 | atomic_inc(¤t->fs_excl); | 879 | atomic_inc(¤t->fs_excl); |
| 878 | } | 880 | } |
| 879 | 881 | ||
| 880 | static inline void put_fs_excl(void) | 882 | static inline void put_fs_excl(void) |
| 881 | { | 883 | { |
| 882 | atomic_dec(¤t->fs_excl); | 884 | atomic_dec(¤t->fs_excl); |
| 883 | } | 885 | } |
| 884 | 886 | ||
| 885 | static inline int has_fs_excl(void) | 887 | static inline int has_fs_excl(void) |
| 886 | { | 888 | { |
| 887 | return atomic_read(¤t->fs_excl); | 889 | return atomic_read(¤t->fs_excl); |
| 888 | } | 890 | } |
| 889 | 891 | ||
| 890 | 892 | ||
| 891 | /* | 893 | /* |
| 892 | * Superblock locking. | 894 | * Superblock locking. |
| 893 | */ | 895 | */ |
| 894 | static inline void lock_super(struct super_block * sb) | 896 | static inline void lock_super(struct super_block * sb) |
| 895 | { | 897 | { |
| 896 | get_fs_excl(); | 898 | get_fs_excl(); |
| 897 | mutex_lock(&sb->s_lock); | 899 | mutex_lock(&sb->s_lock); |
| 898 | } | 900 | } |
| 899 | 901 | ||
| 900 | static inline void unlock_super(struct super_block * sb) | 902 | static inline void unlock_super(struct super_block * sb) |
| 901 | { | 903 | { |
| 902 | put_fs_excl(); | 904 | put_fs_excl(); |
| 903 | mutex_unlock(&sb->s_lock); | 905 | mutex_unlock(&sb->s_lock); |
| 904 | } | 906 | } |
| 905 | 907 | ||
| 906 | /* | 908 | /* |
| 907 | * VFS helper functions.. | 909 | * VFS helper functions.. |
| 908 | */ | 910 | */ |
| 909 | extern int vfs_permission(struct nameidata *, int); | 911 | extern int vfs_permission(struct nameidata *, int); |
| 910 | extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); | 912 | extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); |
| 911 | extern int vfs_mkdir(struct inode *, struct dentry *, int); | 913 | extern int vfs_mkdir(struct inode *, struct dentry *, int); |
| 912 | extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); | 914 | extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); |
| 913 | extern int vfs_symlink(struct inode *, struct dentry *, const char *, int); | 915 | extern int vfs_symlink(struct inode *, struct dentry *, const char *, int); |
| 914 | extern int vfs_link(struct dentry *, struct inode *, struct dentry *); | 916 | extern int vfs_link(struct dentry *, struct inode *, struct dentry *); |
| 915 | extern int vfs_rmdir(struct inode *, struct dentry *); | 917 | extern int vfs_rmdir(struct inode *, struct dentry *); |
| 916 | extern int vfs_unlink(struct inode *, struct dentry *); | 918 | extern int vfs_unlink(struct inode *, struct dentry *); |
| 917 | extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); | 919 | extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); |
| 918 | 920 | ||
| 919 | /* | 921 | /* |
| 920 | * VFS dentry helper functions. | 922 | * VFS dentry helper functions. |
| 921 | */ | 923 | */ |
| 922 | extern void dentry_unhash(struct dentry *dentry); | 924 | extern void dentry_unhash(struct dentry *dentry); |
| 923 | 925 | ||
| 924 | /* | 926 | /* |
| 925 | * VFS file helper functions. | 927 | * VFS file helper functions. |
| 926 | */ | 928 | */ |
| 927 | extern int file_permission(struct file *, int); | 929 | extern int file_permission(struct file *, int); |
| 928 | 930 | ||
| 929 | /* | 931 | /* |
| 930 | * File types | 932 | * File types |
| 931 | * | 933 | * |
| 932 | * NOTE! These match bits 12..15 of stat.st_mode | 934 | * NOTE! These match bits 12..15 of stat.st_mode |
| 933 | * (ie "(i_mode >> 12) & 15"). | 935 | * (ie "(i_mode >> 12) & 15"). |
| 934 | */ | 936 | */ |
| 935 | #define DT_UNKNOWN 0 | 937 | #define DT_UNKNOWN 0 |
| 936 | #define DT_FIFO 1 | 938 | #define DT_FIFO 1 |
| 937 | #define DT_CHR 2 | 939 | #define DT_CHR 2 |
| 938 | #define DT_DIR 4 | 940 | #define DT_DIR 4 |
| 939 | #define DT_BLK 6 | 941 | #define DT_BLK 6 |
| 940 | #define DT_REG 8 | 942 | #define DT_REG 8 |
| 941 | #define DT_LNK 10 | 943 | #define DT_LNK 10 |
| 942 | #define DT_SOCK 12 | 944 | #define DT_SOCK 12 |
| 943 | #define DT_WHT 14 | 945 | #define DT_WHT 14 |
| 944 | 946 | ||
| 945 | #define OSYNC_METADATA (1<<0) | 947 | #define OSYNC_METADATA (1<<0) |
| 946 | #define OSYNC_DATA (1<<1) | 948 | #define OSYNC_DATA (1<<1) |
| 947 | #define OSYNC_INODE (1<<2) | 949 | #define OSYNC_INODE (1<<2) |
| 948 | int generic_osync_inode(struct inode *, struct address_space *, int); | 950 | int generic_osync_inode(struct inode *, struct address_space *, int); |
| 949 | 951 | ||
| 950 | /* | 952 | /* |
| 951 | * This is the "filldir" function type, used by readdir() to let | 953 | * This is the "filldir" function type, used by readdir() to let |
| 952 | * the kernel specify what kind of dirent layout it wants to have. | 954 | * the kernel specify what kind of dirent layout it wants to have. |
| 953 | * This allows the kernel to read directories into kernel space or | 955 | * This allows the kernel to read directories into kernel space or |
| 954 | * to have different dirent layouts depending on the binary type. | 956 | * to have different dirent layouts depending on the binary type. |
| 955 | */ | 957 | */ |
| 956 | typedef int (*filldir_t)(void *, const char *, int, loff_t, ino_t, unsigned); | 958 | typedef int (*filldir_t)(void *, const char *, int, loff_t, ino_t, unsigned); |
| 957 | 959 | ||
| 958 | struct block_device_operations { | 960 | struct block_device_operations { |
| 959 | int (*open) (struct inode *, struct file *); | 961 | int (*open) (struct inode *, struct file *); |
| 960 | int (*release) (struct inode *, struct file *); | 962 | int (*release) (struct inode *, struct file *); |
| 961 | int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); | 963 | int (*ioctl) (struct inode *, struct file *, unsigned, unsigned long); |
| 962 | long (*unlocked_ioctl) (struct file *, unsigned, unsigned long); | 964 | long (*unlocked_ioctl) (struct file *, unsigned, unsigned long); |
| 963 | long (*compat_ioctl) (struct file *, unsigned, unsigned long); | 965 | long (*compat_ioctl) (struct file *, unsigned, unsigned long); |
| 964 | int (*direct_access) (struct block_device *, sector_t, unsigned long *); | 966 | int (*direct_access) (struct block_device *, sector_t, unsigned long *); |
| 965 | int (*media_changed) (struct gendisk *); | 967 | int (*media_changed) (struct gendisk *); |
| 966 | int (*revalidate_disk) (struct gendisk *); | 968 | int (*revalidate_disk) (struct gendisk *); |
| 967 | int (*getgeo)(struct block_device *, struct hd_geometry *); | 969 | int (*getgeo)(struct block_device *, struct hd_geometry *); |
| 968 | struct module *owner; | 970 | struct module *owner; |
| 969 | }; | 971 | }; |
| 970 | 972 | ||
| 971 | /* | 973 | /* |
| 972 | * "descriptor" for what we're up to with a read for sendfile(). | 974 | * "descriptor" for what we're up to with a read for sendfile(). |
| 973 | * This allows us to use the same read code yet | 975 | * This allows us to use the same read code yet |
| 974 | * have multiple different users of the data that | 976 | * have multiple different users of the data that |
| 975 | * we read from a file. | 977 | * we read from a file. |
| 976 | * | 978 | * |
| 977 | * The simplest case just copies the data to user | 979 | * The simplest case just copies the data to user |
| 978 | * mode. | 980 | * mode. |
| 979 | */ | 981 | */ |
| 980 | typedef struct { | 982 | typedef struct { |
| 981 | size_t written; | 983 | size_t written; |
| 982 | size_t count; | 984 | size_t count; |
| 983 | union { | 985 | union { |
| 984 | char __user * buf; | 986 | char __user * buf; |
| 985 | void *data; | 987 | void *data; |
| 986 | } arg; | 988 | } arg; |
| 987 | int error; | 989 | int error; |
| 988 | } read_descriptor_t; | 990 | } read_descriptor_t; |
| 989 | 991 | ||
| 990 | typedef int (*read_actor_t)(read_descriptor_t *, struct page *, unsigned long, unsigned long); | 992 | typedef int (*read_actor_t)(read_descriptor_t *, struct page *, unsigned long, unsigned long); |
| 991 | 993 | ||
| 992 | /* These macros are for out of kernel modules to test that | 994 | /* These macros are for out of kernel modules to test that |
| 993 | * the kernel supports the unlocked_ioctl and compat_ioctl | 995 | * the kernel supports the unlocked_ioctl and compat_ioctl |
| 994 | * fields in struct file_operations. */ | 996 | * fields in struct file_operations. */ |
| 995 | #define HAVE_COMPAT_IOCTL 1 | 997 | #define HAVE_COMPAT_IOCTL 1 |
| 996 | #define HAVE_UNLOCKED_IOCTL 1 | 998 | #define HAVE_UNLOCKED_IOCTL 1 |
| 997 | 999 | ||
| 998 | /* | 1000 | /* |
| 999 | * NOTE: | 1001 | * NOTE: |
| 1000 | * read, write, poll, fsync, readv, writev, unlocked_ioctl and compat_ioctl | 1002 | * read, write, poll, fsync, readv, writev, unlocked_ioctl and compat_ioctl |
| 1001 | * can be called without the big kernel lock held in all filesystems. | 1003 | * can be called without the big kernel lock held in all filesystems. |
| 1002 | */ | 1004 | */ |
| 1003 | struct file_operations { | 1005 | struct file_operations { |
| 1004 | struct module *owner; | 1006 | struct module *owner; |
| 1005 | loff_t (*llseek) (struct file *, loff_t, int); | 1007 | loff_t (*llseek) (struct file *, loff_t, int); |
| 1006 | ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); | 1008 | ssize_t (*read) (struct file *, char __user *, size_t, loff_t *); |
| 1007 | ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t); | 1009 | ssize_t (*aio_read) (struct kiocb *, char __user *, size_t, loff_t); |
| 1008 | ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); | 1010 | ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *); |
| 1009 | ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t); | 1011 | ssize_t (*aio_write) (struct kiocb *, const char __user *, size_t, loff_t); |
| 1010 | int (*readdir) (struct file *, void *, filldir_t); | 1012 | int (*readdir) (struct file *, void *, filldir_t); |
| 1011 | unsigned int (*poll) (struct file *, struct poll_table_struct *); | 1013 | unsigned int (*poll) (struct file *, struct poll_table_struct *); |
| 1012 | int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); | 1014 | int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long); |
| 1013 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); | 1015 | long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); |
| 1014 | long (*compat_ioctl) (struct file *, unsigned int, unsigned long); | 1016 | long (*compat_ioctl) (struct file *, unsigned int, unsigned long); |
| 1015 | int (*mmap) (struct file *, struct vm_area_struct *); | 1017 | int (*mmap) (struct file *, struct vm_area_struct *); |
| 1016 | int (*open) (struct inode *, struct file *); | 1018 | int (*open) (struct inode *, struct file *); |
| 1017 | int (*flush) (struct file *); | 1019 | int (*flush) (struct file *); |
| 1018 | int (*release) (struct inode *, struct file *); | 1020 | int (*release) (struct inode *, struct file *); |
| 1019 | int (*fsync) (struct file *, struct dentry *, int datasync); | 1021 | int (*fsync) (struct file *, struct dentry *, int datasync); |
| 1020 | int (*aio_fsync) (struct kiocb *, int datasync); | 1022 | int (*aio_fsync) (struct kiocb *, int datasync); |
| 1021 | int (*fasync) (int, struct file *, int); | 1023 | int (*fasync) (int, struct file *, int); |
| 1022 | int (*lock) (struct file *, int, struct file_lock *); | 1024 | int (*lock) (struct file *, int, struct file_lock *); |
| 1023 | ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); | 1025 | ssize_t (*readv) (struct file *, const struct iovec *, unsigned long, loff_t *); |
| 1024 | ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); | 1026 | ssize_t (*writev) (struct file *, const struct iovec *, unsigned long, loff_t *); |
| 1025 | ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *); | 1027 | ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *); |
| 1026 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); | 1028 | ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int); |
| 1027 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); | 1029 | unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); |
| 1028 | int (*check_flags)(int); | 1030 | int (*check_flags)(int); |
| 1029 | int (*dir_notify)(struct file *filp, unsigned long arg); | 1031 | int (*dir_notify)(struct file *filp, unsigned long arg); |
| 1030 | int (*flock) (struct file *, int, struct file_lock *); | 1032 | int (*flock) (struct file *, int, struct file_lock *); |
| 1031 | }; | 1033 | }; |
| 1032 | 1034 | ||
| 1033 | struct inode_operations { | 1035 | struct inode_operations { |
| 1034 | int (*create) (struct inode *,struct dentry *,int, struct nameidata *); | 1036 | int (*create) (struct inode *,struct dentry *,int, struct nameidata *); |
| 1035 | struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); | 1037 | struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *); |
| 1036 | int (*link) (struct dentry *,struct inode *,struct dentry *); | 1038 | int (*link) (struct dentry *,struct inode *,struct dentry *); |
| 1037 | int (*unlink) (struct inode *,struct dentry *); | 1039 | int (*unlink) (struct inode *,struct dentry *); |
| 1038 | int (*symlink) (struct inode *,struct dentry *,const char *); | 1040 | int (*symlink) (struct inode *,struct dentry *,const char *); |
| 1039 | int (*mkdir) (struct inode *,struct dentry *,int); | 1041 | int (*mkdir) (struct inode *,struct dentry *,int); |
| 1040 | int (*rmdir) (struct inode *,struct dentry *); | 1042 | int (*rmdir) (struct inode *,struct dentry *); |
| 1041 | int (*mknod) (struct inode *,struct dentry *,int,dev_t); | 1043 | int (*mknod) (struct inode *,struct dentry *,int,dev_t); |
| 1042 | int (*rename) (struct inode *, struct dentry *, | 1044 | int (*rename) (struct inode *, struct dentry *, |
| 1043 | struct inode *, struct dentry *); | 1045 | struct inode *, struct dentry *); |
| 1044 | int (*readlink) (struct dentry *, char __user *,int); | 1046 | int (*readlink) (struct dentry *, char __user *,int); |
| 1045 | void * (*follow_link) (struct dentry *, struct nameidata *); | 1047 | void * (*follow_link) (struct dentry *, struct nameidata *); |
| 1046 | void (*put_link) (struct dentry *, struct nameidata *, void *); | 1048 | void (*put_link) (struct dentry *, struct nameidata *, void *); |
| 1047 | void (*truncate) (struct inode *); | 1049 | void (*truncate) (struct inode *); |
| 1048 | int (*permission) (struct inode *, int, struct nameidata *); | 1050 | int (*permission) (struct inode *, int, struct nameidata *); |
| 1049 | int (*setattr) (struct dentry *, struct iattr *); | 1051 | int (*setattr) (struct dentry *, struct iattr *); |
| 1050 | int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); | 1052 | int (*getattr) (struct vfsmount *mnt, struct dentry *, struct kstat *); |
| 1051 | int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); | 1053 | int (*setxattr) (struct dentry *, const char *,const void *,size_t,int); |
| 1052 | ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); | 1054 | ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t); |
| 1053 | ssize_t (*listxattr) (struct dentry *, char *, size_t); | 1055 | ssize_t (*listxattr) (struct dentry *, char *, size_t); |
| 1054 | int (*removexattr) (struct dentry *, const char *); | 1056 | int (*removexattr) (struct dentry *, const char *); |
| 1055 | void (*truncate_range)(struct inode *, loff_t, loff_t); | 1057 | void (*truncate_range)(struct inode *, loff_t, loff_t); |
| 1056 | }; | 1058 | }; |
| 1057 | 1059 | ||
| 1058 | struct seq_file; | 1060 | struct seq_file; |
| 1059 | 1061 | ||
| 1060 | extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); | 1062 | extern ssize_t vfs_read(struct file *, char __user *, size_t, loff_t *); |
| 1061 | extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); | 1063 | extern ssize_t vfs_write(struct file *, const char __user *, size_t, loff_t *); |
| 1062 | extern ssize_t vfs_readv(struct file *, const struct iovec __user *, | 1064 | extern ssize_t vfs_readv(struct file *, const struct iovec __user *, |
| 1063 | unsigned long, loff_t *); | 1065 | unsigned long, loff_t *); |
| 1064 | extern ssize_t vfs_writev(struct file *, const struct iovec __user *, | 1066 | extern ssize_t vfs_writev(struct file *, const struct iovec __user *, |
| 1065 | unsigned long, loff_t *); | 1067 | unsigned long, loff_t *); |
| 1066 | 1068 | ||
| 1067 | /* | 1069 | /* |
| 1068 | * NOTE: write_inode, delete_inode, clear_inode, put_inode can be called | 1070 | * NOTE: write_inode, delete_inode, clear_inode, put_inode can be called |
| 1069 | * without the big kernel lock held in all filesystems. | 1071 | * without the big kernel lock held in all filesystems. |
| 1070 | */ | 1072 | */ |
| 1071 | struct super_operations { | 1073 | struct super_operations { |
| 1072 | struct inode *(*alloc_inode)(struct super_block *sb); | 1074 | struct inode *(*alloc_inode)(struct super_block *sb); |
| 1073 | void (*destroy_inode)(struct inode *); | 1075 | void (*destroy_inode)(struct inode *); |
| 1074 | 1076 | ||
| 1075 | void (*read_inode) (struct inode *); | 1077 | void (*read_inode) (struct inode *); |
| 1076 | 1078 | ||
| 1077 | void (*dirty_inode) (struct inode *); | 1079 | void (*dirty_inode) (struct inode *); |
| 1078 | int (*write_inode) (struct inode *, int); | 1080 | int (*write_inode) (struct inode *, int); |
| 1079 | void (*put_inode) (struct inode *); | 1081 | void (*put_inode) (struct inode *); |
| 1080 | void (*drop_inode) (struct inode *); | 1082 | void (*drop_inode) (struct inode *); |
| 1081 | void (*delete_inode) (struct inode *); | 1083 | void (*delete_inode) (struct inode *); |
| 1082 | void (*put_super) (struct super_block *); | 1084 | void (*put_super) (struct super_block *); |
| 1083 | void (*write_super) (struct super_block *); | 1085 | void (*write_super) (struct super_block *); |
| 1084 | int (*sync_fs)(struct super_block *sb, int wait); | 1086 | int (*sync_fs)(struct super_block *sb, int wait); |
| 1085 | void (*write_super_lockfs) (struct super_block *); | 1087 | void (*write_super_lockfs) (struct super_block *); |
| 1086 | void (*unlockfs) (struct super_block *); | 1088 | void (*unlockfs) (struct super_block *); |
| 1087 | int (*statfs) (struct super_block *, struct kstatfs *); | 1089 | int (*statfs) (struct super_block *, struct kstatfs *); |
| 1088 | int (*remount_fs) (struct super_block *, int *, char *); | 1090 | int (*remount_fs) (struct super_block *, int *, char *); |
| 1089 | void (*clear_inode) (struct inode *); | 1091 | void (*clear_inode) (struct inode *); |
| 1090 | void (*umount_begin) (struct super_block *); | 1092 | void (*umount_begin) (struct super_block *); |
| 1091 | 1093 | ||
| 1092 | int (*show_options)(struct seq_file *, struct vfsmount *); | 1094 | int (*show_options)(struct seq_file *, struct vfsmount *); |
| 1093 | 1095 | ||
| 1094 | ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); | 1096 | ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); |
| 1095 | ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); | 1097 | ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); |
| 1096 | }; | 1098 | }; |
| 1097 | 1099 | ||
| 1098 | /* Inode state bits. Protected by inode_lock. */ | 1100 | /* Inode state bits. Protected by inode_lock. */ |
| 1099 | #define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */ | 1101 | #define I_DIRTY_SYNC 1 /* Not dirty enough for O_DATASYNC */ |
| 1100 | #define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */ | 1102 | #define I_DIRTY_DATASYNC 2 /* Data-related inode changes pending */ |
| 1101 | #define I_DIRTY_PAGES 4 /* Data-related inode changes pending */ | 1103 | #define I_DIRTY_PAGES 4 /* Data-related inode changes pending */ |
| 1102 | #define __I_LOCK 3 | 1104 | #define __I_LOCK 3 |
| 1103 | #define I_LOCK (1 << __I_LOCK) | 1105 | #define I_LOCK (1 << __I_LOCK) |
| 1104 | #define I_FREEING 16 | 1106 | #define I_FREEING 16 |
| 1105 | #define I_CLEAR 32 | 1107 | #define I_CLEAR 32 |
| 1106 | #define I_NEW 64 | 1108 | #define I_NEW 64 |
| 1107 | #define I_WILL_FREE 128 | 1109 | #define I_WILL_FREE 128 |
| 1108 | 1110 | ||
| 1109 | #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) | 1111 | #define I_DIRTY (I_DIRTY_SYNC | I_DIRTY_DATASYNC | I_DIRTY_PAGES) |
| 1110 | 1112 | ||
| 1111 | extern void __mark_inode_dirty(struct inode *, int); | 1113 | extern void __mark_inode_dirty(struct inode *, int); |
| 1112 | static inline void mark_inode_dirty(struct inode *inode) | 1114 | static inline void mark_inode_dirty(struct inode *inode) |
| 1113 | { | 1115 | { |
| 1114 | __mark_inode_dirty(inode, I_DIRTY); | 1116 | __mark_inode_dirty(inode, I_DIRTY); |
| 1115 | } | 1117 | } |
| 1116 | 1118 | ||
| 1117 | static inline void mark_inode_dirty_sync(struct inode *inode) | 1119 | static inline void mark_inode_dirty_sync(struct inode *inode) |
| 1118 | { | 1120 | { |
| 1119 | __mark_inode_dirty(inode, I_DIRTY_SYNC); | 1121 | __mark_inode_dirty(inode, I_DIRTY_SYNC); |
| 1120 | } | 1122 | } |
| 1121 | 1123 | ||
| 1122 | static inline void inode_inc_link_count(struct inode *inode) | 1124 | static inline void inode_inc_link_count(struct inode *inode) |
| 1123 | { | 1125 | { |
| 1124 | inode->i_nlink++; | 1126 | inode->i_nlink++; |
| 1125 | mark_inode_dirty(inode); | 1127 | mark_inode_dirty(inode); |
| 1126 | } | 1128 | } |
| 1127 | 1129 | ||
| 1128 | static inline void inode_dec_link_count(struct inode *inode) | 1130 | static inline void inode_dec_link_count(struct inode *inode) |
| 1129 | { | 1131 | { |
| 1130 | inode->i_nlink--; | 1132 | inode->i_nlink--; |
| 1131 | mark_inode_dirty(inode); | 1133 | mark_inode_dirty(inode); |
| 1132 | } | 1134 | } |
| 1133 | 1135 | ||
| 1134 | extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry); | 1136 | extern void touch_atime(struct vfsmount *mnt, struct dentry *dentry); |
| 1135 | static inline void file_accessed(struct file *file) | 1137 | static inline void file_accessed(struct file *file) |
| 1136 | { | 1138 | { |
| 1137 | if (!(file->f_flags & O_NOATIME)) | 1139 | if (!(file->f_flags & O_NOATIME)) |
| 1138 | touch_atime(file->f_vfsmnt, file->f_dentry); | 1140 | touch_atime(file->f_vfsmnt, file->f_dentry); |
| 1139 | } | 1141 | } |
| 1140 | 1142 | ||
| 1141 | int sync_inode(struct inode *inode, struct writeback_control *wbc); | 1143 | int sync_inode(struct inode *inode, struct writeback_control *wbc); |
| 1142 | 1144 | ||
| 1143 | /** | 1145 | /** |
| 1144 | * struct export_operations - for nfsd to communicate with file systems | 1146 | * struct export_operations - for nfsd to communicate with file systems |
| 1145 | * @decode_fh: decode a file handle fragment and return a &struct dentry | 1147 | * @decode_fh: decode a file handle fragment and return a &struct dentry |
| 1146 | * @encode_fh: encode a file handle fragment from a dentry | 1148 | * @encode_fh: encode a file handle fragment from a dentry |
| 1147 | * @get_name: find the name for a given inode in a given directory | 1149 | * @get_name: find the name for a given inode in a given directory |
| 1148 | * @get_parent: find the parent of a given directory | 1150 | * @get_parent: find the parent of a given directory |
| 1149 | * @get_dentry: find a dentry for the inode given a file handle sub-fragment | 1151 | * @get_dentry: find a dentry for the inode given a file handle sub-fragment |
| 1150 | * @find_exported_dentry: | 1152 | * @find_exported_dentry: |
| 1151 | * set by the exporting module to a standard helper function. | 1153 | * set by the exporting module to a standard helper function. |
| 1152 | * | 1154 | * |
| 1153 | * Description: | 1155 | * Description: |
| 1154 | * The export_operations structure provides a means for nfsd to communicate | 1156 | * The export_operations structure provides a means for nfsd to communicate |
| 1155 | * with a particular exported file system - particularly enabling nfsd and | 1157 | * with a particular exported file system - particularly enabling nfsd and |
| 1156 | * the filesystem to co-operate when dealing with file handles. | 1158 | * the filesystem to co-operate when dealing with file handles. |
| 1157 | * | 1159 | * |
| 1158 | * export_operations contains two basic operation for dealing with file | 1160 | * export_operations contains two basic operation for dealing with file |
| 1159 | * handles, decode_fh() and encode_fh(), and allows for some other | 1161 | * handles, decode_fh() and encode_fh(), and allows for some other |
| 1160 | * operations to be defined which standard helper routines use to get | 1162 | * operations to be defined which standard helper routines use to get |
| 1161 | * specific information from the filesystem. | 1163 | * specific information from the filesystem. |
| 1162 | * | 1164 | * |
| 1163 | * nfsd encodes information use to determine which filesystem a filehandle | 1165 | * nfsd encodes information use to determine which filesystem a filehandle |
| 1164 | * applies to in the initial part of the file handle. The remainder, termed | 1166 | * applies to in the initial part of the file handle. The remainder, termed |
| 1165 | * a file handle fragment, is controlled completely by the filesystem. The | 1167 | * a file handle fragment, is controlled completely by the filesystem. The |
| 1166 | * standard helper routines assume that this fragment will contain one or | 1168 | * standard helper routines assume that this fragment will contain one or |
| 1167 | * two sub-fragments, one which identifies the file, and one which may be | 1169 | * two sub-fragments, one which identifies the file, and one which may be |
| 1168 | * used to identify the (a) directory containing the file. | 1170 | * used to identify the (a) directory containing the file. |
| 1169 | * | 1171 | * |
| 1170 | * In some situations, nfsd needs to get a dentry which is connected into a | 1172 | * In some situations, nfsd needs to get a dentry which is connected into a |
| 1171 | * specific part of the file tree. To allow for this, it passes the | 1173 | * specific part of the file tree. To allow for this, it passes the |
| 1172 | * function acceptable() together with a @context which can be used to see | 1174 | * function acceptable() together with a @context which can be used to see |
| 1173 | * if the dentry is acceptable. As there can be multiple dentrys for a | 1175 | * if the dentry is acceptable. As there can be multiple dentrys for a |
| 1174 | * given file, the filesystem should check each one for acceptability before | 1176 | * given file, the filesystem should check each one for acceptability before |
| 1175 | * looking for the next. As soon as an acceptable one is found, it should | 1177 | * looking for the next. As soon as an acceptable one is found, it should |
| 1176 | * be returned. | 1178 | * be returned. |
| 1177 | * | 1179 | * |
| 1178 | * decode_fh: | 1180 | * decode_fh: |
| 1179 | * @decode_fh is given a &struct super_block (@sb), a file handle fragment | 1181 | * @decode_fh is given a &struct super_block (@sb), a file handle fragment |
| 1180 | * (@fh, @fh_len) and an acceptability testing function (@acceptable, | 1182 | * (@fh, @fh_len) and an acceptability testing function (@acceptable, |
| 1181 | * @context). It should return a &struct dentry which refers to the same | 1183 | * @context). It should return a &struct dentry which refers to the same |
| 1182 | * file that the file handle fragment refers to, and which passes the | 1184 | * file that the file handle fragment refers to, and which passes the |
| 1183 | * acceptability test. If it cannot, it should return a %NULL pointer if | 1185 | * acceptability test. If it cannot, it should return a %NULL pointer if |
| 1184 | * the file was found but no acceptable &dentries were available, or a | 1186 | * the file was found but no acceptable &dentries were available, or a |
| 1185 | * %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or | 1187 | * %ERR_PTR error code indicating why it couldn't be found (e.g. %ENOENT or |
| 1186 | * %ENOMEM). | 1188 | * %ENOMEM). |
| 1187 | * | 1189 | * |
| 1188 | * encode_fh: | 1190 | * encode_fh: |
| 1189 | * @encode_fh should store in the file handle fragment @fh (using at most | 1191 | * @encode_fh should store in the file handle fragment @fh (using at most |
| 1190 | * @max_len bytes) information that can be used by @decode_fh to recover the | 1192 | * @max_len bytes) information that can be used by @decode_fh to recover the |
| 1191 | * file refered to by the &struct dentry @de. If the @connectable flag is | 1193 | * file refered to by the &struct dentry @de. If the @connectable flag is |
| 1192 | * set, the encode_fh() should store sufficient information so that a good | 1194 | * set, the encode_fh() should store sufficient information so that a good |
| 1193 | * attempt can be made to find not only the file but also it's place in the | 1195 | * attempt can be made to find not only the file but also it's place in the |
| 1194 | * filesystem. This typically means storing a reference to de->d_parent in | 1196 | * filesystem. This typically means storing a reference to de->d_parent in |
| 1195 | * the filehandle fragment. encode_fh() should return the number of bytes | 1197 | * the filehandle fragment. encode_fh() should return the number of bytes |
| 1196 | * stored or a negative error code such as %-ENOSPC | 1198 | * stored or a negative error code such as %-ENOSPC |
| 1197 | * | 1199 | * |
| 1198 | * get_name: | 1200 | * get_name: |
| 1199 | * @get_name should find a name for the given @child in the given @parent | 1201 | * @get_name should find a name for the given @child in the given @parent |
| 1200 | * directory. The name should be stored in the @name (with the | 1202 | * directory. The name should be stored in the @name (with the |
| 1201 | * understanding that it is already pointing to a a %NAME_MAX+1 sized | 1203 | * understanding that it is already pointing to a a %NAME_MAX+1 sized |
| 1202 | * buffer. get_name() should return %0 on success, a negative error code | 1204 | * buffer. get_name() should return %0 on success, a negative error code |
| 1203 | * or error. @get_name will be called without @parent->i_mutex held. | 1205 | * or error. @get_name will be called without @parent->i_mutex held. |
| 1204 | * | 1206 | * |
| 1205 | * get_parent: | 1207 | * get_parent: |
| 1206 | * @get_parent should find the parent directory for the given @child which | 1208 | * @get_parent should find the parent directory for the given @child which |
| 1207 | * is also a directory. In the event that it cannot be found, or storage | 1209 | * is also a directory. In the event that it cannot be found, or storage |
| 1208 | * space cannot be allocated, a %ERR_PTR should be returned. | 1210 | * space cannot be allocated, a %ERR_PTR should be returned. |
| 1209 | * | 1211 | * |
| 1210 | * get_dentry: | 1212 | * get_dentry: |
| 1211 | * Given a &super_block (@sb) and a pointer to a file-system specific inode | 1213 | * Given a &super_block (@sb) and a pointer to a file-system specific inode |
| 1212 | * identifier, possibly an inode number, (@inump) get_dentry() should find | 1214 | * identifier, possibly an inode number, (@inump) get_dentry() should find |
| 1213 | * the identified inode and return a dentry for that inode. Any suitable | 1215 | * the identified inode and return a dentry for that inode. Any suitable |
| 1214 | * dentry can be returned including, if necessary, a new dentry created with | 1216 | * dentry can be returned including, if necessary, a new dentry created with |
| 1215 | * d_alloc_root. The caller can then find any other extant dentrys by | 1217 | * d_alloc_root. The caller can then find any other extant dentrys by |
| 1216 | * following the d_alias links. If a new dentry was created using | 1218 | * following the d_alias links. If a new dentry was created using |
| 1217 | * d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry | 1219 | * d_alloc_root, DCACHE_NFSD_DISCONNECTED should be set, and the dentry |
| 1218 | * should be d_rehash()ed. | 1220 | * should be d_rehash()ed. |
| 1219 | * | 1221 | * |
| 1220 | * If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code | 1222 | * If the inode cannot be found, either a %NULL pointer or an %ERR_PTR code |
| 1221 | * can be returned. The @inump will be whatever was passed to | 1223 | * can be returned. The @inump will be whatever was passed to |
| 1222 | * nfsd_find_fh_dentry() in either the @obj or @parent parameters. | 1224 | * nfsd_find_fh_dentry() in either the @obj or @parent parameters. |
| 1223 | * | 1225 | * |
| 1224 | * Locking rules: | 1226 | * Locking rules: |
| 1225 | * get_parent is called with child->d_inode->i_mutex down | 1227 | * get_parent is called with child->d_inode->i_mutex down |
| 1226 | * get_name is not (which is possibly inconsistent) | 1228 | * get_name is not (which is possibly inconsistent) |
| 1227 | */ | 1229 | */ |
| 1228 | 1230 | ||
| 1229 | struct export_operations { | 1231 | struct export_operations { |
| 1230 | struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, int fh_len, int fh_type, | 1232 | struct dentry *(*decode_fh)(struct super_block *sb, __u32 *fh, int fh_len, int fh_type, |
| 1231 | int (*acceptable)(void *context, struct dentry *de), | 1233 | int (*acceptable)(void *context, struct dentry *de), |
| 1232 | void *context); | 1234 | void *context); |
| 1233 | int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len, | 1235 | int (*encode_fh)(struct dentry *de, __u32 *fh, int *max_len, |
| 1234 | int connectable); | 1236 | int connectable); |
| 1235 | 1237 | ||
| 1236 | /* the following are only called from the filesystem itself */ | 1238 | /* the following are only called from the filesystem itself */ |
| 1237 | int (*get_name)(struct dentry *parent, char *name, | 1239 | int (*get_name)(struct dentry *parent, char *name, |
| 1238 | struct dentry *child); | 1240 | struct dentry *child); |
| 1239 | struct dentry * (*get_parent)(struct dentry *child); | 1241 | struct dentry * (*get_parent)(struct dentry *child); |
| 1240 | struct dentry * (*get_dentry)(struct super_block *sb, void *inump); | 1242 | struct dentry * (*get_dentry)(struct super_block *sb, void *inump); |
| 1241 | 1243 | ||
| 1242 | /* This is set by the exporting module to a standard helper */ | 1244 | /* This is set by the exporting module to a standard helper */ |
| 1243 | struct dentry * (*find_exported_dentry)( | 1245 | struct dentry * (*find_exported_dentry)( |
| 1244 | struct super_block *sb, void *obj, void *parent, | 1246 | struct super_block *sb, void *obj, void *parent, |
| 1245 | int (*acceptable)(void *context, struct dentry *de), | 1247 | int (*acceptable)(void *context, struct dentry *de), |
| 1246 | void *context); | 1248 | void *context); |
| 1247 | 1249 | ||
| 1248 | 1250 | ||
| 1249 | }; | 1251 | }; |
| 1250 | 1252 | ||
| 1251 | extern struct dentry * | 1253 | extern struct dentry * |
| 1252 | find_exported_dentry(struct super_block *sb, void *obj, void *parent, | 1254 | find_exported_dentry(struct super_block *sb, void *obj, void *parent, |
| 1253 | int (*acceptable)(void *context, struct dentry *de), | 1255 | int (*acceptable)(void *context, struct dentry *de), |
| 1254 | void *context); | 1256 | void *context); |
| 1255 | 1257 | ||
| 1256 | struct file_system_type { | 1258 | struct file_system_type { |
| 1257 | const char *name; | 1259 | const char *name; |
| 1258 | int fs_flags; | 1260 | int fs_flags; |
| 1259 | struct super_block *(*get_sb) (struct file_system_type *, int, | 1261 | struct super_block *(*get_sb) (struct file_system_type *, int, |
| 1260 | const char *, void *); | 1262 | const char *, void *); |
| 1261 | void (*kill_sb) (struct super_block *); | 1263 | void (*kill_sb) (struct super_block *); |
| 1262 | struct module *owner; | 1264 | struct module *owner; |
| 1263 | struct file_system_type * next; | 1265 | struct file_system_type * next; |
| 1264 | struct list_head fs_supers; | 1266 | struct list_head fs_supers; |
| 1265 | }; | 1267 | }; |
| 1266 | 1268 | ||
| 1267 | struct super_block *get_sb_bdev(struct file_system_type *fs_type, | 1269 | struct super_block *get_sb_bdev(struct file_system_type *fs_type, |
| 1268 | int flags, const char *dev_name, void *data, | 1270 | int flags, const char *dev_name, void *data, |
| 1269 | int (*fill_super)(struct super_block *, void *, int)); | 1271 | int (*fill_super)(struct super_block *, void *, int)); |
| 1270 | struct super_block *get_sb_single(struct file_system_type *fs_type, | 1272 | struct super_block *get_sb_single(struct file_system_type *fs_type, |
| 1271 | int flags, void *data, | 1273 | int flags, void *data, |
| 1272 | int (*fill_super)(struct super_block *, void *, int)); | 1274 | int (*fill_super)(struct super_block *, void *, int)); |
| 1273 | struct super_block *get_sb_nodev(struct file_system_type *fs_type, | 1275 | struct super_block *get_sb_nodev(struct file_system_type *fs_type, |
| 1274 | int flags, void *data, | 1276 | int flags, void *data, |
| 1275 | int (*fill_super)(struct super_block *, void *, int)); | 1277 | int (*fill_super)(struct super_block *, void *, int)); |
| 1276 | void generic_shutdown_super(struct super_block *sb); | 1278 | void generic_shutdown_super(struct super_block *sb); |
| 1277 | void kill_block_super(struct super_block *sb); | 1279 | void kill_block_super(struct super_block *sb); |
| 1278 | void kill_anon_super(struct super_block *sb); | 1280 | void kill_anon_super(struct super_block *sb); |
| 1279 | void kill_litter_super(struct super_block *sb); | 1281 | void kill_litter_super(struct super_block *sb); |
| 1280 | void deactivate_super(struct super_block *sb); | 1282 | void deactivate_super(struct super_block *sb); |
| 1281 | int set_anon_super(struct super_block *s, void *data); | 1283 | int set_anon_super(struct super_block *s, void *data); |
| 1282 | struct super_block *sget(struct file_system_type *type, | 1284 | struct super_block *sget(struct file_system_type *type, |
| 1283 | int (*test)(struct super_block *,void *), | 1285 | int (*test)(struct super_block *,void *), |
| 1284 | int (*set)(struct super_block *,void *), | 1286 | int (*set)(struct super_block *,void *), |
| 1285 | void *data); | 1287 | void *data); |
| 1286 | struct super_block *get_sb_pseudo(struct file_system_type *, char *, | 1288 | struct super_block *get_sb_pseudo(struct file_system_type *, char *, |
| 1287 | struct super_operations *ops, unsigned long); | 1289 | struct super_operations *ops, unsigned long); |
| 1288 | int __put_super(struct super_block *sb); | 1290 | int __put_super(struct super_block *sb); |
| 1289 | int __put_super_and_need_restart(struct super_block *sb); | 1291 | int __put_super_and_need_restart(struct super_block *sb); |
| 1290 | void unnamed_dev_init(void); | 1292 | void unnamed_dev_init(void); |
| 1291 | 1293 | ||
| 1292 | /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ | 1294 | /* Alas, no aliases. Too much hassle with bringing module.h everywhere */ |
| 1293 | #define fops_get(fops) \ | 1295 | #define fops_get(fops) \ |
| 1294 | (((fops) && try_module_get((fops)->owner) ? (fops) : NULL)) | 1296 | (((fops) && try_module_get((fops)->owner) ? (fops) : NULL)) |
| 1295 | #define fops_put(fops) \ | 1297 | #define fops_put(fops) \ |
| 1296 | do { if (fops) module_put((fops)->owner); } while(0) | 1298 | do { if (fops) module_put((fops)->owner); } while(0) |
| 1297 | 1299 | ||
| 1298 | extern int register_filesystem(struct file_system_type *); | 1300 | extern int register_filesystem(struct file_system_type *); |
| 1299 | extern int unregister_filesystem(struct file_system_type *); | 1301 | extern int unregister_filesystem(struct file_system_type *); |
| 1300 | extern struct vfsmount *kern_mount(struct file_system_type *); | 1302 | extern struct vfsmount *kern_mount(struct file_system_type *); |
| 1301 | extern int may_umount_tree(struct vfsmount *); | 1303 | extern int may_umount_tree(struct vfsmount *); |
| 1302 | extern int may_umount(struct vfsmount *); | 1304 | extern int may_umount(struct vfsmount *); |
| 1303 | extern void umount_tree(struct vfsmount *, int, struct list_head *); | 1305 | extern void umount_tree(struct vfsmount *, int, struct list_head *); |
| 1304 | extern void release_mounts(struct list_head *); | 1306 | extern void release_mounts(struct list_head *); |
| 1305 | extern long do_mount(char *, char *, char *, unsigned long, void *); | 1307 | extern long do_mount(char *, char *, char *, unsigned long, void *); |
| 1306 | extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); | 1308 | extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); |
| 1307 | extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, | 1309 | extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, |
| 1308 | struct vfsmount *); | 1310 | struct vfsmount *); |
| 1309 | 1311 | ||
| 1310 | extern int vfs_statfs(struct super_block *, struct kstatfs *); | 1312 | extern int vfs_statfs(struct super_block *, struct kstatfs *); |
| 1311 | 1313 | ||
| 1312 | /* /sys/fs */ | 1314 | /* /sys/fs */ |
| 1313 | extern struct subsystem fs_subsys; | 1315 | extern struct subsystem fs_subsys; |
| 1314 | 1316 | ||
| 1315 | #define FLOCK_VERIFY_READ 1 | 1317 | #define FLOCK_VERIFY_READ 1 |
| 1316 | #define FLOCK_VERIFY_WRITE 2 | 1318 | #define FLOCK_VERIFY_WRITE 2 |
| 1317 | 1319 | ||
| 1318 | extern int locks_mandatory_locked(struct inode *); | 1320 | extern int locks_mandatory_locked(struct inode *); |
| 1319 | extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t); | 1321 | extern int locks_mandatory_area(int, struct inode *, struct file *, loff_t, size_t); |
| 1320 | 1322 | ||
| 1321 | /* | 1323 | /* |
| 1322 | * Candidates for mandatory locking have the setgid bit set | 1324 | * Candidates for mandatory locking have the setgid bit set |
| 1323 | * but no group execute bit - an otherwise meaningless combination. | 1325 | * but no group execute bit - an otherwise meaningless combination. |
| 1324 | */ | 1326 | */ |
| 1325 | #define MANDATORY_LOCK(inode) \ | 1327 | #define MANDATORY_LOCK(inode) \ |
| 1326 | (IS_MANDLOCK(inode) && ((inode)->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) | 1328 | (IS_MANDLOCK(inode) && ((inode)->i_mode & (S_ISGID | S_IXGRP)) == S_ISGID) |
| 1327 | 1329 | ||
| 1328 | static inline int locks_verify_locked(struct inode *inode) | 1330 | static inline int locks_verify_locked(struct inode *inode) |
| 1329 | { | 1331 | { |
| 1330 | if (MANDATORY_LOCK(inode)) | 1332 | if (MANDATORY_LOCK(inode)) |
| 1331 | return locks_mandatory_locked(inode); | 1333 | return locks_mandatory_locked(inode); |
| 1332 | return 0; | 1334 | return 0; |
| 1333 | } | 1335 | } |
| 1334 | 1336 | ||
| 1335 | extern int rw_verify_area(int, struct file *, loff_t *, size_t); | 1337 | extern int rw_verify_area(int, struct file *, loff_t *, size_t); |
| 1336 | 1338 | ||
| 1337 | static inline int locks_verify_truncate(struct inode *inode, | 1339 | static inline int locks_verify_truncate(struct inode *inode, |
| 1338 | struct file *filp, | 1340 | struct file *filp, |
| 1339 | loff_t size) | 1341 | loff_t size) |
| 1340 | { | 1342 | { |
| 1341 | if (inode->i_flock && MANDATORY_LOCK(inode)) | 1343 | if (inode->i_flock && MANDATORY_LOCK(inode)) |
| 1342 | return locks_mandatory_area( | 1344 | return locks_mandatory_area( |
| 1343 | FLOCK_VERIFY_WRITE, inode, filp, | 1345 | FLOCK_VERIFY_WRITE, inode, filp, |
| 1344 | size < inode->i_size ? size : inode->i_size, | 1346 | size < inode->i_size ? size : inode->i_size, |
| 1345 | (size < inode->i_size ? inode->i_size - size | 1347 | (size < inode->i_size ? inode->i_size - size |
| 1346 | : size - inode->i_size) | 1348 | : size - inode->i_size) |
| 1347 | ); | 1349 | ); |
| 1348 | return 0; | 1350 | return 0; |
| 1349 | } | 1351 | } |
| 1350 | 1352 | ||
| 1351 | static inline int break_lease(struct inode *inode, unsigned int mode) | 1353 | static inline int break_lease(struct inode *inode, unsigned int mode) |
| 1352 | { | 1354 | { |
| 1353 | if (inode->i_flock) | 1355 | if (inode->i_flock) |
| 1354 | return __break_lease(inode, mode); | 1356 | return __break_lease(inode, mode); |
| 1355 | return 0; | 1357 | return 0; |
| 1356 | } | 1358 | } |
| 1357 | 1359 | ||
| 1358 | /* fs/open.c */ | 1360 | /* fs/open.c */ |
| 1359 | 1361 | ||
| 1360 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, | 1362 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, |
| 1361 | struct file *filp); | 1363 | struct file *filp); |
| 1362 | extern long do_sys_open(int fdf, const char __user *filename, int flags, | 1364 | extern long do_sys_open(int fdf, const char __user *filename, int flags, |
| 1363 | int mode); | 1365 | int mode); |
| 1364 | extern struct file *filp_open(const char *, int, int); | 1366 | extern struct file *filp_open(const char *, int, int); |
| 1365 | extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); | 1367 | extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); |
| 1366 | extern int filp_close(struct file *, fl_owner_t id); | 1368 | extern int filp_close(struct file *, fl_owner_t id); |
| 1367 | extern char * getname(const char __user *); | 1369 | extern char * getname(const char __user *); |
| 1368 | 1370 | ||
| 1369 | /* fs/dcache.c */ | 1371 | /* fs/dcache.c */ |
| 1370 | extern void __init vfs_caches_init_early(void); | 1372 | extern void __init vfs_caches_init_early(void); |
| 1371 | extern void __init vfs_caches_init(unsigned long); | 1373 | extern void __init vfs_caches_init(unsigned long); |
| 1372 | 1374 | ||
| 1373 | #define __getname() kmem_cache_alloc(names_cachep, SLAB_KERNEL) | 1375 | #define __getname() kmem_cache_alloc(names_cachep, SLAB_KERNEL) |
| 1374 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) | 1376 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) |
| 1375 | #ifndef CONFIG_AUDITSYSCALL | 1377 | #ifndef CONFIG_AUDITSYSCALL |
| 1376 | #define putname(name) __putname(name) | 1378 | #define putname(name) __putname(name) |
| 1377 | #else | 1379 | #else |
| 1378 | extern void putname(const char *name); | 1380 | extern void putname(const char *name); |
| 1379 | #endif | 1381 | #endif |
| 1380 | 1382 | ||
| 1381 | extern int register_blkdev(unsigned int, const char *); | 1383 | extern int register_blkdev(unsigned int, const char *); |
| 1382 | extern int unregister_blkdev(unsigned int, const char *); | 1384 | extern int unregister_blkdev(unsigned int, const char *); |
| 1383 | extern struct block_device *bdget(dev_t); | 1385 | extern struct block_device *bdget(dev_t); |
| 1384 | extern void bd_set_size(struct block_device *, loff_t size); | 1386 | extern void bd_set_size(struct block_device *, loff_t size); |
| 1385 | extern void bd_forget(struct inode *inode); | 1387 | extern void bd_forget(struct inode *inode); |
| 1386 | extern void bdput(struct block_device *); | 1388 | extern void bdput(struct block_device *); |
| 1387 | extern struct block_device *open_by_devnum(dev_t, unsigned); | 1389 | extern struct block_device *open_by_devnum(dev_t, unsigned); |
| 1388 | extern struct file_operations def_blk_fops; | 1390 | extern struct file_operations def_blk_fops; |
| 1389 | extern struct address_space_operations def_blk_aops; | 1391 | extern struct address_space_operations def_blk_aops; |
| 1390 | extern struct file_operations def_chr_fops; | 1392 | extern struct file_operations def_chr_fops; |
| 1391 | extern struct file_operations bad_sock_fops; | 1393 | extern struct file_operations bad_sock_fops; |
| 1392 | extern struct file_operations def_fifo_fops; | 1394 | extern struct file_operations def_fifo_fops; |
| 1393 | extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); | 1395 | extern int ioctl_by_bdev(struct block_device *, unsigned, unsigned long); |
| 1394 | extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long); | 1396 | extern int blkdev_ioctl(struct inode *, struct file *, unsigned, unsigned long); |
| 1395 | extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); | 1397 | extern long compat_blkdev_ioctl(struct file *, unsigned, unsigned long); |
| 1396 | extern int blkdev_get(struct block_device *, mode_t, unsigned); | 1398 | extern int blkdev_get(struct block_device *, mode_t, unsigned); |
| 1397 | extern int blkdev_put(struct block_device *); | 1399 | extern int blkdev_put(struct block_device *); |
| 1398 | extern int bd_claim(struct block_device *, void *); | 1400 | extern int bd_claim(struct block_device *, void *); |
| 1399 | extern void bd_release(struct block_device *); | 1401 | extern void bd_release(struct block_device *); |
| 1400 | 1402 | ||
| 1401 | /* fs/char_dev.c */ | 1403 | /* fs/char_dev.c */ |
| 1402 | extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); | 1404 | extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); |
| 1403 | extern int register_chrdev_region(dev_t, unsigned, const char *); | 1405 | extern int register_chrdev_region(dev_t, unsigned, const char *); |
| 1404 | extern int register_chrdev(unsigned int, const char *, | 1406 | extern int register_chrdev(unsigned int, const char *, |
| 1405 | struct file_operations *); | 1407 | struct file_operations *); |
| 1406 | extern int unregister_chrdev(unsigned int, const char *); | 1408 | extern int unregister_chrdev(unsigned int, const char *); |
| 1407 | extern void unregister_chrdev_region(dev_t, unsigned); | 1409 | extern void unregister_chrdev_region(dev_t, unsigned); |
| 1408 | extern int chrdev_open(struct inode *, struct file *); | 1410 | extern int chrdev_open(struct inode *, struct file *); |
| 1409 | extern int get_chrdev_list(char *); | 1411 | extern int get_chrdev_list(char *); |
| 1410 | extern void *acquire_chrdev_list(void); | 1412 | extern void *acquire_chrdev_list(void); |
| 1411 | extern int count_chrdev_list(void); | 1413 | extern int count_chrdev_list(void); |
| 1412 | extern void *get_next_chrdev(void *); | 1414 | extern void *get_next_chrdev(void *); |
| 1413 | extern int get_chrdev_info(void *, int *, char **); | 1415 | extern int get_chrdev_info(void *, int *, char **); |
| 1414 | extern void release_chrdev_list(void *); | 1416 | extern void release_chrdev_list(void *); |
| 1415 | 1417 | ||
| 1416 | /* fs/block_dev.c */ | 1418 | /* fs/block_dev.c */ |
| 1417 | #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ | 1419 | #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ |
| 1418 | extern const char *__bdevname(dev_t, char *buffer); | 1420 | extern const char *__bdevname(dev_t, char *buffer); |
| 1419 | extern const char *bdevname(struct block_device *bdev, char *buffer); | 1421 | extern const char *bdevname(struct block_device *bdev, char *buffer); |
| 1420 | extern struct block_device *lookup_bdev(const char *); | 1422 | extern struct block_device *lookup_bdev(const char *); |
| 1421 | extern struct block_device *open_bdev_excl(const char *, int, void *); | 1423 | extern struct block_device *open_bdev_excl(const char *, int, void *); |
| 1422 | extern void close_bdev_excl(struct block_device *); | 1424 | extern void close_bdev_excl(struct block_device *); |
| 1423 | extern void *acquire_blkdev_list(void); | 1425 | extern void *acquire_blkdev_list(void); |
| 1424 | extern int count_blkdev_list(void); | 1426 | extern int count_blkdev_list(void); |
| 1425 | extern void *get_next_blkdev(void *); | 1427 | extern void *get_next_blkdev(void *); |
| 1426 | extern int get_blkdev_info(void *, int *, char **); | 1428 | extern int get_blkdev_info(void *, int *, char **); |
| 1427 | extern void release_blkdev_list(void *); | 1429 | extern void release_blkdev_list(void *); |
| 1428 | 1430 | ||
| 1429 | extern void init_special_inode(struct inode *, umode_t, dev_t); | 1431 | extern void init_special_inode(struct inode *, umode_t, dev_t); |
| 1430 | 1432 | ||
| 1431 | /* Invalid inode operations -- fs/bad_inode.c */ | 1433 | /* Invalid inode operations -- fs/bad_inode.c */ |
| 1432 | extern void make_bad_inode(struct inode *); | 1434 | extern void make_bad_inode(struct inode *); |
| 1433 | extern int is_bad_inode(struct inode *); | 1435 | extern int is_bad_inode(struct inode *); |
| 1434 | 1436 | ||
| 1435 | extern struct file_operations read_fifo_fops; | 1437 | extern struct file_operations read_fifo_fops; |
| 1436 | extern struct file_operations write_fifo_fops; | 1438 | extern struct file_operations write_fifo_fops; |
| 1437 | extern struct file_operations rdwr_fifo_fops; | 1439 | extern struct file_operations rdwr_fifo_fops; |
| 1438 | 1440 | ||
| 1439 | extern int fs_may_remount_ro(struct super_block *); | 1441 | extern int fs_may_remount_ro(struct super_block *); |
| 1440 | 1442 | ||
| 1441 | /* | 1443 | /* |
| 1442 | * return READ, READA, or WRITE | 1444 | * return READ, READA, or WRITE |
| 1443 | */ | 1445 | */ |
| 1444 | #define bio_rw(bio) ((bio)->bi_rw & (RW_MASK | RWA_MASK)) | 1446 | #define bio_rw(bio) ((bio)->bi_rw & (RW_MASK | RWA_MASK)) |
| 1445 | 1447 | ||
| 1446 | /* | 1448 | /* |
| 1447 | * return data direction, READ or WRITE | 1449 | * return data direction, READ or WRITE |
| 1448 | */ | 1450 | */ |
| 1449 | #define bio_data_dir(bio) ((bio)->bi_rw & 1) | 1451 | #define bio_data_dir(bio) ((bio)->bi_rw & 1) |
| 1450 | 1452 | ||
| 1451 | extern int check_disk_change(struct block_device *); | 1453 | extern int check_disk_change(struct block_device *); |
| 1452 | extern int invalidate_inodes(struct super_block *); | 1454 | extern int invalidate_inodes(struct super_block *); |
| 1453 | extern int __invalidate_device(struct block_device *); | 1455 | extern int __invalidate_device(struct block_device *); |
| 1454 | extern int invalidate_partition(struct gendisk *, int); | 1456 | extern int invalidate_partition(struct gendisk *, int); |
| 1455 | unsigned long invalidate_mapping_pages(struct address_space *mapping, | 1457 | unsigned long invalidate_mapping_pages(struct address_space *mapping, |
| 1456 | pgoff_t start, pgoff_t end); | 1458 | pgoff_t start, pgoff_t end); |
| 1457 | unsigned long invalidate_inode_pages(struct address_space *mapping); | 1459 | unsigned long invalidate_inode_pages(struct address_space *mapping); |
| 1458 | static inline void invalidate_remote_inode(struct inode *inode) | 1460 | static inline void invalidate_remote_inode(struct inode *inode) |
| 1459 | { | 1461 | { |
| 1460 | if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || | 1462 | if (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || |
| 1461 | S_ISLNK(inode->i_mode)) | 1463 | S_ISLNK(inode->i_mode)) |
| 1462 | invalidate_inode_pages(inode->i_mapping); | 1464 | invalidate_inode_pages(inode->i_mapping); |
| 1463 | } | 1465 | } |
| 1464 | extern int invalidate_inode_pages2(struct address_space *mapping); | 1466 | extern int invalidate_inode_pages2(struct address_space *mapping); |
| 1465 | extern int invalidate_inode_pages2_range(struct address_space *mapping, | 1467 | extern int invalidate_inode_pages2_range(struct address_space *mapping, |
| 1466 | pgoff_t start, pgoff_t end); | 1468 | pgoff_t start, pgoff_t end); |
| 1467 | extern int write_inode_now(struct inode *, int); | 1469 | extern int write_inode_now(struct inode *, int); |
| 1468 | extern int filemap_fdatawrite(struct address_space *); | 1470 | extern int filemap_fdatawrite(struct address_space *); |
| 1469 | extern int filemap_flush(struct address_space *); | 1471 | extern int filemap_flush(struct address_space *); |
| 1470 | extern int filemap_fdatawait(struct address_space *); | 1472 | extern int filemap_fdatawait(struct address_space *); |
| 1471 | extern int filemap_write_and_wait(struct address_space *mapping); | 1473 | extern int filemap_write_and_wait(struct address_space *mapping); |
| 1472 | extern int filemap_write_and_wait_range(struct address_space *mapping, | 1474 | extern int filemap_write_and_wait_range(struct address_space *mapping, |
| 1473 | loff_t lstart, loff_t lend); | 1475 | loff_t lstart, loff_t lend); |
| 1474 | extern void sync_supers(void); | 1476 | extern void sync_supers(void); |
| 1475 | extern void sync_filesystems(int wait); | 1477 | extern void sync_filesystems(int wait); |
| 1476 | extern void emergency_sync(void); | 1478 | extern void emergency_sync(void); |
| 1477 | extern void emergency_remount(void); | 1479 | extern void emergency_remount(void); |
| 1478 | extern int do_remount_sb(struct super_block *sb, int flags, | 1480 | extern int do_remount_sb(struct super_block *sb, int flags, |
| 1479 | void *data, int force); | 1481 | void *data, int force); |
| 1480 | extern sector_t bmap(struct inode *, sector_t); | 1482 | extern sector_t bmap(struct inode *, sector_t); |
| 1481 | extern int notify_change(struct dentry *, struct iattr *); | 1483 | extern int notify_change(struct dentry *, struct iattr *); |
| 1482 | extern int permission(struct inode *, int, struct nameidata *); | 1484 | extern int permission(struct inode *, int, struct nameidata *); |
| 1483 | extern int generic_permission(struct inode *, int, | 1485 | extern int generic_permission(struct inode *, int, |
| 1484 | int (*check_acl)(struct inode *, int)); | 1486 | int (*check_acl)(struct inode *, int)); |
| 1485 | 1487 | ||
| 1486 | extern int get_write_access(struct inode *); | 1488 | extern int get_write_access(struct inode *); |
| 1487 | extern int deny_write_access(struct file *); | 1489 | extern int deny_write_access(struct file *); |
| 1488 | static inline void put_write_access(struct inode * inode) | 1490 | static inline void put_write_access(struct inode * inode) |
| 1489 | { | 1491 | { |
| 1490 | atomic_dec(&inode->i_writecount); | 1492 | atomic_dec(&inode->i_writecount); |
| 1491 | } | 1493 | } |
| 1492 | static inline void allow_write_access(struct file *file) | 1494 | static inline void allow_write_access(struct file *file) |
| 1493 | { | 1495 | { |
| 1494 | if (file) | 1496 | if (file) |
| 1495 | atomic_inc(&file->f_dentry->d_inode->i_writecount); | 1497 | atomic_inc(&file->f_dentry->d_inode->i_writecount); |
| 1496 | } | 1498 | } |
| 1497 | extern int do_pipe(int *); | 1499 | extern int do_pipe(int *); |
| 1498 | 1500 | ||
| 1499 | extern int open_namei(int dfd, const char *, int, int, struct nameidata *); | 1501 | extern int open_namei(int dfd, const char *, int, int, struct nameidata *); |
| 1500 | extern int may_open(struct nameidata *, int, int); | 1502 | extern int may_open(struct nameidata *, int, int); |
| 1501 | 1503 | ||
| 1502 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); | 1504 | extern int kernel_read(struct file *, unsigned long, char *, unsigned long); |
| 1503 | extern struct file * open_exec(const char *); | 1505 | extern struct file * open_exec(const char *); |
| 1504 | 1506 | ||
| 1505 | /* fs/dcache.c -- generic fs support functions */ | 1507 | /* fs/dcache.c -- generic fs support functions */ |
| 1506 | extern int is_subdir(struct dentry *, struct dentry *); | 1508 | extern int is_subdir(struct dentry *, struct dentry *); |
| 1507 | extern ino_t find_inode_number(struct dentry *, struct qstr *); | 1509 | extern ino_t find_inode_number(struct dentry *, struct qstr *); |
| 1508 | 1510 | ||
| 1509 | #include <linux/err.h> | 1511 | #include <linux/err.h> |
| 1510 | 1512 | ||
| 1511 | /* needed for stackable file system support */ | 1513 | /* needed for stackable file system support */ |
| 1512 | extern loff_t default_llseek(struct file *file, loff_t offset, int origin); | 1514 | extern loff_t default_llseek(struct file *file, loff_t offset, int origin); |
| 1513 | 1515 | ||
| 1514 | extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin); | 1516 | extern loff_t vfs_llseek(struct file *file, loff_t offset, int origin); |
| 1515 | 1517 | ||
| 1516 | extern void inode_init_once(struct inode *); | 1518 | extern void inode_init_once(struct inode *); |
| 1517 | extern void iput(struct inode *); | 1519 | extern void iput(struct inode *); |
| 1518 | extern struct inode * igrab(struct inode *); | 1520 | extern struct inode * igrab(struct inode *); |
| 1519 | extern ino_t iunique(struct super_block *, ino_t); | 1521 | extern ino_t iunique(struct super_block *, ino_t); |
| 1520 | extern int inode_needs_sync(struct inode *inode); | 1522 | extern int inode_needs_sync(struct inode *inode); |
| 1521 | extern void generic_delete_inode(struct inode *inode); | 1523 | extern void generic_delete_inode(struct inode *inode); |
| 1522 | extern void generic_drop_inode(struct inode *inode); | 1524 | extern void generic_drop_inode(struct inode *inode); |
| 1523 | 1525 | ||
| 1524 | extern struct inode *ilookup5_nowait(struct super_block *sb, | 1526 | extern struct inode *ilookup5_nowait(struct super_block *sb, |
| 1525 | unsigned long hashval, int (*test)(struct inode *, void *), | 1527 | unsigned long hashval, int (*test)(struct inode *, void *), |
| 1526 | void *data); | 1528 | void *data); |
| 1527 | extern struct inode *ilookup5(struct super_block *sb, unsigned long hashval, | 1529 | extern struct inode *ilookup5(struct super_block *sb, unsigned long hashval, |
| 1528 | int (*test)(struct inode *, void *), void *data); | 1530 | int (*test)(struct inode *, void *), void *data); |
| 1529 | extern struct inode *ilookup(struct super_block *sb, unsigned long ino); | 1531 | extern struct inode *ilookup(struct super_block *sb, unsigned long ino); |
| 1530 | 1532 | ||
| 1531 | extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); | 1533 | extern struct inode * iget5_locked(struct super_block *, unsigned long, int (*test)(struct inode *, void *), int (*set)(struct inode *, void *), void *); |
| 1532 | extern struct inode * iget_locked(struct super_block *, unsigned long); | 1534 | extern struct inode * iget_locked(struct super_block *, unsigned long); |
| 1533 | extern void unlock_new_inode(struct inode *); | 1535 | extern void unlock_new_inode(struct inode *); |
| 1534 | 1536 | ||
| 1535 | static inline struct inode *iget(struct super_block *sb, unsigned long ino) | 1537 | static inline struct inode *iget(struct super_block *sb, unsigned long ino) |
| 1536 | { | 1538 | { |
| 1537 | struct inode *inode = iget_locked(sb, ino); | 1539 | struct inode *inode = iget_locked(sb, ino); |
| 1538 | 1540 | ||
| 1539 | if (inode && (inode->i_state & I_NEW)) { | 1541 | if (inode && (inode->i_state & I_NEW)) { |
| 1540 | sb->s_op->read_inode(inode); | 1542 | sb->s_op->read_inode(inode); |
| 1541 | unlock_new_inode(inode); | 1543 | unlock_new_inode(inode); |
| 1542 | } | 1544 | } |
| 1543 | 1545 | ||
| 1544 | return inode; | 1546 | return inode; |
| 1545 | } | 1547 | } |
| 1546 | 1548 | ||
| 1547 | extern void __iget(struct inode * inode); | 1549 | extern void __iget(struct inode * inode); |
| 1548 | extern void clear_inode(struct inode *); | 1550 | extern void clear_inode(struct inode *); |
| 1549 | extern void destroy_inode(struct inode *); | 1551 | extern void destroy_inode(struct inode *); |
| 1550 | extern struct inode *new_inode(struct super_block *); | 1552 | extern struct inode *new_inode(struct super_block *); |
| 1551 | extern int remove_suid(struct dentry *); | 1553 | extern int remove_suid(struct dentry *); |
| 1552 | extern void remove_dquot_ref(struct super_block *, int, struct list_head *); | 1554 | extern void remove_dquot_ref(struct super_block *, int, struct list_head *); |
| 1553 | extern struct mutex iprune_mutex; | 1555 | extern struct mutex iprune_mutex; |
| 1554 | 1556 | ||
| 1555 | extern void __insert_inode_hash(struct inode *, unsigned long hashval); | 1557 | extern void __insert_inode_hash(struct inode *, unsigned long hashval); |
| 1556 | extern void remove_inode_hash(struct inode *); | 1558 | extern void remove_inode_hash(struct inode *); |
| 1557 | static inline void insert_inode_hash(struct inode *inode) { | 1559 | static inline void insert_inode_hash(struct inode *inode) { |
| 1558 | __insert_inode_hash(inode, inode->i_ino); | 1560 | __insert_inode_hash(inode, inode->i_ino); |
| 1559 | } | 1561 | } |
| 1560 | 1562 | ||
| 1561 | extern struct file * get_empty_filp(void); | 1563 | extern struct file * get_empty_filp(void); |
| 1562 | extern void file_move(struct file *f, struct list_head *list); | 1564 | extern void file_move(struct file *f, struct list_head *list); |
| 1563 | extern void file_kill(struct file *f); | 1565 | extern void file_kill(struct file *f); |
| 1564 | struct bio; | 1566 | struct bio; |
| 1565 | extern void submit_bio(int, struct bio *); | 1567 | extern void submit_bio(int, struct bio *); |
| 1566 | extern int bdev_read_only(struct block_device *); | 1568 | extern int bdev_read_only(struct block_device *); |
| 1567 | extern int set_blocksize(struct block_device *, int); | 1569 | extern int set_blocksize(struct block_device *, int); |
| 1568 | extern int sb_set_blocksize(struct super_block *, int); | 1570 | extern int sb_set_blocksize(struct super_block *, int); |
| 1569 | extern int sb_min_blocksize(struct super_block *, int); | 1571 | extern int sb_min_blocksize(struct super_block *, int); |
| 1570 | 1572 | ||
| 1571 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); | 1573 | extern int generic_file_mmap(struct file *, struct vm_area_struct *); |
| 1572 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); | 1574 | extern int generic_file_readonly_mmap(struct file *, struct vm_area_struct *); |
| 1573 | extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); | 1575 | extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); |
| 1574 | extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); | 1576 | extern int file_send_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); |
| 1575 | extern ssize_t generic_file_read(struct file *, char __user *, size_t, loff_t *); | 1577 | extern ssize_t generic_file_read(struct file *, char __user *, size_t, loff_t *); |
| 1576 | int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk); | 1578 | int generic_write_checks(struct file *file, loff_t *pos, size_t *count, int isblk); |
| 1577 | extern ssize_t generic_file_write(struct file *, const char __user *, size_t, loff_t *); | 1579 | extern ssize_t generic_file_write(struct file *, const char __user *, size_t, loff_t *); |
| 1578 | extern ssize_t generic_file_aio_read(struct kiocb *, char __user *, size_t, loff_t); | 1580 | extern ssize_t generic_file_aio_read(struct kiocb *, char __user *, size_t, loff_t); |
| 1579 | extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *); | 1581 | extern ssize_t __generic_file_aio_read(struct kiocb *, const struct iovec *, unsigned long, loff_t *); |
| 1580 | extern ssize_t generic_file_aio_write(struct kiocb *, const char __user *, size_t, loff_t); | 1582 | extern ssize_t generic_file_aio_write(struct kiocb *, const char __user *, size_t, loff_t); |
| 1581 | extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *, | 1583 | extern ssize_t generic_file_aio_write_nolock(struct kiocb *, const struct iovec *, |
| 1582 | unsigned long, loff_t *); | 1584 | unsigned long, loff_t *); |
| 1583 | extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *, | 1585 | extern ssize_t generic_file_direct_write(struct kiocb *, const struct iovec *, |
| 1584 | unsigned long *, loff_t, loff_t *, size_t, size_t); | 1586 | unsigned long *, loff_t, loff_t *, size_t, size_t); |
| 1585 | extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *, | 1587 | extern ssize_t generic_file_buffered_write(struct kiocb *, const struct iovec *, |
| 1586 | unsigned long, loff_t, loff_t *, size_t, ssize_t); | 1588 | unsigned long, loff_t, loff_t *, size_t, ssize_t); |
| 1587 | extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos); | 1589 | extern ssize_t do_sync_read(struct file *filp, char __user *buf, size_t len, loff_t *ppos); |
| 1588 | extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); | 1590 | extern ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos); |
| 1589 | ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov, | 1591 | ssize_t generic_file_write_nolock(struct file *file, const struct iovec *iov, |
| 1590 | unsigned long nr_segs, loff_t *ppos); | 1592 | unsigned long nr_segs, loff_t *ppos); |
| 1591 | extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); | 1593 | extern ssize_t generic_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); |
| 1592 | extern void do_generic_mapping_read(struct address_space *mapping, | 1594 | extern void do_generic_mapping_read(struct address_space *mapping, |
| 1593 | struct file_ra_state *, struct file *, | 1595 | struct file_ra_state *, struct file *, |
| 1594 | loff_t *, read_descriptor_t *, read_actor_t); | 1596 | loff_t *, read_descriptor_t *, read_actor_t); |
| 1595 | extern void | 1597 | extern void |
| 1596 | file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); | 1598 | file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); |
| 1597 | extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, | 1599 | extern ssize_t generic_file_readv(struct file *filp, const struct iovec *iov, |
| 1598 | unsigned long nr_segs, loff_t *ppos); | 1600 | unsigned long nr_segs, loff_t *ppos); |
| 1599 | ssize_t generic_file_writev(struct file *filp, const struct iovec *iov, | 1601 | ssize_t generic_file_writev(struct file *filp, const struct iovec *iov, |
| 1600 | unsigned long nr_segs, loff_t *ppos); | 1602 | unsigned long nr_segs, loff_t *ppos); |
| 1601 | extern loff_t no_llseek(struct file *file, loff_t offset, int origin); | 1603 | extern loff_t no_llseek(struct file *file, loff_t offset, int origin); |
| 1602 | extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); | 1604 | extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); |
| 1603 | extern loff_t remote_llseek(struct file *file, loff_t offset, int origin); | 1605 | extern loff_t remote_llseek(struct file *file, loff_t offset, int origin); |
| 1604 | extern int generic_file_open(struct inode * inode, struct file * filp); | 1606 | extern int generic_file_open(struct inode * inode, struct file * filp); |
| 1605 | extern int nonseekable_open(struct inode * inode, struct file * filp); | 1607 | extern int nonseekable_open(struct inode * inode, struct file * filp); |
| 1606 | 1608 | ||
| 1607 | #ifdef CONFIG_FS_XIP | 1609 | #ifdef CONFIG_FS_XIP |
| 1608 | extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len, | 1610 | extern ssize_t xip_file_read(struct file *filp, char __user *buf, size_t len, |
| 1609 | loff_t *ppos); | 1611 | loff_t *ppos); |
| 1610 | extern ssize_t xip_file_sendfile(struct file *in_file, loff_t *ppos, | 1612 | extern ssize_t xip_file_sendfile(struct file *in_file, loff_t *ppos, |
| 1611 | size_t count, read_actor_t actor, | 1613 | size_t count, read_actor_t actor, |
| 1612 | void *target); | 1614 | void *target); |
| 1613 | extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma); | 1615 | extern int xip_file_mmap(struct file * file, struct vm_area_struct * vma); |
| 1614 | extern ssize_t xip_file_write(struct file *filp, const char __user *buf, | 1616 | extern ssize_t xip_file_write(struct file *filp, const char __user *buf, |
| 1615 | size_t len, loff_t *ppos); | 1617 | size_t len, loff_t *ppos); |
| 1616 | extern int xip_truncate_page(struct address_space *mapping, loff_t from); | 1618 | extern int xip_truncate_page(struct address_space *mapping, loff_t from); |
| 1617 | #else | 1619 | #else |
| 1618 | static inline int xip_truncate_page(struct address_space *mapping, loff_t from) | 1620 | static inline int xip_truncate_page(struct address_space *mapping, loff_t from) |
| 1619 | { | 1621 | { |
| 1620 | return 0; | 1622 | return 0; |
| 1621 | } | 1623 | } |
| 1622 | #endif | 1624 | #endif |
| 1623 | 1625 | ||
| 1624 | static inline void do_generic_file_read(struct file * filp, loff_t *ppos, | 1626 | static inline void do_generic_file_read(struct file * filp, loff_t *ppos, |
| 1625 | read_descriptor_t * desc, | 1627 | read_descriptor_t * desc, |
| 1626 | read_actor_t actor) | 1628 | read_actor_t actor) |
| 1627 | { | 1629 | { |
| 1628 | do_generic_mapping_read(filp->f_mapping, | 1630 | do_generic_mapping_read(filp->f_mapping, |
| 1629 | &filp->f_ra, | 1631 | &filp->f_ra, |
| 1630 | filp, | 1632 | filp, |
| 1631 | ppos, | 1633 | ppos, |
| 1632 | desc, | 1634 | desc, |
| 1633 | actor); | 1635 | actor); |
| 1634 | } | 1636 | } |
| 1635 | 1637 | ||
| 1636 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | 1638 | ssize_t __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, |
| 1637 | struct block_device *bdev, const struct iovec *iov, loff_t offset, | 1639 | struct block_device *bdev, const struct iovec *iov, loff_t offset, |
| 1638 | unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io, | 1640 | unsigned long nr_segs, get_blocks_t get_blocks, dio_iodone_t end_io, |
| 1639 | int lock_type); | 1641 | int lock_type); |
| 1640 | 1642 | ||
| 1641 | enum { | 1643 | enum { |
| 1642 | DIO_LOCKING = 1, /* need locking between buffered and direct access */ | 1644 | DIO_LOCKING = 1, /* need locking between buffered and direct access */ |
| 1643 | DIO_NO_LOCKING, /* bdev; no locking at all between buffered/direct */ | 1645 | DIO_NO_LOCKING, /* bdev; no locking at all between buffered/direct */ |
| 1644 | DIO_OWN_LOCKING, /* filesystem locks buffered and direct internally */ | 1646 | DIO_OWN_LOCKING, /* filesystem locks buffered and direct internally */ |
| 1645 | }; | 1647 | }; |
| 1646 | 1648 | ||
| 1647 | static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, | 1649 | static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, |
| 1648 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, | 1650 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, |
| 1649 | loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks, | 1651 | loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks, |
| 1650 | dio_iodone_t end_io) | 1652 | dio_iodone_t end_io) |
| 1651 | { | 1653 | { |
| 1652 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, | 1654 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, |
| 1653 | nr_segs, get_blocks, end_io, DIO_LOCKING); | 1655 | nr_segs, get_blocks, end_io, DIO_LOCKING); |
| 1654 | } | 1656 | } |
| 1655 | 1657 | ||
| 1656 | static inline ssize_t blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb, | 1658 | static inline ssize_t blockdev_direct_IO_no_locking(int rw, struct kiocb *iocb, |
| 1657 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, | 1659 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, |
| 1658 | loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks, | 1660 | loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks, |
| 1659 | dio_iodone_t end_io) | 1661 | dio_iodone_t end_io) |
| 1660 | { | 1662 | { |
| 1661 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, | 1663 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, |
| 1662 | nr_segs, get_blocks, end_io, DIO_NO_LOCKING); | 1664 | nr_segs, get_blocks, end_io, DIO_NO_LOCKING); |
| 1663 | } | 1665 | } |
| 1664 | 1666 | ||
| 1665 | static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb, | 1667 | static inline ssize_t blockdev_direct_IO_own_locking(int rw, struct kiocb *iocb, |
| 1666 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, | 1668 | struct inode *inode, struct block_device *bdev, const struct iovec *iov, |
| 1667 | loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks, | 1669 | loff_t offset, unsigned long nr_segs, get_blocks_t get_blocks, |
| 1668 | dio_iodone_t end_io) | 1670 | dio_iodone_t end_io) |
| 1669 | { | 1671 | { |
| 1670 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, | 1672 | return __blockdev_direct_IO(rw, iocb, inode, bdev, iov, offset, |
| 1671 | nr_segs, get_blocks, end_io, DIO_OWN_LOCKING); | 1673 | nr_segs, get_blocks, end_io, DIO_OWN_LOCKING); |
| 1672 | } | 1674 | } |
| 1673 | 1675 | ||
| 1674 | extern struct file_operations generic_ro_fops; | 1676 | extern struct file_operations generic_ro_fops; |
| 1675 | 1677 | ||
| 1676 | #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) | 1678 | #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) |
| 1677 | 1679 | ||
| 1678 | extern int vfs_readlink(struct dentry *, char __user *, int, const char *); | 1680 | extern int vfs_readlink(struct dentry *, char __user *, int, const char *); |
| 1679 | extern int vfs_follow_link(struct nameidata *, const char *); | 1681 | extern int vfs_follow_link(struct nameidata *, const char *); |
| 1680 | extern int page_readlink(struct dentry *, char __user *, int); | 1682 | extern int page_readlink(struct dentry *, char __user *, int); |
| 1681 | extern void *page_follow_link_light(struct dentry *, struct nameidata *); | 1683 | extern void *page_follow_link_light(struct dentry *, struct nameidata *); |
| 1682 | extern void page_put_link(struct dentry *, struct nameidata *, void *); | 1684 | extern void page_put_link(struct dentry *, struct nameidata *, void *); |
| 1683 | extern int __page_symlink(struct inode *inode, const char *symname, int len, | 1685 | extern int __page_symlink(struct inode *inode, const char *symname, int len, |
| 1684 | gfp_t gfp_mask); | 1686 | gfp_t gfp_mask); |
| 1685 | extern int page_symlink(struct inode *inode, const char *symname, int len); | 1687 | extern int page_symlink(struct inode *inode, const char *symname, int len); |
| 1686 | extern struct inode_operations page_symlink_inode_operations; | 1688 | extern struct inode_operations page_symlink_inode_operations; |
| 1687 | extern int generic_readlink(struct dentry *, char __user *, int); | 1689 | extern int generic_readlink(struct dentry *, char __user *, int); |
| 1688 | extern void generic_fillattr(struct inode *, struct kstat *); | 1690 | extern void generic_fillattr(struct inode *, struct kstat *); |
| 1689 | extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 1691 | extern int vfs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
| 1690 | void inode_add_bytes(struct inode *inode, loff_t bytes); | 1692 | void inode_add_bytes(struct inode *inode, loff_t bytes); |
| 1691 | void inode_sub_bytes(struct inode *inode, loff_t bytes); | 1693 | void inode_sub_bytes(struct inode *inode, loff_t bytes); |
| 1692 | loff_t inode_get_bytes(struct inode *inode); | 1694 | loff_t inode_get_bytes(struct inode *inode); |
| 1693 | void inode_set_bytes(struct inode *inode, loff_t bytes); | 1695 | void inode_set_bytes(struct inode *inode, loff_t bytes); |
| 1694 | 1696 | ||
| 1695 | extern int vfs_readdir(struct file *, filldir_t, void *); | 1697 | extern int vfs_readdir(struct file *, filldir_t, void *); |
| 1696 | 1698 | ||
| 1697 | extern int vfs_stat(char __user *, struct kstat *); | 1699 | extern int vfs_stat(char __user *, struct kstat *); |
| 1698 | extern int vfs_lstat(char __user *, struct kstat *); | 1700 | extern int vfs_lstat(char __user *, struct kstat *); |
| 1699 | extern int vfs_stat_fd(int dfd, char __user *, struct kstat *); | 1701 | extern int vfs_stat_fd(int dfd, char __user *, struct kstat *); |
| 1700 | extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *); | 1702 | extern int vfs_lstat_fd(int dfd, char __user *, struct kstat *); |
| 1701 | extern int vfs_fstat(unsigned int, struct kstat *); | 1703 | extern int vfs_fstat(unsigned int, struct kstat *); |
| 1702 | 1704 | ||
| 1703 | extern int vfs_ioctl(struct file *, unsigned int, unsigned int, unsigned long); | 1705 | extern int vfs_ioctl(struct file *, unsigned int, unsigned int, unsigned long); |
| 1704 | 1706 | ||
| 1705 | extern struct file_system_type *get_fs_type(const char *name); | 1707 | extern struct file_system_type *get_fs_type(const char *name); |
| 1706 | extern struct super_block *get_super(struct block_device *); | 1708 | extern struct super_block *get_super(struct block_device *); |
| 1707 | extern struct super_block *user_get_super(dev_t); | 1709 | extern struct super_block *user_get_super(dev_t); |
| 1708 | extern void drop_super(struct super_block *sb); | 1710 | extern void drop_super(struct super_block *sb); |
| 1709 | 1711 | ||
| 1710 | extern int dcache_dir_open(struct inode *, struct file *); | 1712 | extern int dcache_dir_open(struct inode *, struct file *); |
| 1711 | extern int dcache_dir_close(struct inode *, struct file *); | 1713 | extern int dcache_dir_close(struct inode *, struct file *); |
| 1712 | extern loff_t dcache_dir_lseek(struct file *, loff_t, int); | 1714 | extern loff_t dcache_dir_lseek(struct file *, loff_t, int); |
| 1713 | extern int dcache_readdir(struct file *, void *, filldir_t); | 1715 | extern int dcache_readdir(struct file *, void *, filldir_t); |
| 1714 | extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 1716 | extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
| 1715 | extern int simple_statfs(struct super_block *, struct kstatfs *); | 1717 | extern int simple_statfs(struct super_block *, struct kstatfs *); |
| 1716 | extern int simple_link(struct dentry *, struct inode *, struct dentry *); | 1718 | extern int simple_link(struct dentry *, struct inode *, struct dentry *); |
| 1717 | extern int simple_unlink(struct inode *, struct dentry *); | 1719 | extern int simple_unlink(struct inode *, struct dentry *); |
| 1718 | extern int simple_rmdir(struct inode *, struct dentry *); | 1720 | extern int simple_rmdir(struct inode *, struct dentry *); |
| 1719 | extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); | 1721 | extern int simple_rename(struct inode *, struct dentry *, struct inode *, struct dentry *); |
| 1720 | extern int simple_sync_file(struct file *, struct dentry *, int); | 1722 | extern int simple_sync_file(struct file *, struct dentry *, int); |
| 1721 | extern int simple_empty(struct dentry *); | 1723 | extern int simple_empty(struct dentry *); |
| 1722 | extern int simple_readpage(struct file *file, struct page *page); | 1724 | extern int simple_readpage(struct file *file, struct page *page); |
| 1723 | extern int simple_prepare_write(struct file *file, struct page *page, | 1725 | extern int simple_prepare_write(struct file *file, struct page *page, |
| 1724 | unsigned offset, unsigned to); | 1726 | unsigned offset, unsigned to); |
| 1725 | extern int simple_commit_write(struct file *file, struct page *page, | 1727 | extern int simple_commit_write(struct file *file, struct page *page, |
| 1726 | unsigned offset, unsigned to); | 1728 | unsigned offset, unsigned to); |
| 1727 | 1729 | ||
| 1728 | extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *); | 1730 | extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *); |
| 1729 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); | 1731 | extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *); |
| 1730 | extern struct file_operations simple_dir_operations; | 1732 | extern struct file_operations simple_dir_operations; |
| 1731 | extern struct inode_operations simple_dir_inode_operations; | 1733 | extern struct inode_operations simple_dir_inode_operations; |
| 1732 | struct tree_descr { char *name; struct file_operations *ops; int mode; }; | 1734 | struct tree_descr { char *name; struct file_operations *ops; int mode; }; |
| 1733 | struct dentry *d_alloc_name(struct dentry *, const char *); | 1735 | struct dentry *d_alloc_name(struct dentry *, const char *); |
| 1734 | extern int simple_fill_super(struct super_block *, int, struct tree_descr *); | 1736 | extern int simple_fill_super(struct super_block *, int, struct tree_descr *); |
| 1735 | extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count); | 1737 | extern int simple_pin_fs(char *name, struct vfsmount **mount, int *count); |
| 1736 | extern void simple_release_fs(struct vfsmount **mount, int *count); | 1738 | extern void simple_release_fs(struct vfsmount **mount, int *count); |
| 1737 | 1739 | ||
| 1738 | extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t); | 1740 | extern ssize_t simple_read_from_buffer(void __user *, size_t, loff_t *, const void *, size_t); |
| 1739 | 1741 | ||
| 1740 | #ifdef CONFIG_MIGRATION | 1742 | #ifdef CONFIG_MIGRATION |
| 1741 | extern int buffer_migrate_page(struct page *, struct page *); | 1743 | extern int buffer_migrate_page(struct page *, struct page *); |
| 1742 | #else | 1744 | #else |
| 1743 | #define buffer_migrate_page NULL | 1745 | #define buffer_migrate_page NULL |
| 1744 | #endif | 1746 | #endif |
| 1745 | 1747 | ||
| 1746 | extern int inode_change_ok(struct inode *, struct iattr *); | 1748 | extern int inode_change_ok(struct inode *, struct iattr *); |
| 1747 | extern int __must_check inode_setattr(struct inode *, struct iattr *); | 1749 | extern int __must_check inode_setattr(struct inode *, struct iattr *); |
| 1748 | 1750 | ||
| 1749 | extern void file_update_time(struct file *file); | 1751 | extern void file_update_time(struct file *file); |
| 1750 | 1752 | ||
| 1751 | static inline ino_t parent_ino(struct dentry *dentry) | 1753 | static inline ino_t parent_ino(struct dentry *dentry) |
| 1752 | { | 1754 | { |
| 1753 | ino_t res; | 1755 | ino_t res; |
| 1754 | 1756 | ||
| 1755 | spin_lock(&dentry->d_lock); | 1757 | spin_lock(&dentry->d_lock); |
| 1756 | res = dentry->d_parent->d_inode->i_ino; | 1758 | res = dentry->d_parent->d_inode->i_ino; |
| 1757 | spin_unlock(&dentry->d_lock); | 1759 | spin_unlock(&dentry->d_lock); |
| 1758 | return res; | 1760 | return res; |
| 1759 | } | 1761 | } |
| 1760 | 1762 | ||
| 1761 | /* kernel/fork.c */ | 1763 | /* kernel/fork.c */ |
| 1762 | extern int unshare_files(void); | 1764 | extern int unshare_files(void); |
| 1763 | 1765 | ||
| 1764 | /* Transaction based IO helpers */ | 1766 | /* Transaction based IO helpers */ |
| 1765 | 1767 | ||
| 1766 | /* | 1768 | /* |
| 1767 | * An argresp is stored in an allocated page and holds the | 1769 | * An argresp is stored in an allocated page and holds the |
| 1768 | * size of the argument or response, along with its content | 1770 | * size of the argument or response, along with its content |
| 1769 | */ | 1771 | */ |
| 1770 | struct simple_transaction_argresp { | 1772 | struct simple_transaction_argresp { |
| 1771 | ssize_t size; | 1773 | ssize_t size; |
| 1772 | char data[0]; | 1774 | char data[0]; |
| 1773 | }; | 1775 | }; |
| 1774 | 1776 | ||
| 1775 | #define SIMPLE_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct simple_transaction_argresp)) | 1777 | #define SIMPLE_TRANSACTION_LIMIT (PAGE_SIZE - sizeof(struct simple_transaction_argresp)) |
| 1776 | 1778 | ||
| 1777 | char *simple_transaction_get(struct file *file, const char __user *buf, | 1779 | char *simple_transaction_get(struct file *file, const char __user *buf, |
| 1778 | size_t size); | 1780 | size_t size); |
| 1779 | ssize_t simple_transaction_read(struct file *file, char __user *buf, | 1781 | ssize_t simple_transaction_read(struct file *file, char __user *buf, |
| 1780 | size_t size, loff_t *pos); | 1782 | size_t size, loff_t *pos); |
| 1781 | int simple_transaction_release(struct inode *inode, struct file *file); | 1783 | int simple_transaction_release(struct inode *inode, struct file *file); |
| 1782 | 1784 | ||
| 1783 | static inline void simple_transaction_set(struct file *file, size_t n) | 1785 | static inline void simple_transaction_set(struct file *file, size_t n) |
| 1784 | { | 1786 | { |
| 1785 | struct simple_transaction_argresp *ar = file->private_data; | 1787 | struct simple_transaction_argresp *ar = file->private_data; |
| 1786 | 1788 | ||
| 1787 | BUG_ON(n > SIMPLE_TRANSACTION_LIMIT); | 1789 | BUG_ON(n > SIMPLE_TRANSACTION_LIMIT); |
| 1788 | 1790 | ||
| 1789 | /* | 1791 | /* |
| 1790 | * The barrier ensures that ar->size will really remain zero until | 1792 | * The barrier ensures that ar->size will really remain zero until |
| 1791 | * ar->data is ready for reading. | 1793 | * ar->data is ready for reading. |
| 1792 | */ | 1794 | */ |
| 1793 | smp_mb(); | 1795 | smp_mb(); |
| 1794 | ar->size = n; | 1796 | ar->size = n; |
| 1795 | } | 1797 | } |
| 1796 | 1798 | ||
| 1797 | /* | 1799 | /* |
| 1798 | * simple attribute files | 1800 | * simple attribute files |
| 1799 | * | 1801 | * |
| 1800 | * These attributes behave similar to those in sysfs: | 1802 | * These attributes behave similar to those in sysfs: |
| 1801 | * | 1803 | * |
| 1802 | * Writing to an attribute immediately sets a value, an open file can be | 1804 | * Writing to an attribute immediately sets a value, an open file can be |
| 1803 | * written to multiple times. | 1805 | * written to multiple times. |
| 1804 | * | 1806 | * |
| 1805 | * Reading from an attribute creates a buffer from the value that might get | 1807 | * Reading from an attribute creates a buffer from the value that might get |
| 1806 | * read with multiple read calls. When the attribute has been read | 1808 | * read with multiple read calls. When the attribute has been read |
| 1807 | * completely, no further read calls are possible until the file is opened | 1809 | * completely, no further read calls are possible until the file is opened |
| 1808 | * again. | 1810 | * again. |
| 1809 | * | 1811 | * |
| 1810 | * All attributes contain a text representation of a numeric value | 1812 | * All attributes contain a text representation of a numeric value |
| 1811 | * that are accessed with the get() and set() functions. | 1813 | * that are accessed with the get() and set() functions. |
| 1812 | */ | 1814 | */ |
| 1813 | #define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \ | 1815 | #define DEFINE_SIMPLE_ATTRIBUTE(__fops, __get, __set, __fmt) \ |
| 1814 | static int __fops ## _open(struct inode *inode, struct file *file) \ | 1816 | static int __fops ## _open(struct inode *inode, struct file *file) \ |
| 1815 | { \ | 1817 | { \ |
| 1816 | __simple_attr_check_format(__fmt, 0ull); \ | 1818 | __simple_attr_check_format(__fmt, 0ull); \ |
| 1817 | return simple_attr_open(inode, file, __get, __set, __fmt); \ | 1819 | return simple_attr_open(inode, file, __get, __set, __fmt); \ |
| 1818 | } \ | 1820 | } \ |
| 1819 | static struct file_operations __fops = { \ | 1821 | static struct file_operations __fops = { \ |
| 1820 | .owner = THIS_MODULE, \ | 1822 | .owner = THIS_MODULE, \ |
| 1821 | .open = __fops ## _open, \ | 1823 | .open = __fops ## _open, \ |
| 1822 | .release = simple_attr_close, \ | 1824 | .release = simple_attr_close, \ |
| 1823 | .read = simple_attr_read, \ | 1825 | .read = simple_attr_read, \ |
| 1824 | .write = simple_attr_write, \ | 1826 | .write = simple_attr_write, \ |
| 1825 | }; | 1827 | }; |
| 1826 | 1828 | ||
| 1827 | static inline void __attribute__((format(printf, 1, 2))) | 1829 | static inline void __attribute__((format(printf, 1, 2))) |
| 1828 | __simple_attr_check_format(const char *fmt, ...) | 1830 | __simple_attr_check_format(const char *fmt, ...) |
| 1829 | { | 1831 | { |
| 1830 | /* don't do anything, just let the compiler check the arguments; */ | 1832 | /* don't do anything, just let the compiler check the arguments; */ |
| 1831 | } | 1833 | } |
| 1832 | 1834 | ||
| 1833 | int simple_attr_open(struct inode *inode, struct file *file, | 1835 | int simple_attr_open(struct inode *inode, struct file *file, |
| 1834 | u64 (*get)(void *), void (*set)(void *, u64), | 1836 | u64 (*get)(void *), void (*set)(void *, u64), |
| 1835 | const char *fmt); | 1837 | const char *fmt); |
| 1836 | int simple_attr_close(struct inode *inode, struct file *file); | 1838 | int simple_attr_close(struct inode *inode, struct file *file); |
| 1837 | ssize_t simple_attr_read(struct file *file, char __user *buf, | 1839 | ssize_t simple_attr_read(struct file *file, char __user *buf, |
| 1838 | size_t len, loff_t *ppos); | 1840 | size_t len, loff_t *ppos); |
| 1839 | ssize_t simple_attr_write(struct file *file, const char __user *buf, | 1841 | ssize_t simple_attr_write(struct file *file, const char __user *buf, |
| 1840 | size_t len, loff_t *ppos); | 1842 | size_t len, loff_t *ppos); |
| 1841 | 1843 | ||
| 1842 | 1844 | ||
| 1843 | #ifdef CONFIG_SECURITY | 1845 | #ifdef CONFIG_SECURITY |
| 1844 | static inline char *alloc_secdata(void) | 1846 | static inline char *alloc_secdata(void) |
| 1845 | { | 1847 | { |
| 1846 | return (char *)get_zeroed_page(GFP_KERNEL); | 1848 | return (char *)get_zeroed_page(GFP_KERNEL); |
| 1847 | } | 1849 | } |
| 1848 | 1850 | ||
| 1849 | static inline void free_secdata(void *secdata) | 1851 | static inline void free_secdata(void *secdata) |
| 1850 | { | 1852 | { |
| 1851 | free_page((unsigned long)secdata); | 1853 | free_page((unsigned long)secdata); |
| 1852 | } | 1854 | } |
| 1853 | #else | 1855 | #else |
| 1854 | static inline char *alloc_secdata(void) | 1856 | static inline char *alloc_secdata(void) |
| 1855 | { | 1857 | { |
| 1856 | return (char *)1; | 1858 | return (char *)1; |
| 1857 | } | 1859 | } |
| 1858 | 1860 | ||
| 1859 | static inline void free_secdata(void *secdata) | 1861 | static inline void free_secdata(void *secdata) |
| 1860 | { } | 1862 | { } |
| 1861 | #endif /* CONFIG_SECURITY */ | 1863 | #endif /* CONFIG_SECURITY */ |
| 1862 | 1864 | ||
| 1863 | #endif /* __KERNEL__ */ | 1865 | #endif /* __KERNEL__ */ |
| 1864 | #endif /* _LINUX_FS_H */ | 1866 | #endif /* _LINUX_FS_H */ |
| 1865 | 1867 |
init/do_mounts.c
| 1 | #include <linux/module.h> | 1 | #include <linux/module.h> |
| 2 | #include <linux/sched.h> | 2 | #include <linux/sched.h> |
| 3 | #include <linux/ctype.h> | 3 | #include <linux/ctype.h> |
| 4 | #include <linux/fd.h> | 4 | #include <linux/fd.h> |
| 5 | #include <linux/tty.h> | 5 | #include <linux/tty.h> |
| 6 | #include <linux/suspend.h> | 6 | #include <linux/suspend.h> |
| 7 | #include <linux/root_dev.h> | 7 | #include <linux/root_dev.h> |
| 8 | #include <linux/security.h> | 8 | #include <linux/security.h> |
| 9 | #include <linux/delay.h> | 9 | #include <linux/delay.h> |
| 10 | #include <linux/mount.h> | 10 | #include <linux/mount.h> |
| 11 | 11 | ||
| 12 | #include <linux/nfs_fs.h> | 12 | #include <linux/nfs_fs.h> |
| 13 | #include <linux/nfs_fs_sb.h> | 13 | #include <linux/nfs_fs_sb.h> |
| 14 | #include <linux/nfs_mount.h> | 14 | #include <linux/nfs_mount.h> |
| 15 | 15 | ||
| 16 | #include "do_mounts.h" | 16 | #include "do_mounts.h" |
| 17 | 17 | ||
| 18 | extern int get_filesystem_list(char * buf); | 18 | extern int get_filesystem_list(char * buf); |
| 19 | 19 | ||
| 20 | int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */ | 20 | int __initdata rd_doload; /* 1 = load RAM disk, 0 = don't load */ |
| 21 | 21 | ||
| 22 | int root_mountflags = MS_RDONLY | MS_VERBOSE; | 22 | int root_mountflags = MS_RDONLY | MS_SILENT; |
| 23 | char * __initdata root_device_name; | 23 | char * __initdata root_device_name; |
| 24 | static char __initdata saved_root_name[64]; | 24 | static char __initdata saved_root_name[64]; |
| 25 | 25 | ||
| 26 | /* this is initialized in init/main.c */ | 26 | /* this is initialized in init/main.c */ |
| 27 | dev_t ROOT_DEV; | 27 | dev_t ROOT_DEV; |
| 28 | 28 | ||
| 29 | static int __init load_ramdisk(char *str) | 29 | static int __init load_ramdisk(char *str) |
| 30 | { | 30 | { |
| 31 | rd_doload = simple_strtol(str,NULL,0) & 3; | 31 | rd_doload = simple_strtol(str,NULL,0) & 3; |
| 32 | return 1; | 32 | return 1; |
| 33 | } | 33 | } |
| 34 | __setup("load_ramdisk=", load_ramdisk); | 34 | __setup("load_ramdisk=", load_ramdisk); |
| 35 | 35 | ||
| 36 | static int __init readonly(char *str) | 36 | static int __init readonly(char *str) |
| 37 | { | 37 | { |
| 38 | if (*str) | 38 | if (*str) |
| 39 | return 0; | 39 | return 0; |
| 40 | root_mountflags |= MS_RDONLY; | 40 | root_mountflags |= MS_RDONLY; |
| 41 | return 1; | 41 | return 1; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | static int __init readwrite(char *str) | 44 | static int __init readwrite(char *str) |
| 45 | { | 45 | { |
| 46 | if (*str) | 46 | if (*str) |
| 47 | return 0; | 47 | return 0; |
| 48 | root_mountflags &= ~MS_RDONLY; | 48 | root_mountflags &= ~MS_RDONLY; |
| 49 | return 1; | 49 | return 1; |
| 50 | } | 50 | } |
| 51 | 51 | ||
| 52 | __setup("ro", readonly); | 52 | __setup("ro", readonly); |
| 53 | __setup("rw", readwrite); | 53 | __setup("rw", readwrite); |
| 54 | 54 | ||
| 55 | static dev_t try_name(char *name, int part) | 55 | static dev_t try_name(char *name, int part) |
| 56 | { | 56 | { |
| 57 | char path[64]; | 57 | char path[64]; |
| 58 | char buf[32]; | 58 | char buf[32]; |
| 59 | int range; | 59 | int range; |
| 60 | dev_t res; | 60 | dev_t res; |
| 61 | char *s; | 61 | char *s; |
| 62 | int len; | 62 | int len; |
| 63 | int fd; | 63 | int fd; |
| 64 | unsigned int maj, min; | 64 | unsigned int maj, min; |
| 65 | 65 | ||
| 66 | /* read device number from .../dev */ | 66 | /* read device number from .../dev */ |
| 67 | 67 | ||
| 68 | sprintf(path, "/sys/block/%s/dev", name); | 68 | sprintf(path, "/sys/block/%s/dev", name); |
| 69 | fd = sys_open(path, 0, 0); | 69 | fd = sys_open(path, 0, 0); |
| 70 | if (fd < 0) | 70 | if (fd < 0) |
| 71 | goto fail; | 71 | goto fail; |
| 72 | len = sys_read(fd, buf, 32); | 72 | len = sys_read(fd, buf, 32); |
| 73 | sys_close(fd); | 73 | sys_close(fd); |
| 74 | if (len <= 0 || len == 32 || buf[len - 1] != '\n') | 74 | if (len <= 0 || len == 32 || buf[len - 1] != '\n') |
| 75 | goto fail; | 75 | goto fail; |
| 76 | buf[len - 1] = '\0'; | 76 | buf[len - 1] = '\0'; |
| 77 | if (sscanf(buf, "%u:%u", &maj, &min) == 2) { | 77 | if (sscanf(buf, "%u:%u", &maj, &min) == 2) { |
| 78 | /* | 78 | /* |
| 79 | * Try the %u:%u format -- see print_dev_t() | 79 | * Try the %u:%u format -- see print_dev_t() |
| 80 | */ | 80 | */ |
| 81 | res = MKDEV(maj, min); | 81 | res = MKDEV(maj, min); |
| 82 | if (maj != MAJOR(res) || min != MINOR(res)) | 82 | if (maj != MAJOR(res) || min != MINOR(res)) |
| 83 | goto fail; | 83 | goto fail; |
| 84 | } else { | 84 | } else { |
| 85 | /* | 85 | /* |
| 86 | * Nope. Try old-style "0321" | 86 | * Nope. Try old-style "0321" |
| 87 | */ | 87 | */ |
| 88 | res = new_decode_dev(simple_strtoul(buf, &s, 16)); | 88 | res = new_decode_dev(simple_strtoul(buf, &s, 16)); |
| 89 | if (*s) | 89 | if (*s) |
| 90 | goto fail; | 90 | goto fail; |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | /* if it's there and we are not looking for a partition - that's it */ | 93 | /* if it's there and we are not looking for a partition - that's it */ |
| 94 | if (!part) | 94 | if (!part) |
| 95 | return res; | 95 | return res; |
| 96 | 96 | ||
| 97 | /* otherwise read range from .../range */ | 97 | /* otherwise read range from .../range */ |
| 98 | sprintf(path, "/sys/block/%s/range", name); | 98 | sprintf(path, "/sys/block/%s/range", name); |
| 99 | fd = sys_open(path, 0, 0); | 99 | fd = sys_open(path, 0, 0); |
| 100 | if (fd < 0) | 100 | if (fd < 0) |
| 101 | goto fail; | 101 | goto fail; |
| 102 | len = sys_read(fd, buf, 32); | 102 | len = sys_read(fd, buf, 32); |
| 103 | sys_close(fd); | 103 | sys_close(fd); |
| 104 | if (len <= 0 || len == 32 || buf[len - 1] != '\n') | 104 | if (len <= 0 || len == 32 || buf[len - 1] != '\n') |
| 105 | goto fail; | 105 | goto fail; |
| 106 | buf[len - 1] = '\0'; | 106 | buf[len - 1] = '\0'; |
| 107 | range = simple_strtoul(buf, &s, 10); | 107 | range = simple_strtoul(buf, &s, 10); |
| 108 | if (*s) | 108 | if (*s) |
| 109 | goto fail; | 109 | goto fail; |
| 110 | 110 | ||
| 111 | /* if partition is within range - we got it */ | 111 | /* if partition is within range - we got it */ |
| 112 | if (part < range) | 112 | if (part < range) |
| 113 | return res + part; | 113 | return res + part; |
| 114 | fail: | 114 | fail: |
| 115 | return 0; | 115 | return 0; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | /* | 118 | /* |
| 119 | * Convert a name into device number. We accept the following variants: | 119 | * Convert a name into device number. We accept the following variants: |
| 120 | * | 120 | * |
| 121 | * 1) device number in hexadecimal represents itself | 121 | * 1) device number in hexadecimal represents itself |
| 122 | * 2) /dev/nfs represents Root_NFS (0xff) | 122 | * 2) /dev/nfs represents Root_NFS (0xff) |
| 123 | * 3) /dev/<disk_name> represents the device number of disk | 123 | * 3) /dev/<disk_name> represents the device number of disk |
| 124 | * 4) /dev/<disk_name><decimal> represents the device number | 124 | * 4) /dev/<disk_name><decimal> represents the device number |
| 125 | * of partition - device number of disk plus the partition number | 125 | * of partition - device number of disk plus the partition number |
| 126 | * 5) /dev/<disk_name>p<decimal> - same as the above, that form is | 126 | * 5) /dev/<disk_name>p<decimal> - same as the above, that form is |
| 127 | * used when disk name of partitioned disk ends on a digit. | 127 | * used when disk name of partitioned disk ends on a digit. |
| 128 | * | 128 | * |
| 129 | * If name doesn't have fall into the categories above, we return 0. | 129 | * If name doesn't have fall into the categories above, we return 0. |
| 130 | * Sysfs is used to check if something is a disk name - it has | 130 | * Sysfs is used to check if something is a disk name - it has |
| 131 | * all known disks under bus/block/devices. If the disk name | 131 | * all known disks under bus/block/devices. If the disk name |
| 132 | * contains slashes, name of sysfs node has them replaced with | 132 | * contains slashes, name of sysfs node has them replaced with |
| 133 | * bangs. try_name() does the actual checks, assuming that sysfs | 133 | * bangs. try_name() does the actual checks, assuming that sysfs |
| 134 | * is mounted on rootfs /sys. | 134 | * is mounted on rootfs /sys. |
| 135 | */ | 135 | */ |
| 136 | 136 | ||
| 137 | dev_t name_to_dev_t(char *name) | 137 | dev_t name_to_dev_t(char *name) |
| 138 | { | 138 | { |
| 139 | char s[32]; | 139 | char s[32]; |
| 140 | char *p; | 140 | char *p; |
| 141 | dev_t res = 0; | 141 | dev_t res = 0; |
| 142 | int part; | 142 | int part; |
| 143 | 143 | ||
| 144 | #ifdef CONFIG_SYSFS | 144 | #ifdef CONFIG_SYSFS |
| 145 | int mkdir_err = sys_mkdir("/sys", 0700); | 145 | int mkdir_err = sys_mkdir("/sys", 0700); |
| 146 | if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0) | 146 | if (sys_mount("sysfs", "/sys", "sysfs", 0, NULL) < 0) |
| 147 | goto out; | 147 | goto out; |
| 148 | #endif | 148 | #endif |
| 149 | 149 | ||
| 150 | if (strncmp(name, "/dev/", 5) != 0) { | 150 | if (strncmp(name, "/dev/", 5) != 0) { |
| 151 | unsigned maj, min; | 151 | unsigned maj, min; |
| 152 | 152 | ||
| 153 | if (sscanf(name, "%u:%u", &maj, &min) == 2) { | 153 | if (sscanf(name, "%u:%u", &maj, &min) == 2) { |
| 154 | res = MKDEV(maj, min); | 154 | res = MKDEV(maj, min); |
| 155 | if (maj != MAJOR(res) || min != MINOR(res)) | 155 | if (maj != MAJOR(res) || min != MINOR(res)) |
| 156 | goto fail; | 156 | goto fail; |
| 157 | } else { | 157 | } else { |
| 158 | res = new_decode_dev(simple_strtoul(name, &p, 16)); | 158 | res = new_decode_dev(simple_strtoul(name, &p, 16)); |
| 159 | if (*p) | 159 | if (*p) |
| 160 | goto fail; | 160 | goto fail; |
| 161 | } | 161 | } |
| 162 | goto done; | 162 | goto done; |
| 163 | } | 163 | } |
| 164 | name += 5; | 164 | name += 5; |
| 165 | res = Root_NFS; | 165 | res = Root_NFS; |
| 166 | if (strcmp(name, "nfs") == 0) | 166 | if (strcmp(name, "nfs") == 0) |
| 167 | goto done; | 167 | goto done; |
| 168 | res = Root_RAM0; | 168 | res = Root_RAM0; |
| 169 | if (strcmp(name, "ram") == 0) | 169 | if (strcmp(name, "ram") == 0) |
| 170 | goto done; | 170 | goto done; |
| 171 | 171 | ||
| 172 | if (strlen(name) > 31) | 172 | if (strlen(name) > 31) |
| 173 | goto fail; | 173 | goto fail; |
| 174 | strcpy(s, name); | 174 | strcpy(s, name); |
| 175 | for (p = s; *p; p++) | 175 | for (p = s; *p; p++) |
| 176 | if (*p == '/') | 176 | if (*p == '/') |
| 177 | *p = '!'; | 177 | *p = '!'; |
| 178 | res = try_name(s, 0); | 178 | res = try_name(s, 0); |
| 179 | if (res) | 179 | if (res) |
| 180 | goto done; | 180 | goto done; |
| 181 | 181 | ||
| 182 | while (p > s && isdigit(p[-1])) | 182 | while (p > s && isdigit(p[-1])) |
| 183 | p--; | 183 | p--; |
| 184 | if (p == s || !*p || *p == '0') | 184 | if (p == s || !*p || *p == '0') |
| 185 | goto fail; | 185 | goto fail; |
| 186 | part = simple_strtoul(p, NULL, 10); | 186 | part = simple_strtoul(p, NULL, 10); |
| 187 | *p = '\0'; | 187 | *p = '\0'; |
| 188 | res = try_name(s, part); | 188 | res = try_name(s, part); |
| 189 | if (res) | 189 | if (res) |
| 190 | goto done; | 190 | goto done; |
| 191 | 191 | ||
| 192 | if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') | 192 | if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') |
| 193 | goto fail; | 193 | goto fail; |
| 194 | p[-1] = '\0'; | 194 | p[-1] = '\0'; |
| 195 | res = try_name(s, part); | 195 | res = try_name(s, part); |
| 196 | done: | 196 | done: |
| 197 | #ifdef CONFIG_SYSFS | 197 | #ifdef CONFIG_SYSFS |
| 198 | sys_umount("/sys", 0); | 198 | sys_umount("/sys", 0); |
| 199 | out: | 199 | out: |
| 200 | if (!mkdir_err) | 200 | if (!mkdir_err) |
| 201 | sys_rmdir("/sys"); | 201 | sys_rmdir("/sys"); |
| 202 | #endif | 202 | #endif |
| 203 | return res; | 203 | return res; |
| 204 | fail: | 204 | fail: |
| 205 | res = 0; | 205 | res = 0; |
| 206 | goto done; | 206 | goto done; |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | static int __init root_dev_setup(char *line) | 209 | static int __init root_dev_setup(char *line) |
| 210 | { | 210 | { |
| 211 | strlcpy(saved_root_name, line, sizeof(saved_root_name)); | 211 | strlcpy(saved_root_name, line, sizeof(saved_root_name)); |
| 212 | return 1; | 212 | return 1; |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | __setup("root=", root_dev_setup); | 215 | __setup("root=", root_dev_setup); |
| 216 | 216 | ||
| 217 | static char * __initdata root_mount_data; | 217 | static char * __initdata root_mount_data; |
| 218 | static int __init root_data_setup(char *str) | 218 | static int __init root_data_setup(char *str) |
| 219 | { | 219 | { |
| 220 | root_mount_data = str; | 220 | root_mount_data = str; |
| 221 | return 1; | 221 | return 1; |
| 222 | } | 222 | } |
| 223 | 223 | ||
| 224 | static char * __initdata root_fs_names; | 224 | static char * __initdata root_fs_names; |
| 225 | static int __init fs_names_setup(char *str) | 225 | static int __init fs_names_setup(char *str) |
| 226 | { | 226 | { |
| 227 | root_fs_names = str; | 227 | root_fs_names = str; |
| 228 | return 1; | 228 | return 1; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | static unsigned int __initdata root_delay; | 231 | static unsigned int __initdata root_delay; |
| 232 | static int __init root_delay_setup(char *str) | 232 | static int __init root_delay_setup(char *str) |
| 233 | { | 233 | { |
| 234 | root_delay = simple_strtoul(str, NULL, 0); | 234 | root_delay = simple_strtoul(str, NULL, 0); |
| 235 | return 1; | 235 | return 1; |
| 236 | } | 236 | } |
| 237 | 237 | ||
| 238 | __setup("rootflags=", root_data_setup); | 238 | __setup("rootflags=", root_data_setup); |
| 239 | __setup("rootfstype=", fs_names_setup); | 239 | __setup("rootfstype=", fs_names_setup); |
| 240 | __setup("rootdelay=", root_delay_setup); | 240 | __setup("rootdelay=", root_delay_setup); |
| 241 | 241 | ||
| 242 | static void __init get_fs_names(char *page) | 242 | static void __init get_fs_names(char *page) |
| 243 | { | 243 | { |
| 244 | char *s = page; | 244 | char *s = page; |
| 245 | 245 | ||
| 246 | if (root_fs_names) { | 246 | if (root_fs_names) { |
| 247 | strcpy(page, root_fs_names); | 247 | strcpy(page, root_fs_names); |
| 248 | while (*s++) { | 248 | while (*s++) { |
| 249 | if (s[-1] == ',') | 249 | if (s[-1] == ',') |
| 250 | s[-1] = '\0'; | 250 | s[-1] = '\0'; |
| 251 | } | 251 | } |
| 252 | } else { | 252 | } else { |
| 253 | int len = get_filesystem_list(page); | 253 | int len = get_filesystem_list(page); |
| 254 | char *p, *next; | 254 | char *p, *next; |
| 255 | 255 | ||
| 256 | page[len] = '\0'; | 256 | page[len] = '\0'; |
| 257 | for (p = page-1; p; p = next) { | 257 | for (p = page-1; p; p = next) { |
| 258 | next = strchr(++p, '\n'); | 258 | next = strchr(++p, '\n'); |
| 259 | if (*p++ != '\t') | 259 | if (*p++ != '\t') |
| 260 | continue; | 260 | continue; |
| 261 | while ((*s++ = *p++) != '\n') | 261 | while ((*s++ = *p++) != '\n') |
| 262 | ; | 262 | ; |
| 263 | s[-1] = '\0'; | 263 | s[-1] = '\0'; |
| 264 | } | 264 | } |
| 265 | } | 265 | } |
| 266 | *s = '\0'; | 266 | *s = '\0'; |
| 267 | } | 267 | } |
| 268 | 268 | ||
| 269 | static int __init do_mount_root(char *name, char *fs, int flags, void *data) | 269 | static int __init do_mount_root(char *name, char *fs, int flags, void *data) |
| 270 | { | 270 | { |
| 271 | int err = sys_mount(name, "/root", fs, flags, data); | 271 | int err = sys_mount(name, "/root", fs, flags, data); |
| 272 | if (err) | 272 | if (err) |
| 273 | return err; | 273 | return err; |
| 274 | 274 | ||
| 275 | sys_chdir("/root"); | 275 | sys_chdir("/root"); |
| 276 | ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; | 276 | ROOT_DEV = current->fs->pwdmnt->mnt_sb->s_dev; |
| 277 | printk("VFS: Mounted root (%s filesystem)%s.\n", | 277 | printk("VFS: Mounted root (%s filesystem)%s.\n", |
| 278 | current->fs->pwdmnt->mnt_sb->s_type->name, | 278 | current->fs->pwdmnt->mnt_sb->s_type->name, |
| 279 | current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY ? | 279 | current->fs->pwdmnt->mnt_sb->s_flags & MS_RDONLY ? |
| 280 | " readonly" : ""); | 280 | " readonly" : ""); |
| 281 | return 0; | 281 | return 0; |
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | void __init mount_block_root(char *name, int flags) | 284 | void __init mount_block_root(char *name, int flags) |
| 285 | { | 285 | { |
| 286 | char *fs_names = __getname(); | 286 | char *fs_names = __getname(); |
| 287 | char *p; | 287 | char *p; |
| 288 | char b[BDEVNAME_SIZE]; | 288 | char b[BDEVNAME_SIZE]; |
| 289 | 289 | ||
| 290 | get_fs_names(fs_names); | 290 | get_fs_names(fs_names); |
| 291 | retry: | 291 | retry: |
| 292 | for (p = fs_names; *p; p += strlen(p)+1) { | 292 | for (p = fs_names; *p; p += strlen(p)+1) { |
| 293 | int err = do_mount_root(name, p, flags, root_mount_data); | 293 | int err = do_mount_root(name, p, flags, root_mount_data); |
| 294 | switch (err) { | 294 | switch (err) { |
| 295 | case 0: | 295 | case 0: |
| 296 | goto out; | 296 | goto out; |
| 297 | case -EACCES: | 297 | case -EACCES: |
| 298 | flags |= MS_RDONLY; | 298 | flags |= MS_RDONLY; |
| 299 | goto retry; | 299 | goto retry; |
| 300 | case -EINVAL: | 300 | case -EINVAL: |
| 301 | continue; | 301 | continue; |
| 302 | } | 302 | } |
| 303 | /* | 303 | /* |
| 304 | * Allow the user to distinguish between failed sys_open | 304 | * Allow the user to distinguish between failed sys_open |
| 305 | * and bad superblock on root device. | 305 | * and bad superblock on root device. |
| 306 | */ | 306 | */ |
| 307 | __bdevname(ROOT_DEV, b); | 307 | __bdevname(ROOT_DEV, b); |
| 308 | printk("VFS: Cannot open root device \"%s\" or %s\n", | 308 | printk("VFS: Cannot open root device \"%s\" or %s\n", |
| 309 | root_device_name, b); | 309 | root_device_name, b); |
| 310 | printk("Please append a correct \"root=\" boot option\n"); | 310 | printk("Please append a correct \"root=\" boot option\n"); |
| 311 | 311 | ||
| 312 | panic("VFS: Unable to mount root fs on %s", b); | 312 | panic("VFS: Unable to mount root fs on %s", b); |
| 313 | } | 313 | } |
| 314 | panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b)); | 314 | panic("VFS: Unable to mount root fs on %s", __bdevname(ROOT_DEV, b)); |
| 315 | out: | 315 | out: |
| 316 | putname(fs_names); | 316 | putname(fs_names); |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | #ifdef CONFIG_ROOT_NFS | 319 | #ifdef CONFIG_ROOT_NFS |
| 320 | static int __init mount_nfs_root(void) | 320 | static int __init mount_nfs_root(void) |
| 321 | { | 321 | { |
| 322 | void *data = nfs_root_data(); | 322 | void *data = nfs_root_data(); |
| 323 | 323 | ||
| 324 | create_dev("/dev/root", ROOT_DEV, NULL); | 324 | create_dev("/dev/root", ROOT_DEV, NULL); |
| 325 | if (data && | 325 | if (data && |
| 326 | do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0) | 326 | do_mount_root("/dev/root", "nfs", root_mountflags, data) == 0) |
| 327 | return 1; | 327 | return 1; |
| 328 | return 0; | 328 | return 0; |
| 329 | } | 329 | } |
| 330 | #endif | 330 | #endif |
| 331 | 331 | ||
| 332 | #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) | 332 | #if defined(CONFIG_BLK_DEV_RAM) || defined(CONFIG_BLK_DEV_FD) |
| 333 | void __init change_floppy(char *fmt, ...) | 333 | void __init change_floppy(char *fmt, ...) |
| 334 | { | 334 | { |
| 335 | struct termios termios; | 335 | struct termios termios; |
| 336 | char buf[80]; | 336 | char buf[80]; |
| 337 | char c; | 337 | char c; |
| 338 | int fd; | 338 | int fd; |
| 339 | va_list args; | 339 | va_list args; |
| 340 | va_start(args, fmt); | 340 | va_start(args, fmt); |
| 341 | vsprintf(buf, fmt, args); | 341 | vsprintf(buf, fmt, args); |
| 342 | va_end(args); | 342 | va_end(args); |
| 343 | fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); | 343 | fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); |
| 344 | if (fd >= 0) { | 344 | if (fd >= 0) { |
| 345 | sys_ioctl(fd, FDEJECT, 0); | 345 | sys_ioctl(fd, FDEJECT, 0); |
| 346 | sys_close(fd); | 346 | sys_close(fd); |
| 347 | } | 347 | } |
| 348 | printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); | 348 | printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); |
| 349 | fd = sys_open("/dev/console", O_RDWR, 0); | 349 | fd = sys_open("/dev/console", O_RDWR, 0); |
| 350 | if (fd >= 0) { | 350 | if (fd >= 0) { |
| 351 | sys_ioctl(fd, TCGETS, (long)&termios); | 351 | sys_ioctl(fd, TCGETS, (long)&termios); |
| 352 | termios.c_lflag &= ~ICANON; | 352 | termios.c_lflag &= ~ICANON; |
| 353 | sys_ioctl(fd, TCSETSF, (long)&termios); | 353 | sys_ioctl(fd, TCSETSF, (long)&termios); |
| 354 | sys_read(fd, &c, 1); | 354 | sys_read(fd, &c, 1); |
| 355 | termios.c_lflag |= ICANON; | 355 | termios.c_lflag |= ICANON; |
| 356 | sys_ioctl(fd, TCSETSF, (long)&termios); | 356 | sys_ioctl(fd, TCSETSF, (long)&termios); |
| 357 | sys_close(fd); | 357 | sys_close(fd); |
| 358 | } | 358 | } |
| 359 | } | 359 | } |
| 360 | #endif | 360 | #endif |
| 361 | 361 | ||
| 362 | void __init mount_root(void) | 362 | void __init mount_root(void) |
| 363 | { | 363 | { |
| 364 | #ifdef CONFIG_ROOT_NFS | 364 | #ifdef CONFIG_ROOT_NFS |
| 365 | if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { | 365 | if (MAJOR(ROOT_DEV) == UNNAMED_MAJOR) { |
| 366 | if (mount_nfs_root()) | 366 | if (mount_nfs_root()) |
| 367 | return; | 367 | return; |
| 368 | 368 | ||
| 369 | printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); | 369 | printk(KERN_ERR "VFS: Unable to mount root fs via NFS, trying floppy.\n"); |
| 370 | ROOT_DEV = Root_FD0; | 370 | ROOT_DEV = Root_FD0; |
| 371 | } | 371 | } |
| 372 | #endif | 372 | #endif |
| 373 | #ifdef CONFIG_BLK_DEV_FD | 373 | #ifdef CONFIG_BLK_DEV_FD |
| 374 | if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { | 374 | if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) { |
| 375 | /* rd_doload is 2 for a dual initrd/ramload setup */ | 375 | /* rd_doload is 2 for a dual initrd/ramload setup */ |
| 376 | if (rd_doload==2) { | 376 | if (rd_doload==2) { |
| 377 | if (rd_load_disk(1)) { | 377 | if (rd_load_disk(1)) { |
| 378 | ROOT_DEV = Root_RAM1; | 378 | ROOT_DEV = Root_RAM1; |
| 379 | root_device_name = NULL; | 379 | root_device_name = NULL; |
| 380 | } | 380 | } |
| 381 | } else | 381 | } else |
| 382 | change_floppy("root floppy"); | 382 | change_floppy("root floppy"); |
| 383 | } | 383 | } |
| 384 | #endif | 384 | #endif |
| 385 | create_dev("/dev/root", ROOT_DEV, root_device_name); | 385 | create_dev("/dev/root", ROOT_DEV, root_device_name); |
| 386 | mount_block_root("/dev/root", root_mountflags); | 386 | mount_block_root("/dev/root", root_mountflags); |
| 387 | } | 387 | } |
| 388 | 388 | ||
| 389 | /* | 389 | /* |
| 390 | * Prepare the namespace - decide what/where to mount, load ramdisks, etc. | 390 | * Prepare the namespace - decide what/where to mount, load ramdisks, etc. |
| 391 | */ | 391 | */ |
| 392 | void __init prepare_namespace(void) | 392 | void __init prepare_namespace(void) |
| 393 | { | 393 | { |
| 394 | int is_floppy; | 394 | int is_floppy; |
| 395 | 395 | ||
| 396 | mount_devfs(); | 396 | mount_devfs(); |
| 397 | 397 | ||
| 398 | if (root_delay) { | 398 | if (root_delay) { |
| 399 | printk(KERN_INFO "Waiting %dsec before mounting root device...\n", | 399 | printk(KERN_INFO "Waiting %dsec before mounting root device...\n", |
| 400 | root_delay); | 400 | root_delay); |
| 401 | ssleep(root_delay); | 401 | ssleep(root_delay); |
| 402 | } | 402 | } |
| 403 | 403 | ||
| 404 | md_run_setup(); | 404 | md_run_setup(); |
| 405 | 405 | ||
| 406 | if (saved_root_name[0]) { | 406 | if (saved_root_name[0]) { |
| 407 | root_device_name = saved_root_name; | 407 | root_device_name = saved_root_name; |
| 408 | ROOT_DEV = name_to_dev_t(root_device_name); | 408 | ROOT_DEV = name_to_dev_t(root_device_name); |
| 409 | if (strncmp(root_device_name, "/dev/", 5) == 0) | 409 | if (strncmp(root_device_name, "/dev/", 5) == 0) |
| 410 | root_device_name += 5; | 410 | root_device_name += 5; |
| 411 | } | 411 | } |
| 412 | 412 | ||
| 413 | is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; | 413 | is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR; |
| 414 | 414 | ||
| 415 | if (initrd_load()) | 415 | if (initrd_load()) |
| 416 | goto out; | 416 | goto out; |
| 417 | 417 | ||
| 418 | if (is_floppy && rd_doload && rd_load_disk(0)) | 418 | if (is_floppy && rd_doload && rd_load_disk(0)) |
| 419 | ROOT_DEV = Root_RAM0; | 419 | ROOT_DEV = Root_RAM0; |
| 420 | 420 | ||
| 421 | mount_root(); | 421 | mount_root(); |
| 422 | out: | 422 | out: |
| 423 | umount_devfs("/dev"); | 423 | umount_devfs("/dev"); |
| 424 | sys_mount(".", "/", NULL, MS_MOVE, NULL); | 424 | sys_mount(".", "/", NULL, MS_MOVE, NULL); |
| 425 | sys_chroot("."); | 425 | sys_chroot("."); |
| 426 | security_sb_post_mountroot(); | 426 | security_sb_post_mountroot(); |
| 427 | mount_devfs_fs (); | 427 | mount_devfs_fs (); |
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | 430 |