diff options
Diffstat (limited to 'fs')
84 files changed, 1065 insertions, 968 deletions
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 20c106f24927..1b0b19550015 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
| @@ -584,11 +584,11 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | |||
| 584 | 584 | ||
| 585 | success: | 585 | success: |
| 586 | d_add(dentry, inode); | 586 | d_add(dentry, inode); |
| 587 | _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%llu }", | 587 | _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%u }", |
| 588 | fid.vnode, | 588 | fid.vnode, |
| 589 | fid.unique, | 589 | fid.unique, |
| 590 | dentry->d_inode->i_ino, | 590 | dentry->d_inode->i_ino, |
| 591 | (unsigned long long)dentry->d_inode->i_version); | 591 | dentry->d_inode->i_generation); |
| 592 | 592 | ||
| 593 | return NULL; | 593 | return NULL; |
| 594 | } | 594 | } |
| @@ -671,10 +671,10 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd) | |||
| 671 | * been deleted and replaced, and the original vnode ID has | 671 | * been deleted and replaced, and the original vnode ID has |
| 672 | * been reused */ | 672 | * been reused */ |
| 673 | if (fid.unique != vnode->fid.unique) { | 673 | if (fid.unique != vnode->fid.unique) { |
| 674 | _debug("%s: file deleted (uq %u -> %u I:%llu)", | 674 | _debug("%s: file deleted (uq %u -> %u I:%u)", |
| 675 | dentry->d_name.name, fid.unique, | 675 | dentry->d_name.name, fid.unique, |
| 676 | vnode->fid.unique, | 676 | vnode->fid.unique, |
| 677 | (unsigned long long)dentry->d_inode->i_version); | 677 | dentry->d_inode->i_generation); |
| 678 | spin_lock(&vnode->lock); | 678 | spin_lock(&vnode->lock); |
| 679 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | 679 | set_bit(AFS_VNODE_DELETED, &vnode->flags); |
| 680 | spin_unlock(&vnode->lock); | 680 | spin_unlock(&vnode->lock); |
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 4bd0218473a9..346e3289abd7 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
| @@ -89,7 +89,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, | |||
| 89 | i_size_write(&vnode->vfs_inode, size); | 89 | i_size_write(&vnode->vfs_inode, size); |
| 90 | vnode->vfs_inode.i_uid = status->owner; | 90 | vnode->vfs_inode.i_uid = status->owner; |
| 91 | vnode->vfs_inode.i_gid = status->group; | 91 | vnode->vfs_inode.i_gid = status->group; |
| 92 | vnode->vfs_inode.i_version = vnode->fid.unique; | 92 | vnode->vfs_inode.i_generation = vnode->fid.unique; |
| 93 | vnode->vfs_inode.i_nlink = status->nlink; | 93 | vnode->vfs_inode.i_nlink = status->nlink; |
| 94 | 94 | ||
| 95 | mode = vnode->vfs_inode.i_mode; | 95 | mode = vnode->vfs_inode.i_mode; |
| @@ -102,6 +102,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, | |||
| 102 | vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server; | 102 | vnode->vfs_inode.i_ctime.tv_sec = status->mtime_server; |
| 103 | vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime; | 103 | vnode->vfs_inode.i_mtime = vnode->vfs_inode.i_ctime; |
| 104 | vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime; | 104 | vnode->vfs_inode.i_atime = vnode->vfs_inode.i_ctime; |
| 105 | vnode->vfs_inode.i_version = data_version; | ||
| 105 | } | 106 | } |
| 106 | 107 | ||
| 107 | expected_version = status->data_version; | 108 | expected_version = status->data_version; |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index db66c5201474..0fdab6e03d87 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
| @@ -75,7 +75,8 @@ static int afs_inode_map_status(struct afs_vnode *vnode, struct key *key) | |||
| 75 | inode->i_ctime.tv_nsec = 0; | 75 | inode->i_ctime.tv_nsec = 0; |
| 76 | inode->i_atime = inode->i_mtime = inode->i_ctime; | 76 | inode->i_atime = inode->i_mtime = inode->i_ctime; |
| 77 | inode->i_blocks = 0; | 77 | inode->i_blocks = 0; |
| 78 | inode->i_version = vnode->fid.unique; | 78 | inode->i_generation = vnode->fid.unique; |
| 79 | inode->i_version = vnode->status.data_version; | ||
| 79 | inode->i_mapping->a_ops = &afs_fs_aops; | 80 | inode->i_mapping->a_ops = &afs_fs_aops; |
| 80 | 81 | ||
| 81 | /* check to see whether a symbolic link is really a mountpoint */ | 82 | /* check to see whether a symbolic link is really a mountpoint */ |
| @@ -100,7 +101,7 @@ static int afs_iget5_test(struct inode *inode, void *opaque) | |||
| 100 | struct afs_iget_data *data = opaque; | 101 | struct afs_iget_data *data = opaque; |
| 101 | 102 | ||
| 102 | return inode->i_ino == data->fid.vnode && | 103 | return inode->i_ino == data->fid.vnode && |
| 103 | inode->i_version == data->fid.unique; | 104 | inode->i_generation == data->fid.unique; |
| 104 | } | 105 | } |
| 105 | 106 | ||
| 106 | /* | 107 | /* |
| @@ -122,7 +123,7 @@ static int afs_iget5_set(struct inode *inode, void *opaque) | |||
| 122 | struct afs_vnode *vnode = AFS_FS_I(inode); | 123 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 123 | 124 | ||
| 124 | inode->i_ino = data->fid.vnode; | 125 | inode->i_ino = data->fid.vnode; |
| 125 | inode->i_version = data->fid.unique; | 126 | inode->i_generation = data->fid.unique; |
| 126 | vnode->fid = data->fid; | 127 | vnode->fid = data->fid; |
| 127 | vnode->volume = data->volume; | 128 | vnode->volume = data->volume; |
| 128 | 129 | ||
| @@ -380,8 +381,7 @@ int afs_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
| 380 | 381 | ||
| 381 | inode = dentry->d_inode; | 382 | inode = dentry->d_inode; |
| 382 | 383 | ||
| 383 | _enter("{ ino=%lu v=%llu }", inode->i_ino, | 384 | _enter("{ ino=%lu v=%u }", inode->i_ino, inode->i_generation); |
| 384 | (unsigned long long)inode->i_version); | ||
| 385 | 385 | ||
| 386 | generic_fillattr(inode, stat); | 386 | generic_fillattr(inode, stat); |
| 387 | return 0; | 387 | return 0; |
diff --git a/fs/afs/super.c b/fs/afs/super.c index fb240e8766d6..356dcf0929e8 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
| @@ -31,8 +31,8 @@ | |||
| 31 | static void afs_i_init_once(void *foo); | 31 | static void afs_i_init_once(void *foo); |
| 32 | static struct dentry *afs_mount(struct file_system_type *fs_type, | 32 | static struct dentry *afs_mount(struct file_system_type *fs_type, |
| 33 | int flags, const char *dev_name, void *data); | 33 | int flags, const char *dev_name, void *data); |
| 34 | static void afs_kill_super(struct super_block *sb); | ||
| 34 | static struct inode *afs_alloc_inode(struct super_block *sb); | 35 | static struct inode *afs_alloc_inode(struct super_block *sb); |
| 35 | static void afs_put_super(struct super_block *sb); | ||
| 36 | static void afs_destroy_inode(struct inode *inode); | 36 | static void afs_destroy_inode(struct inode *inode); |
| 37 | static int afs_statfs(struct dentry *dentry, struct kstatfs *buf); | 37 | static int afs_statfs(struct dentry *dentry, struct kstatfs *buf); |
| 38 | 38 | ||
| @@ -40,7 +40,7 @@ struct file_system_type afs_fs_type = { | |||
| 40 | .owner = THIS_MODULE, | 40 | .owner = THIS_MODULE, |
| 41 | .name = "afs", | 41 | .name = "afs", |
| 42 | .mount = afs_mount, | 42 | .mount = afs_mount, |
| 43 | .kill_sb = kill_anon_super, | 43 | .kill_sb = afs_kill_super, |
| 44 | .fs_flags = 0, | 44 | .fs_flags = 0, |
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| @@ -50,7 +50,6 @@ static const struct super_operations afs_super_ops = { | |||
| 50 | .drop_inode = afs_drop_inode, | 50 | .drop_inode = afs_drop_inode, |
| 51 | .destroy_inode = afs_destroy_inode, | 51 | .destroy_inode = afs_destroy_inode, |
| 52 | .evict_inode = afs_evict_inode, | 52 | .evict_inode = afs_evict_inode, |
| 53 | .put_super = afs_put_super, | ||
| 54 | .show_options = generic_show_options, | 53 | .show_options = generic_show_options, |
| 55 | }; | 54 | }; |
| 56 | 55 | ||
| @@ -282,19 +281,25 @@ static int afs_parse_device_name(struct afs_mount_params *params, | |||
| 282 | */ | 281 | */ |
| 283 | static int afs_test_super(struct super_block *sb, void *data) | 282 | static int afs_test_super(struct super_block *sb, void *data) |
| 284 | { | 283 | { |
| 285 | struct afs_mount_params *params = data; | 284 | struct afs_super_info *as1 = data; |
| 286 | struct afs_super_info *as = sb->s_fs_info; | 285 | struct afs_super_info *as = sb->s_fs_info; |
| 287 | 286 | ||
| 288 | return as->volume == params->volume; | 287 | return as->volume == as1->volume; |
| 288 | } | ||
| 289 | |||
| 290 | static int afs_set_super(struct super_block *sb, void *data) | ||
| 291 | { | ||
| 292 | sb->s_fs_info = data; | ||
| 293 | return set_anon_super(sb, NULL); | ||
| 289 | } | 294 | } |
| 290 | 295 | ||
| 291 | /* | 296 | /* |
| 292 | * fill in the superblock | 297 | * fill in the superblock |
| 293 | */ | 298 | */ |
| 294 | static int afs_fill_super(struct super_block *sb, void *data) | 299 | static int afs_fill_super(struct super_block *sb, |
| 300 | struct afs_mount_params *params) | ||
| 295 | { | 301 | { |
| 296 | struct afs_mount_params *params = data; | 302 | struct afs_super_info *as = sb->s_fs_info; |
| 297 | struct afs_super_info *as = NULL; | ||
| 298 | struct afs_fid fid; | 303 | struct afs_fid fid; |
| 299 | struct dentry *root = NULL; | 304 | struct dentry *root = NULL; |
| 300 | struct inode *inode = NULL; | 305 | struct inode *inode = NULL; |
| @@ -302,23 +307,13 @@ static int afs_fill_super(struct super_block *sb, void *data) | |||
| 302 | 307 | ||
| 303 | _enter(""); | 308 | _enter(""); |
| 304 | 309 | ||
| 305 | /* allocate a superblock info record */ | ||
| 306 | as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); | ||
| 307 | if (!as) { | ||
| 308 | _leave(" = -ENOMEM"); | ||
| 309 | return -ENOMEM; | ||
| 310 | } | ||
| 311 | |||
| 312 | afs_get_volume(params->volume); | ||
| 313 | as->volume = params->volume; | ||
| 314 | |||
| 315 | /* fill in the superblock */ | 310 | /* fill in the superblock */ |
| 316 | sb->s_blocksize = PAGE_CACHE_SIZE; | 311 | sb->s_blocksize = PAGE_CACHE_SIZE; |
| 317 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; | 312 | sb->s_blocksize_bits = PAGE_CACHE_SHIFT; |
| 318 | sb->s_magic = AFS_FS_MAGIC; | 313 | sb->s_magic = AFS_FS_MAGIC; |
| 319 | sb->s_op = &afs_super_ops; | 314 | sb->s_op = &afs_super_ops; |
| 320 | sb->s_fs_info = as; | ||
| 321 | sb->s_bdi = &as->volume->bdi; | 315 | sb->s_bdi = &as->volume->bdi; |
| 316 | strlcpy(sb->s_id, as->volume->vlocation->vldb.name, sizeof(sb->s_id)); | ||
| 322 | 317 | ||
| 323 | /* allocate the root inode and dentry */ | 318 | /* allocate the root inode and dentry */ |
| 324 | fid.vid = as->volume->vid; | 319 | fid.vid = as->volume->vid; |
| @@ -326,7 +321,7 @@ static int afs_fill_super(struct super_block *sb, void *data) | |||
| 326 | fid.unique = 1; | 321 | fid.unique = 1; |
| 327 | inode = afs_iget(sb, params->key, &fid, NULL, NULL); | 322 | inode = afs_iget(sb, params->key, &fid, NULL, NULL); |
| 328 | if (IS_ERR(inode)) | 323 | if (IS_ERR(inode)) |
| 329 | goto error_inode; | 324 | return PTR_ERR(inode); |
| 330 | 325 | ||
| 331 | if (params->autocell) | 326 | if (params->autocell) |
| 332 | set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags); | 327 | set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags); |
| @@ -342,16 +337,8 @@ static int afs_fill_super(struct super_block *sb, void *data) | |||
| 342 | _leave(" = 0"); | 337 | _leave(" = 0"); |
| 343 | return 0; | 338 | return 0; |
| 344 | 339 | ||
| 345 | error_inode: | ||
| 346 | ret = PTR_ERR(inode); | ||
| 347 | inode = NULL; | ||
| 348 | error: | 340 | error: |
| 349 | iput(inode); | 341 | iput(inode); |
| 350 | afs_put_volume(as->volume); | ||
| 351 | kfree(as); | ||
| 352 | |||
| 353 | sb->s_fs_info = NULL; | ||
| 354 | |||
| 355 | _leave(" = %d", ret); | 342 | _leave(" = %d", ret); |
| 356 | return ret; | 343 | return ret; |
| 357 | } | 344 | } |
| @@ -367,6 +354,7 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, | |||
| 367 | struct afs_volume *vol; | 354 | struct afs_volume *vol; |
| 368 | struct key *key; | 355 | struct key *key; |
| 369 | char *new_opts = kstrdup(options, GFP_KERNEL); | 356 | char *new_opts = kstrdup(options, GFP_KERNEL); |
| 357 | struct afs_super_info *as; | ||
| 370 | int ret; | 358 | int ret; |
| 371 | 359 | ||
| 372 | _enter(",,%s,%p", dev_name, options); | 360 | _enter(",,%s,%p", dev_name, options); |
| @@ -399,12 +387,22 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, | |||
| 399 | ret = PTR_ERR(vol); | 387 | ret = PTR_ERR(vol); |
| 400 | goto error; | 388 | goto error; |
| 401 | } | 389 | } |
| 402 | params.volume = vol; | 390 | |
| 391 | /* allocate a superblock info record */ | ||
| 392 | as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); | ||
| 393 | if (!as) { | ||
| 394 | ret = -ENOMEM; | ||
| 395 | afs_put_volume(vol); | ||
| 396 | goto error; | ||
| 397 | } | ||
| 398 | as->volume = vol; | ||
| 403 | 399 | ||
| 404 | /* allocate a deviceless superblock */ | 400 | /* allocate a deviceless superblock */ |
| 405 | sb = sget(fs_type, afs_test_super, set_anon_super, ¶ms); | 401 | sb = sget(fs_type, afs_test_super, afs_set_super, as); |
| 406 | if (IS_ERR(sb)) { | 402 | if (IS_ERR(sb)) { |
| 407 | ret = PTR_ERR(sb); | 403 | ret = PTR_ERR(sb); |
| 404 | afs_put_volume(vol); | ||
| 405 | kfree(as); | ||
| 408 | goto error; | 406 | goto error; |
| 409 | } | 407 | } |
| 410 | 408 | ||
| @@ -422,16 +420,16 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, | |||
| 422 | } else { | 420 | } else { |
| 423 | _debug("reuse"); | 421 | _debug("reuse"); |
| 424 | ASSERTCMP(sb->s_flags, &, MS_ACTIVE); | 422 | ASSERTCMP(sb->s_flags, &, MS_ACTIVE); |
| 423 | afs_put_volume(vol); | ||
| 424 | kfree(as); | ||
| 425 | } | 425 | } |
| 426 | 426 | ||
| 427 | afs_put_volume(params.volume); | ||
| 428 | afs_put_cell(params.cell); | 427 | afs_put_cell(params.cell); |
| 429 | kfree(new_opts); | 428 | kfree(new_opts); |
| 430 | _leave(" = 0 [%p]", sb); | 429 | _leave(" = 0 [%p]", sb); |
| 431 | return dget(sb->s_root); | 430 | return dget(sb->s_root); |
| 432 | 431 | ||
| 433 | error: | 432 | error: |
| 434 | afs_put_volume(params.volume); | ||
| 435 | afs_put_cell(params.cell); | 433 | afs_put_cell(params.cell); |
| 436 | key_put(params.key); | 434 | key_put(params.key); |
| 437 | kfree(new_opts); | 435 | kfree(new_opts); |
| @@ -439,18 +437,12 @@ error: | |||
| 439 | return ERR_PTR(ret); | 437 | return ERR_PTR(ret); |
| 440 | } | 438 | } |
| 441 | 439 | ||
| 442 | /* | 440 | static void afs_kill_super(struct super_block *sb) |
| 443 | * finish the unmounting process on the superblock | ||
| 444 | */ | ||
| 445 | static void afs_put_super(struct super_block *sb) | ||
| 446 | { | 441 | { |
| 447 | struct afs_super_info *as = sb->s_fs_info; | 442 | struct afs_super_info *as = sb->s_fs_info; |
| 448 | 443 | kill_anon_super(sb); | |
| 449 | _enter(""); | ||
| 450 | |||
| 451 | afs_put_volume(as->volume); | 444 | afs_put_volume(as->volume); |
| 452 | 445 | kfree(as); | |
| 453 | _leave(""); | ||
| 454 | } | 446 | } |
| 455 | 447 | ||
| 456 | /* | 448 | /* |
diff --git a/fs/afs/write.c b/fs/afs/write.c index 789b3afb3423..b806285ff853 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c | |||
| @@ -84,23 +84,21 @@ void afs_put_writeback(struct afs_writeback *wb) | |||
| 84 | * partly or wholly fill a page that's under preparation for writing | 84 | * partly or wholly fill a page that's under preparation for writing |
| 85 | */ | 85 | */ |
| 86 | static int afs_fill_page(struct afs_vnode *vnode, struct key *key, | 86 | static int afs_fill_page(struct afs_vnode *vnode, struct key *key, |
| 87 | loff_t pos, unsigned len, struct page *page) | 87 | loff_t pos, struct page *page) |
| 88 | { | 88 | { |
| 89 | loff_t i_size; | 89 | loff_t i_size; |
| 90 | unsigned eof; | ||
| 91 | int ret; | 90 | int ret; |
| 91 | int len; | ||
| 92 | 92 | ||
| 93 | _enter(",,%llu,%u", (unsigned long long)pos, len); | 93 | _enter(",,%llu", (unsigned long long)pos); |
| 94 | |||
| 95 | ASSERTCMP(len, <=, PAGE_CACHE_SIZE); | ||
| 96 | 94 | ||
| 97 | i_size = i_size_read(&vnode->vfs_inode); | 95 | i_size = i_size_read(&vnode->vfs_inode); |
| 98 | if (pos + len > i_size) | 96 | if (pos + PAGE_CACHE_SIZE > i_size) |
| 99 | eof = i_size; | 97 | len = i_size - pos; |
| 100 | else | 98 | else |
| 101 | eof = PAGE_CACHE_SIZE; | 99 | len = PAGE_CACHE_SIZE; |
| 102 | 100 | ||
| 103 | ret = afs_vnode_fetch_data(vnode, key, 0, eof, page); | 101 | ret = afs_vnode_fetch_data(vnode, key, pos, len, page); |
| 104 | if (ret < 0) { | 102 | if (ret < 0) { |
| 105 | if (ret == -ENOENT) { | 103 | if (ret == -ENOENT) { |
| 106 | _debug("got NOENT from server" | 104 | _debug("got NOENT from server" |
| @@ -153,9 +151,8 @@ int afs_write_begin(struct file *file, struct address_space *mapping, | |||
| 153 | *pagep = page; | 151 | *pagep = page; |
| 154 | /* page won't leak in error case: it eventually gets cleaned off LRU */ | 152 | /* page won't leak in error case: it eventually gets cleaned off LRU */ |
| 155 | 153 | ||
| 156 | if (!PageUptodate(page)) { | 154 | if (!PageUptodate(page) && len != PAGE_CACHE_SIZE) { |
| 157 | _debug("not up to date"); | 155 | ret = afs_fill_page(vnode, key, index << PAGE_CACHE_SHIFT, page); |
| 158 | ret = afs_fill_page(vnode, key, pos, len, page); | ||
| 159 | if (ret < 0) { | 156 | if (ret < 0) { |
| 160 | kfree(candidate); | 157 | kfree(candidate); |
| 161 | _leave(" = %d [prep]", ret); | 158 | _leave(" = %d [prep]", ret); |
diff --git a/fs/bad_inode.c b/fs/bad_inode.c index 9ad2369d9e35..bfcb18feb1df 100644 --- a/fs/bad_inode.c +++ b/fs/bad_inode.c | |||
| @@ -231,9 +231,6 @@ static int bad_inode_readlink(struct dentry *dentry, char __user *buffer, | |||
| 231 | 231 | ||
| 232 | static int bad_inode_permission(struct inode *inode, int mask, unsigned int flags) | 232 | static int bad_inode_permission(struct inode *inode, int mask, unsigned int flags) |
| 233 | { | 233 | { |
| 234 | if (flags & IPERM_FLAG_RCU) | ||
| 235 | return -ECHILD; | ||
| 236 | |||
| 237 | return -EIO; | 234 | return -EIO; |
| 238 | } | 235 | } |
| 239 | 236 | ||
diff --git a/fs/block_dev.c b/fs/block_dev.c index 1a2421f908f0..610e8e0b04b8 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -762,7 +762,19 @@ static struct block_device *bd_start_claiming(struct block_device *bdev, | |||
| 762 | if (!disk) | 762 | if (!disk) |
| 763 | return ERR_PTR(-ENXIO); | 763 | return ERR_PTR(-ENXIO); |
| 764 | 764 | ||
| 765 | whole = bdget_disk(disk, 0); | 765 | /* |
| 766 | * Normally, @bdev should equal what's returned from bdget_disk() | ||
| 767 | * if partno is 0; however, some drivers (floppy) use multiple | ||
| 768 | * bdev's for the same physical device and @bdev may be one of the | ||
| 769 | * aliases. Keep @bdev if partno is 0. This means claimer | ||
| 770 | * tracking is broken for those devices but it has always been that | ||
| 771 | * way. | ||
| 772 | */ | ||
| 773 | if (partno) | ||
| 774 | whole = bdget_disk(disk, 0); | ||
| 775 | else | ||
| 776 | whole = bdgrab(bdev); | ||
| 777 | |||
| 766 | module_put(disk->fops->owner); | 778 | module_put(disk->fops->owner); |
| 767 | put_disk(disk); | 779 | put_disk(disk); |
| 768 | if (!whole) | 780 | if (!whole) |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 378b5b4443f3..f30ac05dbda7 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -19,7 +19,6 @@ | |||
| 19 | #ifndef __BTRFS_CTREE__ | 19 | #ifndef __BTRFS_CTREE__ |
| 20 | #define __BTRFS_CTREE__ | 20 | #define __BTRFS_CTREE__ |
| 21 | 21 | ||
| 22 | #include <linux/version.h> | ||
| 23 | #include <linux/mm.h> | 22 | #include <linux/mm.h> |
| 24 | #include <linux/highmem.h> | 23 | #include <linux/highmem.h> |
| 25 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
| @@ -967,6 +966,12 @@ struct btrfs_fs_info { | |||
| 967 | struct srcu_struct subvol_srcu; | 966 | struct srcu_struct subvol_srcu; |
| 968 | 967 | ||
| 969 | spinlock_t trans_lock; | 968 | spinlock_t trans_lock; |
| 969 | /* | ||
| 970 | * the reloc mutex goes with the trans lock, it is taken | ||
| 971 | * during commit to protect us from the relocation code | ||
| 972 | */ | ||
| 973 | struct mutex reloc_mutex; | ||
| 974 | |||
| 970 | struct list_head trans_list; | 975 | struct list_head trans_list; |
| 971 | struct list_head hashers; | 976 | struct list_head hashers; |
| 972 | struct list_head dead_roots; | 977 | struct list_head dead_roots; |
| @@ -1172,6 +1177,14 @@ struct btrfs_root { | |||
| 1172 | u32 type; | 1177 | u32 type; |
| 1173 | 1178 | ||
| 1174 | u64 highest_objectid; | 1179 | u64 highest_objectid; |
| 1180 | |||
| 1181 | /* btrfs_record_root_in_trans is a multi-step process, | ||
| 1182 | * and it can race with the balancing code. But the | ||
| 1183 | * race is very small, and only the first time the root | ||
| 1184 | * is added to each transaction. So in_trans_setup | ||
| 1185 | * is used to tell us when more checks are required | ||
| 1186 | */ | ||
| 1187 | unsigned long in_trans_setup; | ||
| 1175 | int ref_cows; | 1188 | int ref_cows; |
| 1176 | int track_dirty; | 1189 | int track_dirty; |
| 1177 | int in_radix; | 1190 | int in_radix; |
| @@ -1181,7 +1194,6 @@ struct btrfs_root { | |||
| 1181 | struct btrfs_key defrag_max; | 1194 | struct btrfs_key defrag_max; |
| 1182 | int defrag_running; | 1195 | int defrag_running; |
| 1183 | char *name; | 1196 | char *name; |
| 1184 | int in_sysfs; | ||
| 1185 | 1197 | ||
| 1186 | /* the dirty list is only used by non-reference counted roots */ | 1198 | /* the dirty list is only used by non-reference counted roots */ |
| 1187 | struct list_head dirty_list; | 1199 | struct list_head dirty_list; |
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 6462c29d2d37..98c68e658a9b 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
| @@ -82,19 +82,16 @@ static inline struct btrfs_delayed_root *btrfs_get_delayed_root( | |||
| 82 | return root->fs_info->delayed_root; | 82 | return root->fs_info->delayed_root; |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node( | 85 | static struct btrfs_delayed_node *btrfs_get_delayed_node(struct inode *inode) |
| 86 | struct inode *inode) | ||
| 87 | { | 86 | { |
| 88 | struct btrfs_delayed_node *node; | ||
| 89 | struct btrfs_inode *btrfs_inode = BTRFS_I(inode); | 87 | struct btrfs_inode *btrfs_inode = BTRFS_I(inode); |
| 90 | struct btrfs_root *root = btrfs_inode->root; | 88 | struct btrfs_root *root = btrfs_inode->root; |
| 91 | u64 ino = btrfs_ino(inode); | 89 | u64 ino = btrfs_ino(inode); |
| 92 | int ret; | 90 | struct btrfs_delayed_node *node; |
| 93 | 91 | ||
| 94 | again: | ||
| 95 | node = ACCESS_ONCE(btrfs_inode->delayed_node); | 92 | node = ACCESS_ONCE(btrfs_inode->delayed_node); |
| 96 | if (node) { | 93 | if (node) { |
| 97 | atomic_inc(&node->refs); /* can be accessed */ | 94 | atomic_inc(&node->refs); |
| 98 | return node; | 95 | return node; |
| 99 | } | 96 | } |
| 100 | 97 | ||
| @@ -102,8 +99,10 @@ again: | |||
| 102 | node = radix_tree_lookup(&root->delayed_nodes_tree, ino); | 99 | node = radix_tree_lookup(&root->delayed_nodes_tree, ino); |
| 103 | if (node) { | 100 | if (node) { |
| 104 | if (btrfs_inode->delayed_node) { | 101 | if (btrfs_inode->delayed_node) { |
| 102 | atomic_inc(&node->refs); /* can be accessed */ | ||
| 103 | BUG_ON(btrfs_inode->delayed_node != node); | ||
| 105 | spin_unlock(&root->inode_lock); | 104 | spin_unlock(&root->inode_lock); |
| 106 | goto again; | 105 | return node; |
| 107 | } | 106 | } |
| 108 | btrfs_inode->delayed_node = node; | 107 | btrfs_inode->delayed_node = node; |
| 109 | atomic_inc(&node->refs); /* can be accessed */ | 108 | atomic_inc(&node->refs); /* can be accessed */ |
| @@ -113,6 +112,23 @@ again: | |||
| 113 | } | 112 | } |
| 114 | spin_unlock(&root->inode_lock); | 113 | spin_unlock(&root->inode_lock); |
| 115 | 114 | ||
| 115 | return NULL; | ||
| 116 | } | ||
| 117 | |||
| 118 | static struct btrfs_delayed_node *btrfs_get_or_create_delayed_node( | ||
| 119 | struct inode *inode) | ||
| 120 | { | ||
| 121 | struct btrfs_delayed_node *node; | ||
| 122 | struct btrfs_inode *btrfs_inode = BTRFS_I(inode); | ||
| 123 | struct btrfs_root *root = btrfs_inode->root; | ||
| 124 | u64 ino = btrfs_ino(inode); | ||
| 125 | int ret; | ||
| 126 | |||
| 127 | again: | ||
| 128 | node = btrfs_get_delayed_node(inode); | ||
| 129 | if (node) | ||
| 130 | return node; | ||
| 131 | |||
| 116 | node = kmem_cache_alloc(delayed_node_cache, GFP_NOFS); | 132 | node = kmem_cache_alloc(delayed_node_cache, GFP_NOFS); |
| 117 | if (!node) | 133 | if (!node) |
| 118 | return ERR_PTR(-ENOMEM); | 134 | return ERR_PTR(-ENOMEM); |
| @@ -297,7 +313,6 @@ struct btrfs_delayed_item *btrfs_alloc_delayed_item(u32 data_len) | |||
| 297 | item->data_len = data_len; | 313 | item->data_len = data_len; |
| 298 | item->ins_or_del = 0; | 314 | item->ins_or_del = 0; |
| 299 | item->bytes_reserved = 0; | 315 | item->bytes_reserved = 0; |
| 300 | item->block_rsv = NULL; | ||
| 301 | item->delayed_node = NULL; | 316 | item->delayed_node = NULL; |
| 302 | atomic_set(&item->refs, 1); | 317 | atomic_set(&item->refs, 1); |
| 303 | } | 318 | } |
| @@ -549,19 +564,6 @@ struct btrfs_delayed_item *__btrfs_next_delayed_item( | |||
| 549 | return next; | 564 | return next; |
| 550 | } | 565 | } |
| 551 | 566 | ||
| 552 | static inline struct btrfs_delayed_node *btrfs_get_delayed_node( | ||
| 553 | struct inode *inode) | ||
| 554 | { | ||
| 555 | struct btrfs_inode *btrfs_inode = BTRFS_I(inode); | ||
| 556 | struct btrfs_delayed_node *delayed_node; | ||
| 557 | |||
| 558 | delayed_node = btrfs_inode->delayed_node; | ||
| 559 | if (delayed_node) | ||
| 560 | atomic_inc(&delayed_node->refs); | ||
| 561 | |||
| 562 | return delayed_node; | ||
| 563 | } | ||
| 564 | |||
| 565 | static inline struct btrfs_root *btrfs_get_fs_root(struct btrfs_root *root, | 567 | static inline struct btrfs_root *btrfs_get_fs_root(struct btrfs_root *root, |
| 566 | u64 root_id) | 568 | u64 root_id) |
| 567 | { | 569 | { |
| @@ -593,10 +595,8 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, | |||
| 593 | 595 | ||
| 594 | num_bytes = btrfs_calc_trans_metadata_size(root, 1); | 596 | num_bytes = btrfs_calc_trans_metadata_size(root, 1); |
| 595 | ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); | 597 | ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); |
| 596 | if (!ret) { | 598 | if (!ret) |
| 597 | item->bytes_reserved = num_bytes; | 599 | item->bytes_reserved = num_bytes; |
| 598 | item->block_rsv = dst_rsv; | ||
| 599 | } | ||
| 600 | 600 | ||
| 601 | return ret; | 601 | return ret; |
| 602 | } | 602 | } |
| @@ -604,10 +604,13 @@ static int btrfs_delayed_item_reserve_metadata(struct btrfs_trans_handle *trans, | |||
| 604 | static void btrfs_delayed_item_release_metadata(struct btrfs_root *root, | 604 | static void btrfs_delayed_item_release_metadata(struct btrfs_root *root, |
| 605 | struct btrfs_delayed_item *item) | 605 | struct btrfs_delayed_item *item) |
| 606 | { | 606 | { |
| 607 | struct btrfs_block_rsv *rsv; | ||
| 608 | |||
| 607 | if (!item->bytes_reserved) | 609 | if (!item->bytes_reserved) |
| 608 | return; | 610 | return; |
| 609 | 611 | ||
| 610 | btrfs_block_rsv_release(root, item->block_rsv, | 612 | rsv = &root->fs_info->global_block_rsv; |
| 613 | btrfs_block_rsv_release(root, rsv, | ||
| 611 | item->bytes_reserved); | 614 | item->bytes_reserved); |
| 612 | } | 615 | } |
| 613 | 616 | ||
| @@ -1014,6 +1017,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, | |||
| 1014 | struct btrfs_delayed_root *delayed_root; | 1017 | struct btrfs_delayed_root *delayed_root; |
| 1015 | struct btrfs_delayed_node *curr_node, *prev_node; | 1018 | struct btrfs_delayed_node *curr_node, *prev_node; |
| 1016 | struct btrfs_path *path; | 1019 | struct btrfs_path *path; |
| 1020 | struct btrfs_block_rsv *block_rsv; | ||
| 1017 | int ret = 0; | 1021 | int ret = 0; |
| 1018 | 1022 | ||
| 1019 | path = btrfs_alloc_path(); | 1023 | path = btrfs_alloc_path(); |
| @@ -1021,6 +1025,9 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, | |||
| 1021 | return -ENOMEM; | 1025 | return -ENOMEM; |
| 1022 | path->leave_spinning = 1; | 1026 | path->leave_spinning = 1; |
| 1023 | 1027 | ||
| 1028 | block_rsv = trans->block_rsv; | ||
| 1029 | trans->block_rsv = &root->fs_info->global_block_rsv; | ||
| 1030 | |||
| 1024 | delayed_root = btrfs_get_delayed_root(root); | 1031 | delayed_root = btrfs_get_delayed_root(root); |
| 1025 | 1032 | ||
| 1026 | curr_node = btrfs_first_delayed_node(delayed_root); | 1033 | curr_node = btrfs_first_delayed_node(delayed_root); |
| @@ -1045,6 +1052,7 @@ int btrfs_run_delayed_items(struct btrfs_trans_handle *trans, | |||
| 1045 | } | 1052 | } |
| 1046 | 1053 | ||
| 1047 | btrfs_free_path(path); | 1054 | btrfs_free_path(path); |
| 1055 | trans->block_rsv = block_rsv; | ||
| 1048 | return ret; | 1056 | return ret; |
| 1049 | } | 1057 | } |
| 1050 | 1058 | ||
| @@ -1052,6 +1060,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, | |||
| 1052 | struct btrfs_delayed_node *node) | 1060 | struct btrfs_delayed_node *node) |
| 1053 | { | 1061 | { |
| 1054 | struct btrfs_path *path; | 1062 | struct btrfs_path *path; |
| 1063 | struct btrfs_block_rsv *block_rsv; | ||
| 1055 | int ret; | 1064 | int ret; |
| 1056 | 1065 | ||
| 1057 | path = btrfs_alloc_path(); | 1066 | path = btrfs_alloc_path(); |
| @@ -1059,6 +1068,9 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, | |||
| 1059 | return -ENOMEM; | 1068 | return -ENOMEM; |
| 1060 | path->leave_spinning = 1; | 1069 | path->leave_spinning = 1; |
| 1061 | 1070 | ||
| 1071 | block_rsv = trans->block_rsv; | ||
| 1072 | trans->block_rsv = &node->root->fs_info->global_block_rsv; | ||
| 1073 | |||
| 1062 | ret = btrfs_insert_delayed_items(trans, path, node->root, node); | 1074 | ret = btrfs_insert_delayed_items(trans, path, node->root, node); |
| 1063 | if (!ret) | 1075 | if (!ret) |
| 1064 | ret = btrfs_delete_delayed_items(trans, path, node->root, node); | 1076 | ret = btrfs_delete_delayed_items(trans, path, node->root, node); |
| @@ -1066,6 +1078,7 @@ static int __btrfs_commit_inode_delayed_items(struct btrfs_trans_handle *trans, | |||
| 1066 | ret = btrfs_update_delayed_inode(trans, node->root, path, node); | 1078 | ret = btrfs_update_delayed_inode(trans, node->root, path, node); |
| 1067 | btrfs_free_path(path); | 1079 | btrfs_free_path(path); |
| 1068 | 1080 | ||
| 1081 | trans->block_rsv = block_rsv; | ||
| 1069 | return ret; | 1082 | return ret; |
| 1070 | } | 1083 | } |
| 1071 | 1084 | ||
| @@ -1116,6 +1129,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) | |||
| 1116 | struct btrfs_path *path; | 1129 | struct btrfs_path *path; |
| 1117 | struct btrfs_delayed_node *delayed_node = NULL; | 1130 | struct btrfs_delayed_node *delayed_node = NULL; |
| 1118 | struct btrfs_root *root; | 1131 | struct btrfs_root *root; |
| 1132 | struct btrfs_block_rsv *block_rsv; | ||
| 1119 | unsigned long nr = 0; | 1133 | unsigned long nr = 0; |
| 1120 | int need_requeue = 0; | 1134 | int need_requeue = 0; |
| 1121 | int ret; | 1135 | int ret; |
| @@ -1134,6 +1148,9 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) | |||
| 1134 | if (IS_ERR(trans)) | 1148 | if (IS_ERR(trans)) |
| 1135 | goto free_path; | 1149 | goto free_path; |
| 1136 | 1150 | ||
| 1151 | block_rsv = trans->block_rsv; | ||
| 1152 | trans->block_rsv = &root->fs_info->global_block_rsv; | ||
| 1153 | |||
| 1137 | ret = btrfs_insert_delayed_items(trans, path, root, delayed_node); | 1154 | ret = btrfs_insert_delayed_items(trans, path, root, delayed_node); |
| 1138 | if (!ret) | 1155 | if (!ret) |
| 1139 | ret = btrfs_delete_delayed_items(trans, path, root, | 1156 | ret = btrfs_delete_delayed_items(trans, path, root, |
| @@ -1176,6 +1193,7 @@ static void btrfs_async_run_delayed_node_done(struct btrfs_work *work) | |||
| 1176 | 1193 | ||
| 1177 | nr = trans->blocks_used; | 1194 | nr = trans->blocks_used; |
| 1178 | 1195 | ||
| 1196 | trans->block_rsv = block_rsv; | ||
| 1179 | btrfs_end_transaction_dmeta(trans, root); | 1197 | btrfs_end_transaction_dmeta(trans, root); |
| 1180 | __btrfs_btree_balance_dirty(root, nr); | 1198 | __btrfs_btree_balance_dirty(root, nr); |
| 1181 | free_path: | 1199 | free_path: |
| @@ -1222,6 +1240,13 @@ again: | |||
| 1222 | return 0; | 1240 | return 0; |
| 1223 | } | 1241 | } |
| 1224 | 1242 | ||
| 1243 | void btrfs_assert_delayed_root_empty(struct btrfs_root *root) | ||
| 1244 | { | ||
| 1245 | struct btrfs_delayed_root *delayed_root; | ||
| 1246 | delayed_root = btrfs_get_delayed_root(root); | ||
| 1247 | WARN_ON(btrfs_first_delayed_node(delayed_root)); | ||
| 1248 | } | ||
| 1249 | |||
| 1225 | void btrfs_balance_delayed_items(struct btrfs_root *root) | 1250 | void btrfs_balance_delayed_items(struct btrfs_root *root) |
| 1226 | { | 1251 | { |
| 1227 | struct btrfs_delayed_root *delayed_root; | 1252 | struct btrfs_delayed_root *delayed_root; |
| @@ -1382,8 +1407,7 @@ end: | |||
| 1382 | 1407 | ||
| 1383 | int btrfs_inode_delayed_dir_index_count(struct inode *inode) | 1408 | int btrfs_inode_delayed_dir_index_count(struct inode *inode) |
| 1384 | { | 1409 | { |
| 1385 | struct btrfs_delayed_node *delayed_node = BTRFS_I(inode)->delayed_node; | 1410 | struct btrfs_delayed_node *delayed_node = btrfs_get_delayed_node(inode); |
| 1386 | int ret = 0; | ||
| 1387 | 1411 | ||
| 1388 | if (!delayed_node) | 1412 | if (!delayed_node) |
| 1389 | return -ENOENT; | 1413 | return -ENOENT; |
| @@ -1393,11 +1417,14 @@ int btrfs_inode_delayed_dir_index_count(struct inode *inode) | |||
| 1393 | * a new directory index is added into the delayed node and index_cnt | 1417 | * a new directory index is added into the delayed node and index_cnt |
| 1394 | * is updated now. So we needn't lock the delayed node. | 1418 | * is updated now. So we needn't lock the delayed node. |
| 1395 | */ | 1419 | */ |
| 1396 | if (!delayed_node->index_cnt) | 1420 | if (!delayed_node->index_cnt) { |
| 1421 | btrfs_release_delayed_node(delayed_node); | ||
| 1397 | return -EINVAL; | 1422 | return -EINVAL; |
| 1423 | } | ||
| 1398 | 1424 | ||
| 1399 | BTRFS_I(inode)->index_cnt = delayed_node->index_cnt; | 1425 | BTRFS_I(inode)->index_cnt = delayed_node->index_cnt; |
| 1400 | return ret; | 1426 | btrfs_release_delayed_node(delayed_node); |
| 1427 | return 0; | ||
| 1401 | } | 1428 | } |
| 1402 | 1429 | ||
| 1403 | void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, | 1430 | void btrfs_get_delayed_items(struct inode *inode, struct list_head *ins_list, |
| @@ -1591,6 +1618,57 @@ static void fill_stack_inode_item(struct btrfs_trans_handle *trans, | |||
| 1591 | inode->i_ctime.tv_nsec); | 1618 | inode->i_ctime.tv_nsec); |
| 1592 | } | 1619 | } |
| 1593 | 1620 | ||
| 1621 | int btrfs_fill_inode(struct inode *inode, u32 *rdev) | ||
| 1622 | { | ||
| 1623 | struct btrfs_delayed_node *delayed_node; | ||
| 1624 | struct btrfs_inode_item *inode_item; | ||
| 1625 | struct btrfs_timespec *tspec; | ||
| 1626 | |||
| 1627 | delayed_node = btrfs_get_delayed_node(inode); | ||
| 1628 | if (!delayed_node) | ||
| 1629 | return -ENOENT; | ||
| 1630 | |||
| 1631 | mutex_lock(&delayed_node->mutex); | ||
| 1632 | if (!delayed_node->inode_dirty) { | ||
| 1633 | mutex_unlock(&delayed_node->mutex); | ||
| 1634 | btrfs_release_delayed_node(delayed_node); | ||
| 1635 | return -ENOENT; | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | inode_item = &delayed_node->inode_item; | ||
| 1639 | |||
| 1640 | inode->i_uid = btrfs_stack_inode_uid(inode_item); | ||
| 1641 | inode->i_gid = btrfs_stack_inode_gid(inode_item); | ||
| 1642 | btrfs_i_size_write(inode, btrfs_stack_inode_size(inode_item)); | ||
| 1643 | inode->i_mode = btrfs_stack_inode_mode(inode_item); | ||
| 1644 | inode->i_nlink = btrfs_stack_inode_nlink(inode_item); | ||
| 1645 | inode_set_bytes(inode, btrfs_stack_inode_nbytes(inode_item)); | ||
| 1646 | BTRFS_I(inode)->generation = btrfs_stack_inode_generation(inode_item); | ||
| 1647 | BTRFS_I(inode)->sequence = btrfs_stack_inode_sequence(inode_item); | ||
| 1648 | inode->i_rdev = 0; | ||
| 1649 | *rdev = btrfs_stack_inode_rdev(inode_item); | ||
| 1650 | BTRFS_I(inode)->flags = btrfs_stack_inode_flags(inode_item); | ||
| 1651 | |||
| 1652 | tspec = btrfs_inode_atime(inode_item); | ||
| 1653 | inode->i_atime.tv_sec = btrfs_stack_timespec_sec(tspec); | ||
| 1654 | inode->i_atime.tv_nsec = btrfs_stack_timespec_nsec(tspec); | ||
| 1655 | |||
| 1656 | tspec = btrfs_inode_mtime(inode_item); | ||
| 1657 | inode->i_mtime.tv_sec = btrfs_stack_timespec_sec(tspec); | ||
| 1658 | inode->i_mtime.tv_nsec = btrfs_stack_timespec_nsec(tspec); | ||
| 1659 | |||
| 1660 | tspec = btrfs_inode_ctime(inode_item); | ||
| 1661 | inode->i_ctime.tv_sec = btrfs_stack_timespec_sec(tspec); | ||
| 1662 | inode->i_ctime.tv_nsec = btrfs_stack_timespec_nsec(tspec); | ||
| 1663 | |||
| 1664 | inode->i_generation = BTRFS_I(inode)->generation; | ||
| 1665 | BTRFS_I(inode)->index_cnt = (u64)-1; | ||
| 1666 | |||
| 1667 | mutex_unlock(&delayed_node->mutex); | ||
| 1668 | btrfs_release_delayed_node(delayed_node); | ||
| 1669 | return 0; | ||
| 1670 | } | ||
| 1671 | |||
| 1594 | int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, | 1672 | int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, |
| 1595 | struct btrfs_root *root, struct inode *inode) | 1673 | struct btrfs_root *root, struct inode *inode) |
| 1596 | { | 1674 | { |
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index eb7d240aa648..8d27af4bd8b9 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h | |||
| @@ -75,7 +75,6 @@ struct btrfs_delayed_item { | |||
| 75 | struct list_head tree_list; /* used for batch insert/delete items */ | 75 | struct list_head tree_list; /* used for batch insert/delete items */ |
| 76 | struct list_head readdir_list; /* used for readdir items */ | 76 | struct list_head readdir_list; /* used for readdir items */ |
| 77 | u64 bytes_reserved; | 77 | u64 bytes_reserved; |
| 78 | struct btrfs_block_rsv *block_rsv; | ||
| 79 | struct btrfs_delayed_node *delayed_node; | 78 | struct btrfs_delayed_node *delayed_node; |
| 80 | atomic_t refs; | 79 | atomic_t refs; |
| 81 | int ins_or_del; | 80 | int ins_or_del; |
| @@ -120,6 +119,7 @@ void btrfs_kill_delayed_inode_items(struct inode *inode); | |||
| 120 | 119 | ||
| 121 | int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, | 120 | int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, |
| 122 | struct btrfs_root *root, struct inode *inode); | 121 | struct btrfs_root *root, struct inode *inode); |
| 122 | int btrfs_fill_inode(struct inode *inode, u32 *rdev); | ||
| 123 | 123 | ||
| 124 | /* Used for drop dead root */ | 124 | /* Used for drop dead root */ |
| 125 | void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); | 125 | void btrfs_kill_all_delayed_nodes(struct btrfs_root *root); |
| @@ -138,4 +138,8 @@ int btrfs_readdir_delayed_dir_index(struct file *filp, void *dirent, | |||
| 138 | /* for init */ | 138 | /* for init */ |
| 139 | int __init btrfs_delayed_inode_init(void); | 139 | int __init btrfs_delayed_inode_init(void); |
| 140 | void btrfs_delayed_inode_exit(void); | 140 | void btrfs_delayed_inode_exit(void); |
| 141 | |||
| 142 | /* for debugging */ | ||
| 143 | void btrfs_assert_delayed_root_empty(struct btrfs_root *root); | ||
| 144 | |||
| 141 | #endif | 145 | #endif |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 9f68c6898653..1ac8db5dc0a3 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -1044,7 +1044,6 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize, | |||
| 1044 | root->last_trans = 0; | 1044 | root->last_trans = 0; |
| 1045 | root->highest_objectid = 0; | 1045 | root->highest_objectid = 0; |
| 1046 | root->name = NULL; | 1046 | root->name = NULL; |
| 1047 | root->in_sysfs = 0; | ||
| 1048 | root->inode_tree = RB_ROOT; | 1047 | root->inode_tree = RB_ROOT; |
| 1049 | INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC); | 1048 | INIT_RADIX_TREE(&root->delayed_nodes_tree, GFP_ATOMIC); |
| 1050 | root->block_rsv = NULL; | 1049 | root->block_rsv = NULL; |
| @@ -1300,19 +1299,21 @@ again: | |||
| 1300 | return root; | 1299 | return root; |
| 1301 | 1300 | ||
| 1302 | root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS); | 1301 | root->free_ino_ctl = kzalloc(sizeof(*root->free_ino_ctl), GFP_NOFS); |
| 1303 | if (!root->free_ino_ctl) | ||
| 1304 | goto fail; | ||
| 1305 | root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned), | 1302 | root->free_ino_pinned = kzalloc(sizeof(*root->free_ino_pinned), |
| 1306 | GFP_NOFS); | 1303 | GFP_NOFS); |
| 1307 | if (!root->free_ino_pinned) | 1304 | if (!root->free_ino_pinned || !root->free_ino_ctl) { |
| 1305 | ret = -ENOMEM; | ||
| 1308 | goto fail; | 1306 | goto fail; |
| 1307 | } | ||
| 1309 | 1308 | ||
| 1310 | btrfs_init_free_ino_ctl(root); | 1309 | btrfs_init_free_ino_ctl(root); |
| 1311 | mutex_init(&root->fs_commit_mutex); | 1310 | mutex_init(&root->fs_commit_mutex); |
| 1312 | spin_lock_init(&root->cache_lock); | 1311 | spin_lock_init(&root->cache_lock); |
| 1313 | init_waitqueue_head(&root->cache_wait); | 1312 | init_waitqueue_head(&root->cache_wait); |
| 1314 | 1313 | ||
| 1315 | set_anon_super(&root->anon_super, NULL); | 1314 | ret = set_anon_super(&root->anon_super, NULL); |
| 1315 | if (ret) | ||
| 1316 | goto fail; | ||
| 1316 | 1317 | ||
| 1317 | if (btrfs_root_refs(&root->root_item) == 0) { | 1318 | if (btrfs_root_refs(&root->root_item) == 0) { |
| 1318 | ret = -ENOENT; | 1319 | ret = -ENOENT; |
| @@ -1618,6 +1619,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1618 | spin_lock_init(&fs_info->fs_roots_radix_lock); | 1619 | spin_lock_init(&fs_info->fs_roots_radix_lock); |
| 1619 | spin_lock_init(&fs_info->delayed_iput_lock); | 1620 | spin_lock_init(&fs_info->delayed_iput_lock); |
| 1620 | spin_lock_init(&fs_info->defrag_inodes_lock); | 1621 | spin_lock_init(&fs_info->defrag_inodes_lock); |
| 1622 | mutex_init(&fs_info->reloc_mutex); | ||
| 1621 | 1623 | ||
| 1622 | init_completion(&fs_info->kobj_unregister); | 1624 | init_completion(&fs_info->kobj_unregister); |
| 1623 | fs_info->tree_root = tree_root; | 1625 | fs_info->tree_root = tree_root; |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b42efc2ded51..71cd456fdb60 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3314,10 +3314,6 @@ static int shrink_delalloc(struct btrfs_trans_handle *trans, | |||
| 3314 | if (reserved == 0) | 3314 | if (reserved == 0) |
| 3315 | return 0; | 3315 | return 0; |
| 3316 | 3316 | ||
| 3317 | /* nothing to shrink - nothing to reclaim */ | ||
| 3318 | if (root->fs_info->delalloc_bytes == 0) | ||
| 3319 | return 0; | ||
| 3320 | |||
| 3321 | max_reclaim = min(reserved, to_reclaim); | 3317 | max_reclaim = min(reserved, to_reclaim); |
| 3322 | 3318 | ||
| 3323 | while (loops < 1024) { | 3319 | while (loops < 1024) { |
| @@ -4846,7 +4842,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
| 4846 | u64 num_bytes, u64 empty_size, | 4842 | u64 num_bytes, u64 empty_size, |
| 4847 | u64 search_start, u64 search_end, | 4843 | u64 search_start, u64 search_end, |
| 4848 | u64 hint_byte, struct btrfs_key *ins, | 4844 | u64 hint_byte, struct btrfs_key *ins, |
| 4849 | int data) | 4845 | u64 data) |
| 4850 | { | 4846 | { |
| 4851 | int ret = 0; | 4847 | int ret = 0; |
| 4852 | struct btrfs_root *root = orig_root->fs_info->extent_root; | 4848 | struct btrfs_root *root = orig_root->fs_info->extent_root; |
| @@ -4873,7 +4869,7 @@ static noinline int find_free_extent(struct btrfs_trans_handle *trans, | |||
| 4873 | 4869 | ||
| 4874 | space_info = __find_space_info(root->fs_info, data); | 4870 | space_info = __find_space_info(root->fs_info, data); |
| 4875 | if (!space_info) { | 4871 | if (!space_info) { |
| 4876 | printk(KERN_ERR "No space info for %d\n", data); | 4872 | printk(KERN_ERR "No space info for %llu\n", data); |
| 4877 | return -ENOSPC; | 4873 | return -ENOSPC; |
| 4878 | } | 4874 | } |
| 4879 | 4875 | ||
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 9f985a429877..bf0d61567f3d 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
| @@ -1893,9 +1893,12 @@ void __btrfs_remove_free_space_cache_locked(struct btrfs_free_space_ctl *ctl) | |||
| 1893 | 1893 | ||
| 1894 | while ((node = rb_last(&ctl->free_space_offset)) != NULL) { | 1894 | while ((node = rb_last(&ctl->free_space_offset)) != NULL) { |
| 1895 | info = rb_entry(node, struct btrfs_free_space, offset_index); | 1895 | info = rb_entry(node, struct btrfs_free_space, offset_index); |
| 1896 | unlink_free_space(ctl, info); | 1896 | if (!info->bitmap) { |
| 1897 | kfree(info->bitmap); | 1897 | unlink_free_space(ctl, info); |
| 1898 | kmem_cache_free(btrfs_free_space_cachep, info); | 1898 | kmem_cache_free(btrfs_free_space_cachep, info); |
| 1899 | } else { | ||
| 1900 | free_bitmap(ctl, info); | ||
| 1901 | } | ||
| 1899 | if (need_resched()) { | 1902 | if (need_resched()) { |
| 1900 | spin_unlock(&ctl->tree_lock); | 1903 | spin_unlock(&ctl->tree_lock); |
| 1901 | cond_resched(); | 1904 | cond_resched(); |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 751ddf8fc58a..d340f63d8f07 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -2509,6 +2509,11 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
| 2509 | int maybe_acls; | 2509 | int maybe_acls; |
| 2510 | u32 rdev; | 2510 | u32 rdev; |
| 2511 | int ret; | 2511 | int ret; |
| 2512 | bool filled = false; | ||
| 2513 | |||
| 2514 | ret = btrfs_fill_inode(inode, &rdev); | ||
| 2515 | if (!ret) | ||
| 2516 | filled = true; | ||
| 2512 | 2517 | ||
| 2513 | path = btrfs_alloc_path(); | 2518 | path = btrfs_alloc_path(); |
| 2514 | BUG_ON(!path); | 2519 | BUG_ON(!path); |
| @@ -2520,6 +2525,10 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
| 2520 | goto make_bad; | 2525 | goto make_bad; |
| 2521 | 2526 | ||
| 2522 | leaf = path->nodes[0]; | 2527 | leaf = path->nodes[0]; |
| 2528 | |||
| 2529 | if (filled) | ||
| 2530 | goto cache_acl; | ||
| 2531 | |||
| 2523 | inode_item = btrfs_item_ptr(leaf, path->slots[0], | 2532 | inode_item = btrfs_item_ptr(leaf, path->slots[0], |
| 2524 | struct btrfs_inode_item); | 2533 | struct btrfs_inode_item); |
| 2525 | if (!leaf->map_token) | 2534 | if (!leaf->map_token) |
| @@ -2556,7 +2565,7 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
| 2556 | 2565 | ||
| 2557 | BTRFS_I(inode)->index_cnt = (u64)-1; | 2566 | BTRFS_I(inode)->index_cnt = (u64)-1; |
| 2558 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); | 2567 | BTRFS_I(inode)->flags = btrfs_inode_flags(leaf, inode_item); |
| 2559 | 2568 | cache_acl: | |
| 2560 | /* | 2569 | /* |
| 2561 | * try to precache a NULL acl entry for files that don't have | 2570 | * try to precache a NULL acl entry for files that don't have |
| 2562 | * any xattrs or acls | 2571 | * any xattrs or acls |
| @@ -2572,7 +2581,6 @@ static void btrfs_read_locked_inode(struct inode *inode) | |||
| 2572 | } | 2581 | } |
| 2573 | 2582 | ||
| 2574 | btrfs_free_path(path); | 2583 | btrfs_free_path(path); |
| 2575 | inode_item = NULL; | ||
| 2576 | 2584 | ||
| 2577 | switch (inode->i_mode & S_IFMT) { | 2585 | switch (inode->i_mode & S_IFMT) { |
| 2578 | case S_IFREG: | 2586 | case S_IFREG: |
| @@ -3076,6 +3084,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans, | |||
| 3076 | ret = btrfs_update_inode(trans, root, dir); | 3084 | ret = btrfs_update_inode(trans, root, dir); |
| 3077 | BUG_ON(ret); | 3085 | BUG_ON(ret); |
| 3078 | 3086 | ||
| 3087 | btrfs_free_path(path); | ||
| 3079 | return 0; | 3088 | return 0; |
| 3080 | } | 3089 | } |
| 3081 | 3090 | ||
| @@ -4519,6 +4528,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
| 4519 | inode_tree_add(inode); | 4528 | inode_tree_add(inode); |
| 4520 | 4529 | ||
| 4521 | trace_btrfs_inode_new(inode); | 4530 | trace_btrfs_inode_new(inode); |
| 4531 | btrfs_set_inode_last_trans(trans, inode); | ||
| 4522 | 4532 | ||
| 4523 | return inode; | 4533 | return inode; |
| 4524 | fail: | 4534 | fail: |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b793d112d1f6..a3c4751e07db 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -482,8 +482,10 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 482 | ret = btrfs_snap_reserve_metadata(trans, pending_snapshot); | 482 | ret = btrfs_snap_reserve_metadata(trans, pending_snapshot); |
| 483 | BUG_ON(ret); | 483 | BUG_ON(ret); |
| 484 | 484 | ||
| 485 | spin_lock(&root->fs_info->trans_lock); | ||
| 485 | list_add(&pending_snapshot->list, | 486 | list_add(&pending_snapshot->list, |
| 486 | &trans->transaction->pending_snapshots); | 487 | &trans->transaction->pending_snapshots); |
| 488 | spin_unlock(&root->fs_info->trans_lock); | ||
| 487 | if (async_transid) { | 489 | if (async_transid) { |
| 488 | *async_transid = trans->transid; | 490 | *async_transid = trans->transid; |
| 489 | ret = btrfs_commit_transaction_async(trans, | 491 | ret = btrfs_commit_transaction_async(trans, |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index b1ef27cc673b..5e0a3dc79a45 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
| @@ -1368,7 +1368,7 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, | |||
| 1368 | int ret; | 1368 | int ret; |
| 1369 | 1369 | ||
| 1370 | if (!root->reloc_root) | 1370 | if (!root->reloc_root) |
| 1371 | return 0; | 1371 | goto out; |
| 1372 | 1372 | ||
| 1373 | reloc_root = root->reloc_root; | 1373 | reloc_root = root->reloc_root; |
| 1374 | root_item = &reloc_root->root_item; | 1374 | root_item = &reloc_root->root_item; |
| @@ -1390,6 +1390,8 @@ int btrfs_update_reloc_root(struct btrfs_trans_handle *trans, | |||
| 1390 | ret = btrfs_update_root(trans, root->fs_info->tree_root, | 1390 | ret = btrfs_update_root(trans, root->fs_info->tree_root, |
| 1391 | &reloc_root->root_key, root_item); | 1391 | &reloc_root->root_key, root_item); |
| 1392 | BUG_ON(ret); | 1392 | BUG_ON(ret); |
| 1393 | |||
| 1394 | out: | ||
| 1393 | return 0; | 1395 | return 0; |
| 1394 | } | 1396 | } |
| 1395 | 1397 | ||
| @@ -2142,10 +2144,11 @@ int prepare_to_merge(struct reloc_control *rc, int err) | |||
| 2142 | u64 num_bytes = 0; | 2144 | u64 num_bytes = 0; |
| 2143 | int ret; | 2145 | int ret; |
| 2144 | 2146 | ||
| 2145 | spin_lock(&root->fs_info->trans_lock); | 2147 | mutex_lock(&root->fs_info->reloc_mutex); |
| 2146 | rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; | 2148 | rc->merging_rsv_size += root->nodesize * (BTRFS_MAX_LEVEL - 1) * 2; |
| 2147 | rc->merging_rsv_size += rc->nodes_relocated * 2; | 2149 | rc->merging_rsv_size += rc->nodes_relocated * 2; |
| 2148 | spin_unlock(&root->fs_info->trans_lock); | 2150 | mutex_unlock(&root->fs_info->reloc_mutex); |
| 2151 | |||
| 2149 | again: | 2152 | again: |
| 2150 | if (!err) { | 2153 | if (!err) { |
| 2151 | num_bytes = rc->merging_rsv_size; | 2154 | num_bytes = rc->merging_rsv_size; |
| @@ -2214,9 +2217,16 @@ int merge_reloc_roots(struct reloc_control *rc) | |||
| 2214 | int ret; | 2217 | int ret; |
| 2215 | again: | 2218 | again: |
| 2216 | root = rc->extent_root; | 2219 | root = rc->extent_root; |
| 2217 | spin_lock(&root->fs_info->trans_lock); | 2220 | |
| 2221 | /* | ||
| 2222 | * this serializes us with btrfs_record_root_in_transaction, | ||
| 2223 | * we have to make sure nobody is in the middle of | ||
| 2224 | * adding their roots to the list while we are | ||
| 2225 | * doing this splice | ||
| 2226 | */ | ||
| 2227 | mutex_lock(&root->fs_info->reloc_mutex); | ||
| 2218 | list_splice_init(&rc->reloc_roots, &reloc_roots); | 2228 | list_splice_init(&rc->reloc_roots, &reloc_roots); |
| 2219 | spin_unlock(&root->fs_info->trans_lock); | 2229 | mutex_unlock(&root->fs_info->reloc_mutex); |
| 2220 | 2230 | ||
| 2221 | while (!list_empty(&reloc_roots)) { | 2231 | while (!list_empty(&reloc_roots)) { |
| 2222 | found = 1; | 2232 | found = 1; |
| @@ -3590,17 +3600,19 @@ next: | |||
| 3590 | static void set_reloc_control(struct reloc_control *rc) | 3600 | static void set_reloc_control(struct reloc_control *rc) |
| 3591 | { | 3601 | { |
| 3592 | struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; | 3602 | struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; |
| 3593 | spin_lock(&fs_info->trans_lock); | 3603 | |
| 3604 | mutex_lock(&fs_info->reloc_mutex); | ||
| 3594 | fs_info->reloc_ctl = rc; | 3605 | fs_info->reloc_ctl = rc; |
| 3595 | spin_unlock(&fs_info->trans_lock); | 3606 | mutex_unlock(&fs_info->reloc_mutex); |
| 3596 | } | 3607 | } |
| 3597 | 3608 | ||
| 3598 | static void unset_reloc_control(struct reloc_control *rc) | 3609 | static void unset_reloc_control(struct reloc_control *rc) |
| 3599 | { | 3610 | { |
| 3600 | struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; | 3611 | struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; |
| 3601 | spin_lock(&fs_info->trans_lock); | 3612 | |
| 3613 | mutex_lock(&fs_info->reloc_mutex); | ||
| 3602 | fs_info->reloc_ctl = NULL; | 3614 | fs_info->reloc_ctl = NULL; |
| 3603 | spin_unlock(&fs_info->trans_lock); | 3615 | mutex_unlock(&fs_info->reloc_mutex); |
| 3604 | } | 3616 | } |
| 3605 | 3617 | ||
| 3606 | static int check_extent_flags(u64 flags) | 3618 | static int check_extent_flags(u64 flags) |
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index c3c223ae6691..daac9ae6d731 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c | |||
| @@ -28,152 +28,6 @@ | |||
| 28 | #include "disk-io.h" | 28 | #include "disk-io.h" |
| 29 | #include "transaction.h" | 29 | #include "transaction.h" |
| 30 | 30 | ||
| 31 | static ssize_t root_blocks_used_show(struct btrfs_root *root, char *buf) | ||
| 32 | { | ||
| 33 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 34 | (unsigned long long)btrfs_root_used(&root->root_item)); | ||
| 35 | } | ||
| 36 | |||
| 37 | static ssize_t root_block_limit_show(struct btrfs_root *root, char *buf) | ||
| 38 | { | ||
| 39 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 40 | (unsigned long long)btrfs_root_limit(&root->root_item)); | ||
| 41 | } | ||
| 42 | |||
| 43 | static ssize_t super_blocks_used_show(struct btrfs_fs_info *fs, char *buf) | ||
| 44 | { | ||
| 45 | |||
| 46 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 47 | (unsigned long long)btrfs_super_bytes_used(&fs->super_copy)); | ||
| 48 | } | ||
| 49 | |||
| 50 | static ssize_t super_total_blocks_show(struct btrfs_fs_info *fs, char *buf) | ||
| 51 | { | ||
| 52 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 53 | (unsigned long long)btrfs_super_total_bytes(&fs->super_copy)); | ||
| 54 | } | ||
| 55 | |||
| 56 | static ssize_t super_blocksize_show(struct btrfs_fs_info *fs, char *buf) | ||
| 57 | { | ||
| 58 | return snprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 59 | (unsigned long long)btrfs_super_sectorsize(&fs->super_copy)); | ||
| 60 | } | ||
| 61 | |||
| 62 | /* this is for root attrs (subvols/snapshots) */ | ||
| 63 | struct btrfs_root_attr { | ||
| 64 | struct attribute attr; | ||
| 65 | ssize_t (*show)(struct btrfs_root *, char *); | ||
| 66 | ssize_t (*store)(struct btrfs_root *, const char *, size_t); | ||
| 67 | }; | ||
| 68 | |||
| 69 | #define ROOT_ATTR(name, mode, show, store) \ | ||
| 70 | static struct btrfs_root_attr btrfs_root_attr_##name = __ATTR(name, mode, \ | ||
| 71 | show, store) | ||
| 72 | |||
| 73 | ROOT_ATTR(blocks_used, 0444, root_blocks_used_show, NULL); | ||
| 74 | ROOT_ATTR(block_limit, 0644, root_block_limit_show, NULL); | ||
| 75 | |||
| 76 | static struct attribute *btrfs_root_attrs[] = { | ||
| 77 | &btrfs_root_attr_blocks_used.attr, | ||
| 78 | &btrfs_root_attr_block_limit.attr, | ||
| 79 | NULL, | ||
| 80 | }; | ||
| 81 | |||
| 82 | /* this is for super attrs (actual full fs) */ | ||
| 83 | struct btrfs_super_attr { | ||
| 84 | struct attribute attr; | ||
| 85 | ssize_t (*show)(struct btrfs_fs_info *, char *); | ||
| 86 | ssize_t (*store)(struct btrfs_fs_info *, const char *, size_t); | ||
| 87 | }; | ||
| 88 | |||
| 89 | #define SUPER_ATTR(name, mode, show, store) \ | ||
| 90 | static struct btrfs_super_attr btrfs_super_attr_##name = __ATTR(name, mode, \ | ||
| 91 | show, store) | ||
| 92 | |||
| 93 | SUPER_ATTR(blocks_used, 0444, super_blocks_used_show, NULL); | ||
| 94 | SUPER_ATTR(total_blocks, 0444, super_total_blocks_show, NULL); | ||
| 95 | SUPER_ATTR(blocksize, 0444, super_blocksize_show, NULL); | ||
| 96 | |||
| 97 | static struct attribute *btrfs_super_attrs[] = { | ||
| 98 | &btrfs_super_attr_blocks_used.attr, | ||
| 99 | &btrfs_super_attr_total_blocks.attr, | ||
| 100 | &btrfs_super_attr_blocksize.attr, | ||
| 101 | NULL, | ||
| 102 | }; | ||
| 103 | |||
| 104 | static ssize_t btrfs_super_attr_show(struct kobject *kobj, | ||
| 105 | struct attribute *attr, char *buf) | ||
| 106 | { | ||
| 107 | struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, | ||
| 108 | super_kobj); | ||
| 109 | struct btrfs_super_attr *a = container_of(attr, | ||
| 110 | struct btrfs_super_attr, | ||
| 111 | attr); | ||
| 112 | |||
| 113 | return a->show ? a->show(fs, buf) : 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static ssize_t btrfs_super_attr_store(struct kobject *kobj, | ||
| 117 | struct attribute *attr, | ||
| 118 | const char *buf, size_t len) | ||
| 119 | { | ||
| 120 | struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, | ||
| 121 | super_kobj); | ||
| 122 | struct btrfs_super_attr *a = container_of(attr, | ||
| 123 | struct btrfs_super_attr, | ||
| 124 | attr); | ||
| 125 | |||
| 126 | return a->store ? a->store(fs, buf, len) : 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static ssize_t btrfs_root_attr_show(struct kobject *kobj, | ||
| 130 | struct attribute *attr, char *buf) | ||
| 131 | { | ||
| 132 | struct btrfs_root *root = container_of(kobj, struct btrfs_root, | ||
| 133 | root_kobj); | ||
| 134 | struct btrfs_root_attr *a = container_of(attr, | ||
| 135 | struct btrfs_root_attr, | ||
| 136 | attr); | ||
| 137 | |||
| 138 | return a->show ? a->show(root, buf) : 0; | ||
| 139 | } | ||
| 140 | |||
| 141 | static ssize_t btrfs_root_attr_store(struct kobject *kobj, | ||
| 142 | struct attribute *attr, | ||
| 143 | const char *buf, size_t len) | ||
| 144 | { | ||
| 145 | struct btrfs_root *root = container_of(kobj, struct btrfs_root, | ||
| 146 | root_kobj); | ||
| 147 | struct btrfs_root_attr *a = container_of(attr, | ||
| 148 | struct btrfs_root_attr, | ||
| 149 | attr); | ||
| 150 | return a->store ? a->store(root, buf, len) : 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | static void btrfs_super_release(struct kobject *kobj) | ||
| 154 | { | ||
| 155 | struct btrfs_fs_info *fs = container_of(kobj, struct btrfs_fs_info, | ||
| 156 | super_kobj); | ||
| 157 | complete(&fs->kobj_unregister); | ||
| 158 | } | ||
| 159 | |||
| 160 | static void btrfs_root_release(struct kobject *kobj) | ||
| 161 | { | ||
| 162 | struct btrfs_root *root = container_of(kobj, struct btrfs_root, | ||
| 163 | root_kobj); | ||
| 164 | complete(&root->kobj_unregister); | ||
| 165 | } | ||
| 166 | |||
| 167 | static const struct sysfs_ops btrfs_super_attr_ops = { | ||
| 168 | .show = btrfs_super_attr_show, | ||
| 169 | .store = btrfs_super_attr_store, | ||
| 170 | }; | ||
| 171 | |||
| 172 | static const struct sysfs_ops btrfs_root_attr_ops = { | ||
| 173 | .show = btrfs_root_attr_show, | ||
| 174 | .store = btrfs_root_attr_store, | ||
| 175 | }; | ||
| 176 | |||
| 177 | /* /sys/fs/btrfs/ entry */ | 31 | /* /sys/fs/btrfs/ entry */ |
| 178 | static struct kset *btrfs_kset; | 32 | static struct kset *btrfs_kset; |
| 179 | 33 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 2b3590b9fe98..51dcec86757f 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -126,28 +126,85 @@ static noinline int join_transaction(struct btrfs_root *root, int nofail) | |||
| 126 | * to make sure the old root from before we joined the transaction is deleted | 126 | * to make sure the old root from before we joined the transaction is deleted |
| 127 | * when the transaction commits | 127 | * when the transaction commits |
| 128 | */ | 128 | */ |
| 129 | int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, | 129 | static int record_root_in_trans(struct btrfs_trans_handle *trans, |
| 130 | struct btrfs_root *root) | 130 | struct btrfs_root *root) |
| 131 | { | 131 | { |
| 132 | if (root->ref_cows && root->last_trans < trans->transid) { | 132 | if (root->ref_cows && root->last_trans < trans->transid) { |
| 133 | WARN_ON(root == root->fs_info->extent_root); | 133 | WARN_ON(root == root->fs_info->extent_root); |
| 134 | WARN_ON(root->commit_root != root->node); | 134 | WARN_ON(root->commit_root != root->node); |
| 135 | 135 | ||
| 136 | /* | ||
| 137 | * see below for in_trans_setup usage rules | ||
| 138 | * we have the reloc mutex held now, so there | ||
| 139 | * is only one writer in this function | ||
| 140 | */ | ||
| 141 | root->in_trans_setup = 1; | ||
| 142 | |||
| 143 | /* make sure readers find in_trans_setup before | ||
| 144 | * they find our root->last_trans update | ||
| 145 | */ | ||
| 146 | smp_wmb(); | ||
| 147 | |||
| 136 | spin_lock(&root->fs_info->fs_roots_radix_lock); | 148 | spin_lock(&root->fs_info->fs_roots_radix_lock); |
| 137 | if (root->last_trans == trans->transid) { | 149 | if (root->last_trans == trans->transid) { |
| 138 | spin_unlock(&root->fs_info->fs_roots_radix_lock); | 150 | spin_unlock(&root->fs_info->fs_roots_radix_lock); |
| 139 | return 0; | 151 | return 0; |
| 140 | } | 152 | } |
| 141 | root->last_trans = trans->transid; | ||
| 142 | radix_tree_tag_set(&root->fs_info->fs_roots_radix, | 153 | radix_tree_tag_set(&root->fs_info->fs_roots_radix, |
| 143 | (unsigned long)root->root_key.objectid, | 154 | (unsigned long)root->root_key.objectid, |
| 144 | BTRFS_ROOT_TRANS_TAG); | 155 | BTRFS_ROOT_TRANS_TAG); |
| 145 | spin_unlock(&root->fs_info->fs_roots_radix_lock); | 156 | spin_unlock(&root->fs_info->fs_roots_radix_lock); |
| 157 | root->last_trans = trans->transid; | ||
| 158 | |||
| 159 | /* this is pretty tricky. We don't want to | ||
| 160 | * take the relocation lock in btrfs_record_root_in_trans | ||
| 161 | * unless we're really doing the first setup for this root in | ||
| 162 | * this transaction. | ||
| 163 | * | ||
| 164 | * Normally we'd use root->last_trans as a flag to decide | ||
| 165 | * if we want to take the expensive mutex. | ||
| 166 | * | ||
| 167 | * But, we have to set root->last_trans before we | ||
| 168 | * init the relocation root, otherwise, we trip over warnings | ||
| 169 | * in ctree.c. The solution used here is to flag ourselves | ||
| 170 | * with root->in_trans_setup. When this is 1, we're still | ||
| 171 | * fixing up the reloc trees and everyone must wait. | ||
| 172 | * | ||
| 173 | * When this is zero, they can trust root->last_trans and fly | ||
| 174 | * through btrfs_record_root_in_trans without having to take the | ||
| 175 | * lock. smp_wmb() makes sure that all the writes above are | ||
| 176 | * done before we pop in the zero below | ||
| 177 | */ | ||
| 146 | btrfs_init_reloc_root(trans, root); | 178 | btrfs_init_reloc_root(trans, root); |
| 179 | smp_wmb(); | ||
| 180 | root->in_trans_setup = 0; | ||
| 147 | } | 181 | } |
| 148 | return 0; | 182 | return 0; |
| 149 | } | 183 | } |
| 150 | 184 | ||
| 185 | |||
| 186 | int btrfs_record_root_in_trans(struct btrfs_trans_handle *trans, | ||
| 187 | struct btrfs_root *root) | ||
| 188 | { | ||
| 189 | if (!root->ref_cows) | ||
| 190 | return 0; | ||
| 191 | |||
| 192 | /* | ||
| 193 | * see record_root_in_trans for comments about in_trans_setup usage | ||
| 194 | * and barriers | ||
| 195 | */ | ||
| 196 | smp_rmb(); | ||
| 197 | if (root->last_trans == trans->transid && | ||
| 198 | !root->in_trans_setup) | ||
| 199 | return 0; | ||
| 200 | |||
| 201 | mutex_lock(&root->fs_info->reloc_mutex); | ||
| 202 | record_root_in_trans(trans, root); | ||
| 203 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
| 204 | |||
| 205 | return 0; | ||
| 206 | } | ||
| 207 | |||
| 151 | /* wait for commit against the current transaction to become unblocked | 208 | /* wait for commit against the current transaction to become unblocked |
| 152 | * when this is done, it is safe to start a new transaction, but the current | 209 | * when this is done, it is safe to start a new transaction, but the current |
| 153 | * transaction might not be fully on disk. | 210 | * transaction might not be fully on disk. |
| @@ -882,7 +939,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 882 | parent = dget_parent(dentry); | 939 | parent = dget_parent(dentry); |
| 883 | parent_inode = parent->d_inode; | 940 | parent_inode = parent->d_inode; |
| 884 | parent_root = BTRFS_I(parent_inode)->root; | 941 | parent_root = BTRFS_I(parent_inode)->root; |
| 885 | btrfs_record_root_in_trans(trans, parent_root); | 942 | record_root_in_trans(trans, parent_root); |
| 886 | 943 | ||
| 887 | /* | 944 | /* |
| 888 | * insert the directory item | 945 | * insert the directory item |
| @@ -900,7 +957,16 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 900 | ret = btrfs_update_inode(trans, parent_root, parent_inode); | 957 | ret = btrfs_update_inode(trans, parent_root, parent_inode); |
| 901 | BUG_ON(ret); | 958 | BUG_ON(ret); |
| 902 | 959 | ||
| 903 | btrfs_record_root_in_trans(trans, root); | 960 | /* |
| 961 | * pull in the delayed directory update | ||
| 962 | * and the delayed inode item | ||
| 963 | * otherwise we corrupt the FS during | ||
| 964 | * snapshot | ||
| 965 | */ | ||
| 966 | ret = btrfs_run_delayed_items(trans, root); | ||
| 967 | BUG_ON(ret); | ||
| 968 | |||
| 969 | record_root_in_trans(trans, root); | ||
| 904 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); | 970 | btrfs_set_root_last_snapshot(&root->root_item, trans->transid); |
| 905 | memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); | 971 | memcpy(new_root_item, &root->root_item, sizeof(*new_root_item)); |
| 906 | btrfs_check_and_init_root_item(new_root_item); | 972 | btrfs_check_and_init_root_item(new_root_item); |
| @@ -961,14 +1027,6 @@ static noinline int create_pending_snapshots(struct btrfs_trans_handle *trans, | |||
| 961 | int ret; | 1027 | int ret; |
| 962 | 1028 | ||
| 963 | list_for_each_entry(pending, head, list) { | 1029 | list_for_each_entry(pending, head, list) { |
| 964 | /* | ||
| 965 | * We must deal with the delayed items before creating | ||
| 966 | * snapshots, or we will create a snapthot with inconsistent | ||
| 967 | * information. | ||
| 968 | */ | ||
| 969 | ret = btrfs_run_delayed_items(trans, fs_info->fs_root); | ||
| 970 | BUG_ON(ret); | ||
| 971 | |||
| 972 | ret = create_pending_snapshot(trans, fs_info, pending); | 1030 | ret = create_pending_snapshot(trans, fs_info, pending); |
| 973 | BUG_ON(ret); | 1031 | BUG_ON(ret); |
| 974 | } | 1032 | } |
| @@ -1241,21 +1299,42 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1241 | schedule_timeout(1); | 1299 | schedule_timeout(1); |
| 1242 | 1300 | ||
| 1243 | finish_wait(&cur_trans->writer_wait, &wait); | 1301 | finish_wait(&cur_trans->writer_wait, &wait); |
| 1244 | spin_lock(&root->fs_info->trans_lock); | ||
| 1245 | root->fs_info->trans_no_join = 1; | ||
| 1246 | spin_unlock(&root->fs_info->trans_lock); | ||
| 1247 | } while (atomic_read(&cur_trans->num_writers) > 1 || | 1302 | } while (atomic_read(&cur_trans->num_writers) > 1 || |
| 1248 | (should_grow && cur_trans->num_joined != joined)); | 1303 | (should_grow && cur_trans->num_joined != joined)); |
| 1249 | 1304 | ||
| 1250 | ret = create_pending_snapshots(trans, root->fs_info); | 1305 | /* |
| 1251 | BUG_ON(ret); | 1306 | * Ok now we need to make sure to block out any other joins while we |
| 1307 | * commit the transaction. We could have started a join before setting | ||
| 1308 | * no_join so make sure to wait for num_writers to == 1 again. | ||
| 1309 | */ | ||
| 1310 | spin_lock(&root->fs_info->trans_lock); | ||
| 1311 | root->fs_info->trans_no_join = 1; | ||
| 1312 | spin_unlock(&root->fs_info->trans_lock); | ||
| 1313 | wait_event(cur_trans->writer_wait, | ||
| 1314 | atomic_read(&cur_trans->num_writers) == 1); | ||
| 1315 | |||
| 1316 | /* | ||
| 1317 | * the reloc mutex makes sure that we stop | ||
| 1318 | * the balancing code from coming in and moving | ||
| 1319 | * extents around in the middle of the commit | ||
| 1320 | */ | ||
| 1321 | mutex_lock(&root->fs_info->reloc_mutex); | ||
| 1252 | 1322 | ||
| 1253 | ret = btrfs_run_delayed_items(trans, root); | 1323 | ret = btrfs_run_delayed_items(trans, root); |
| 1254 | BUG_ON(ret); | 1324 | BUG_ON(ret); |
| 1255 | 1325 | ||
| 1326 | ret = create_pending_snapshots(trans, root->fs_info); | ||
| 1327 | BUG_ON(ret); | ||
| 1328 | |||
| 1256 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); | 1329 | ret = btrfs_run_delayed_refs(trans, root, (unsigned long)-1); |
| 1257 | BUG_ON(ret); | 1330 | BUG_ON(ret); |
| 1258 | 1331 | ||
| 1332 | /* | ||
| 1333 | * make sure none of the code above managed to slip in a | ||
| 1334 | * delayed item | ||
| 1335 | */ | ||
| 1336 | btrfs_assert_delayed_root_empty(root); | ||
| 1337 | |||
| 1259 | WARN_ON(cur_trans != trans->transaction); | 1338 | WARN_ON(cur_trans != trans->transaction); |
| 1260 | 1339 | ||
| 1261 | btrfs_scrub_pause(root); | 1340 | btrfs_scrub_pause(root); |
| @@ -1312,6 +1391,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans, | |||
| 1312 | root->fs_info->running_transaction = NULL; | 1391 | root->fs_info->running_transaction = NULL; |
| 1313 | root->fs_info->trans_no_join = 0; | 1392 | root->fs_info->trans_no_join = 0; |
| 1314 | spin_unlock(&root->fs_info->trans_lock); | 1393 | spin_unlock(&root->fs_info->trans_lock); |
| 1394 | mutex_unlock(&root->fs_info->reloc_mutex); | ||
| 1315 | 1395 | ||
| 1316 | wake_up(&root->fs_info->transaction_wait); | 1396 | wake_up(&root->fs_info->transaction_wait); |
| 1317 | 1397 | ||
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 592396c6dc47..4ce8a9f41d1e 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -3177,7 +3177,7 @@ again: | |||
| 3177 | tmp_key.offset = (u64)-1; | 3177 | tmp_key.offset = (u64)-1; |
| 3178 | 3178 | ||
| 3179 | wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); | 3179 | wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); |
| 3180 | BUG_ON(!wc.replay_dest); | 3180 | BUG_ON(IS_ERR_OR_NULL(wc.replay_dest)); |
| 3181 | 3181 | ||
| 3182 | wc.replay_dest->log_root = log; | 3182 | wc.replay_dest->log_root = log; |
| 3183 | btrfs_record_root_in_trans(trans, wc.replay_dest); | 3183 | btrfs_record_root_in_trans(trans, wc.replay_dest); |
diff --git a/fs/buffer.c b/fs/buffer.c index 49c9aada0374..1a80b048ade8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -1902,10 +1902,8 @@ int __block_write_begin(struct page *page, loff_t pos, unsigned len, | |||
| 1902 | if (!buffer_uptodate(*wait_bh)) | 1902 | if (!buffer_uptodate(*wait_bh)) |
| 1903 | err = -EIO; | 1903 | err = -EIO; |
| 1904 | } | 1904 | } |
| 1905 | if (unlikely(err)) { | 1905 | if (unlikely(err)) |
| 1906 | page_zero_new_buffers(page, from, to); | 1906 | page_zero_new_buffers(page, from, to); |
| 1907 | ClearPageUptodate(page); | ||
| 1908 | } | ||
| 1909 | return err; | 1907 | return err; |
| 1910 | } | 1908 | } |
| 1911 | EXPORT_SYMBOL(__block_write_begin); | 1909 | EXPORT_SYMBOL(__block_write_begin); |
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 53ed1ad2c112..f66cc1625150 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
| @@ -156,6 +156,6 @@ config CIFS_ACL | |||
| 156 | 156 | ||
| 157 | config CIFS_NFSD_EXPORT | 157 | config CIFS_NFSD_EXPORT |
| 158 | bool "Allow nfsd to export CIFS file system (EXPERIMENTAL)" | 158 | bool "Allow nfsd to export CIFS file system (EXPERIMENTAL)" |
| 159 | depends on CIFS && EXPERIMENTAL | 159 | depends on CIFS && EXPERIMENTAL && BROKEN |
| 160 | help | 160 | help |
| 161 | Allows NFS server to export a CIFS mounted share (nfsd over cifs) | 161 | Allows NFS server to export a CIFS mounted share (nfsd over cifs) |
diff --git a/fs/cifs/cache.c b/fs/cifs/cache.c index dd8584d35a14..545509c3313b 100644 --- a/fs/cifs/cache.c +++ b/fs/cifs/cache.c | |||
| @@ -92,7 +92,7 @@ static uint16_t cifs_server_get_key(const void *cookie_netfs_data, | |||
| 92 | break; | 92 | break; |
| 93 | 93 | ||
| 94 | default: | 94 | default: |
| 95 | cERROR(1, "CIFS: Unknown network family '%d'", sa->sa_family); | 95 | cERROR(1, "Unknown network family '%d'", sa->sa_family); |
| 96 | key_len = 0; | 96 | key_len = 0; |
| 97 | break; | 97 | break; |
| 98 | } | 98 | } |
| @@ -152,7 +152,7 @@ static uint16_t cifs_super_get_key(const void *cookie_netfs_data, void *buffer, | |||
| 152 | 152 | ||
| 153 | sharename = extract_sharename(tcon->treeName); | 153 | sharename = extract_sharename(tcon->treeName); |
| 154 | if (IS_ERR(sharename)) { | 154 | if (IS_ERR(sharename)) { |
| 155 | cFYI(1, "CIFS: couldn't extract sharename\n"); | 155 | cFYI(1, "%s: couldn't extract sharename\n", __func__); |
| 156 | sharename = NULL; | 156 | sharename = NULL; |
| 157 | return 0; | 157 | return 0; |
| 158 | } | 158 | } |
| @@ -302,7 +302,7 @@ static void cifs_fscache_inode_now_uncached(void *cookie_netfs_data) | |||
| 302 | pagevec_init(&pvec, 0); | 302 | pagevec_init(&pvec, 0); |
| 303 | first = 0; | 303 | first = 0; |
| 304 | 304 | ||
| 305 | cFYI(1, "cifs inode 0x%p now uncached", cifsi); | 305 | cFYI(1, "%s: cifs inode 0x%p now uncached", __func__, cifsi); |
| 306 | 306 | ||
| 307 | for (;;) { | 307 | for (;;) { |
| 308 | nr_pages = pagevec_lookup(&pvec, | 308 | nr_pages = pagevec_lookup(&pvec, |
diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index ffb1459dc6ec..7260e11e21f8 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ | 42 | #define CIFS_MOUNT_MULTIUSER 0x20000 /* multiuser mount */ |
| 43 | #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ | 43 | #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ |
| 44 | #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ | 44 | #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ |
| 45 | #define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */ | ||
| 45 | 46 | ||
| 46 | struct cifs_sb_info { | 47 | struct cifs_sb_info { |
| 47 | struct rb_root tlink_tree; | 48 | struct rb_root tlink_tree; |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 989442dcfb45..35f9154615fa 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -104,8 +104,7 @@ cifs_sb_deactive(struct super_block *sb) | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | static int | 106 | static int |
| 107 | cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, | 107 | cifs_read_super(struct super_block *sb) |
| 108 | const char *devname, int silent) | ||
| 109 | { | 108 | { |
| 110 | struct inode *inode; | 109 | struct inode *inode; |
| 111 | struct cifs_sb_info *cifs_sb; | 110 | struct cifs_sb_info *cifs_sb; |
| @@ -113,22 +112,16 @@ cifs_read_super(struct super_block *sb, struct smb_vol *volume_info, | |||
| 113 | 112 | ||
| 114 | cifs_sb = CIFS_SB(sb); | 113 | cifs_sb = CIFS_SB(sb); |
| 115 | 114 | ||
| 116 | spin_lock_init(&cifs_sb->tlink_tree_lock); | 115 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIXACL) |
| 117 | cifs_sb->tlink_tree = RB_ROOT; | 116 | sb->s_flags |= MS_POSIXACL; |
| 118 | 117 | ||
| 119 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); | 118 | if (cifs_sb_master_tcon(cifs_sb)->ses->capabilities & CAP_LARGE_FILES) |
| 120 | if (rc) | 119 | sb->s_maxbytes = MAX_LFS_FILESIZE; |
| 121 | return rc; | 120 | else |
| 122 | 121 | sb->s_maxbytes = MAX_NON_LFS; | |
| 123 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; | ||
| 124 | 122 | ||
| 125 | rc = cifs_mount(sb, cifs_sb, volume_info, devname); | 123 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ |
| 126 | 124 | sb->s_time_gran = 100; | |
| 127 | if (rc) { | ||
| 128 | if (!silent) | ||
| 129 | cERROR(1, "cifs_mount failed w/return code = %d", rc); | ||
| 130 | goto out_mount_failed; | ||
| 131 | } | ||
| 132 | 125 | ||
| 133 | sb->s_magic = CIFS_MAGIC_NUMBER; | 126 | sb->s_magic = CIFS_MAGIC_NUMBER; |
| 134 | sb->s_op = &cifs_super_ops; | 127 | sb->s_op = &cifs_super_ops; |
| @@ -170,37 +163,14 @@ out_no_root: | |||
| 170 | if (inode) | 163 | if (inode) |
| 171 | iput(inode); | 164 | iput(inode); |
| 172 | 165 | ||
| 173 | cifs_umount(sb, cifs_sb); | ||
| 174 | |||
| 175 | out_mount_failed: | ||
| 176 | bdi_destroy(&cifs_sb->bdi); | ||
| 177 | return rc; | 166 | return rc; |
| 178 | } | 167 | } |
| 179 | 168 | ||
| 180 | static void | 169 | static void cifs_kill_sb(struct super_block *sb) |
| 181 | cifs_put_super(struct super_block *sb) | ||
| 182 | { | 170 | { |
| 183 | int rc = 0; | 171 | struct cifs_sb_info *cifs_sb = CIFS_SB(sb); |
| 184 | struct cifs_sb_info *cifs_sb; | 172 | kill_anon_super(sb); |
| 185 | 173 | cifs_umount(cifs_sb); | |
| 186 | cFYI(1, "In cifs_put_super"); | ||
| 187 | cifs_sb = CIFS_SB(sb); | ||
| 188 | if (cifs_sb == NULL) { | ||
| 189 | cFYI(1, "Empty cifs superblock info passed to unmount"); | ||
| 190 | return; | ||
| 191 | } | ||
| 192 | |||
| 193 | rc = cifs_umount(sb, cifs_sb); | ||
| 194 | if (rc) | ||
| 195 | cERROR(1, "cifs_umount failed with return code %d", rc); | ||
| 196 | if (cifs_sb->mountdata) { | ||
| 197 | kfree(cifs_sb->mountdata); | ||
| 198 | cifs_sb->mountdata = NULL; | ||
| 199 | } | ||
| 200 | |||
| 201 | unload_nls(cifs_sb->local_nls); | ||
| 202 | bdi_destroy(&cifs_sb->bdi); | ||
| 203 | kfree(cifs_sb); | ||
| 204 | } | 174 | } |
| 205 | 175 | ||
| 206 | static int | 176 | static int |
| @@ -257,9 +227,6 @@ static int cifs_permission(struct inode *inode, int mask, unsigned int flags) | |||
| 257 | { | 227 | { |
| 258 | struct cifs_sb_info *cifs_sb; | 228 | struct cifs_sb_info *cifs_sb; |
| 259 | 229 | ||
| 260 | if (flags & IPERM_FLAG_RCU) | ||
| 261 | return -ECHILD; | ||
| 262 | |||
| 263 | cifs_sb = CIFS_SB(inode->i_sb); | 230 | cifs_sb = CIFS_SB(inode->i_sb); |
| 264 | 231 | ||
| 265 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { | 232 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) { |
| @@ -352,6 +319,37 @@ cifs_show_address(struct seq_file *s, struct TCP_Server_Info *server) | |||
| 352 | } | 319 | } |
| 353 | } | 320 | } |
| 354 | 321 | ||
| 322 | static void | ||
| 323 | cifs_show_security(struct seq_file *s, struct TCP_Server_Info *server) | ||
| 324 | { | ||
| 325 | seq_printf(s, ",sec="); | ||
| 326 | |||
| 327 | switch (server->secType) { | ||
| 328 | case LANMAN: | ||
| 329 | seq_printf(s, "lanman"); | ||
| 330 | break; | ||
| 331 | case NTLMv2: | ||
| 332 | seq_printf(s, "ntlmv2"); | ||
| 333 | break; | ||
| 334 | case NTLM: | ||
| 335 | seq_printf(s, "ntlm"); | ||
| 336 | break; | ||
| 337 | case Kerberos: | ||
| 338 | seq_printf(s, "krb5"); | ||
| 339 | break; | ||
| 340 | case RawNTLMSSP: | ||
| 341 | seq_printf(s, "ntlmssp"); | ||
| 342 | break; | ||
| 343 | default: | ||
| 344 | /* shouldn't ever happen */ | ||
| 345 | seq_printf(s, "unknown"); | ||
| 346 | break; | ||
| 347 | } | ||
| 348 | |||
| 349 | if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) | ||
| 350 | seq_printf(s, "i"); | ||
| 351 | } | ||
| 352 | |||
| 355 | /* | 353 | /* |
| 356 | * cifs_show_options() is for displaying mount options in /proc/mounts. | 354 | * cifs_show_options() is for displaying mount options in /proc/mounts. |
| 357 | * Not all settable options are displayed but most of the important | 355 | * Not all settable options are displayed but most of the important |
| @@ -365,6 +363,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
| 365 | struct sockaddr *srcaddr; | 363 | struct sockaddr *srcaddr; |
| 366 | srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; | 364 | srcaddr = (struct sockaddr *)&tcon->ses->server->srcaddr; |
| 367 | 365 | ||
| 366 | cifs_show_security(s, tcon->ses->server); | ||
| 367 | |||
| 368 | seq_printf(s, ",unc=%s", tcon->treeName); | 368 | seq_printf(s, ",unc=%s", tcon->treeName); |
| 369 | 369 | ||
| 370 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) | 370 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MULTIUSER) |
| @@ -518,7 +518,6 @@ static int cifs_drop_inode(struct inode *inode) | |||
| 518 | } | 518 | } |
| 519 | 519 | ||
| 520 | static const struct super_operations cifs_super_ops = { | 520 | static const struct super_operations cifs_super_ops = { |
| 521 | .put_super = cifs_put_super, | ||
| 522 | .statfs = cifs_statfs, | 521 | .statfs = cifs_statfs, |
| 523 | .alloc_inode = cifs_alloc_inode, | 522 | .alloc_inode = cifs_alloc_inode, |
| 524 | .destroy_inode = cifs_destroy_inode, | 523 | .destroy_inode = cifs_destroy_inode, |
| @@ -555,7 +554,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) | |||
| 555 | full_path = cifs_build_path_to_root(vol, cifs_sb, | 554 | full_path = cifs_build_path_to_root(vol, cifs_sb, |
| 556 | cifs_sb_master_tcon(cifs_sb)); | 555 | cifs_sb_master_tcon(cifs_sb)); |
| 557 | if (full_path == NULL) | 556 | if (full_path == NULL) |
| 558 | return NULL; | 557 | return ERR_PTR(-ENOMEM); |
| 559 | 558 | ||
| 560 | cFYI(1, "Get root dentry for %s", full_path); | 559 | cFYI(1, "Get root dentry for %s", full_path); |
| 561 | 560 | ||
| @@ -584,7 +583,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) | |||
| 584 | dchild = d_alloc(dparent, &name); | 583 | dchild = d_alloc(dparent, &name); |
| 585 | if (dchild == NULL) { | 584 | if (dchild == NULL) { |
| 586 | dput(dparent); | 585 | dput(dparent); |
| 587 | dparent = NULL; | 586 | dparent = ERR_PTR(-ENOMEM); |
| 588 | goto out; | 587 | goto out; |
| 589 | } | 588 | } |
| 590 | } | 589 | } |
| @@ -602,7 +601,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) | |||
| 602 | if (rc) { | 601 | if (rc) { |
| 603 | dput(dchild); | 602 | dput(dchild); |
| 604 | dput(dparent); | 603 | dput(dparent); |
| 605 | dparent = NULL; | 604 | dparent = ERR_PTR(rc); |
| 606 | goto out; | 605 | goto out; |
| 607 | } | 606 | } |
| 608 | alias = d_materialise_unique(dchild, inode); | 607 | alias = d_materialise_unique(dchild, inode); |
| @@ -610,7 +609,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) | |||
| 610 | dput(dchild); | 609 | dput(dchild); |
| 611 | if (IS_ERR(alias)) { | 610 | if (IS_ERR(alias)) { |
| 612 | dput(dparent); | 611 | dput(dparent); |
| 613 | dparent = NULL; | 612 | dparent = ERR_PTR(-EINVAL); /* XXX */ |
| 614 | goto out; | 613 | goto out; |
| 615 | } | 614 | } |
| 616 | dchild = alias; | 615 | dchild = alias; |
| @@ -630,6 +629,13 @@ out: | |||
| 630 | return dparent; | 629 | return dparent; |
| 631 | } | 630 | } |
| 632 | 631 | ||
| 632 | static int cifs_set_super(struct super_block *sb, void *data) | ||
| 633 | { | ||
| 634 | struct cifs_mnt_data *mnt_data = data; | ||
| 635 | sb->s_fs_info = mnt_data->cifs_sb; | ||
| 636 | return set_anon_super(sb, NULL); | ||
| 637 | } | ||
| 638 | |||
| 633 | static struct dentry * | 639 | static struct dentry * |
| 634 | cifs_do_mount(struct file_system_type *fs_type, | 640 | cifs_do_mount(struct file_system_type *fs_type, |
| 635 | int flags, const char *dev_name, void *data) | 641 | int flags, const char *dev_name, void *data) |
| @@ -650,75 +656,73 @@ cifs_do_mount(struct file_system_type *fs_type, | |||
| 650 | cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); | 656 | cifs_sb = kzalloc(sizeof(struct cifs_sb_info), GFP_KERNEL); |
| 651 | if (cifs_sb == NULL) { | 657 | if (cifs_sb == NULL) { |
| 652 | root = ERR_PTR(-ENOMEM); | 658 | root = ERR_PTR(-ENOMEM); |
| 653 | goto out; | 659 | goto out_nls; |
| 660 | } | ||
| 661 | |||
| 662 | cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); | ||
| 663 | if (cifs_sb->mountdata == NULL) { | ||
| 664 | root = ERR_PTR(-ENOMEM); | ||
| 665 | goto out_cifs_sb; | ||
| 654 | } | 666 | } |
| 655 | 667 | ||
| 656 | cifs_setup_cifs_sb(volume_info, cifs_sb); | 668 | cifs_setup_cifs_sb(volume_info, cifs_sb); |
| 657 | 669 | ||
| 670 | rc = cifs_mount(cifs_sb, volume_info); | ||
| 671 | if (rc) { | ||
| 672 | if (!(flags & MS_SILENT)) | ||
| 673 | cERROR(1, "cifs_mount failed w/return code = %d", rc); | ||
| 674 | root = ERR_PTR(rc); | ||
| 675 | goto out_mountdata; | ||
| 676 | } | ||
| 677 | |||
| 658 | mnt_data.vol = volume_info; | 678 | mnt_data.vol = volume_info; |
| 659 | mnt_data.cifs_sb = cifs_sb; | 679 | mnt_data.cifs_sb = cifs_sb; |
| 660 | mnt_data.flags = flags; | 680 | mnt_data.flags = flags; |
| 661 | 681 | ||
| 662 | sb = sget(fs_type, cifs_match_super, set_anon_super, &mnt_data); | 682 | sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data); |
| 663 | if (IS_ERR(sb)) { | 683 | if (IS_ERR(sb)) { |
| 664 | root = ERR_CAST(sb); | 684 | root = ERR_CAST(sb); |
| 665 | goto out_cifs_sb; | 685 | cifs_umount(cifs_sb); |
| 686 | goto out; | ||
| 666 | } | 687 | } |
| 667 | 688 | ||
| 668 | if (sb->s_fs_info) { | 689 | if (sb->s_root) { |
| 669 | cFYI(1, "Use existing superblock"); | 690 | cFYI(1, "Use existing superblock"); |
| 670 | goto out_shared; | 691 | cifs_umount(cifs_sb); |
| 671 | } | 692 | } else { |
| 672 | 693 | sb->s_flags = flags; | |
| 673 | /* | 694 | /* BB should we make this contingent on mount parm? */ |
| 674 | * Copy mount params for use in submounts. Better to do | 695 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; |
| 675 | * the copy here and deal with the error before cleanup gets | 696 | |
| 676 | * complicated post-mount. | 697 | rc = cifs_read_super(sb); |
| 677 | */ | 698 | if (rc) { |
| 678 | cifs_sb->mountdata = kstrndup(data, PAGE_SIZE, GFP_KERNEL); | 699 | root = ERR_PTR(rc); |
| 679 | if (cifs_sb->mountdata == NULL) { | 700 | goto out_super; |
| 680 | root = ERR_PTR(-ENOMEM); | 701 | } |
| 681 | goto out_super; | ||
| 682 | } | ||
| 683 | |||
| 684 | sb->s_flags = flags; | ||
| 685 | /* BB should we make this contingent on mount parm? */ | ||
| 686 | sb->s_flags |= MS_NODIRATIME | MS_NOATIME; | ||
| 687 | sb->s_fs_info = cifs_sb; | ||
| 688 | 702 | ||
| 689 | rc = cifs_read_super(sb, volume_info, dev_name, | 703 | sb->s_flags |= MS_ACTIVE; |
| 690 | flags & MS_SILENT ? 1 : 0); | ||
| 691 | if (rc) { | ||
| 692 | root = ERR_PTR(rc); | ||
| 693 | goto out_super; | ||
| 694 | } | 704 | } |
| 695 | 705 | ||
| 696 | sb->s_flags |= MS_ACTIVE; | ||
| 697 | |||
| 698 | root = cifs_get_root(volume_info, sb); | 706 | root = cifs_get_root(volume_info, sb); |
| 699 | if (root == NULL) | 707 | if (IS_ERR(root)) |
| 700 | goto out_super; | 708 | goto out_super; |
| 701 | 709 | ||
| 702 | cFYI(1, "dentry root is: %p", root); | 710 | cFYI(1, "dentry root is: %p", root); |
| 703 | goto out; | 711 | goto out; |
| 704 | 712 | ||
| 705 | out_shared: | ||
| 706 | root = cifs_get_root(volume_info, sb); | ||
| 707 | if (root) | ||
| 708 | cFYI(1, "dentry root is: %p", root); | ||
| 709 | goto out; | ||
| 710 | |||
| 711 | out_super: | 713 | out_super: |
| 712 | kfree(cifs_sb->mountdata); | ||
| 713 | deactivate_locked_super(sb); | 714 | deactivate_locked_super(sb); |
| 714 | |||
| 715 | out_cifs_sb: | ||
| 716 | unload_nls(cifs_sb->local_nls); | ||
| 717 | kfree(cifs_sb); | ||
| 718 | |||
| 719 | out: | 715 | out: |
| 720 | cifs_cleanup_volume_info(&volume_info); | 716 | cifs_cleanup_volume_info(&volume_info); |
| 721 | return root; | 717 | return root; |
| 718 | |||
| 719 | out_mountdata: | ||
| 720 | kfree(cifs_sb->mountdata); | ||
| 721 | out_cifs_sb: | ||
| 722 | kfree(cifs_sb); | ||
| 723 | out_nls: | ||
| 724 | unload_nls(volume_info->local_nls); | ||
| 725 | goto out; | ||
| 722 | } | 726 | } |
| 723 | 727 | ||
| 724 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, | 728 | static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, |
| @@ -807,7 +811,7 @@ struct file_system_type cifs_fs_type = { | |||
| 807 | .owner = THIS_MODULE, | 811 | .owner = THIS_MODULE, |
| 808 | .name = "cifs", | 812 | .name = "cifs", |
| 809 | .mount = cifs_do_mount, | 813 | .mount = cifs_do_mount, |
| 810 | .kill_sb = kill_anon_super, | 814 | .kill_sb = cifs_kill_sb, |
| 811 | /* .fs_flags */ | 815 | /* .fs_flags */ |
| 812 | }; | 816 | }; |
| 813 | const struct inode_operations cifs_dir_inode_ops = { | 817 | const struct inode_operations cifs_dir_inode_ops = { |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 64313f778ebf..0900e1658c96 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
| @@ -129,5 +129,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); | |||
| 129 | extern const struct export_operations cifs_export_ops; | 129 | extern const struct export_operations cifs_export_ops; |
| 130 | #endif /* CIFS_NFSD_EXPORT */ | 130 | #endif /* CIFS_NFSD_EXPORT */ |
| 131 | 131 | ||
| 132 | #define CIFS_VERSION "1.72" | 132 | #define CIFS_VERSION "1.73" |
| 133 | #endif /* _CIFSFS_H */ | 133 | #endif /* _CIFSFS_H */ |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 953f84413c77..257f312ede42 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -157,9 +157,8 @@ extern int cifs_match_super(struct super_block *, void *); | |||
| 157 | extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info); | 157 | extern void cifs_cleanup_volume_info(struct smb_vol **pvolume_info); |
| 158 | extern int cifs_setup_volume_info(struct smb_vol **pvolume_info, | 158 | extern int cifs_setup_volume_info(struct smb_vol **pvolume_info, |
| 159 | char *mount_data, const char *devname); | 159 | char *mount_data, const char *devname); |
| 160 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, | 160 | extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); |
| 161 | struct smb_vol *, const char *); | 161 | extern void cifs_umount(struct cifs_sb_info *); |
| 162 | extern int cifs_umount(struct super_block *, struct cifs_sb_info *); | ||
| 163 | extern void cifs_dfs_release_automount_timer(void); | 162 | extern void cifs_dfs_release_automount_timer(void); |
| 164 | void cifs_proc_init(void); | 163 | void cifs_proc_init(void); |
| 165 | void cifs_proc_clean(void); | 164 | void cifs_proc_clean(void); |
| @@ -218,7 +217,8 @@ extern int get_dfs_path(int xid, struct cifs_ses *pSesInfo, | |||
| 218 | struct dfs_info3_param **preferrals, | 217 | struct dfs_info3_param **preferrals, |
| 219 | int remap); | 218 | int remap); |
| 220 | extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, | 219 | extern void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, |
| 221 | struct super_block *sb, struct smb_vol *vol); | 220 | struct cifs_sb_info *cifs_sb, |
| 221 | struct smb_vol *vol); | ||
| 222 | extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, | 222 | extern int CIFSSMBQFSInfo(const int xid, struct cifs_tcon *tcon, |
| 223 | struct kstatfs *FSData); | 223 | struct kstatfs *FSData); |
| 224 | extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, | 224 | extern int SMBOldQFSInfo(const int xid, struct cifs_tcon *tcon, |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index bb659eb73810..7f540df52527 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -152,7 +152,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 152 | mid_entry->callback(mid_entry); | 152 | mid_entry->callback(mid_entry); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | while (server->tcpStatus == CifsNeedReconnect) { | 155 | do { |
| 156 | try_to_freeze(); | 156 | try_to_freeze(); |
| 157 | 157 | ||
| 158 | /* we should try only the port we connected to before */ | 158 | /* we should try only the port we connected to before */ |
| @@ -167,7 +167,7 @@ cifs_reconnect(struct TCP_Server_Info *server) | |||
| 167 | server->tcpStatus = CifsNeedNegotiate; | 167 | server->tcpStatus = CifsNeedNegotiate; |
| 168 | spin_unlock(&GlobalMid_Lock); | 168 | spin_unlock(&GlobalMid_Lock); |
| 169 | } | 169 | } |
| 170 | } | 170 | } while (server->tcpStatus == CifsNeedReconnect); |
| 171 | 171 | ||
| 172 | return rc; | 172 | return rc; |
| 173 | } | 173 | } |
| @@ -2149,7 +2149,10 @@ cifs_put_tlink(struct tcon_link *tlink) | |||
| 2149 | } | 2149 | } |
| 2150 | 2150 | ||
| 2151 | static inline struct tcon_link * | 2151 | static inline struct tcon_link * |
| 2152 | cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb); | 2152 | cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb) |
| 2153 | { | ||
| 2154 | return cifs_sb->master_tlink; | ||
| 2155 | } | ||
| 2153 | 2156 | ||
| 2154 | static int | 2157 | static int |
| 2155 | compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) | 2158 | compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) |
| @@ -2543,7 +2546,7 @@ ip_connect(struct TCP_Server_Info *server) | |||
| 2543 | } | 2546 | } |
| 2544 | 2547 | ||
| 2545 | void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, | 2548 | void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, |
| 2546 | struct super_block *sb, struct smb_vol *vol_info) | 2549 | struct cifs_sb_info *cifs_sb, struct smb_vol *vol_info) |
| 2547 | { | 2550 | { |
| 2548 | /* if we are reconnecting then should we check to see if | 2551 | /* if we are reconnecting then should we check to see if |
| 2549 | * any requested capabilities changed locally e.g. via | 2552 | * any requested capabilities changed locally e.g. via |
| @@ -2597,22 +2600,23 @@ void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, | |||
| 2597 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; | 2600 | cap &= ~CIFS_UNIX_POSIX_ACL_CAP; |
| 2598 | else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { | 2601 | else if (CIFS_UNIX_POSIX_ACL_CAP & cap) { |
| 2599 | cFYI(1, "negotiated posix acl support"); | 2602 | cFYI(1, "negotiated posix acl support"); |
| 2600 | if (sb) | 2603 | if (cifs_sb) |
| 2601 | sb->s_flags |= MS_POSIXACL; | 2604 | cifs_sb->mnt_cifs_flags |= |
| 2605 | CIFS_MOUNT_POSIXACL; | ||
| 2602 | } | 2606 | } |
| 2603 | 2607 | ||
| 2604 | if (vol_info && vol_info->posix_paths == 0) | 2608 | if (vol_info && vol_info->posix_paths == 0) |
| 2605 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; | 2609 | cap &= ~CIFS_UNIX_POSIX_PATHNAMES_CAP; |
| 2606 | else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { | 2610 | else if (cap & CIFS_UNIX_POSIX_PATHNAMES_CAP) { |
| 2607 | cFYI(1, "negotiate posix pathnames"); | 2611 | cFYI(1, "negotiate posix pathnames"); |
| 2608 | if (sb) | 2612 | if (cifs_sb) |
| 2609 | CIFS_SB(sb)->mnt_cifs_flags |= | 2613 | cifs_sb->mnt_cifs_flags |= |
| 2610 | CIFS_MOUNT_POSIX_PATHS; | 2614 | CIFS_MOUNT_POSIX_PATHS; |
| 2611 | } | 2615 | } |
| 2612 | 2616 | ||
| 2613 | if (sb && (CIFS_SB(sb)->rsize > 127 * 1024)) { | 2617 | if (cifs_sb && (cifs_sb->rsize > 127 * 1024)) { |
| 2614 | if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { | 2618 | if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { |
| 2615 | CIFS_SB(sb)->rsize = 127 * 1024; | 2619 | cifs_sb->rsize = 127 * 1024; |
| 2616 | cFYI(DBG2, "larger reads not supported by srv"); | 2620 | cFYI(DBG2, "larger reads not supported by srv"); |
| 2617 | } | 2621 | } |
| 2618 | } | 2622 | } |
| @@ -2659,6 +2663,9 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
| 2659 | { | 2663 | { |
| 2660 | INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); | 2664 | INIT_DELAYED_WORK(&cifs_sb->prune_tlinks, cifs_prune_tlinks); |
| 2661 | 2665 | ||
| 2666 | spin_lock_init(&cifs_sb->tlink_tree_lock); | ||
| 2667 | cifs_sb->tlink_tree = RB_ROOT; | ||
| 2668 | |||
| 2662 | if (pvolume_info->rsize > CIFSMaxBufSize) { | 2669 | if (pvolume_info->rsize > CIFSMaxBufSize) { |
| 2663 | cERROR(1, "rsize %d too large, using MaxBufSize", | 2670 | cERROR(1, "rsize %d too large, using MaxBufSize", |
| 2664 | pvolume_info->rsize); | 2671 | pvolume_info->rsize); |
| @@ -2747,21 +2754,21 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, | |||
| 2747 | 2754 | ||
| 2748 | /* | 2755 | /* |
| 2749 | * When the server supports very large writes via POSIX extensions, we can | 2756 | * When the server supports very large writes via POSIX extensions, we can |
| 2750 | * allow up to 2^24 - PAGE_CACHE_SIZE. | 2757 | * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including |
| 2758 | * the RFC1001 length. | ||
| 2751 | * | 2759 | * |
| 2752 | * Note that this might make for "interesting" allocation problems during | 2760 | * Note that this might make for "interesting" allocation problems during |
| 2753 | * writeback however (as we have to allocate an array of pointers for the | 2761 | * writeback however as we have to allocate an array of pointers for the |
| 2754 | * pages). A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096. | 2762 | * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096. |
| 2755 | */ | 2763 | */ |
| 2756 | #define CIFS_MAX_WSIZE ((1<<24) - PAGE_CACHE_SIZE) | 2764 | #define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4) |
| 2757 | 2765 | ||
| 2758 | /* | 2766 | /* |
| 2759 | * When the server doesn't allow large posix writes, default to a wsize of | 2767 | * When the server doesn't allow large posix writes, only allow a wsize of |
| 2760 | * 128k - PAGE_CACHE_SIZE -- one page less than the largest frame size | 2768 | * 128k minus the size of the WRITE_AND_X header. That allows for a write up |
| 2761 | * described in RFC1001. This allows space for the header without going over | 2769 | * to the maximum size described by RFC1002. |
| 2762 | * that by default. | ||
| 2763 | */ | 2770 | */ |
| 2764 | #define CIFS_MAX_RFC1001_WSIZE (128 * 1024 - PAGE_CACHE_SIZE) | 2771 | #define CIFS_MAX_RFC1002_WSIZE (128 * 1024 - sizeof(WRITE_REQ) + 4) |
| 2765 | 2772 | ||
| 2766 | /* | 2773 | /* |
| 2767 | * The default wsize is 1M. find_get_pages seems to return a maximum of 256 | 2774 | * The default wsize is 1M. find_get_pages seems to return a maximum of 256 |
| @@ -2780,11 +2787,18 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) | |||
| 2780 | 2787 | ||
| 2781 | /* can server support 24-bit write sizes? (via UNIX extensions) */ | 2788 | /* can server support 24-bit write sizes? (via UNIX extensions) */ |
| 2782 | if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) | 2789 | if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) |
| 2783 | wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1001_WSIZE); | 2790 | wsize = min_t(unsigned int, wsize, CIFS_MAX_RFC1002_WSIZE); |
| 2784 | 2791 | ||
| 2785 | /* no CAP_LARGE_WRITE_X? Limit it to 16 bits */ | 2792 | /* |
| 2786 | if (!(server->capabilities & CAP_LARGE_WRITE_X)) | 2793 | * no CAP_LARGE_WRITE_X or is signing enabled without CAP_UNIX set? |
| 2787 | wsize = min_t(unsigned int, wsize, USHRT_MAX); | 2794 | * Limit it to max buffer offered by the server, minus the size of the |
| 2795 | * WRITEX header, not including the 4 byte RFC1001 length. | ||
| 2796 | */ | ||
| 2797 | if (!(server->capabilities & CAP_LARGE_WRITE_X) || | ||
| 2798 | (!(server->capabilities & CAP_UNIX) && | ||
| 2799 | (server->sec_mode & (SECMODE_SIGN_ENABLED|SECMODE_SIGN_REQUIRED)))) | ||
| 2800 | wsize = min_t(unsigned int, wsize, | ||
| 2801 | server->maxBuf - sizeof(WRITE_REQ) + 4); | ||
| 2788 | 2802 | ||
| 2789 | /* hard limit of CIFS_MAX_WSIZE */ | 2803 | /* hard limit of CIFS_MAX_WSIZE */ |
| 2790 | wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); | 2804 | wsize = min_t(unsigned int, wsize, CIFS_MAX_WSIZE); |
| @@ -2934,7 +2948,11 @@ int cifs_setup_volume_info(struct smb_vol **pvolume_info, char *mount_data, | |||
| 2934 | 2948 | ||
| 2935 | if (volume_info->nullauth) { | 2949 | if (volume_info->nullauth) { |
| 2936 | cFYI(1, "null user"); | 2950 | cFYI(1, "null user"); |
| 2937 | volume_info->username = ""; | 2951 | volume_info->username = kzalloc(1, GFP_KERNEL); |
| 2952 | if (volume_info->username == NULL) { | ||
| 2953 | rc = -ENOMEM; | ||
| 2954 | goto out; | ||
| 2955 | } | ||
| 2938 | } else if (volume_info->username) { | 2956 | } else if (volume_info->username) { |
| 2939 | /* BB fixme parse for domain name here */ | 2957 | /* BB fixme parse for domain name here */ |
| 2940 | cFYI(1, "Username: %s", volume_info->username); | 2958 | cFYI(1, "Username: %s", volume_info->username); |
| @@ -2968,8 +2986,7 @@ out: | |||
| 2968 | } | 2986 | } |
| 2969 | 2987 | ||
| 2970 | int | 2988 | int |
| 2971 | cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | 2989 | cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) |
| 2972 | struct smb_vol *volume_info, const char *devname) | ||
| 2973 | { | 2990 | { |
| 2974 | int rc = 0; | 2991 | int rc = 0; |
| 2975 | int xid; | 2992 | int xid; |
| @@ -2980,6 +2997,13 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, | |||
| 2980 | struct tcon_link *tlink; | 2997 | struct tcon_link *tlink; |
| 2981 | #ifdef CONFIG_CIFS_DFS_UPCALL | 2998 | #ifdef CONFIG_CIFS_DFS_UPCALL |
| 2982 | int referral_walks_count = 0; | 2999 | int referral_walks_count = 0; |
| 3000 | |||
| 3001 | rc = bdi_setup_and_register(&cifs_sb->bdi, "cifs", BDI_CAP_MAP_COPY); | ||
| 3002 | if (rc) | ||
| 3003 | return rc; | ||
| 3004 | |||
| 3005 | cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; | ||
| 3006 | |||
| 2983 | try_mount_again: | 3007 | try_mount_again: |
| 2984 | /* cleanup activities if we're chasing a referral */ | 3008 | /* cleanup activities if we're chasing a referral */ |
| 2985 | if (referral_walks_count) { | 3009 | if (referral_walks_count) { |
| @@ -3004,6 +3028,7 @@ try_mount_again: | |||
| 3004 | srvTcp = cifs_get_tcp_session(volume_info); | 3028 | srvTcp = cifs_get_tcp_session(volume_info); |
| 3005 | if (IS_ERR(srvTcp)) { | 3029 | if (IS_ERR(srvTcp)) { |
| 3006 | rc = PTR_ERR(srvTcp); | 3030 | rc = PTR_ERR(srvTcp); |
| 3031 | bdi_destroy(&cifs_sb->bdi); | ||
| 3007 | goto out; | 3032 | goto out; |
| 3008 | } | 3033 | } |
| 3009 | 3034 | ||
| @@ -3015,14 +3040,6 @@ try_mount_again: | |||
| 3015 | goto mount_fail_check; | 3040 | goto mount_fail_check; |
| 3016 | } | 3041 | } |
| 3017 | 3042 | ||
| 3018 | if (pSesInfo->capabilities & CAP_LARGE_FILES) | ||
| 3019 | sb->s_maxbytes = MAX_LFS_FILESIZE; | ||
| 3020 | else | ||
| 3021 | sb->s_maxbytes = MAX_NON_LFS; | ||
| 3022 | |||
| 3023 | /* BB FIXME fix time_gran to be larger for LANMAN sessions */ | ||
| 3024 | sb->s_time_gran = 100; | ||
| 3025 | |||
| 3026 | /* search for existing tcon to this server share */ | 3043 | /* search for existing tcon to this server share */ |
| 3027 | tcon = cifs_get_tcon(pSesInfo, volume_info); | 3044 | tcon = cifs_get_tcon(pSesInfo, volume_info); |
| 3028 | if (IS_ERR(tcon)) { | 3045 | if (IS_ERR(tcon)) { |
| @@ -3035,7 +3052,7 @@ try_mount_again: | |||
| 3035 | if (tcon->ses->capabilities & CAP_UNIX) { | 3052 | if (tcon->ses->capabilities & CAP_UNIX) { |
| 3036 | /* reset of caps checks mount to see if unix extensions | 3053 | /* reset of caps checks mount to see if unix extensions |
| 3037 | disabled for just this mount */ | 3054 | disabled for just this mount */ |
| 3038 | reset_cifs_unix_caps(xid, tcon, sb, volume_info); | 3055 | reset_cifs_unix_caps(xid, tcon, cifs_sb, volume_info); |
| 3039 | if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && | 3056 | if ((tcon->ses->server->tcpStatus == CifsNeedReconnect) && |
| 3040 | (le64_to_cpu(tcon->fsUnixInfo.Capability) & | 3057 | (le64_to_cpu(tcon->fsUnixInfo.Capability) & |
| 3041 | CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { | 3058 | CIFS_UNIX_TRANSPORT_ENCRYPTION_MANDATORY_CAP)) { |
| @@ -3158,6 +3175,7 @@ mount_fail_check: | |||
| 3158 | cifs_put_smb_ses(pSesInfo); | 3175 | cifs_put_smb_ses(pSesInfo); |
| 3159 | else | 3176 | else |
| 3160 | cifs_put_tcp_session(srvTcp); | 3177 | cifs_put_tcp_session(srvTcp); |
| 3178 | bdi_destroy(&cifs_sb->bdi); | ||
| 3161 | goto out; | 3179 | goto out; |
| 3162 | } | 3180 | } |
| 3163 | 3181 | ||
| @@ -3171,6 +3189,10 @@ out: | |||
| 3171 | return rc; | 3189 | return rc; |
| 3172 | } | 3190 | } |
| 3173 | 3191 | ||
| 3192 | /* | ||
| 3193 | * Issue a TREE_CONNECT request. Note that for IPC$ shares, that the tcon | ||
| 3194 | * pointer may be NULL. | ||
| 3195 | */ | ||
| 3174 | int | 3196 | int |
| 3175 | CIFSTCon(unsigned int xid, struct cifs_ses *ses, | 3197 | CIFSTCon(unsigned int xid, struct cifs_ses *ses, |
| 3176 | const char *tree, struct cifs_tcon *tcon, | 3198 | const char *tree, struct cifs_tcon *tcon, |
| @@ -3205,7 +3227,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, | |||
| 3205 | pSMB->AndXCommand = 0xFF; | 3227 | pSMB->AndXCommand = 0xFF; |
| 3206 | pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); | 3228 | pSMB->Flags = cpu_to_le16(TCON_EXTENDED_SECINFO); |
| 3207 | bcc_ptr = &pSMB->Password[0]; | 3229 | bcc_ptr = &pSMB->Password[0]; |
| 3208 | if ((ses->server->sec_mode) & SECMODE_USER) { | 3230 | if (!tcon || (ses->server->sec_mode & SECMODE_USER)) { |
| 3209 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ | 3231 | pSMB->PasswordLength = cpu_to_le16(1); /* minimum */ |
| 3210 | *bcc_ptr = 0; /* password is null byte */ | 3232 | *bcc_ptr = 0; /* password is null byte */ |
| 3211 | bcc_ptr++; /* skip password */ | 3233 | bcc_ptr++; /* skip password */ |
| @@ -3328,8 +3350,8 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, | |||
| 3328 | return rc; | 3350 | return rc; |
| 3329 | } | 3351 | } |
| 3330 | 3352 | ||
| 3331 | int | 3353 | void |
| 3332 | cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | 3354 | cifs_umount(struct cifs_sb_info *cifs_sb) |
| 3333 | { | 3355 | { |
| 3334 | struct rb_root *root = &cifs_sb->tlink_tree; | 3356 | struct rb_root *root = &cifs_sb->tlink_tree; |
| 3335 | struct rb_node *node; | 3357 | struct rb_node *node; |
| @@ -3350,7 +3372,10 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) | |||
| 3350 | } | 3372 | } |
| 3351 | spin_unlock(&cifs_sb->tlink_tree_lock); | 3373 | spin_unlock(&cifs_sb->tlink_tree_lock); |
| 3352 | 3374 | ||
| 3353 | return 0; | 3375 | bdi_destroy(&cifs_sb->bdi); |
| 3376 | kfree(cifs_sb->mountdata); | ||
| 3377 | unload_nls(cifs_sb->local_nls); | ||
| 3378 | kfree(cifs_sb); | ||
| 3354 | } | 3379 | } |
| 3355 | 3380 | ||
| 3356 | int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) | 3381 | int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) |
| @@ -3371,7 +3396,7 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) | |||
| 3371 | } | 3396 | } |
| 3372 | if (rc == 0) { | 3397 | if (rc == 0) { |
| 3373 | spin_lock(&GlobalMid_Lock); | 3398 | spin_lock(&GlobalMid_Lock); |
| 3374 | if (server->tcpStatus != CifsExiting) | 3399 | if (server->tcpStatus == CifsNeedNegotiate) |
| 3375 | server->tcpStatus = CifsGood; | 3400 | server->tcpStatus = CifsGood; |
| 3376 | else | 3401 | else |
| 3377 | rc = -EHOSTDOWN; | 3402 | rc = -EHOSTDOWN; |
| @@ -3484,12 +3509,6 @@ out: | |||
| 3484 | return tcon; | 3509 | return tcon; |
| 3485 | } | 3510 | } |
| 3486 | 3511 | ||
| 3487 | static inline struct tcon_link * | ||
| 3488 | cifs_sb_master_tlink(struct cifs_sb_info *cifs_sb) | ||
| 3489 | { | ||
| 3490 | return cifs_sb->master_tlink; | ||
| 3491 | } | ||
| 3492 | |||
| 3493 | struct cifs_tcon * | 3512 | struct cifs_tcon * |
| 3494 | cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) | 3513 | cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb) |
| 3495 | { | 3514 | { |
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index d368a47ba5eb..816696621ec9 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c | |||
| @@ -28,14 +28,14 @@ void cifs_fscache_get_client_cookie(struct TCP_Server_Info *server) | |||
| 28 | server->fscache = | 28 | server->fscache = |
| 29 | fscache_acquire_cookie(cifs_fscache_netfs.primary_index, | 29 | fscache_acquire_cookie(cifs_fscache_netfs.primary_index, |
| 30 | &cifs_fscache_server_index_def, server); | 30 | &cifs_fscache_server_index_def, server); |
| 31 | cFYI(1, "CIFS: get client cookie (0x%p/0x%p)", server, | 31 | cFYI(1, "%s: (0x%p/0x%p)", __func__, server, |
| 32 | server->fscache); | 32 | server->fscache); |
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) | 35 | void cifs_fscache_release_client_cookie(struct TCP_Server_Info *server) |
| 36 | { | 36 | { |
| 37 | cFYI(1, "CIFS: release client cookie (0x%p/0x%p)", server, | 37 | cFYI(1, "%s: (0x%p/0x%p)", __func__, server, |
| 38 | server->fscache); | 38 | server->fscache); |
| 39 | fscache_relinquish_cookie(server->fscache, 0); | 39 | fscache_relinquish_cookie(server->fscache, 0); |
| 40 | server->fscache = NULL; | 40 | server->fscache = NULL; |
| 41 | } | 41 | } |
| @@ -47,13 +47,13 @@ void cifs_fscache_get_super_cookie(struct cifs_tcon *tcon) | |||
| 47 | tcon->fscache = | 47 | tcon->fscache = |
| 48 | fscache_acquire_cookie(server->fscache, | 48 | fscache_acquire_cookie(server->fscache, |
| 49 | &cifs_fscache_super_index_def, tcon); | 49 | &cifs_fscache_super_index_def, tcon); |
| 50 | cFYI(1, "CIFS: get superblock cookie (0x%p/0x%p)", | 50 | cFYI(1, "%s: (0x%p/0x%p)", __func__, server->fscache, |
| 51 | server->fscache, tcon->fscache); | 51 | tcon->fscache); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| 54 | void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) | 54 | void cifs_fscache_release_super_cookie(struct cifs_tcon *tcon) |
| 55 | { | 55 | { |
| 56 | cFYI(1, "CIFS: releasing superblock cookie (0x%p)", tcon->fscache); | 56 | cFYI(1, "%s: (0x%p)", __func__, tcon->fscache); |
| 57 | fscache_relinquish_cookie(tcon->fscache, 0); | 57 | fscache_relinquish_cookie(tcon->fscache, 0); |
| 58 | tcon->fscache = NULL; | 58 | tcon->fscache = NULL; |
| 59 | } | 59 | } |
| @@ -70,8 +70,8 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode) | |||
| 70 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { | 70 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { |
| 71 | cifsi->fscache = fscache_acquire_cookie(tcon->fscache, | 71 | cifsi->fscache = fscache_acquire_cookie(tcon->fscache, |
| 72 | &cifs_fscache_inode_object_def, cifsi); | 72 | &cifs_fscache_inode_object_def, cifsi); |
| 73 | cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, | 73 | cFYI(1, "%s: got FH cookie (0x%p/0x%p)", __func__, |
| 74 | cifsi->fscache); | 74 | tcon->fscache, cifsi->fscache); |
| 75 | } | 75 | } |
| 76 | } | 76 | } |
| 77 | 77 | ||
| @@ -80,8 +80,7 @@ void cifs_fscache_release_inode_cookie(struct inode *inode) | |||
| 80 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 80 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
| 81 | 81 | ||
| 82 | if (cifsi->fscache) { | 82 | if (cifsi->fscache) { |
| 83 | cFYI(1, "CIFS releasing inode cookie (0x%p)", | 83 | cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); |
| 84 | cifsi->fscache); | ||
| 85 | fscache_relinquish_cookie(cifsi->fscache, 0); | 84 | fscache_relinquish_cookie(cifsi->fscache, 0); |
| 86 | cifsi->fscache = NULL; | 85 | cifsi->fscache = NULL; |
| 87 | } | 86 | } |
| @@ -92,8 +91,7 @@ static void cifs_fscache_disable_inode_cookie(struct inode *inode) | |||
| 92 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 91 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
| 93 | 92 | ||
| 94 | if (cifsi->fscache) { | 93 | if (cifsi->fscache) { |
| 95 | cFYI(1, "CIFS disabling inode cookie (0x%p)", | 94 | cFYI(1, "%s: (0x%p)", __func__, cifsi->fscache); |
| 96 | cifsi->fscache); | ||
| 97 | fscache_relinquish_cookie(cifsi->fscache, 1); | 95 | fscache_relinquish_cookie(cifsi->fscache, 1); |
| 98 | cifsi->fscache = NULL; | 96 | cifsi->fscache = NULL; |
| 99 | } | 97 | } |
| @@ -121,8 +119,8 @@ void cifs_fscache_reset_inode_cookie(struct inode *inode) | |||
| 121 | cifs_sb_master_tcon(cifs_sb)->fscache, | 119 | cifs_sb_master_tcon(cifs_sb)->fscache, |
| 122 | &cifs_fscache_inode_object_def, | 120 | &cifs_fscache_inode_object_def, |
| 123 | cifsi); | 121 | cifsi); |
| 124 | cFYI(1, "CIFS: new cookie 0x%p oldcookie 0x%p", | 122 | cFYI(1, "%s: new cookie 0x%p oldcookie 0x%p", |
| 125 | cifsi->fscache, old); | 123 | __func__, cifsi->fscache, old); |
| 126 | } | 124 | } |
| 127 | } | 125 | } |
| 128 | 126 | ||
| @@ -132,8 +130,8 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp) | |||
| 132 | struct inode *inode = page->mapping->host; | 130 | struct inode *inode = page->mapping->host; |
| 133 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 131 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
| 134 | 132 | ||
| 135 | cFYI(1, "CIFS: fscache release page (0x%p/0x%p)", | 133 | cFYI(1, "%s: (0x%p/0x%p)", __func__, page, |
| 136 | page, cifsi->fscache); | 134 | cifsi->fscache); |
| 137 | if (!fscache_maybe_release_page(cifsi->fscache, page, gfp)) | 135 | if (!fscache_maybe_release_page(cifsi->fscache, page, gfp)) |
| 138 | return 0; | 136 | return 0; |
| 139 | } | 137 | } |
| @@ -144,8 +142,7 @@ int cifs_fscache_release_page(struct page *page, gfp_t gfp) | |||
| 144 | static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx, | 142 | static void cifs_readpage_from_fscache_complete(struct page *page, void *ctx, |
| 145 | int error) | 143 | int error) |
| 146 | { | 144 | { |
| 147 | cFYI(1, "CFS: readpage_from_fscache_complete (0x%p/%d)", | 145 | cFYI(1, "%s: (0x%p/%d)", __func__, page, error); |
| 148 | page, error); | ||
| 149 | if (!error) | 146 | if (!error) |
| 150 | SetPageUptodate(page); | 147 | SetPageUptodate(page); |
| 151 | unlock_page(page); | 148 | unlock_page(page); |
| @@ -158,7 +155,7 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) | |||
| 158 | { | 155 | { |
| 159 | int ret; | 156 | int ret; |
| 160 | 157 | ||
| 161 | cFYI(1, "CIFS: readpage_from_fscache(fsc:%p, p:%p, i:0x%p", | 158 | cFYI(1, "%s: (fsc:%p, p:%p, i:0x%p", __func__, |
| 162 | CIFS_I(inode)->fscache, page, inode); | 159 | CIFS_I(inode)->fscache, page, inode); |
| 163 | ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page, | 160 | ret = fscache_read_or_alloc_page(CIFS_I(inode)->fscache, page, |
| 164 | cifs_readpage_from_fscache_complete, | 161 | cifs_readpage_from_fscache_complete, |
| @@ -167,11 +164,11 @@ int __cifs_readpage_from_fscache(struct inode *inode, struct page *page) | |||
| 167 | switch (ret) { | 164 | switch (ret) { |
| 168 | 165 | ||
| 169 | case 0: /* page found in fscache, read submitted */ | 166 | case 0: /* page found in fscache, read submitted */ |
| 170 | cFYI(1, "CIFS: readpage_from_fscache: submitted"); | 167 | cFYI(1, "%s: submitted", __func__); |
| 171 | return ret; | 168 | return ret; |
| 172 | case -ENOBUFS: /* page won't be cached */ | 169 | case -ENOBUFS: /* page won't be cached */ |
| 173 | case -ENODATA: /* page not in cache */ | 170 | case -ENODATA: /* page not in cache */ |
| 174 | cFYI(1, "CIFS: readpage_from_fscache %d", ret); | 171 | cFYI(1, "%s: %d", __func__, ret); |
| 175 | return 1; | 172 | return 1; |
| 176 | 173 | ||
| 177 | default: | 174 | default: |
| @@ -190,7 +187,7 @@ int __cifs_readpages_from_fscache(struct inode *inode, | |||
| 190 | { | 187 | { |
| 191 | int ret; | 188 | int ret; |
| 192 | 189 | ||
| 193 | cFYI(1, "CIFS: __cifs_readpages_from_fscache (0x%p/%u/0x%p)", | 190 | cFYI(1, "%s: (0x%p/%u/0x%p)", __func__, |
| 194 | CIFS_I(inode)->fscache, *nr_pages, inode); | 191 | CIFS_I(inode)->fscache, *nr_pages, inode); |
| 195 | ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping, | 192 | ret = fscache_read_or_alloc_pages(CIFS_I(inode)->fscache, mapping, |
| 196 | pages, nr_pages, | 193 | pages, nr_pages, |
| @@ -199,12 +196,12 @@ int __cifs_readpages_from_fscache(struct inode *inode, | |||
| 199 | mapping_gfp_mask(mapping)); | 196 | mapping_gfp_mask(mapping)); |
| 200 | switch (ret) { | 197 | switch (ret) { |
| 201 | case 0: /* read submitted to the cache for all pages */ | 198 | case 0: /* read submitted to the cache for all pages */ |
| 202 | cFYI(1, "CIFS: readpages_from_fscache: submitted"); | 199 | cFYI(1, "%s: submitted", __func__); |
| 203 | return ret; | 200 | return ret; |
| 204 | 201 | ||
| 205 | case -ENOBUFS: /* some pages are not cached and can't be */ | 202 | case -ENOBUFS: /* some pages are not cached and can't be */ |
| 206 | case -ENODATA: /* some pages are not cached */ | 203 | case -ENODATA: /* some pages are not cached */ |
| 207 | cFYI(1, "CIFS: readpages_from_fscache: no page"); | 204 | cFYI(1, "%s: no page", __func__); |
| 208 | return 1; | 205 | return 1; |
| 209 | 206 | ||
| 210 | default: | 207 | default: |
| @@ -218,7 +215,7 @@ void __cifs_readpage_to_fscache(struct inode *inode, struct page *page) | |||
| 218 | { | 215 | { |
| 219 | int ret; | 216 | int ret; |
| 220 | 217 | ||
| 221 | cFYI(1, "CIFS: readpage_to_fscache(fsc: %p, p: %p, i: %p", | 218 | cFYI(1, "%s: (fsc: %p, p: %p, i: %p)", __func__, |
| 222 | CIFS_I(inode)->fscache, page, inode); | 219 | CIFS_I(inode)->fscache, page, inode); |
| 223 | ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL); | 220 | ret = fscache_write_page(CIFS_I(inode)->fscache, page, GFP_KERNEL); |
| 224 | if (ret != 0) | 221 | if (ret != 0) |
| @@ -230,7 +227,7 @@ void __cifs_fscache_invalidate_page(struct page *page, struct inode *inode) | |||
| 230 | struct cifsInodeInfo *cifsi = CIFS_I(inode); | 227 | struct cifsInodeInfo *cifsi = CIFS_I(inode); |
| 231 | struct fscache_cookie *cookie = cifsi->fscache; | 228 | struct fscache_cookie *cookie = cifsi->fscache; |
| 232 | 229 | ||
| 233 | cFYI(1, "CIFS: fscache invalidatepage (0x%p/0x%p)", page, cookie); | 230 | cFYI(1, "%s: (0x%p/0x%p)", __func__, page, cookie); |
| 234 | fscache_wait_on_page_write(cookie, page); | 231 | fscache_wait_on_page_write(cookie, page); |
| 235 | fscache_uncache_page(cookie, page); | 232 | fscache_uncache_page(cookie, page); |
| 236 | } | 233 | } |
diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index 1525d5e662b6..1c5b770c3141 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c | |||
| @@ -90,12 +90,10 @@ smbhash(unsigned char *out, const unsigned char *in, unsigned char *key) | |||
| 90 | sg_init_one(&sgout, out, 8); | 90 | sg_init_one(&sgout, out, 8); |
| 91 | 91 | ||
| 92 | rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8); | 92 | rc = crypto_blkcipher_encrypt(&desc, &sgout, &sgin, 8); |
| 93 | if (rc) { | 93 | if (rc) |
| 94 | cERROR(1, "could not encrypt crypt key rc: %d\n", rc); | 94 | cERROR(1, "could not encrypt crypt key rc: %d\n", rc); |
| 95 | crypto_free_blkcipher(tfm_des); | ||
| 96 | goto smbhash_err; | ||
| 97 | } | ||
| 98 | 95 | ||
| 96 | crypto_free_blkcipher(tfm_des); | ||
| 99 | smbhash_err: | 97 | smbhash_err: |
| 100 | return rc; | 98 | return rc; |
| 101 | } | 99 | } |
diff --git a/fs/coda/pioctl.c b/fs/coda/pioctl.c index 6cbb3afb36dc..cb140ef293e4 100644 --- a/fs/coda/pioctl.c +++ b/fs/coda/pioctl.c | |||
| @@ -43,8 +43,6 @@ const struct file_operations coda_ioctl_operations = { | |||
| 43 | /* the coda pioctl inode ops */ | 43 | /* the coda pioctl inode ops */ |
| 44 | static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags) | 44 | static int coda_ioctl_permission(struct inode *inode, int mask, unsigned int flags) |
| 45 | { | 45 | { |
| 46 | if (flags & IPERM_FLAG_RCU) | ||
| 47 | return -ECHILD; | ||
| 48 | return (mask & MAY_EXEC) ? -EACCES : 0; | 46 | return (mask & MAY_EXEC) ? -EACCES : 0; |
| 49 | } | 47 | } |
| 50 | 48 | ||
| @@ -1996,7 +1996,7 @@ static void wait_for_dump_helpers(struct file *file) | |||
| 1996 | * is a special value that we use to trap recursive | 1996 | * is a special value that we use to trap recursive |
| 1997 | * core dumps | 1997 | * core dumps |
| 1998 | */ | 1998 | */ |
| 1999 | static int umh_pipe_setup(struct subprocess_info *info) | 1999 | static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) |
| 2000 | { | 2000 | { |
| 2001 | struct file *rp, *wp; | 2001 | struct file *rp, *wp; |
| 2002 | struct fdtable *fdt; | 2002 | struct fdtable *fdt; |
diff --git a/fs/ext4/ext4_extents.h b/fs/ext4/ext4_extents.h index 2e29abb30f76..095c36f3b612 100644 --- a/fs/ext4/ext4_extents.h +++ b/fs/ext4/ext4_extents.h | |||
| @@ -125,7 +125,7 @@ struct ext4_ext_path { | |||
| 125 | * positive retcode - signal for ext4_ext_walk_space(), see below | 125 | * positive retcode - signal for ext4_ext_walk_space(), see below |
| 126 | * callback must return valid extent (passed or newly created) | 126 | * callback must return valid extent (passed or newly created) |
| 127 | */ | 127 | */ |
| 128 | typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *, | 128 | typedef int (*ext_prepare_callback)(struct inode *, ext4_lblk_t, |
| 129 | struct ext4_ext_cache *, | 129 | struct ext4_ext_cache *, |
| 130 | struct ext4_extent *, void *); | 130 | struct ext4_extent *, void *); |
| 131 | 131 | ||
| @@ -133,8 +133,11 @@ typedef int (*ext_prepare_callback)(struct inode *, struct ext4_ext_path *, | |||
| 133 | #define EXT_BREAK 1 | 133 | #define EXT_BREAK 1 |
| 134 | #define EXT_REPEAT 2 | 134 | #define EXT_REPEAT 2 |
| 135 | 135 | ||
| 136 | /* Maximum logical block in a file; ext4_extent's ee_block is __le32 */ | 136 | /* |
| 137 | #define EXT_MAX_BLOCK 0xffffffff | 137 | * Maximum number of logical blocks in a file; ext4_extent's ee_block is |
| 138 | * __le32. | ||
| 139 | */ | ||
| 140 | #define EXT_MAX_BLOCKS 0xffffffff | ||
| 138 | 141 | ||
| 139 | /* | 142 | /* |
| 140 | * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an | 143 | * EXT_INIT_MAX_LEN is the maximum number of blocks we can have in an |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 5199bac7fc62..f815cc81e7a2 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -1408,7 +1408,7 @@ got_index: | |||
| 1408 | 1408 | ||
| 1409 | /* | 1409 | /* |
| 1410 | * ext4_ext_next_allocated_block: | 1410 | * ext4_ext_next_allocated_block: |
| 1411 | * returns allocated block in subsequent extent or EXT_MAX_BLOCK. | 1411 | * returns allocated block in subsequent extent or EXT_MAX_BLOCKS. |
| 1412 | * NOTE: it considers block number from index entry as | 1412 | * NOTE: it considers block number from index entry as |
| 1413 | * allocated block. Thus, index entries have to be consistent | 1413 | * allocated block. Thus, index entries have to be consistent |
| 1414 | * with leaves. | 1414 | * with leaves. |
| @@ -1422,7 +1422,7 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path) | |||
| 1422 | depth = path->p_depth; | 1422 | depth = path->p_depth; |
| 1423 | 1423 | ||
| 1424 | if (depth == 0 && path->p_ext == NULL) | 1424 | if (depth == 0 && path->p_ext == NULL) |
| 1425 | return EXT_MAX_BLOCK; | 1425 | return EXT_MAX_BLOCKS; |
| 1426 | 1426 | ||
| 1427 | while (depth >= 0) { | 1427 | while (depth >= 0) { |
| 1428 | if (depth == path->p_depth) { | 1428 | if (depth == path->p_depth) { |
| @@ -1439,12 +1439,12 @@ ext4_ext_next_allocated_block(struct ext4_ext_path *path) | |||
| 1439 | depth--; | 1439 | depth--; |
| 1440 | } | 1440 | } |
| 1441 | 1441 | ||
| 1442 | return EXT_MAX_BLOCK; | 1442 | return EXT_MAX_BLOCKS; |
| 1443 | } | 1443 | } |
| 1444 | 1444 | ||
| 1445 | /* | 1445 | /* |
| 1446 | * ext4_ext_next_leaf_block: | 1446 | * ext4_ext_next_leaf_block: |
| 1447 | * returns first allocated block from next leaf or EXT_MAX_BLOCK | 1447 | * returns first allocated block from next leaf or EXT_MAX_BLOCKS |
| 1448 | */ | 1448 | */ |
| 1449 | static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, | 1449 | static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, |
| 1450 | struct ext4_ext_path *path) | 1450 | struct ext4_ext_path *path) |
| @@ -1456,7 +1456,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, | |||
| 1456 | 1456 | ||
| 1457 | /* zero-tree has no leaf blocks at all */ | 1457 | /* zero-tree has no leaf blocks at all */ |
| 1458 | if (depth == 0) | 1458 | if (depth == 0) |
| 1459 | return EXT_MAX_BLOCK; | 1459 | return EXT_MAX_BLOCKS; |
| 1460 | 1460 | ||
| 1461 | /* go to index block */ | 1461 | /* go to index block */ |
| 1462 | depth--; | 1462 | depth--; |
| @@ -1469,7 +1469,7 @@ static ext4_lblk_t ext4_ext_next_leaf_block(struct inode *inode, | |||
| 1469 | depth--; | 1469 | depth--; |
| 1470 | } | 1470 | } |
| 1471 | 1471 | ||
| 1472 | return EXT_MAX_BLOCK; | 1472 | return EXT_MAX_BLOCKS; |
| 1473 | } | 1473 | } |
| 1474 | 1474 | ||
| 1475 | /* | 1475 | /* |
| @@ -1677,13 +1677,13 @@ static unsigned int ext4_ext_check_overlap(struct inode *inode, | |||
| 1677 | */ | 1677 | */ |
| 1678 | if (b2 < b1) { | 1678 | if (b2 < b1) { |
| 1679 | b2 = ext4_ext_next_allocated_block(path); | 1679 | b2 = ext4_ext_next_allocated_block(path); |
| 1680 | if (b2 == EXT_MAX_BLOCK) | 1680 | if (b2 == EXT_MAX_BLOCKS) |
| 1681 | goto out; | 1681 | goto out; |
| 1682 | } | 1682 | } |
| 1683 | 1683 | ||
| 1684 | /* check for wrap through zero on extent logical start block*/ | 1684 | /* check for wrap through zero on extent logical start block*/ |
| 1685 | if (b1 + len1 < b1) { | 1685 | if (b1 + len1 < b1) { |
| 1686 | len1 = EXT_MAX_BLOCK - b1; | 1686 | len1 = EXT_MAX_BLOCKS - b1; |
| 1687 | newext->ee_len = cpu_to_le16(len1); | 1687 | newext->ee_len = cpu_to_le16(len1); |
| 1688 | ret = 1; | 1688 | ret = 1; |
| 1689 | } | 1689 | } |
| @@ -1767,7 +1767,7 @@ repeat: | |||
| 1767 | fex = EXT_LAST_EXTENT(eh); | 1767 | fex = EXT_LAST_EXTENT(eh); |
| 1768 | next = ext4_ext_next_leaf_block(inode, path); | 1768 | next = ext4_ext_next_leaf_block(inode, path); |
| 1769 | if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block) | 1769 | if (le32_to_cpu(newext->ee_block) > le32_to_cpu(fex->ee_block) |
| 1770 | && next != EXT_MAX_BLOCK) { | 1770 | && next != EXT_MAX_BLOCKS) { |
| 1771 | ext_debug("next leaf block - %d\n", next); | 1771 | ext_debug("next leaf block - %d\n", next); |
| 1772 | BUG_ON(npath != NULL); | 1772 | BUG_ON(npath != NULL); |
| 1773 | npath = ext4_ext_find_extent(inode, next, NULL); | 1773 | npath = ext4_ext_find_extent(inode, next, NULL); |
| @@ -1887,7 +1887,7 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block, | |||
| 1887 | BUG_ON(func == NULL); | 1887 | BUG_ON(func == NULL); |
| 1888 | BUG_ON(inode == NULL); | 1888 | BUG_ON(inode == NULL); |
| 1889 | 1889 | ||
| 1890 | while (block < last && block != EXT_MAX_BLOCK) { | 1890 | while (block < last && block != EXT_MAX_BLOCKS) { |
| 1891 | num = last - block; | 1891 | num = last - block; |
| 1892 | /* find extent for this block */ | 1892 | /* find extent for this block */ |
| 1893 | down_read(&EXT4_I(inode)->i_data_sem); | 1893 | down_read(&EXT4_I(inode)->i_data_sem); |
| @@ -1958,7 +1958,7 @@ static int ext4_ext_walk_space(struct inode *inode, ext4_lblk_t block, | |||
| 1958 | err = -EIO; | 1958 | err = -EIO; |
| 1959 | break; | 1959 | break; |
| 1960 | } | 1960 | } |
| 1961 | err = func(inode, path, &cbex, ex, cbdata); | 1961 | err = func(inode, next, &cbex, ex, cbdata); |
| 1962 | ext4_ext_drop_refs(path); | 1962 | ext4_ext_drop_refs(path); |
| 1963 | 1963 | ||
| 1964 | if (err < 0) | 1964 | if (err < 0) |
| @@ -2020,7 +2020,7 @@ ext4_ext_put_gap_in_cache(struct inode *inode, struct ext4_ext_path *path, | |||
| 2020 | if (ex == NULL) { | 2020 | if (ex == NULL) { |
| 2021 | /* there is no extent yet, so gap is [0;-] */ | 2021 | /* there is no extent yet, so gap is [0;-] */ |
| 2022 | lblock = 0; | 2022 | lblock = 0; |
| 2023 | len = EXT_MAX_BLOCK; | 2023 | len = EXT_MAX_BLOCKS; |
| 2024 | ext_debug("cache gap(whole file):"); | 2024 | ext_debug("cache gap(whole file):"); |
| 2025 | } else if (block < le32_to_cpu(ex->ee_block)) { | 2025 | } else if (block < le32_to_cpu(ex->ee_block)) { |
| 2026 | lblock = block; | 2026 | lblock = block; |
| @@ -2350,7 +2350,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
| 2350 | * never happen because at least one of the end points | 2350 | * never happen because at least one of the end points |
| 2351 | * needs to be on the edge of the extent. | 2351 | * needs to be on the edge of the extent. |
| 2352 | */ | 2352 | */ |
| 2353 | if (end == EXT_MAX_BLOCK) { | 2353 | if (end == EXT_MAX_BLOCKS - 1) { |
| 2354 | ext_debug(" bad truncate %u:%u\n", | 2354 | ext_debug(" bad truncate %u:%u\n", |
| 2355 | start, end); | 2355 | start, end); |
| 2356 | block = 0; | 2356 | block = 0; |
| @@ -2398,7 +2398,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
| 2398 | * If this is a truncate, this condition | 2398 | * If this is a truncate, this condition |
| 2399 | * should never happen | 2399 | * should never happen |
| 2400 | */ | 2400 | */ |
| 2401 | if (end == EXT_MAX_BLOCK) { | 2401 | if (end == EXT_MAX_BLOCKS - 1) { |
| 2402 | ext_debug(" bad truncate %u:%u\n", | 2402 | ext_debug(" bad truncate %u:%u\n", |
| 2403 | start, end); | 2403 | start, end); |
| 2404 | err = -EIO; | 2404 | err = -EIO; |
| @@ -2478,7 +2478,7 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode, | |||
| 2478 | * we need to remove it from the leaf | 2478 | * we need to remove it from the leaf |
| 2479 | */ | 2479 | */ |
| 2480 | if (num == 0) { | 2480 | if (num == 0) { |
| 2481 | if (end != EXT_MAX_BLOCK) { | 2481 | if (end != EXT_MAX_BLOCKS - 1) { |
| 2482 | /* | 2482 | /* |
| 2483 | * For hole punching, we need to scoot all the | 2483 | * For hole punching, we need to scoot all the |
| 2484 | * extents up when an extent is removed so that | 2484 | * extents up when an extent is removed so that |
| @@ -3699,7 +3699,7 @@ void ext4_ext_truncate(struct inode *inode) | |||
| 3699 | 3699 | ||
| 3700 | last_block = (inode->i_size + sb->s_blocksize - 1) | 3700 | last_block = (inode->i_size + sb->s_blocksize - 1) |
| 3701 | >> EXT4_BLOCK_SIZE_BITS(sb); | 3701 | >> EXT4_BLOCK_SIZE_BITS(sb); |
| 3702 | err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCK); | 3702 | err = ext4_ext_remove_space(inode, last_block, EXT_MAX_BLOCKS - 1); |
| 3703 | 3703 | ||
| 3704 | /* In a multi-transaction truncate, we only make the final | 3704 | /* In a multi-transaction truncate, we only make the final |
| 3705 | * transaction synchronous. | 3705 | * transaction synchronous. |
| @@ -3914,14 +3914,13 @@ int ext4_convert_unwritten_extents(struct inode *inode, loff_t offset, | |||
| 3914 | /* | 3914 | /* |
| 3915 | * Callback function called for each extent to gather FIEMAP information. | 3915 | * Callback function called for each extent to gather FIEMAP information. |
| 3916 | */ | 3916 | */ |
| 3917 | static int ext4_ext_fiemap_cb(struct inode *inode, struct ext4_ext_path *path, | 3917 | static int ext4_ext_fiemap_cb(struct inode *inode, ext4_lblk_t next, |
| 3918 | struct ext4_ext_cache *newex, struct ext4_extent *ex, | 3918 | struct ext4_ext_cache *newex, struct ext4_extent *ex, |
| 3919 | void *data) | 3919 | void *data) |
| 3920 | { | 3920 | { |
| 3921 | __u64 logical; | 3921 | __u64 logical; |
| 3922 | __u64 physical; | 3922 | __u64 physical; |
| 3923 | __u64 length; | 3923 | __u64 length; |
| 3924 | loff_t size; | ||
| 3925 | __u32 flags = 0; | 3924 | __u32 flags = 0; |
| 3926 | int ret = 0; | 3925 | int ret = 0; |
| 3927 | struct fiemap_extent_info *fieinfo = data; | 3926 | struct fiemap_extent_info *fieinfo = data; |
| @@ -4103,8 +4102,7 @@ found_delayed_extent: | |||
| 4103 | if (ex && ext4_ext_is_uninitialized(ex)) | 4102 | if (ex && ext4_ext_is_uninitialized(ex)) |
| 4104 | flags |= FIEMAP_EXTENT_UNWRITTEN; | 4103 | flags |= FIEMAP_EXTENT_UNWRITTEN; |
| 4105 | 4104 | ||
| 4106 | size = i_size_read(inode); | 4105 | if (next == EXT_MAX_BLOCKS) |
| 4107 | if (logical + length >= size) | ||
| 4108 | flags |= FIEMAP_EXTENT_LAST; | 4106 | flags |= FIEMAP_EXTENT_LAST; |
| 4109 | 4107 | ||
| 4110 | ret = fiemap_fill_next_extent(fieinfo, logical, physical, | 4108 | ret = fiemap_fill_next_extent(fieinfo, logical, physical, |
| @@ -4347,8 +4345,8 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 4347 | 4345 | ||
| 4348 | start_blk = start >> inode->i_sb->s_blocksize_bits; | 4346 | start_blk = start >> inode->i_sb->s_blocksize_bits; |
| 4349 | last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits; | 4347 | last_blk = (start + len - 1) >> inode->i_sb->s_blocksize_bits; |
| 4350 | if (last_blk >= EXT_MAX_BLOCK) | 4348 | if (last_blk >= EXT_MAX_BLOCKS) |
| 4351 | last_blk = EXT_MAX_BLOCK-1; | 4349 | last_blk = EXT_MAX_BLOCKS-1; |
| 4352 | len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1; | 4350 | len_blks = ((ext4_lblk_t) last_blk) - start_blk + 1; |
| 4353 | 4351 | ||
| 4354 | /* | 4352 | /* |
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index a5763e3505ba..e3126c051006 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
| @@ -2634,7 +2634,7 @@ static int ext4_writepage(struct page *page, | |||
| 2634 | struct buffer_head *page_bufs = NULL; | 2634 | struct buffer_head *page_bufs = NULL; |
| 2635 | struct inode *inode = page->mapping->host; | 2635 | struct inode *inode = page->mapping->host; |
| 2636 | 2636 | ||
| 2637 | trace_ext4_writepage(inode, page); | 2637 | trace_ext4_writepage(page); |
| 2638 | size = i_size_read(inode); | 2638 | size = i_size_read(inode); |
| 2639 | if (page->index == size >> PAGE_CACHE_SHIFT) | 2639 | if (page->index == size >> PAGE_CACHE_SHIFT) |
| 2640 | len = size & ~PAGE_CACHE_MASK; | 2640 | len = size & ~PAGE_CACHE_MASK; |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 859f2ae8864e..6ed859d56850 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -3578,8 +3578,8 @@ ext4_mb_release_inode_pa(struct ext4_buddy *e4b, struct buffer_head *bitmap_bh, | |||
| 3578 | free += next - bit; | 3578 | free += next - bit; |
| 3579 | 3579 | ||
| 3580 | trace_ext4_mballoc_discard(sb, NULL, group, bit, next - bit); | 3580 | trace_ext4_mballoc_discard(sb, NULL, group, bit, next - bit); |
| 3581 | trace_ext4_mb_release_inode_pa(sb, pa->pa_inode, pa, | 3581 | trace_ext4_mb_release_inode_pa(pa, grp_blk_start + bit, |
| 3582 | grp_blk_start + bit, next - bit); | 3582 | next - bit); |
| 3583 | mb_free_blocks(pa->pa_inode, e4b, bit, next - bit); | 3583 | mb_free_blocks(pa->pa_inode, e4b, bit, next - bit); |
| 3584 | bit = next + 1; | 3584 | bit = next + 1; |
| 3585 | } | 3585 | } |
| @@ -3608,7 +3608,7 @@ ext4_mb_release_group_pa(struct ext4_buddy *e4b, | |||
| 3608 | ext4_group_t group; | 3608 | ext4_group_t group; |
| 3609 | ext4_grpblk_t bit; | 3609 | ext4_grpblk_t bit; |
| 3610 | 3610 | ||
| 3611 | trace_ext4_mb_release_group_pa(sb, pa); | 3611 | trace_ext4_mb_release_group_pa(pa); |
| 3612 | BUG_ON(pa->pa_deleted == 0); | 3612 | BUG_ON(pa->pa_deleted == 0); |
| 3613 | ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); | 3613 | ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); |
| 3614 | BUG_ON(group != e4b->bd_group && pa->pa_len != 0); | 3614 | BUG_ON(group != e4b->bd_group && pa->pa_len != 0); |
| @@ -4448,7 +4448,7 @@ ext4_mb_free_metadata(handle_t *handle, struct ext4_buddy *e4b, | |||
| 4448 | * @inode: inode | 4448 | * @inode: inode |
| 4449 | * @block: start physical block to free | 4449 | * @block: start physical block to free |
| 4450 | * @count: number of blocks to count | 4450 | * @count: number of blocks to count |
| 4451 | * @metadata: Are these metadata blocks | 4451 | * @flags: flags used by ext4_free_blocks |
| 4452 | */ | 4452 | */ |
| 4453 | void ext4_free_blocks(handle_t *handle, struct inode *inode, | 4453 | void ext4_free_blocks(handle_t *handle, struct inode *inode, |
| 4454 | struct buffer_head *bh, ext4_fsblk_t block, | 4454 | struct buffer_head *bh, ext4_fsblk_t block, |
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c index 2b8304bf3c50..f57455a1b1b2 100644 --- a/fs/ext4/move_extent.c +++ b/fs/ext4/move_extent.c | |||
| @@ -1002,12 +1002,12 @@ mext_check_arguments(struct inode *orig_inode, | |||
| 1002 | return -EINVAL; | 1002 | return -EINVAL; |
| 1003 | } | 1003 | } |
| 1004 | 1004 | ||
| 1005 | if ((orig_start > EXT_MAX_BLOCK) || | 1005 | if ((orig_start >= EXT_MAX_BLOCKS) || |
| 1006 | (donor_start > EXT_MAX_BLOCK) || | 1006 | (donor_start >= EXT_MAX_BLOCKS) || |
| 1007 | (*len > EXT_MAX_BLOCK) || | 1007 | (*len > EXT_MAX_BLOCKS) || |
| 1008 | (orig_start + *len > EXT_MAX_BLOCK)) { | 1008 | (orig_start + *len >= EXT_MAX_BLOCKS)) { |
| 1009 | ext4_debug("ext4 move extent: Can't handle over [%u] blocks " | 1009 | ext4_debug("ext4 move extent: Can't handle over [%u] blocks " |
| 1010 | "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCK, | 1010 | "[ino:orig %lu, donor %lu]\n", EXT_MAX_BLOCKS, |
| 1011 | orig_inode->i_ino, donor_inode->i_ino); | 1011 | orig_inode->i_ino, donor_inode->i_ino); |
| 1012 | return -EINVAL; | 1012 | return -EINVAL; |
| 1013 | } | 1013 | } |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index cc5c157aa11d..9ea71aa864b3 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -2243,6 +2243,12 @@ static void ext4_orphan_cleanup(struct super_block *sb, | |||
| 2243 | * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, | 2243 | * in the vfs. ext4 inode has 48 bits of i_block in fsblock units, |
| 2244 | * so that won't be a limiting factor. | 2244 | * so that won't be a limiting factor. |
| 2245 | * | 2245 | * |
| 2246 | * However there is other limiting factor. We do store extents in the form | ||
| 2247 | * of starting block and length, hence the resulting length of the extent | ||
| 2248 | * covering maximum file size must fit into on-disk format containers as | ||
| 2249 | * well. Given that length is always by 1 unit bigger than max unit (because | ||
| 2250 | * we count 0 as well) we have to lower the s_maxbytes by one fs block. | ||
| 2251 | * | ||
| 2246 | * Note, this does *not* consider any metadata overhead for vfs i_blocks. | 2252 | * Note, this does *not* consider any metadata overhead for vfs i_blocks. |
| 2247 | */ | 2253 | */ |
| 2248 | static loff_t ext4_max_size(int blkbits, int has_huge_files) | 2254 | static loff_t ext4_max_size(int blkbits, int has_huge_files) |
| @@ -2264,10 +2270,13 @@ static loff_t ext4_max_size(int blkbits, int has_huge_files) | |||
| 2264 | upper_limit <<= blkbits; | 2270 | upper_limit <<= blkbits; |
| 2265 | } | 2271 | } |
| 2266 | 2272 | ||
| 2267 | /* 32-bit extent-start container, ee_block */ | 2273 | /* |
| 2268 | res = 1LL << 32; | 2274 | * 32-bit extent-start container, ee_block. We lower the maxbytes |
| 2275 | * by one fs block, so ee_len can cover the extent of maximum file | ||
| 2276 | * size | ||
| 2277 | */ | ||
| 2278 | res = (1LL << 32) - 1; | ||
| 2269 | res <<= blkbits; | 2279 | res <<= blkbits; |
| 2270 | res -= 1; | ||
| 2271 | 2280 | ||
| 2272 | /* Sanity check against vm- & vfs- imposed limits */ | 2281 | /* Sanity check against vm- & vfs- imposed limits */ |
| 2273 | if (res > upper_limit) | 2282 | if (res > upper_limit) |
diff --git a/fs/inode.c b/fs/inode.c index 0f7e88a7803f..43566d17d1b8 100644 --- a/fs/inode.c +++ b/fs/inode.c | |||
| @@ -423,7 +423,14 @@ EXPORT_SYMBOL(remove_inode_hash); | |||
| 423 | void end_writeback(struct inode *inode) | 423 | void end_writeback(struct inode *inode) |
| 424 | { | 424 | { |
| 425 | might_sleep(); | 425 | might_sleep(); |
| 426 | /* | ||
| 427 | * We have to cycle tree_lock here because reclaim can be still in the | ||
| 428 | * process of removing the last page (in __delete_from_page_cache()) | ||
| 429 | * and we must not free mapping under it. | ||
| 430 | */ | ||
| 431 | spin_lock_irq(&inode->i_data.tree_lock); | ||
| 426 | BUG_ON(inode->i_data.nrpages); | 432 | BUG_ON(inode->i_data.nrpages); |
| 433 | spin_unlock_irq(&inode->i_data.tree_lock); | ||
| 427 | BUG_ON(!list_empty(&inode->i_data.private_list)); | 434 | BUG_ON(!list_empty(&inode->i_data.private_list)); |
| 428 | BUG_ON(!(inode->i_state & I_FREEING)); | 435 | BUG_ON(!(inode->i_state & I_FREEING)); |
| 429 | BUG_ON(inode->i_state & I_CLEAR); | 436 | BUG_ON(inode->i_state & I_CLEAR); |
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 3db5ba4568fc..b3cc8586984e 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
| @@ -974,7 +974,7 @@ out_no_inode: | |||
| 974 | out_no_read: | 974 | out_no_read: |
| 975 | printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n", | 975 | printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n", |
| 976 | __func__, s->s_id, iso_blknum, block); | 976 | __func__, s->s_id, iso_blknum, block); |
| 977 | goto out_freesbi; | 977 | goto out_freebh; |
| 978 | out_bad_zone_size: | 978 | out_bad_zone_size: |
| 979 | printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n", | 979 | printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n", |
| 980 | sbi->s_log_zone_size); | 980 | sbi->s_log_zone_size); |
| @@ -989,6 +989,7 @@ out_unknown_format: | |||
| 989 | 989 | ||
| 990 | out_freebh: | 990 | out_freebh: |
| 991 | brelse(bh); | 991 | brelse(bh); |
| 992 | brelse(pri_bh); | ||
| 992 | out_freesbi: | 993 | out_freesbi: |
| 993 | kfree(opt.iocharset); | 994 | kfree(opt.iocharset); |
| 994 | kfree(sbi); | 995 | kfree(sbi); |
diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 6a79fd0a1a32..2c62c5aae82f 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c | |||
| @@ -97,10 +97,14 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
| 97 | 97 | ||
| 98 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && | 98 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && |
| 99 | !buffer_dirty(bh) && !buffer_write_io_error(bh)) { | 99 | !buffer_dirty(bh) && !buffer_write_io_error(bh)) { |
| 100 | /* | ||
| 101 | * Get our reference so that bh cannot be freed before | ||
| 102 | * we unlock it | ||
| 103 | */ | ||
| 104 | get_bh(bh); | ||
| 100 | JBUFFER_TRACE(jh, "remove from checkpoint list"); | 105 | JBUFFER_TRACE(jh, "remove from checkpoint list"); |
| 101 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; | 106 | ret = __jbd2_journal_remove_checkpoint(jh) + 1; |
| 102 | jbd_unlock_bh_state(bh); | 107 | jbd_unlock_bh_state(bh); |
| 103 | jbd2_journal_remove_journal_head(bh); | ||
| 104 | BUFFER_TRACE(bh, "release"); | 108 | BUFFER_TRACE(bh, "release"); |
| 105 | __brelse(bh); | 109 | __brelse(bh); |
| 106 | } else { | 110 | } else { |
| @@ -223,8 +227,8 @@ restart: | |||
| 223 | spin_lock(&journal->j_list_lock); | 227 | spin_lock(&journal->j_list_lock); |
| 224 | goto restart; | 228 | goto restart; |
| 225 | } | 229 | } |
| 230 | get_bh(bh); | ||
| 226 | if (buffer_locked(bh)) { | 231 | if (buffer_locked(bh)) { |
| 227 | atomic_inc(&bh->b_count); | ||
| 228 | spin_unlock(&journal->j_list_lock); | 232 | spin_unlock(&journal->j_list_lock); |
| 229 | jbd_unlock_bh_state(bh); | 233 | jbd_unlock_bh_state(bh); |
| 230 | wait_on_buffer(bh); | 234 | wait_on_buffer(bh); |
| @@ -243,7 +247,6 @@ restart: | |||
| 243 | */ | 247 | */ |
| 244 | released = __jbd2_journal_remove_checkpoint(jh); | 248 | released = __jbd2_journal_remove_checkpoint(jh); |
| 245 | jbd_unlock_bh_state(bh); | 249 | jbd_unlock_bh_state(bh); |
| 246 | jbd2_journal_remove_journal_head(bh); | ||
| 247 | __brelse(bh); | 250 | __brelse(bh); |
| 248 | } | 251 | } |
| 249 | 252 | ||
| @@ -284,7 +287,7 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
| 284 | int ret = 0; | 287 | int ret = 0; |
| 285 | 288 | ||
| 286 | if (buffer_locked(bh)) { | 289 | if (buffer_locked(bh)) { |
| 287 | atomic_inc(&bh->b_count); | 290 | get_bh(bh); |
| 288 | spin_unlock(&journal->j_list_lock); | 291 | spin_unlock(&journal->j_list_lock); |
| 289 | jbd_unlock_bh_state(bh); | 292 | jbd_unlock_bh_state(bh); |
| 290 | wait_on_buffer(bh); | 293 | wait_on_buffer(bh); |
| @@ -316,12 +319,12 @@ static int __process_buffer(journal_t *journal, struct journal_head *jh, | |||
| 316 | ret = 1; | 319 | ret = 1; |
| 317 | if (unlikely(buffer_write_io_error(bh))) | 320 | if (unlikely(buffer_write_io_error(bh))) |
| 318 | ret = -EIO; | 321 | ret = -EIO; |
| 322 | get_bh(bh); | ||
| 319 | J_ASSERT_JH(jh, !buffer_jbddirty(bh)); | 323 | J_ASSERT_JH(jh, !buffer_jbddirty(bh)); |
| 320 | BUFFER_TRACE(bh, "remove from checkpoint"); | 324 | BUFFER_TRACE(bh, "remove from checkpoint"); |
| 321 | __jbd2_journal_remove_checkpoint(jh); | 325 | __jbd2_journal_remove_checkpoint(jh); |
| 322 | spin_unlock(&journal->j_list_lock); | 326 | spin_unlock(&journal->j_list_lock); |
| 323 | jbd_unlock_bh_state(bh); | 327 | jbd_unlock_bh_state(bh); |
| 324 | jbd2_journal_remove_journal_head(bh); | ||
| 325 | __brelse(bh); | 328 | __brelse(bh); |
| 326 | } else { | 329 | } else { |
| 327 | /* | 330 | /* |
| @@ -554,7 +557,8 @@ int jbd2_cleanup_journal_tail(journal_t *journal) | |||
| 554 | /* | 557 | /* |
| 555 | * journal_clean_one_cp_list | 558 | * journal_clean_one_cp_list |
| 556 | * | 559 | * |
| 557 | * Find all the written-back checkpoint buffers in the given list and release them. | 560 | * Find all the written-back checkpoint buffers in the given list and |
| 561 | * release them. | ||
| 558 | * | 562 | * |
| 559 | * Called with the journal locked. | 563 | * Called with the journal locked. |
| 560 | * Called with j_list_lock held. | 564 | * Called with j_list_lock held. |
| @@ -663,8 +667,8 @@ out: | |||
| 663 | * checkpoint lists. | 667 | * checkpoint lists. |
| 664 | * | 668 | * |
| 665 | * The function returns 1 if it frees the transaction, 0 otherwise. | 669 | * The function returns 1 if it frees the transaction, 0 otherwise. |
| 670 | * The function can free jh and bh. | ||
| 666 | * | 671 | * |
| 667 | * This function is called with the journal locked. | ||
| 668 | * This function is called with j_list_lock held. | 672 | * This function is called with j_list_lock held. |
| 669 | * This function is called with jbd_lock_bh_state(jh2bh(jh)) | 673 | * This function is called with jbd_lock_bh_state(jh2bh(jh)) |
| 670 | */ | 674 | */ |
| @@ -684,13 +688,14 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) | |||
| 684 | } | 688 | } |
| 685 | journal = transaction->t_journal; | 689 | journal = transaction->t_journal; |
| 686 | 690 | ||
| 691 | JBUFFER_TRACE(jh, "removing from transaction"); | ||
| 687 | __buffer_unlink(jh); | 692 | __buffer_unlink(jh); |
| 688 | jh->b_cp_transaction = NULL; | 693 | jh->b_cp_transaction = NULL; |
| 694 | jbd2_journal_put_journal_head(jh); | ||
| 689 | 695 | ||
| 690 | if (transaction->t_checkpoint_list != NULL || | 696 | if (transaction->t_checkpoint_list != NULL || |
| 691 | transaction->t_checkpoint_io_list != NULL) | 697 | transaction->t_checkpoint_io_list != NULL) |
| 692 | goto out; | 698 | goto out; |
| 693 | JBUFFER_TRACE(jh, "transaction has no more buffers"); | ||
| 694 | 699 | ||
| 695 | /* | 700 | /* |
| 696 | * There is one special case to worry about: if we have just pulled the | 701 | * There is one special case to worry about: if we have just pulled the |
| @@ -701,10 +706,8 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) | |||
| 701 | * The locking here around t_state is a bit sleazy. | 706 | * The locking here around t_state is a bit sleazy. |
| 702 | * See the comment at the end of jbd2_journal_commit_transaction(). | 707 | * See the comment at the end of jbd2_journal_commit_transaction(). |
| 703 | */ | 708 | */ |
| 704 | if (transaction->t_state != T_FINISHED) { | 709 | if (transaction->t_state != T_FINISHED) |
| 705 | JBUFFER_TRACE(jh, "belongs to running/committing transaction"); | ||
| 706 | goto out; | 710 | goto out; |
| 707 | } | ||
| 708 | 711 | ||
| 709 | /* OK, that was the last buffer for the transaction: we can now | 712 | /* OK, that was the last buffer for the transaction: we can now |
| 710 | safely remove this transaction from the log */ | 713 | safely remove this transaction from the log */ |
| @@ -723,7 +726,6 @@ int __jbd2_journal_remove_checkpoint(struct journal_head *jh) | |||
| 723 | wake_up(&journal->j_wait_logspace); | 726 | wake_up(&journal->j_wait_logspace); |
| 724 | ret = 1; | 727 | ret = 1; |
| 725 | out: | 728 | out: |
| 726 | JBUFFER_TRACE(jh, "exit"); | ||
| 727 | return ret; | 729 | return ret; |
| 728 | } | 730 | } |
| 729 | 731 | ||
| @@ -742,6 +744,8 @@ void __jbd2_journal_insert_checkpoint(struct journal_head *jh, | |||
| 742 | J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh))); | 744 | J_ASSERT_JH(jh, buffer_dirty(jh2bh(jh)) || buffer_jbddirty(jh2bh(jh))); |
| 743 | J_ASSERT_JH(jh, jh->b_cp_transaction == NULL); | 745 | J_ASSERT_JH(jh, jh->b_cp_transaction == NULL); |
| 744 | 746 | ||
| 747 | /* Get reference for checkpointing transaction */ | ||
| 748 | jbd2_journal_grab_journal_head(jh2bh(jh)); | ||
| 745 | jh->b_cp_transaction = transaction; | 749 | jh->b_cp_transaction = transaction; |
| 746 | 750 | ||
| 747 | if (!transaction->t_checkpoint_list) { | 751 | if (!transaction->t_checkpoint_list) { |
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 7f21cf3aaf92..eef6979821a4 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -848,10 +848,16 @@ restart_loop: | |||
| 848 | while (commit_transaction->t_forget) { | 848 | while (commit_transaction->t_forget) { |
| 849 | transaction_t *cp_transaction; | 849 | transaction_t *cp_transaction; |
| 850 | struct buffer_head *bh; | 850 | struct buffer_head *bh; |
| 851 | int try_to_free = 0; | ||
| 851 | 852 | ||
| 852 | jh = commit_transaction->t_forget; | 853 | jh = commit_transaction->t_forget; |
| 853 | spin_unlock(&journal->j_list_lock); | 854 | spin_unlock(&journal->j_list_lock); |
| 854 | bh = jh2bh(jh); | 855 | bh = jh2bh(jh); |
| 856 | /* | ||
| 857 | * Get a reference so that bh cannot be freed before we are | ||
| 858 | * done with it. | ||
| 859 | */ | ||
| 860 | get_bh(bh); | ||
| 855 | jbd_lock_bh_state(bh); | 861 | jbd_lock_bh_state(bh); |
| 856 | J_ASSERT_JH(jh, jh->b_transaction == commit_transaction); | 862 | J_ASSERT_JH(jh, jh->b_transaction == commit_transaction); |
| 857 | 863 | ||
| @@ -914,28 +920,27 @@ restart_loop: | |||
| 914 | __jbd2_journal_insert_checkpoint(jh, commit_transaction); | 920 | __jbd2_journal_insert_checkpoint(jh, commit_transaction); |
| 915 | if (is_journal_aborted(journal)) | 921 | if (is_journal_aborted(journal)) |
| 916 | clear_buffer_jbddirty(bh); | 922 | clear_buffer_jbddirty(bh); |
| 917 | JBUFFER_TRACE(jh, "refile for checkpoint writeback"); | ||
| 918 | __jbd2_journal_refile_buffer(jh); | ||
| 919 | jbd_unlock_bh_state(bh); | ||
| 920 | } else { | 923 | } else { |
| 921 | J_ASSERT_BH(bh, !buffer_dirty(bh)); | 924 | J_ASSERT_BH(bh, !buffer_dirty(bh)); |
| 922 | /* The buffer on BJ_Forget list and not jbddirty means | 925 | /* |
| 926 | * The buffer on BJ_Forget list and not jbddirty means | ||
| 923 | * it has been freed by this transaction and hence it | 927 | * it has been freed by this transaction and hence it |
| 924 | * could not have been reallocated until this | 928 | * could not have been reallocated until this |
| 925 | * transaction has committed. *BUT* it could be | 929 | * transaction has committed. *BUT* it could be |
| 926 | * reallocated once we have written all the data to | 930 | * reallocated once we have written all the data to |
| 927 | * disk and before we process the buffer on BJ_Forget | 931 | * disk and before we process the buffer on BJ_Forget |
| 928 | * list. */ | 932 | * list. |
| 929 | JBUFFER_TRACE(jh, "refile or unfile freed buffer"); | 933 | */ |
| 930 | __jbd2_journal_refile_buffer(jh); | 934 | if (!jh->b_next_transaction) |
| 931 | if (!jh->b_transaction) { | 935 | try_to_free = 1; |
| 932 | jbd_unlock_bh_state(bh); | ||
| 933 | /* needs a brelse */ | ||
| 934 | jbd2_journal_remove_journal_head(bh); | ||
| 935 | release_buffer_page(bh); | ||
| 936 | } else | ||
| 937 | jbd_unlock_bh_state(bh); | ||
| 938 | } | 936 | } |
| 937 | JBUFFER_TRACE(jh, "refile or unfile buffer"); | ||
| 938 | __jbd2_journal_refile_buffer(jh); | ||
| 939 | jbd_unlock_bh_state(bh); | ||
| 940 | if (try_to_free) | ||
| 941 | release_buffer_page(bh); /* Drops bh reference */ | ||
| 942 | else | ||
| 943 | __brelse(bh); | ||
| 939 | cond_resched_lock(&journal->j_list_lock); | 944 | cond_resched_lock(&journal->j_list_lock); |
| 940 | } | 945 | } |
| 941 | spin_unlock(&journal->j_list_lock); | 946 | spin_unlock(&journal->j_list_lock); |
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 9a7826990304..0dfa5b598e68 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c | |||
| @@ -2078,10 +2078,9 @@ static void journal_free_journal_head(struct journal_head *jh) | |||
| 2078 | * When a buffer has its BH_JBD bit set it is immune from being released by | 2078 | * When a buffer has its BH_JBD bit set it is immune from being released by |
| 2079 | * core kernel code, mainly via ->b_count. | 2079 | * core kernel code, mainly via ->b_count. |
| 2080 | * | 2080 | * |
| 2081 | * A journal_head may be detached from its buffer_head when the journal_head's | 2081 | * A journal_head is detached from its buffer_head when the journal_head's |
| 2082 | * b_transaction, b_cp_transaction and b_next_transaction pointers are NULL. | 2082 | * b_jcount reaches zero. Running transaction (b_transaction) and checkpoint |
| 2083 | * Various places in JBD call jbd2_journal_remove_journal_head() to indicate that the | 2083 | * transaction (b_cp_transaction) hold their references to b_jcount. |
| 2084 | * journal_head can be dropped if needed. | ||
| 2085 | * | 2084 | * |
| 2086 | * Various places in the kernel want to attach a journal_head to a buffer_head | 2085 | * Various places in the kernel want to attach a journal_head to a buffer_head |
| 2087 | * _before_ attaching the journal_head to a transaction. To protect the | 2086 | * _before_ attaching the journal_head to a transaction. To protect the |
| @@ -2094,17 +2093,16 @@ static void journal_free_journal_head(struct journal_head *jh) | |||
| 2094 | * (Attach a journal_head if needed. Increments b_jcount) | 2093 | * (Attach a journal_head if needed. Increments b_jcount) |
| 2095 | * struct journal_head *jh = jbd2_journal_add_journal_head(bh); | 2094 | * struct journal_head *jh = jbd2_journal_add_journal_head(bh); |
| 2096 | * ... | 2095 | * ... |
| 2096 | * (Get another reference for transaction) | ||
| 2097 | * jbd2_journal_grab_journal_head(bh); | ||
| 2097 | * jh->b_transaction = xxx; | 2098 | * jh->b_transaction = xxx; |
| 2099 | * (Put original reference) | ||
| 2098 | * jbd2_journal_put_journal_head(jh); | 2100 | * jbd2_journal_put_journal_head(jh); |
| 2099 | * | ||
| 2100 | * Now, the journal_head's b_jcount is zero, but it is safe from being released | ||
| 2101 | * because it has a non-zero b_transaction. | ||
| 2102 | */ | 2101 | */ |
| 2103 | 2102 | ||
| 2104 | /* | 2103 | /* |
| 2105 | * Give a buffer_head a journal_head. | 2104 | * Give a buffer_head a journal_head. |
| 2106 | * | 2105 | * |
| 2107 | * Doesn't need the journal lock. | ||
| 2108 | * May sleep. | 2106 | * May sleep. |
| 2109 | */ | 2107 | */ |
| 2110 | struct journal_head *jbd2_journal_add_journal_head(struct buffer_head *bh) | 2108 | struct journal_head *jbd2_journal_add_journal_head(struct buffer_head *bh) |
| @@ -2168,61 +2166,29 @@ static void __journal_remove_journal_head(struct buffer_head *bh) | |||
| 2168 | struct journal_head *jh = bh2jh(bh); | 2166 | struct journal_head *jh = bh2jh(bh); |
| 2169 | 2167 | ||
| 2170 | J_ASSERT_JH(jh, jh->b_jcount >= 0); | 2168 | J_ASSERT_JH(jh, jh->b_jcount >= 0); |
| 2171 | 2169 | J_ASSERT_JH(jh, jh->b_transaction == NULL); | |
| 2172 | get_bh(bh); | 2170 | J_ASSERT_JH(jh, jh->b_next_transaction == NULL); |
| 2173 | if (jh->b_jcount == 0) { | 2171 | J_ASSERT_JH(jh, jh->b_cp_transaction == NULL); |
| 2174 | if (jh->b_transaction == NULL && | 2172 | J_ASSERT_JH(jh, jh->b_jlist == BJ_None); |
| 2175 | jh->b_next_transaction == NULL && | 2173 | J_ASSERT_BH(bh, buffer_jbd(bh)); |
| 2176 | jh->b_cp_transaction == NULL) { | 2174 | J_ASSERT_BH(bh, jh2bh(jh) == bh); |
| 2177 | J_ASSERT_JH(jh, jh->b_jlist == BJ_None); | 2175 | BUFFER_TRACE(bh, "remove journal_head"); |
| 2178 | J_ASSERT_BH(bh, buffer_jbd(bh)); | 2176 | if (jh->b_frozen_data) { |
| 2179 | J_ASSERT_BH(bh, jh2bh(jh) == bh); | 2177 | printk(KERN_WARNING "%s: freeing b_frozen_data\n", __func__); |
| 2180 | BUFFER_TRACE(bh, "remove journal_head"); | 2178 | jbd2_free(jh->b_frozen_data, bh->b_size); |
| 2181 | if (jh->b_frozen_data) { | ||
| 2182 | printk(KERN_WARNING "%s: freeing " | ||
| 2183 | "b_frozen_data\n", | ||
| 2184 | __func__); | ||
| 2185 | jbd2_free(jh->b_frozen_data, bh->b_size); | ||
| 2186 | } | ||
| 2187 | if (jh->b_committed_data) { | ||
| 2188 | printk(KERN_WARNING "%s: freeing " | ||
| 2189 | "b_committed_data\n", | ||
| 2190 | __func__); | ||
| 2191 | jbd2_free(jh->b_committed_data, bh->b_size); | ||
| 2192 | } | ||
| 2193 | bh->b_private = NULL; | ||
| 2194 | jh->b_bh = NULL; /* debug, really */ | ||
| 2195 | clear_buffer_jbd(bh); | ||
| 2196 | __brelse(bh); | ||
| 2197 | journal_free_journal_head(jh); | ||
| 2198 | } else { | ||
| 2199 | BUFFER_TRACE(bh, "journal_head was locked"); | ||
| 2200 | } | ||
| 2201 | } | 2179 | } |
| 2180 | if (jh->b_committed_data) { | ||
| 2181 | printk(KERN_WARNING "%s: freeing b_committed_data\n", __func__); | ||
| 2182 | jbd2_free(jh->b_committed_data, bh->b_size); | ||
| 2183 | } | ||
| 2184 | bh->b_private = NULL; | ||
| 2185 | jh->b_bh = NULL; /* debug, really */ | ||
| 2186 | clear_buffer_jbd(bh); | ||
| 2187 | journal_free_journal_head(jh); | ||
| 2202 | } | 2188 | } |
| 2203 | 2189 | ||
| 2204 | /* | 2190 | /* |
| 2205 | * jbd2_journal_remove_journal_head(): if the buffer isn't attached to a transaction | 2191 | * Drop a reference on the passed journal_head. If it fell to zero then |
| 2206 | * and has a zero b_jcount then remove and release its journal_head. If we did | ||
| 2207 | * see that the buffer is not used by any transaction we also "logically" | ||
| 2208 | * decrement ->b_count. | ||
| 2209 | * | ||
| 2210 | * We in fact take an additional increment on ->b_count as a convenience, | ||
| 2211 | * because the caller usually wants to do additional things with the bh | ||
| 2212 | * after calling here. | ||
| 2213 | * The caller of jbd2_journal_remove_journal_head() *must* run __brelse(bh) at some | ||
| 2214 | * time. Once the caller has run __brelse(), the buffer is eligible for | ||
| 2215 | * reaping by try_to_free_buffers(). | ||
| 2216 | */ | ||
| 2217 | void jbd2_journal_remove_journal_head(struct buffer_head *bh) | ||
| 2218 | { | ||
| 2219 | jbd_lock_bh_journal_head(bh); | ||
| 2220 | __journal_remove_journal_head(bh); | ||
| 2221 | jbd_unlock_bh_journal_head(bh); | ||
| 2222 | } | ||
| 2223 | |||
| 2224 | /* | ||
| 2225 | * Drop a reference on the passed journal_head. If it fell to zero then try to | ||
| 2226 | * release the journal_head from the buffer_head. | 2192 | * release the journal_head from the buffer_head. |
| 2227 | */ | 2193 | */ |
| 2228 | void jbd2_journal_put_journal_head(struct journal_head *jh) | 2194 | void jbd2_journal_put_journal_head(struct journal_head *jh) |
| @@ -2232,11 +2198,12 @@ void jbd2_journal_put_journal_head(struct journal_head *jh) | |||
| 2232 | jbd_lock_bh_journal_head(bh); | 2198 | jbd_lock_bh_journal_head(bh); |
| 2233 | J_ASSERT_JH(jh, jh->b_jcount > 0); | 2199 | J_ASSERT_JH(jh, jh->b_jcount > 0); |
| 2234 | --jh->b_jcount; | 2200 | --jh->b_jcount; |
| 2235 | if (!jh->b_jcount && !jh->b_transaction) { | 2201 | if (!jh->b_jcount) { |
| 2236 | __journal_remove_journal_head(bh); | 2202 | __journal_remove_journal_head(bh); |
| 2203 | jbd_unlock_bh_journal_head(bh); | ||
| 2237 | __brelse(bh); | 2204 | __brelse(bh); |
| 2238 | } | 2205 | } else |
| 2239 | jbd_unlock_bh_journal_head(bh); | 2206 | jbd_unlock_bh_journal_head(bh); |
| 2240 | } | 2207 | } |
| 2241 | 2208 | ||
| 2242 | /* | 2209 | /* |
diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 3eec82d32fd4..2d7109414cdd 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 31 | 31 | ||
| 32 | static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh); | 32 | static void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh); |
| 33 | static void __jbd2_journal_unfile_buffer(struct journal_head *jh); | ||
| 33 | 34 | ||
| 34 | /* | 35 | /* |
| 35 | * jbd2_get_transaction: obtain a new transaction_t object. | 36 | * jbd2_get_transaction: obtain a new transaction_t object. |
| @@ -764,7 +765,6 @@ repeat: | |||
| 764 | if (!jh->b_transaction) { | 765 | if (!jh->b_transaction) { |
| 765 | JBUFFER_TRACE(jh, "no transaction"); | 766 | JBUFFER_TRACE(jh, "no transaction"); |
| 766 | J_ASSERT_JH(jh, !jh->b_next_transaction); | 767 | J_ASSERT_JH(jh, !jh->b_next_transaction); |
| 767 | jh->b_transaction = transaction; | ||
| 768 | JBUFFER_TRACE(jh, "file as BJ_Reserved"); | 768 | JBUFFER_TRACE(jh, "file as BJ_Reserved"); |
| 769 | spin_lock(&journal->j_list_lock); | 769 | spin_lock(&journal->j_list_lock); |
| 770 | __jbd2_journal_file_buffer(jh, transaction, BJ_Reserved); | 770 | __jbd2_journal_file_buffer(jh, transaction, BJ_Reserved); |
| @@ -814,7 +814,6 @@ out: | |||
| 814 | * int jbd2_journal_get_write_access() - notify intent to modify a buffer for metadata (not data) update. | 814 | * int jbd2_journal_get_write_access() - notify intent to modify a buffer for metadata (not data) update. |
| 815 | * @handle: transaction to add buffer modifications to | 815 | * @handle: transaction to add buffer modifications to |
| 816 | * @bh: bh to be used for metadata writes | 816 | * @bh: bh to be used for metadata writes |
| 817 | * @credits: variable that will receive credits for the buffer | ||
| 818 | * | 817 | * |
| 819 | * Returns an error code or 0 on success. | 818 | * Returns an error code or 0 on success. |
| 820 | * | 819 | * |
| @@ -896,8 +895,6 @@ int jbd2_journal_get_create_access(handle_t *handle, struct buffer_head *bh) | |||
| 896 | * committed and so it's safe to clear the dirty bit. | 895 | * committed and so it's safe to clear the dirty bit. |
| 897 | */ | 896 | */ |
| 898 | clear_buffer_dirty(jh2bh(jh)); | 897 | clear_buffer_dirty(jh2bh(jh)); |
| 899 | jh->b_transaction = transaction; | ||
| 900 | |||
| 901 | /* first access by this transaction */ | 898 | /* first access by this transaction */ |
| 902 | jh->b_modified = 0; | 899 | jh->b_modified = 0; |
| 903 | 900 | ||
| @@ -932,7 +929,6 @@ out: | |||
| 932 | * non-rewindable consequences | 929 | * non-rewindable consequences |
| 933 | * @handle: transaction | 930 | * @handle: transaction |
| 934 | * @bh: buffer to undo | 931 | * @bh: buffer to undo |
| 935 | * @credits: store the number of taken credits here (if not NULL) | ||
| 936 | * | 932 | * |
| 937 | * Sometimes there is a need to distinguish between metadata which has | 933 | * Sometimes there is a need to distinguish between metadata which has |
| 938 | * been committed to disk and that which has not. The ext3fs code uses | 934 | * been committed to disk and that which has not. The ext3fs code uses |
| @@ -1232,8 +1228,6 @@ int jbd2_journal_forget (handle_t *handle, struct buffer_head *bh) | |||
| 1232 | __jbd2_journal_file_buffer(jh, transaction, BJ_Forget); | 1228 | __jbd2_journal_file_buffer(jh, transaction, BJ_Forget); |
| 1233 | } else { | 1229 | } else { |
| 1234 | __jbd2_journal_unfile_buffer(jh); | 1230 | __jbd2_journal_unfile_buffer(jh); |
| 1235 | jbd2_journal_remove_journal_head(bh); | ||
| 1236 | __brelse(bh); | ||
| 1237 | if (!buffer_jbd(bh)) { | 1231 | if (!buffer_jbd(bh)) { |
| 1238 | spin_unlock(&journal->j_list_lock); | 1232 | spin_unlock(&journal->j_list_lock); |
| 1239 | jbd_unlock_bh_state(bh); | 1233 | jbd_unlock_bh_state(bh); |
| @@ -1556,19 +1550,32 @@ void __jbd2_journal_temp_unlink_buffer(struct journal_head *jh) | |||
| 1556 | mark_buffer_dirty(bh); /* Expose it to the VM */ | 1550 | mark_buffer_dirty(bh); /* Expose it to the VM */ |
| 1557 | } | 1551 | } |
| 1558 | 1552 | ||
| 1559 | void __jbd2_journal_unfile_buffer(struct journal_head *jh) | 1553 | /* |
| 1554 | * Remove buffer from all transactions. | ||
| 1555 | * | ||
| 1556 | * Called with bh_state lock and j_list_lock | ||
| 1557 | * | ||
| 1558 | * jh and bh may be already freed when this function returns. | ||
| 1559 | */ | ||
| 1560 | static void __jbd2_journal_unfile_buffer(struct journal_head *jh) | ||
| 1560 | { | 1561 | { |
| 1561 | __jbd2_journal_temp_unlink_buffer(jh); | 1562 | __jbd2_journal_temp_unlink_buffer(jh); |
| 1562 | jh->b_transaction = NULL; | 1563 | jh->b_transaction = NULL; |
| 1564 | jbd2_journal_put_journal_head(jh); | ||
| 1563 | } | 1565 | } |
| 1564 | 1566 | ||
| 1565 | void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh) | 1567 | void jbd2_journal_unfile_buffer(journal_t *journal, struct journal_head *jh) |
| 1566 | { | 1568 | { |
| 1567 | jbd_lock_bh_state(jh2bh(jh)); | 1569 | struct buffer_head *bh = jh2bh(jh); |
| 1570 | |||
| 1571 | /* Get reference so that buffer cannot be freed before we unlock it */ | ||
| 1572 | get_bh(bh); | ||
| 1573 | jbd_lock_bh_state(bh); | ||
| 1568 | spin_lock(&journal->j_list_lock); | 1574 | spin_lock(&journal->j_list_lock); |
| 1569 | __jbd2_journal_unfile_buffer(jh); | 1575 | __jbd2_journal_unfile_buffer(jh); |
| 1570 | spin_unlock(&journal->j_list_lock); | 1576 | spin_unlock(&journal->j_list_lock); |
| 1571 | jbd_unlock_bh_state(jh2bh(jh)); | 1577 | jbd_unlock_bh_state(bh); |
| 1578 | __brelse(bh); | ||
| 1572 | } | 1579 | } |
| 1573 | 1580 | ||
| 1574 | /* | 1581 | /* |
| @@ -1595,8 +1602,6 @@ __journal_try_to_free_buffer(journal_t *journal, struct buffer_head *bh) | |||
| 1595 | if (jh->b_jlist == BJ_None) { | 1602 | if (jh->b_jlist == BJ_None) { |
| 1596 | JBUFFER_TRACE(jh, "remove from checkpoint list"); | 1603 | JBUFFER_TRACE(jh, "remove from checkpoint list"); |
| 1597 | __jbd2_journal_remove_checkpoint(jh); | 1604 | __jbd2_journal_remove_checkpoint(jh); |
| 1598 | jbd2_journal_remove_journal_head(bh); | ||
| 1599 | __brelse(bh); | ||
| 1600 | } | 1605 | } |
| 1601 | } | 1606 | } |
| 1602 | spin_unlock(&journal->j_list_lock); | 1607 | spin_unlock(&journal->j_list_lock); |
| @@ -1659,7 +1664,6 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal, | |||
| 1659 | /* | 1664 | /* |
| 1660 | * We take our own ref against the journal_head here to avoid | 1665 | * We take our own ref against the journal_head here to avoid |
| 1661 | * having to add tons of locking around each instance of | 1666 | * having to add tons of locking around each instance of |
| 1662 | * jbd2_journal_remove_journal_head() and | ||
| 1663 | * jbd2_journal_put_journal_head(). | 1667 | * jbd2_journal_put_journal_head(). |
| 1664 | */ | 1668 | */ |
| 1665 | jh = jbd2_journal_grab_journal_head(bh); | 1669 | jh = jbd2_journal_grab_journal_head(bh); |
| @@ -1697,10 +1701,9 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) | |||
| 1697 | int may_free = 1; | 1701 | int may_free = 1; |
| 1698 | struct buffer_head *bh = jh2bh(jh); | 1702 | struct buffer_head *bh = jh2bh(jh); |
| 1699 | 1703 | ||
| 1700 | __jbd2_journal_unfile_buffer(jh); | ||
| 1701 | |||
| 1702 | if (jh->b_cp_transaction) { | 1704 | if (jh->b_cp_transaction) { |
| 1703 | JBUFFER_TRACE(jh, "on running+cp transaction"); | 1705 | JBUFFER_TRACE(jh, "on running+cp transaction"); |
| 1706 | __jbd2_journal_temp_unlink_buffer(jh); | ||
| 1704 | /* | 1707 | /* |
| 1705 | * We don't want to write the buffer anymore, clear the | 1708 | * We don't want to write the buffer anymore, clear the |
| 1706 | * bit so that we don't confuse checks in | 1709 | * bit so that we don't confuse checks in |
| @@ -1711,8 +1714,7 @@ static int __dispose_buffer(struct journal_head *jh, transaction_t *transaction) | |||
| 1711 | may_free = 0; | 1714 | may_free = 0; |
| 1712 | } else { | 1715 | } else { |
| 1713 | JBUFFER_TRACE(jh, "on running transaction"); | 1716 | JBUFFER_TRACE(jh, "on running transaction"); |
| 1714 | jbd2_journal_remove_journal_head(bh); | 1717 | __jbd2_journal_unfile_buffer(jh); |
| 1715 | __brelse(bh); | ||
| 1716 | } | 1718 | } |
| 1717 | return may_free; | 1719 | return may_free; |
| 1718 | } | 1720 | } |
| @@ -1990,6 +1992,8 @@ void __jbd2_journal_file_buffer(struct journal_head *jh, | |||
| 1990 | 1992 | ||
| 1991 | if (jh->b_transaction) | 1993 | if (jh->b_transaction) |
| 1992 | __jbd2_journal_temp_unlink_buffer(jh); | 1994 | __jbd2_journal_temp_unlink_buffer(jh); |
| 1995 | else | ||
| 1996 | jbd2_journal_grab_journal_head(bh); | ||
| 1993 | jh->b_transaction = transaction; | 1997 | jh->b_transaction = transaction; |
| 1994 | 1998 | ||
| 1995 | switch (jlist) { | 1999 | switch (jlist) { |
| @@ -2041,9 +2045,10 @@ void jbd2_journal_file_buffer(struct journal_head *jh, | |||
| 2041 | * already started to be used by a subsequent transaction, refile the | 2045 | * already started to be used by a subsequent transaction, refile the |
| 2042 | * buffer on that transaction's metadata list. | 2046 | * buffer on that transaction's metadata list. |
| 2043 | * | 2047 | * |
| 2044 | * Called under journal->j_list_lock | 2048 | * Called under j_list_lock |
| 2045 | * | ||
| 2046 | * Called under jbd_lock_bh_state(jh2bh(jh)) | 2049 | * Called under jbd_lock_bh_state(jh2bh(jh)) |
| 2050 | * | ||
| 2051 | * jh and bh may be already free when this function returns | ||
| 2047 | */ | 2052 | */ |
| 2048 | void __jbd2_journal_refile_buffer(struct journal_head *jh) | 2053 | void __jbd2_journal_refile_buffer(struct journal_head *jh) |
| 2049 | { | 2054 | { |
| @@ -2067,6 +2072,11 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh) | |||
| 2067 | 2072 | ||
| 2068 | was_dirty = test_clear_buffer_jbddirty(bh); | 2073 | was_dirty = test_clear_buffer_jbddirty(bh); |
| 2069 | __jbd2_journal_temp_unlink_buffer(jh); | 2074 | __jbd2_journal_temp_unlink_buffer(jh); |
| 2075 | /* | ||
| 2076 | * We set b_transaction here because b_next_transaction will inherit | ||
| 2077 | * our jh reference and thus __jbd2_journal_file_buffer() must not | ||
| 2078 | * take a new one. | ||
| 2079 | */ | ||
| 2070 | jh->b_transaction = jh->b_next_transaction; | 2080 | jh->b_transaction = jh->b_next_transaction; |
| 2071 | jh->b_next_transaction = NULL; | 2081 | jh->b_next_transaction = NULL; |
| 2072 | if (buffer_freed(bh)) | 2082 | if (buffer_freed(bh)) |
| @@ -2083,30 +2093,21 @@ void __jbd2_journal_refile_buffer(struct journal_head *jh) | |||
| 2083 | } | 2093 | } |
| 2084 | 2094 | ||
| 2085 | /* | 2095 | /* |
| 2086 | * For the unlocked version of this call, also make sure that any | 2096 | * __jbd2_journal_refile_buffer() with necessary locking added. We take our |
| 2087 | * hanging journal_head is cleaned up if necessary. | 2097 | * bh reference so that we can safely unlock bh. |
| 2088 | * | 2098 | * |
| 2089 | * __jbd2_journal_refile_buffer is usually called as part of a single locked | 2099 | * The jh and bh may be freed by this call. |
| 2090 | * operation on a buffer_head, in which the caller is probably going to | ||
| 2091 | * be hooking the journal_head onto other lists. In that case it is up | ||
| 2092 | * to the caller to remove the journal_head if necessary. For the | ||
| 2093 | * unlocked jbd2_journal_refile_buffer call, the caller isn't going to be | ||
| 2094 | * doing anything else to the buffer so we need to do the cleanup | ||
| 2095 | * ourselves to avoid a jh leak. | ||
| 2096 | * | ||
| 2097 | * *** The journal_head may be freed by this call! *** | ||
| 2098 | */ | 2100 | */ |
| 2099 | void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh) | 2101 | void jbd2_journal_refile_buffer(journal_t *journal, struct journal_head *jh) |
| 2100 | { | 2102 | { |
| 2101 | struct buffer_head *bh = jh2bh(jh); | 2103 | struct buffer_head *bh = jh2bh(jh); |
| 2102 | 2104 | ||
| 2105 | /* Get reference so that buffer cannot be freed before we unlock it */ | ||
| 2106 | get_bh(bh); | ||
| 2103 | jbd_lock_bh_state(bh); | 2107 | jbd_lock_bh_state(bh); |
| 2104 | spin_lock(&journal->j_list_lock); | 2108 | spin_lock(&journal->j_list_lock); |
| 2105 | |||
| 2106 | __jbd2_journal_refile_buffer(jh); | 2109 | __jbd2_journal_refile_buffer(jh); |
| 2107 | jbd_unlock_bh_state(bh); | 2110 | jbd_unlock_bh_state(bh); |
| 2108 | jbd2_journal_remove_journal_head(bh); | ||
| 2109 | |||
| 2110 | spin_unlock(&journal->j_list_lock); | 2111 | spin_unlock(&journal->j_list_lock); |
| 2111 | __brelse(bh); | 2112 | __brelse(bh); |
| 2112 | } | 2113 | } |
diff --git a/fs/jfs/file.c b/fs/jfs/file.c index c5ce6c1d1ff4..2f3f531f3606 100644 --- a/fs/jfs/file.c +++ b/fs/jfs/file.c | |||
| @@ -66,9 +66,9 @@ static int jfs_open(struct inode *inode, struct file *file) | |||
| 66 | struct jfs_inode_info *ji = JFS_IP(inode); | 66 | struct jfs_inode_info *ji = JFS_IP(inode); |
| 67 | spin_lock_irq(&ji->ag_lock); | 67 | spin_lock_irq(&ji->ag_lock); |
| 68 | if (ji->active_ag == -1) { | 68 | if (ji->active_ag == -1) { |
| 69 | ji->active_ag = ji->agno; | 69 | struct jfs_sb_info *jfs_sb = JFS_SBI(inode->i_sb); |
| 70 | atomic_inc( | 70 | ji->active_ag = BLKTOAG(addressPXD(&ji->ixpxd), jfs_sb); |
| 71 | &JFS_SBI(inode->i_sb)->bmap->db_active[ji->agno]); | 71 | atomic_inc( &jfs_sb->bmap->db_active[ji->active_ag]); |
| 72 | } | 72 | } |
| 73 | spin_unlock_irq(&ji->ag_lock); | 73 | spin_unlock_irq(&ji->ag_lock); |
| 74 | } | 74 | } |
diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index ed53a4740168..b78b2f978f04 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c | |||
| @@ -397,7 +397,7 @@ int diRead(struct inode *ip) | |||
| 397 | release_metapage(mp); | 397 | release_metapage(mp); |
| 398 | 398 | ||
| 399 | /* set the ag for the inode */ | 399 | /* set the ag for the inode */ |
| 400 | JFS_IP(ip)->agno = BLKTOAG(agstart, sbi); | 400 | JFS_IP(ip)->agstart = agstart; |
| 401 | JFS_IP(ip)->active_ag = -1; | 401 | JFS_IP(ip)->active_ag = -1; |
| 402 | 402 | ||
| 403 | return (rc); | 403 | return (rc); |
| @@ -901,7 +901,7 @@ int diFree(struct inode *ip) | |||
| 901 | 901 | ||
| 902 | /* get the allocation group for this ino. | 902 | /* get the allocation group for this ino. |
| 903 | */ | 903 | */ |
| 904 | agno = JFS_IP(ip)->agno; | 904 | agno = BLKTOAG(JFS_IP(ip)->agstart, JFS_SBI(ip->i_sb)); |
| 905 | 905 | ||
| 906 | /* Lock the AG specific inode map information | 906 | /* Lock the AG specific inode map information |
| 907 | */ | 907 | */ |
| @@ -1315,12 +1315,11 @@ int diFree(struct inode *ip) | |||
| 1315 | static inline void | 1315 | static inline void |
| 1316 | diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp) | 1316 | diInitInode(struct inode *ip, int iagno, int ino, int extno, struct iag * iagp) |
| 1317 | { | 1317 | { |
| 1318 | struct jfs_sb_info *sbi = JFS_SBI(ip->i_sb); | ||
| 1319 | struct jfs_inode_info *jfs_ip = JFS_IP(ip); | 1318 | struct jfs_inode_info *jfs_ip = JFS_IP(ip); |
| 1320 | 1319 | ||
| 1321 | ip->i_ino = (iagno << L2INOSPERIAG) + ino; | 1320 | ip->i_ino = (iagno << L2INOSPERIAG) + ino; |
| 1322 | jfs_ip->ixpxd = iagp->inoext[extno]; | 1321 | jfs_ip->ixpxd = iagp->inoext[extno]; |
| 1323 | jfs_ip->agno = BLKTOAG(le64_to_cpu(iagp->agstart), sbi); | 1322 | jfs_ip->agstart = le64_to_cpu(iagp->agstart); |
| 1324 | jfs_ip->active_ag = -1; | 1323 | jfs_ip->active_ag = -1; |
| 1325 | } | 1324 | } |
| 1326 | 1325 | ||
| @@ -1379,7 +1378,7 @@ int diAlloc(struct inode *pip, bool dir, struct inode *ip) | |||
| 1379 | */ | 1378 | */ |
| 1380 | 1379 | ||
| 1381 | /* get the ag number of this iag */ | 1380 | /* get the ag number of this iag */ |
| 1382 | agno = JFS_IP(pip)->agno; | 1381 | agno = BLKTOAG(JFS_IP(pip)->agstart, JFS_SBI(pip->i_sb)); |
| 1383 | 1382 | ||
| 1384 | if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) { | 1383 | if (atomic_read(&JFS_SBI(pip->i_sb)->bmap->db_active[agno])) { |
| 1385 | /* | 1384 | /* |
| @@ -2921,10 +2920,9 @@ int diExtendFS(struct inode *ipimap, struct inode *ipbmap) | |||
| 2921 | continue; | 2920 | continue; |
| 2922 | } | 2921 | } |
| 2923 | 2922 | ||
| 2924 | /* agstart that computes to the same ag is treated as same; */ | ||
| 2925 | agstart = le64_to_cpu(iagp->agstart); | 2923 | agstart = le64_to_cpu(iagp->agstart); |
| 2926 | /* iagp->agstart = agstart & ~(mp->db_agsize - 1); */ | ||
| 2927 | n = agstart >> mp->db_agl2size; | 2924 | n = agstart >> mp->db_agl2size; |
| 2925 | iagp->agstart = cpu_to_le64((s64)n << mp->db_agl2size); | ||
| 2928 | 2926 | ||
| 2929 | /* compute backed inodes */ | 2927 | /* compute backed inodes */ |
| 2930 | numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts)) | 2928 | numinos = (EXTSPERIAG - le32_to_cpu(iagp->nfreeexts)) |
diff --git a/fs/jfs/jfs_incore.h b/fs/jfs/jfs_incore.h index 1439f119ec83..584a4a1a6e81 100644 --- a/fs/jfs/jfs_incore.h +++ b/fs/jfs/jfs_incore.h | |||
| @@ -50,8 +50,9 @@ struct jfs_inode_info { | |||
| 50 | short btindex; /* btpage entry index*/ | 50 | short btindex; /* btpage entry index*/ |
| 51 | struct inode *ipimap; /* inode map */ | 51 | struct inode *ipimap; /* inode map */ |
| 52 | unsigned long cflag; /* commit flags */ | 52 | unsigned long cflag; /* commit flags */ |
| 53 | u64 agstart; /* agstart of the containing IAG */ | ||
| 53 | u16 bxflag; /* xflag of pseudo buffer? */ | 54 | u16 bxflag; /* xflag of pseudo buffer? */ |
| 54 | unchar agno; /* ag number */ | 55 | unchar pad; |
| 55 | signed char active_ag; /* ag currently allocating from */ | 56 | signed char active_ag; /* ag currently allocating from */ |
| 56 | lid_t blid; /* lid of pseudo buffer? */ | 57 | lid_t blid; /* lid of pseudo buffer? */ |
| 57 | lid_t atlhead; /* anonymous tlock list head */ | 58 | lid_t atlhead; /* anonymous tlock list head */ |
diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c index 8ea5efb5a34e..8d0c1c7c0820 100644 --- a/fs/jfs/resize.c +++ b/fs/jfs/resize.c | |||
| @@ -80,7 +80,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) | |||
| 80 | int log_formatted = 0; | 80 | int log_formatted = 0; |
| 81 | struct inode *iplist[1]; | 81 | struct inode *iplist[1]; |
| 82 | struct jfs_superblock *j_sb, *j_sb2; | 82 | struct jfs_superblock *j_sb, *j_sb2; |
| 83 | uint old_agsize; | 83 | s64 old_agsize; |
| 84 | int agsizechanged = 0; | 84 | int agsizechanged = 0; |
| 85 | struct buffer_head *bh, *bh2; | 85 | struct buffer_head *bh, *bh2; |
| 86 | 86 | ||
diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index adb45ec9038c..e374050a911c 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c | |||
| @@ -708,7 +708,13 @@ static void nlmclnt_unlock_callback(struct rpc_task *task, void *data) | |||
| 708 | 708 | ||
| 709 | if (task->tk_status < 0) { | 709 | if (task->tk_status < 0) { |
| 710 | dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status); | 710 | dprintk("lockd: unlock failed (err = %d)\n", -task->tk_status); |
| 711 | goto retry_rebind; | 711 | switch (task->tk_status) { |
| 712 | case -EACCES: | ||
| 713 | case -EIO: | ||
| 714 | goto die; | ||
| 715 | default: | ||
| 716 | goto retry_rebind; | ||
| 717 | } | ||
| 712 | } | 718 | } |
| 713 | if (status == NLM_LCK_DENIED_GRACE_PERIOD) { | 719 | if (status == NLM_LCK_DENIED_GRACE_PERIOD) { |
| 714 | rpc_delay(task, NLMCLNT_GRACE_WAIT); | 720 | rpc_delay(task, NLMCLNT_GRACE_WAIT); |
diff --git a/fs/logfs/dir.c b/fs/logfs/dir.c index 9ed89d1663f8..1afae26cf236 100644 --- a/fs/logfs/dir.c +++ b/fs/logfs/dir.c | |||
| @@ -555,13 +555,6 @@ static int logfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 555 | return __logfs_create(dir, dentry, inode, target, destlen); | 555 | return __logfs_create(dir, dentry, inode, target, destlen); |
| 556 | } | 556 | } |
| 557 | 557 | ||
| 558 | static int logfs_permission(struct inode *inode, int mask, unsigned int flags) | ||
| 559 | { | ||
| 560 | if (flags & IPERM_FLAG_RCU) | ||
| 561 | return -ECHILD; | ||
| 562 | return generic_permission(inode, mask, flags, NULL); | ||
| 563 | } | ||
| 564 | |||
| 565 | static int logfs_link(struct dentry *old_dentry, struct inode *dir, | 558 | static int logfs_link(struct dentry *old_dentry, struct inode *dir, |
| 566 | struct dentry *dentry) | 559 | struct dentry *dentry) |
| 567 | { | 560 | { |
| @@ -820,7 +813,6 @@ const struct inode_operations logfs_dir_iops = { | |||
| 820 | .mknod = logfs_mknod, | 813 | .mknod = logfs_mknod, |
| 821 | .rename = logfs_rename, | 814 | .rename = logfs_rename, |
| 822 | .rmdir = logfs_rmdir, | 815 | .rmdir = logfs_rmdir, |
| 823 | .permission = logfs_permission, | ||
| 824 | .symlink = logfs_symlink, | 816 | .symlink = logfs_symlink, |
| 825 | .unlink = logfs_unlink, | 817 | .unlink = logfs_unlink, |
| 826 | }; | 818 | }; |
diff --git a/fs/namei.c b/fs/namei.c index 9802345df5e7..0223c41fb114 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -238,7 +238,8 @@ int generic_permission(struct inode *inode, int mask, unsigned int flags, | |||
| 238 | 238 | ||
| 239 | /* | 239 | /* |
| 240 | * Read/write DACs are always overridable. | 240 | * Read/write DACs are always overridable. |
| 241 | * Executable DACs are overridable if at least one exec bit is set. | 241 | * Executable DACs are overridable for all directories and |
| 242 | * for non-directories that have least one exec bit set. | ||
| 242 | */ | 243 | */ |
| 243 | if (!(mask & MAY_EXEC) || execute_ok(inode)) | 244 | if (!(mask & MAY_EXEC) || execute_ok(inode)) |
| 244 | if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) | 245 | if (ns_capable(inode_userns(inode), CAP_DAC_OVERRIDE)) |
| @@ -812,6 +813,11 @@ static int follow_automount(struct path *path, unsigned flags, | |||
| 812 | if (!mnt) /* mount collision */ | 813 | if (!mnt) /* mount collision */ |
| 813 | return 0; | 814 | return 0; |
| 814 | 815 | ||
| 816 | if (!*need_mntput) { | ||
| 817 | /* lock_mount() may release path->mnt on error */ | ||
| 818 | mntget(path->mnt); | ||
| 819 | *need_mntput = true; | ||
| 820 | } | ||
| 815 | err = finish_automount(mnt, path); | 821 | err = finish_automount(mnt, path); |
| 816 | 822 | ||
| 817 | switch (err) { | 823 | switch (err) { |
| @@ -819,12 +825,9 @@ static int follow_automount(struct path *path, unsigned flags, | |||
| 819 | /* Someone else made a mount here whilst we were busy */ | 825 | /* Someone else made a mount here whilst we were busy */ |
| 820 | return 0; | 826 | return 0; |
| 821 | case 0: | 827 | case 0: |
| 822 | dput(path->dentry); | 828 | path_put(path); |
| 823 | if (*need_mntput) | ||
| 824 | mntput(path->mnt); | ||
| 825 | path->mnt = mnt; | 829 | path->mnt = mnt; |
| 826 | path->dentry = dget(mnt->mnt_root); | 830 | path->dentry = dget(mnt->mnt_root); |
| 827 | *need_mntput = true; | ||
| 828 | return 0; | 831 | return 0; |
| 829 | default: | 832 | default: |
| 830 | return err; | 833 | return err; |
| @@ -844,9 +847,10 @@ static int follow_automount(struct path *path, unsigned flags, | |||
| 844 | */ | 847 | */ |
| 845 | static int follow_managed(struct path *path, unsigned flags) | 848 | static int follow_managed(struct path *path, unsigned flags) |
| 846 | { | 849 | { |
| 850 | struct vfsmount *mnt = path->mnt; /* held by caller, must be left alone */ | ||
| 847 | unsigned managed; | 851 | unsigned managed; |
| 848 | bool need_mntput = false; | 852 | bool need_mntput = false; |
| 849 | int ret; | 853 | int ret = 0; |
| 850 | 854 | ||
| 851 | /* Given that we're not holding a lock here, we retain the value in a | 855 | /* Given that we're not holding a lock here, we retain the value in a |
| 852 | * local variable for each dentry as we look at it so that we don't see | 856 | * local variable for each dentry as we look at it so that we don't see |
| @@ -861,7 +865,7 @@ static int follow_managed(struct path *path, unsigned flags) | |||
| 861 | BUG_ON(!path->dentry->d_op->d_manage); | 865 | BUG_ON(!path->dentry->d_op->d_manage); |
| 862 | ret = path->dentry->d_op->d_manage(path->dentry, false); | 866 | ret = path->dentry->d_op->d_manage(path->dentry, false); |
| 863 | if (ret < 0) | 867 | if (ret < 0) |
| 864 | return ret == -EISDIR ? 0 : ret; | 868 | break; |
| 865 | } | 869 | } |
| 866 | 870 | ||
| 867 | /* Transit to a mounted filesystem. */ | 871 | /* Transit to a mounted filesystem. */ |
| @@ -887,14 +891,19 @@ static int follow_managed(struct path *path, unsigned flags) | |||
| 887 | if (managed & DCACHE_NEED_AUTOMOUNT) { | 891 | if (managed & DCACHE_NEED_AUTOMOUNT) { |
| 888 | ret = follow_automount(path, flags, &need_mntput); | 892 | ret = follow_automount(path, flags, &need_mntput); |
| 889 | if (ret < 0) | 893 | if (ret < 0) |
| 890 | return ret == -EISDIR ? 0 : ret; | 894 | break; |
| 891 | continue; | 895 | continue; |
| 892 | } | 896 | } |
| 893 | 897 | ||
| 894 | /* We didn't change the current path point */ | 898 | /* We didn't change the current path point */ |
| 895 | break; | 899 | break; |
| 896 | } | 900 | } |
| 897 | return 0; | 901 | |
| 902 | if (need_mntput && path->mnt == mnt) | ||
| 903 | mntput(path->mnt); | ||
| 904 | if (ret == -EISDIR) | ||
| 905 | ret = 0; | ||
| 906 | return ret; | ||
| 898 | } | 907 | } |
| 899 | 908 | ||
| 900 | int follow_down_one(struct path *path) | 909 | int follow_down_one(struct path *path) |
| @@ -1003,9 +1012,6 @@ failed: | |||
| 1003 | * Follow down to the covering mount currently visible to userspace. At each | 1012 | * Follow down to the covering mount currently visible to userspace. At each |
| 1004 | * point, the filesystem owning that dentry may be queried as to whether the | 1013 | * point, the filesystem owning that dentry may be queried as to whether the |
| 1005 | * caller is permitted to proceed or not. | 1014 | * caller is permitted to proceed or not. |
| 1006 | * | ||
| 1007 | * Care must be taken as namespace_sem may be held (indicated by mounting_here | ||
| 1008 | * being true). | ||
| 1009 | */ | 1015 | */ |
| 1010 | int follow_down(struct path *path) | 1016 | int follow_down(struct path *path) |
| 1011 | { | 1017 | { |
| @@ -2713,8 +2719,10 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
| 2713 | error = PTR_ERR(dentry); | 2719 | error = PTR_ERR(dentry); |
| 2714 | if (!IS_ERR(dentry)) { | 2720 | if (!IS_ERR(dentry)) { |
| 2715 | /* Why not before? Because we want correct error value */ | 2721 | /* Why not before? Because we want correct error value */ |
| 2722 | if (nd.last.name[nd.last.len]) | ||
| 2723 | goto slashes; | ||
| 2716 | inode = dentry->d_inode; | 2724 | inode = dentry->d_inode; |
| 2717 | if (nd.last.name[nd.last.len] || !inode) | 2725 | if (!inode) |
| 2718 | goto slashes; | 2726 | goto slashes; |
| 2719 | ihold(inode); | 2727 | ihold(inode); |
| 2720 | error = mnt_want_write(nd.path.mnt); | 2728 | error = mnt_want_write(nd.path.mnt); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 144f2a3c7185..6f4850deb272 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -256,7 +256,8 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
| 256 | 256 | ||
| 257 | nfs_attr_check_mountpoint(sb, fattr); | 257 | nfs_attr_check_mountpoint(sb, fattr); |
| 258 | 258 | ||
| 259 | if ((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0 && (fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) | 259 | if (((fattr->valid & NFS_ATTR_FATTR_FILEID) == 0) && |
| 260 | !nfs_attr_use_mounted_on_fileid(fattr)) | ||
| 260 | goto out_no_inode; | 261 | goto out_no_inode; |
| 261 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) | 262 | if ((fattr->valid & NFS_ATTR_FATTR_TYPE) == 0) |
| 262 | goto out_no_inode; | 263 | goto out_no_inode; |
| @@ -1294,7 +1295,8 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
| 1294 | if (new_isize != cur_isize) { | 1295 | if (new_isize != cur_isize) { |
| 1295 | /* Do we perhaps have any outstanding writes, or has | 1296 | /* Do we perhaps have any outstanding writes, or has |
| 1296 | * the file grown beyond our last write? */ | 1297 | * the file grown beyond our last write? */ |
| 1297 | if (nfsi->npages == 0 || new_isize > cur_isize) { | 1298 | if ((nfsi->npages == 0 && !test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags)) || |
| 1299 | new_isize > cur_isize) { | ||
| 1298 | i_size_write(inode, new_isize); | 1300 | i_size_write(inode, new_isize); |
| 1299 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; | 1301 | invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA; |
| 1300 | } | 1302 | } |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index b9056cbe68d6..2a55347a2daa 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -45,6 +45,17 @@ static inline void nfs_attr_check_mountpoint(struct super_block *parent, struct | |||
| 45 | fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; | 45 | fattr->valid |= NFS_ATTR_FATTR_MOUNTPOINT; |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | static inline int nfs_attr_use_mounted_on_fileid(struct nfs_fattr *fattr) | ||
| 49 | { | ||
| 50 | if (((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) == 0) || | ||
| 51 | (((fattr->valid & NFS_ATTR_FATTR_MOUNTPOINT) == 0) && | ||
| 52 | ((fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL) == 0))) | ||
| 53 | return 0; | ||
| 54 | |||
| 55 | fattr->fileid = fattr->mounted_on_fileid; | ||
| 56 | return 1; | ||
| 57 | } | ||
| 58 | |||
| 48 | struct nfs_clone_mount { | 59 | struct nfs_clone_mount { |
| 49 | const struct super_block *sb; | 60 | const struct super_block *sb; |
| 50 | const struct dentry *dentry; | 61 | const struct dentry *dentry; |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 426908809c97..0bafcc91c27f 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | */ | 30 | */ |
| 31 | 31 | ||
| 32 | #include <linux/nfs_fs.h> | 32 | #include <linux/nfs_fs.h> |
| 33 | #include <linux/nfs_page.h> | ||
| 33 | 34 | ||
| 34 | #include "internal.h" | 35 | #include "internal.h" |
| 35 | #include "nfs4filelayout.h" | 36 | #include "nfs4filelayout.h" |
| @@ -552,13 +553,18 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
| 552 | __func__, nfl_util, fl->num_fh, fl->first_stripe_index, | 553 | __func__, nfl_util, fl->num_fh, fl->first_stripe_index, |
| 553 | fl->pattern_offset); | 554 | fl->pattern_offset); |
| 554 | 555 | ||
| 555 | if (!fl->num_fh) | 556 | /* Note that a zero value for num_fh is legal for STRIPE_SPARSE. |
| 557 | * Futher checking is done in filelayout_check_layout */ | ||
| 558 | if (fl->num_fh < 0 || fl->num_fh > | ||
| 559 | max(NFS4_PNFS_MAX_STRIPE_CNT, NFS4_PNFS_MAX_MULTI_CNT)) | ||
| 556 | goto out_err; | 560 | goto out_err; |
| 557 | 561 | ||
| 558 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), | 562 | if (fl->num_fh > 0) { |
| 559 | gfp_flags); | 563 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), |
| 560 | if (!fl->fh_array) | 564 | gfp_flags); |
| 561 | goto out_err; | 565 | if (!fl->fh_array) |
| 566 | goto out_err; | ||
| 567 | } | ||
| 562 | 568 | ||
| 563 | for (i = 0; i < fl->num_fh; i++) { | 569 | for (i = 0; i < fl->num_fh; i++) { |
| 564 | /* Do we want to use a mempool here? */ | 570 | /* Do we want to use a mempool here? */ |
| @@ -661,8 +667,9 @@ filelayout_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
| 661 | u64 p_stripe, r_stripe; | 667 | u64 p_stripe, r_stripe; |
| 662 | u32 stripe_unit; | 668 | u32 stripe_unit; |
| 663 | 669 | ||
| 664 | if (!pnfs_generic_pg_test(pgio, prev, req)) | 670 | if (!pnfs_generic_pg_test(pgio, prev, req) || |
| 665 | return 0; | 671 | !nfs_generic_pg_test(pgio, prev, req)) |
| 672 | return false; | ||
| 666 | 673 | ||
| 667 | if (!pgio->pg_lseg) | 674 | if (!pgio->pg_lseg) |
| 668 | return 1; | 675 | return 1; |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index d2c4b59c896d..5879b23e0c99 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -2265,12 +2265,14 @@ static int nfs4_proc_get_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
| 2265 | return nfs4_map_errors(status); | 2265 | return nfs4_map_errors(status); |
| 2266 | } | 2266 | } |
| 2267 | 2267 | ||
| 2268 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); | ||
| 2268 | /* | 2269 | /* |
| 2269 | * Get locations and (maybe) other attributes of a referral. | 2270 | * Get locations and (maybe) other attributes of a referral. |
| 2270 | * Note that we'll actually follow the referral later when | 2271 | * Note that we'll actually follow the referral later when |
| 2271 | * we detect fsid mismatch in inode revalidation | 2272 | * we detect fsid mismatch in inode revalidation |
| 2272 | */ | 2273 | */ |
| 2273 | static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct nfs_fattr *fattr, struct nfs_fh *fhandle) | 2274 | static int nfs4_get_referral(struct inode *dir, const struct qstr *name, |
| 2275 | struct nfs_fattr *fattr, struct nfs_fh *fhandle) | ||
| 2274 | { | 2276 | { |
| 2275 | int status = -ENOMEM; | 2277 | int status = -ENOMEM; |
| 2276 | struct page *page = NULL; | 2278 | struct page *page = NULL; |
| @@ -2288,15 +2290,16 @@ static int nfs4_get_referral(struct inode *dir, const struct qstr *name, struct | |||
| 2288 | goto out; | 2290 | goto out; |
| 2289 | /* Make sure server returned a different fsid for the referral */ | 2291 | /* Make sure server returned a different fsid for the referral */ |
| 2290 | if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) { | 2292 | if (nfs_fsid_equal(&NFS_SERVER(dir)->fsid, &locations->fattr.fsid)) { |
| 2291 | dprintk("%s: server did not return a different fsid for a referral at %s\n", __func__, name->name); | 2293 | dprintk("%s: server did not return a different fsid for" |
| 2294 | " a referral at %s\n", __func__, name->name); | ||
| 2292 | status = -EIO; | 2295 | status = -EIO; |
| 2293 | goto out; | 2296 | goto out; |
| 2294 | } | 2297 | } |
| 2298 | /* Fixup attributes for the nfs_lookup() call to nfs_fhget() */ | ||
| 2299 | nfs_fixup_referral_attributes(&locations->fattr); | ||
| 2295 | 2300 | ||
| 2301 | /* replace the lookup nfs_fattr with the locations nfs_fattr */ | ||
| 2296 | memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr)); | 2302 | memcpy(fattr, &locations->fattr, sizeof(struct nfs_fattr)); |
| 2297 | fattr->valid |= NFS_ATTR_FATTR_V4_REFERRAL; | ||
| 2298 | if (!fattr->mode) | ||
| 2299 | fattr->mode = S_IFDIR; | ||
| 2300 | memset(fhandle, 0, sizeof(struct nfs_fh)); | 2303 | memset(fhandle, 0, sizeof(struct nfs_fh)); |
| 2301 | out: | 2304 | out: |
| 2302 | if (page) | 2305 | if (page) |
| @@ -4667,11 +4670,15 @@ static size_t nfs4_xattr_list_nfs4_acl(struct dentry *dentry, char *list, | |||
| 4667 | return len; | 4670 | return len; |
| 4668 | } | 4671 | } |
| 4669 | 4672 | ||
| 4673 | /* | ||
| 4674 | * nfs_fhget will use either the mounted_on_fileid or the fileid | ||
| 4675 | */ | ||
| 4670 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) | 4676 | static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr) |
| 4671 | { | 4677 | { |
| 4672 | if (!((fattr->valid & NFS_ATTR_FATTR_FILEID) && | 4678 | if (!(((fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) || |
| 4673 | (fattr->valid & NFS_ATTR_FATTR_FSID) && | 4679 | (fattr->valid & NFS_ATTR_FATTR_FILEID)) && |
| 4674 | (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL))) | 4680 | (fattr->valid & NFS_ATTR_FATTR_FSID) && |
| 4681 | (fattr->valid & NFS_ATTR_FATTR_V4_REFERRAL))) | ||
| 4675 | return; | 4682 | return; |
| 4676 | 4683 | ||
| 4677 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | | 4684 | fattr->valid |= NFS_ATTR_FATTR_TYPE | NFS_ATTR_FATTR_MODE | |
| @@ -4686,7 +4693,6 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
| 4686 | struct nfs_server *server = NFS_SERVER(dir); | 4693 | struct nfs_server *server = NFS_SERVER(dir); |
| 4687 | u32 bitmask[2] = { | 4694 | u32 bitmask[2] = { |
| 4688 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, | 4695 | [0] = FATTR4_WORD0_FSID | FATTR4_WORD0_FS_LOCATIONS, |
| 4689 | [1] = FATTR4_WORD1_MOUNTED_ON_FILEID, | ||
| 4690 | }; | 4696 | }; |
| 4691 | struct nfs4_fs_locations_arg args = { | 4697 | struct nfs4_fs_locations_arg args = { |
| 4692 | .dir_fh = NFS_FH(dir), | 4698 | .dir_fh = NFS_FH(dir), |
| @@ -4705,11 +4711,18 @@ int nfs4_proc_fs_locations(struct inode *dir, const struct qstr *name, | |||
| 4705 | int status; | 4711 | int status; |
| 4706 | 4712 | ||
| 4707 | dprintk("%s: start\n", __func__); | 4713 | dprintk("%s: start\n", __func__); |
| 4714 | |||
| 4715 | /* Ask for the fileid of the absent filesystem if mounted_on_fileid | ||
| 4716 | * is not supported */ | ||
| 4717 | if (NFS_SERVER(dir)->attr_bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) | ||
| 4718 | bitmask[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID; | ||
| 4719 | else | ||
| 4720 | bitmask[0] |= FATTR4_WORD0_FILEID; | ||
| 4721 | |||
| 4708 | nfs_fattr_init(&fs_locations->fattr); | 4722 | nfs_fattr_init(&fs_locations->fattr); |
| 4709 | fs_locations->server = server; | 4723 | fs_locations->server = server; |
| 4710 | fs_locations->nlocations = 0; | 4724 | fs_locations->nlocations = 0; |
| 4711 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 4725 | status = nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
| 4712 | nfs_fixup_referral_attributes(&fs_locations->fattr); | ||
| 4713 | dprintk("%s: returned status = %d\n", __func__, status); | 4726 | dprintk("%s: returned status = %d\n", __func__, status); |
| 4714 | return status; | 4727 | return status; |
| 4715 | } | 4728 | } |
| @@ -5098,7 +5111,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | |||
| 5098 | if (mxresp_sz == 0) | 5111 | if (mxresp_sz == 0) |
| 5099 | mxresp_sz = NFS_MAX_FILE_IO_SIZE; | 5112 | mxresp_sz = NFS_MAX_FILE_IO_SIZE; |
| 5100 | /* Fore channel attributes */ | 5113 | /* Fore channel attributes */ |
| 5101 | args->fc_attrs.headerpadsz = 0; | ||
| 5102 | args->fc_attrs.max_rqst_sz = mxrqst_sz; | 5114 | args->fc_attrs.max_rqst_sz = mxrqst_sz; |
| 5103 | args->fc_attrs.max_resp_sz = mxresp_sz; | 5115 | args->fc_attrs.max_resp_sz = mxresp_sz; |
| 5104 | args->fc_attrs.max_ops = NFS4_MAX_OPS; | 5116 | args->fc_attrs.max_ops = NFS4_MAX_OPS; |
| @@ -5111,7 +5123,6 @@ static void nfs4_init_channel_attrs(struct nfs41_create_session_args *args) | |||
| 5111 | args->fc_attrs.max_ops, args->fc_attrs.max_reqs); | 5123 | args->fc_attrs.max_ops, args->fc_attrs.max_reqs); |
| 5112 | 5124 | ||
| 5113 | /* Back channel attributes */ | 5125 | /* Back channel attributes */ |
| 5114 | args->bc_attrs.headerpadsz = 0; | ||
| 5115 | args->bc_attrs.max_rqst_sz = PAGE_SIZE; | 5126 | args->bc_attrs.max_rqst_sz = PAGE_SIZE; |
| 5116 | args->bc_attrs.max_resp_sz = PAGE_SIZE; | 5127 | args->bc_attrs.max_resp_sz = PAGE_SIZE; |
| 5117 | args->bc_attrs.max_resp_sz_cached = 0; | 5128 | args->bc_attrs.max_resp_sz_cached = 0; |
| @@ -5131,8 +5142,6 @@ static int nfs4_verify_fore_channel_attrs(struct nfs41_create_session_args *args | |||
| 5131 | struct nfs4_channel_attrs *sent = &args->fc_attrs; | 5142 | struct nfs4_channel_attrs *sent = &args->fc_attrs; |
| 5132 | struct nfs4_channel_attrs *rcvd = &session->fc_attrs; | 5143 | struct nfs4_channel_attrs *rcvd = &session->fc_attrs; |
| 5133 | 5144 | ||
| 5134 | if (rcvd->headerpadsz > sent->headerpadsz) | ||
| 5135 | return -EINVAL; | ||
| 5136 | if (rcvd->max_resp_sz > sent->max_resp_sz) | 5145 | if (rcvd->max_resp_sz > sent->max_resp_sz) |
| 5137 | return -EINVAL; | 5146 | return -EINVAL; |
| 5138 | /* | 5147 | /* |
| @@ -5697,6 +5706,7 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
| 5697 | { | 5706 | { |
| 5698 | struct nfs4_layoutreturn *lrp = calldata; | 5707 | struct nfs4_layoutreturn *lrp = calldata; |
| 5699 | struct nfs_server *server; | 5708 | struct nfs_server *server; |
| 5709 | struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout; | ||
| 5700 | 5710 | ||
| 5701 | dprintk("--> %s\n", __func__); | 5711 | dprintk("--> %s\n", __func__); |
| 5702 | 5712 | ||
| @@ -5708,16 +5718,15 @@ static void nfs4_layoutreturn_done(struct rpc_task *task, void *calldata) | |||
| 5708 | nfs_restart_rpc(task, lrp->clp); | 5718 | nfs_restart_rpc(task, lrp->clp); |
| 5709 | return; | 5719 | return; |
| 5710 | } | 5720 | } |
| 5721 | spin_lock(&lo->plh_inode->i_lock); | ||
| 5711 | if (task->tk_status == 0) { | 5722 | if (task->tk_status == 0) { |
| 5712 | struct pnfs_layout_hdr *lo = NFS_I(lrp->args.inode)->layout; | ||
| 5713 | |||
| 5714 | if (lrp->res.lrs_present) { | 5723 | if (lrp->res.lrs_present) { |
| 5715 | spin_lock(&lo->plh_inode->i_lock); | ||
| 5716 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); | 5724 | pnfs_set_layout_stateid(lo, &lrp->res.stateid, true); |
| 5717 | spin_unlock(&lo->plh_inode->i_lock); | ||
| 5718 | } else | 5725 | } else |
| 5719 | BUG_ON(!list_empty(&lo->plh_segs)); | 5726 | BUG_ON(!list_empty(&lo->plh_segs)); |
| 5720 | } | 5727 | } |
| 5728 | lo->plh_block_lgets--; | ||
| 5729 | spin_unlock(&lo->plh_inode->i_lock); | ||
| 5721 | dprintk("<-- %s\n", __func__); | 5730 | dprintk("<-- %s\n", __func__); |
| 5722 | } | 5731 | } |
| 5723 | 5732 | ||
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index d869a5e5464b..6870bc61ceec 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -255,7 +255,7 @@ static int nfs4_stat_to_errno(int); | |||
| 255 | #define decode_fs_locations_maxsz \ | 255 | #define decode_fs_locations_maxsz \ |
| 256 | (0) | 256 | (0) |
| 257 | #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) | 257 | #define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz) |
| 258 | #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 4 + (NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN))) | 258 | #define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4)) |
| 259 | 259 | ||
| 260 | #if defined(CONFIG_NFS_V4_1) | 260 | #if defined(CONFIG_NFS_V4_1) |
| 261 | #define NFS4_MAX_MACHINE_NAME_LEN (64) | 261 | #define NFS4_MAX_MACHINE_NAME_LEN (64) |
| @@ -1725,7 +1725,7 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
| 1725 | *p++ = cpu_to_be32(args->flags); /*flags */ | 1725 | *p++ = cpu_to_be32(args->flags); /*flags */ |
| 1726 | 1726 | ||
| 1727 | /* Fore Channel */ | 1727 | /* Fore Channel */ |
| 1728 | *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ | 1728 | *p++ = cpu_to_be32(0); /* header padding size */ |
| 1729 | *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ | 1729 | *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */ |
| 1730 | *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ | 1730 | *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */ |
| 1731 | *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ | 1731 | *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */ |
| @@ -1734,7 +1734,7 @@ static void encode_create_session(struct xdr_stream *xdr, | |||
| 1734 | *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ | 1734 | *p++ = cpu_to_be32(0); /* rdmachannel_attrs */ |
| 1735 | 1735 | ||
| 1736 | /* Back Channel */ | 1736 | /* Back Channel */ |
| 1737 | *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */ | 1737 | *p++ = cpu_to_be32(0); /* header padding size */ |
| 1738 | *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ | 1738 | *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */ |
| 1739 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ | 1739 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */ |
| 1740 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ | 1740 | *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */ |
| @@ -3098,7 +3098,7 @@ out_overflow: | |||
| 3098 | return -EIO; | 3098 | return -EIO; |
| 3099 | } | 3099 | } |
| 3100 | 3100 | ||
| 3101 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) | 3101 | static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res) |
| 3102 | { | 3102 | { |
| 3103 | __be32 *p; | 3103 | __be32 *p; |
| 3104 | 3104 | ||
| @@ -3109,7 +3109,7 @@ static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap) | |||
| 3109 | if (unlikely(!p)) | 3109 | if (unlikely(!p)) |
| 3110 | goto out_overflow; | 3110 | goto out_overflow; |
| 3111 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; | 3111 | bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; |
| 3112 | return -be32_to_cpup(p); | 3112 | *res = -be32_to_cpup(p); |
| 3113 | } | 3113 | } |
| 3114 | return 0; | 3114 | return 0; |
| 3115 | out_overflow: | 3115 | out_overflow: |
| @@ -4070,6 +4070,7 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
| 4070 | int status; | 4070 | int status; |
| 4071 | umode_t fmode = 0; | 4071 | umode_t fmode = 0; |
| 4072 | uint32_t type; | 4072 | uint32_t type; |
| 4073 | int32_t err; | ||
| 4073 | 4074 | ||
| 4074 | status = decode_attr_type(xdr, bitmap, &type); | 4075 | status = decode_attr_type(xdr, bitmap, &type); |
| 4075 | if (status < 0) | 4076 | if (status < 0) |
| @@ -4095,13 +4096,12 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
| 4095 | goto xdr_error; | 4096 | goto xdr_error; |
| 4096 | fattr->valid |= status; | 4097 | fattr->valid |= status; |
| 4097 | 4098 | ||
| 4098 | status = decode_attr_error(xdr, bitmap); | 4099 | err = 0; |
| 4099 | if (status == -NFS4ERR_WRONGSEC) { | 4100 | status = decode_attr_error(xdr, bitmap, &err); |
| 4100 | nfs_fixup_secinfo_attributes(fattr, fh); | ||
| 4101 | status = 0; | ||
| 4102 | } | ||
| 4103 | if (status < 0) | 4101 | if (status < 0) |
| 4104 | goto xdr_error; | 4102 | goto xdr_error; |
| 4103 | if (err == -NFS4ERR_WRONGSEC) | ||
| 4104 | nfs_fixup_secinfo_attributes(fattr, fh); | ||
| 4105 | 4105 | ||
| 4106 | status = decode_attr_filehandle(xdr, bitmap, fh); | 4106 | status = decode_attr_filehandle(xdr, bitmap, fh); |
| 4107 | if (status < 0) | 4107 | if (status < 0) |
| @@ -4997,12 +4997,14 @@ static int decode_chan_attrs(struct xdr_stream *xdr, | |||
| 4997 | struct nfs4_channel_attrs *attrs) | 4997 | struct nfs4_channel_attrs *attrs) |
| 4998 | { | 4998 | { |
| 4999 | __be32 *p; | 4999 | __be32 *p; |
| 5000 | u32 nr_attrs; | 5000 | u32 nr_attrs, val; |
| 5001 | 5001 | ||
| 5002 | p = xdr_inline_decode(xdr, 28); | 5002 | p = xdr_inline_decode(xdr, 28); |
| 5003 | if (unlikely(!p)) | 5003 | if (unlikely(!p)) |
| 5004 | goto out_overflow; | 5004 | goto out_overflow; |
| 5005 | attrs->headerpadsz = be32_to_cpup(p++); | 5005 | val = be32_to_cpup(p++); /* headerpadsz */ |
| 5006 | if (val) | ||
| 5007 | return -EINVAL; /* no support for header padding yet */ | ||
| 5006 | attrs->max_rqst_sz = be32_to_cpup(p++); | 5008 | attrs->max_rqst_sz = be32_to_cpup(p++); |
| 5007 | attrs->max_resp_sz = be32_to_cpup(p++); | 5009 | attrs->max_resp_sz = be32_to_cpup(p++); |
| 5008 | attrs->max_resp_sz_cached = be32_to_cpup(p++); | 5010 | attrs->max_resp_sz_cached = be32_to_cpup(p++); |
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index 9cf208df1f25..8ff2ea3f10ef 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
| @@ -108,7 +108,6 @@ _dev_list_add(const struct nfs_server *nfss, | |||
| 108 | de = n; | 108 | de = n; |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | atomic_inc(&de->id_node.ref); | ||
| 112 | return de; | 111 | return de; |
| 113 | } | 112 | } |
| 114 | 113 | ||
| @@ -1001,6 +1000,9 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, | |||
| 1001 | if (!pnfs_generic_pg_test(pgio, prev, req)) | 1000 | if (!pnfs_generic_pg_test(pgio, prev, req)) |
| 1002 | return false; | 1001 | return false; |
| 1003 | 1002 | ||
| 1003 | if (pgio->pg_lseg == NULL) | ||
| 1004 | return true; | ||
| 1005 | |||
| 1004 | return pgio->pg_count + req->wb_bytes <= | 1006 | return pgio->pg_count + req->wb_bytes <= |
| 1005 | OBJIO_LSEG(pgio->pg_lseg)->max_io_size; | 1007 | OBJIO_LSEG(pgio->pg_lseg)->max_io_size; |
| 1006 | } | 1008 | } |
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c index dc3956c0de80..1d06f8e2adea 100644 --- a/fs/nfs/objlayout/objlayout.c +++ b/fs/nfs/objlayout/objlayout.c | |||
| @@ -291,7 +291,7 @@ objlayout_read_done(struct objlayout_io_state *state, ssize_t status, bool sync) | |||
| 291 | struct nfs_read_data *rdata; | 291 | struct nfs_read_data *rdata; |
| 292 | 292 | ||
| 293 | state->status = status; | 293 | state->status = status; |
| 294 | dprintk("%s: Begin status=%ld eof=%d\n", __func__, status, eof); | 294 | dprintk("%s: Begin status=%zd eof=%d\n", __func__, status, eof); |
| 295 | rdata = state->rpcdata; | 295 | rdata = state->rpcdata; |
| 296 | rdata->task.tk_status = status; | 296 | rdata->task.tk_status = status; |
| 297 | if (status >= 0) { | 297 | if (status >= 0) { |
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 7913961aff22..009855716286 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
| @@ -204,7 +204,7 @@ nfs_wait_on_request(struct nfs_page *req) | |||
| 204 | TASK_UNINTERRUPTIBLE); | 204 | TASK_UNINTERRUPTIBLE); |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req) | 207 | bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_page *prev, struct nfs_page *req) |
| 208 | { | 208 | { |
| 209 | /* | 209 | /* |
| 210 | * FIXME: ideally we should be able to coalesce all requests | 210 | * FIXME: ideally we should be able to coalesce all requests |
| @@ -218,6 +218,7 @@ static bool nfs_generic_pg_test(struct nfs_pageio_descriptor *desc, struct nfs_p | |||
| 218 | 218 | ||
| 219 | return desc->pg_count + req->wb_bytes <= desc->pg_bsize; | 219 | return desc->pg_count + req->wb_bytes <= desc->pg_bsize; |
| 220 | } | 220 | } |
| 221 | EXPORT_SYMBOL_GPL(nfs_generic_pg_test); | ||
| 221 | 222 | ||
| 222 | /** | 223 | /** |
| 223 | * nfs_pageio_init - initialise a page io descriptor | 224 | * nfs_pageio_init - initialise a page io descriptor |
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 8c1309d852a6..29c0ca7fc347 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c | |||
| @@ -634,14 +634,16 @@ _pnfs_return_layout(struct inode *ino) | |||
| 634 | 634 | ||
| 635 | spin_lock(&ino->i_lock); | 635 | spin_lock(&ino->i_lock); |
| 636 | lo = nfsi->layout; | 636 | lo = nfsi->layout; |
| 637 | if (!lo || !mark_matching_lsegs_invalid(lo, &tmp_list, NULL)) { | 637 | if (!lo) { |
| 638 | spin_unlock(&ino->i_lock); | 638 | spin_unlock(&ino->i_lock); |
| 639 | dprintk("%s: no layout segments to return\n", __func__); | 639 | dprintk("%s: no layout to return\n", __func__); |
| 640 | goto out; | 640 | return status; |
| 641 | } | 641 | } |
| 642 | stateid = nfsi->layout->plh_stateid; | 642 | stateid = nfsi->layout->plh_stateid; |
| 643 | /* Reference matched in nfs4_layoutreturn_release */ | 643 | /* Reference matched in nfs4_layoutreturn_release */ |
| 644 | get_layout_hdr(lo); | 644 | get_layout_hdr(lo); |
| 645 | mark_matching_lsegs_invalid(lo, &tmp_list, NULL); | ||
| 646 | lo->plh_block_lgets++; | ||
| 645 | spin_unlock(&ino->i_lock); | 647 | spin_unlock(&ino->i_lock); |
| 646 | pnfs_free_lseg_list(&tmp_list); | 648 | pnfs_free_lseg_list(&tmp_list); |
| 647 | 649 | ||
| @@ -650,6 +652,9 @@ _pnfs_return_layout(struct inode *ino) | |||
| 650 | lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); | 652 | lrp = kzalloc(sizeof(*lrp), GFP_KERNEL); |
| 651 | if (unlikely(lrp == NULL)) { | 653 | if (unlikely(lrp == NULL)) { |
| 652 | status = -ENOMEM; | 654 | status = -ENOMEM; |
| 655 | set_bit(NFS_LAYOUT_RW_FAILED, &lo->plh_flags); | ||
| 656 | set_bit(NFS_LAYOUT_RO_FAILED, &lo->plh_flags); | ||
| 657 | put_layout_hdr(lo); | ||
| 653 | goto out; | 658 | goto out; |
| 654 | } | 659 | } |
| 655 | 660 | ||
| @@ -887,7 +892,7 @@ pnfs_find_lseg(struct pnfs_layout_hdr *lo, | |||
| 887 | ret = get_lseg(lseg); | 892 | ret = get_lseg(lseg); |
| 888 | break; | 893 | break; |
| 889 | } | 894 | } |
| 890 | if (cmp_layout(range, &lseg->pls_range) > 0) | 895 | if (lseg->pls_range.offset > range->offset) |
| 891 | break; | 896 | break; |
| 892 | } | 897 | } |
| 893 | 898 | ||
| @@ -1059,23 +1064,36 @@ pnfs_generic_pg_test(struct nfs_pageio_descriptor *pgio, struct nfs_page *prev, | |||
| 1059 | gfp_flags = GFP_NOFS; | 1064 | gfp_flags = GFP_NOFS; |
| 1060 | } | 1065 | } |
| 1061 | 1066 | ||
| 1062 | if (pgio->pg_count == prev->wb_bytes) { | 1067 | if (pgio->pg_lseg == NULL) { |
| 1068 | if (pgio->pg_count != prev->wb_bytes) | ||
| 1069 | return true; | ||
| 1063 | /* This is first coelesce call for a series of nfs_pages */ | 1070 | /* This is first coelesce call for a series of nfs_pages */ |
| 1064 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, | 1071 | pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode, |
| 1065 | prev->wb_context, | 1072 | prev->wb_context, |
| 1066 | req_offset(req), | 1073 | req_offset(prev), |
| 1067 | pgio->pg_count, | 1074 | pgio->pg_count, |
| 1068 | access_type, | 1075 | access_type, |
| 1069 | gfp_flags); | 1076 | gfp_flags); |
| 1070 | return true; | 1077 | if (pgio->pg_lseg == NULL) |
| 1078 | return true; | ||
| 1071 | } | 1079 | } |
| 1072 | 1080 | ||
| 1073 | if (pgio->pg_lseg && | 1081 | /* |
| 1074 | req_offset(req) > end_offset(pgio->pg_lseg->pls_range.offset, | 1082 | * Test if a nfs_page is fully contained in the pnfs_layout_range. |
| 1075 | pgio->pg_lseg->pls_range.length)) | 1083 | * Note that this test makes several assumptions: |
| 1076 | return false; | 1084 | * - that the previous nfs_page in the struct nfs_pageio_descriptor |
| 1077 | 1085 | * is known to lie within the range. | |
| 1078 | return true; | 1086 | * - that the nfs_page being tested is known to be contiguous with the |
| 1087 | * previous nfs_page. | ||
| 1088 | * - Layout ranges are page aligned, so we only have to test the | ||
| 1089 | * start offset of the request. | ||
| 1090 | * | ||
| 1091 | * Please also note that 'end_offset' is actually the offset of the | ||
| 1092 | * first byte that lies outside the pnfs_layout_range. FIXME? | ||
| 1093 | * | ||
| 1094 | */ | ||
| 1095 | return req_offset(req) < end_offset(pgio->pg_lseg->pls_range.offset, | ||
| 1096 | pgio->pg_lseg->pls_range.length); | ||
| 1079 | } | 1097 | } |
| 1080 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); | 1098 | EXPORT_SYMBOL_GPL(pnfs_generic_pg_test); |
| 1081 | 1099 | ||
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 48d0a8e4d062..96bf4e6f45be 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
| @@ -186,6 +186,7 @@ int pnfs_ld_read_done(struct nfs_read_data *); | |||
| 186 | /* pnfs_dev.c */ | 186 | /* pnfs_dev.c */ |
| 187 | struct nfs4_deviceid_node { | 187 | struct nfs4_deviceid_node { |
| 188 | struct hlist_node node; | 188 | struct hlist_node node; |
| 189 | struct hlist_node tmpnode; | ||
| 189 | const struct pnfs_layoutdriver_type *ld; | 190 | const struct pnfs_layoutdriver_type *ld; |
| 190 | const struct nfs_client *nfs_client; | 191 | const struct nfs_client *nfs_client; |
| 191 | struct nfs4_deviceid deviceid; | 192 | struct nfs4_deviceid deviceid; |
diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c index c65e133ce9c0..f0f8e1e22f6c 100644 --- a/fs/nfs/pnfs_dev.c +++ b/fs/nfs/pnfs_dev.c | |||
| @@ -174,6 +174,7 @@ nfs4_init_deviceid_node(struct nfs4_deviceid_node *d, | |||
| 174 | const struct nfs4_deviceid *id) | 174 | const struct nfs4_deviceid *id) |
| 175 | { | 175 | { |
| 176 | INIT_HLIST_NODE(&d->node); | 176 | INIT_HLIST_NODE(&d->node); |
| 177 | INIT_HLIST_NODE(&d->tmpnode); | ||
| 177 | d->ld = ld; | 178 | d->ld = ld; |
| 178 | d->nfs_client = nfs_client; | 179 | d->nfs_client = nfs_client; |
| 179 | d->deviceid = *id; | 180 | d->deviceid = *id; |
| @@ -208,6 +209,7 @@ nfs4_insert_deviceid_node(struct nfs4_deviceid_node *new) | |||
| 208 | 209 | ||
| 209 | hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); | 210 | hlist_add_head_rcu(&new->node, &nfs4_deviceid_cache[hash]); |
| 210 | spin_unlock(&nfs4_deviceid_lock); | 211 | spin_unlock(&nfs4_deviceid_lock); |
| 212 | atomic_inc(&new->ref); | ||
| 211 | 213 | ||
| 212 | return new; | 214 | return new; |
| 213 | } | 215 | } |
| @@ -238,24 +240,29 @@ static void | |||
| 238 | _deviceid_purge_client(const struct nfs_client *clp, long hash) | 240 | _deviceid_purge_client(const struct nfs_client *clp, long hash) |
| 239 | { | 241 | { |
| 240 | struct nfs4_deviceid_node *d; | 242 | struct nfs4_deviceid_node *d; |
| 241 | struct hlist_node *n, *next; | 243 | struct hlist_node *n; |
| 242 | HLIST_HEAD(tmp); | 244 | HLIST_HEAD(tmp); |
| 243 | 245 | ||
| 246 | spin_lock(&nfs4_deviceid_lock); | ||
| 244 | rcu_read_lock(); | 247 | rcu_read_lock(); |
| 245 | hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node) | 248 | hlist_for_each_entry_rcu(d, n, &nfs4_deviceid_cache[hash], node) |
| 246 | if (d->nfs_client == clp && atomic_read(&d->ref)) { | 249 | if (d->nfs_client == clp && atomic_read(&d->ref)) { |
| 247 | hlist_del_init_rcu(&d->node); | 250 | hlist_del_init_rcu(&d->node); |
| 248 | hlist_add_head(&d->node, &tmp); | 251 | hlist_add_head(&d->tmpnode, &tmp); |
| 249 | } | 252 | } |
| 250 | rcu_read_unlock(); | 253 | rcu_read_unlock(); |
| 254 | spin_unlock(&nfs4_deviceid_lock); | ||
| 251 | 255 | ||
| 252 | if (hlist_empty(&tmp)) | 256 | if (hlist_empty(&tmp)) |
| 253 | return; | 257 | return; |
| 254 | 258 | ||
| 255 | synchronize_rcu(); | 259 | synchronize_rcu(); |
| 256 | hlist_for_each_entry_safe(d, n, next, &tmp, node) | 260 | while (!hlist_empty(&tmp)) { |
| 261 | d = hlist_entry(tmp.first, struct nfs4_deviceid_node, tmpnode); | ||
| 262 | hlist_del(&d->tmpnode); | ||
| 257 | if (atomic_dec_and_test(&d->ref)) | 263 | if (atomic_dec_and_test(&d->ref)) |
| 258 | d->ld->free_deviceid_node(d); | 264 | d->ld->free_deviceid_node(d); |
| 265 | } | ||
| 259 | } | 266 | } |
| 260 | 267 | ||
| 261 | void | 268 | void |
| @@ -263,8 +270,8 @@ nfs4_deviceid_purge_client(const struct nfs_client *clp) | |||
| 263 | { | 270 | { |
| 264 | long h; | 271 | long h; |
| 265 | 272 | ||
| 266 | spin_lock(&nfs4_deviceid_lock); | 273 | if (!(clp->cl_exchange_flags & EXCHGID4_FLAG_USE_PNFS_MDS)) |
| 274 | return; | ||
| 267 | for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++) | 275 | for (h = 0; h < NFS4_DEVICE_ID_HASH_SIZE; h++) |
| 268 | _deviceid_purge_client(clp, h); | 276 | _deviceid_purge_client(clp, h); |
| 269 | spin_unlock(&nfs4_deviceid_lock); | ||
| 270 | } | 277 | } |
diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 18b3e8975fe0..fbb2a5ef5817 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig | |||
| @@ -82,6 +82,7 @@ config NFSD_V4 | |||
| 82 | select NFSD_V3 | 82 | select NFSD_V3 |
| 83 | select FS_POSIX_ACL | 83 | select FS_POSIX_ACL |
| 84 | select SUNRPC_GSS | 84 | select SUNRPC_GSS |
| 85 | select CRYPTO | ||
| 85 | help | 86 | help |
| 86 | This option enables support in your system's NFS server for | 87 | This option enables support in your system's NFS server for |
| 87 | version 4 of the NFS protocol (RFC 3530). | 88 | version 4 of the NFS protocol (RFC 3530). |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 1f5eae40f34e..2b1449dd2f49 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <linux/lockd/lockd.h> | 13 | #include <linux/lockd/lockd.h> |
| 14 | #include <linux/sunrpc/clnt.h> | 14 | #include <linux/sunrpc/clnt.h> |
| 15 | #include <linux/sunrpc/gss_api.h> | 15 | #include <linux/sunrpc/gss_api.h> |
| 16 | #include <linux/sunrpc/gss_krb5_enctypes.h> | ||
| 16 | 17 | ||
| 17 | #include "idmap.h" | 18 | #include "idmap.h" |
| 18 | #include "nfsd.h" | 19 | #include "nfsd.h" |
| @@ -189,18 +190,10 @@ static struct file_operations export_features_operations = { | |||
| 189 | .release = single_release, | 190 | .release = single_release, |
| 190 | }; | 191 | }; |
| 191 | 192 | ||
| 192 | #ifdef CONFIG_SUNRPC_GSS | 193 | #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) |
| 193 | static int supported_enctypes_show(struct seq_file *m, void *v) | 194 | static int supported_enctypes_show(struct seq_file *m, void *v) |
| 194 | { | 195 | { |
| 195 | struct gss_api_mech *k5mech; | 196 | seq_printf(m, KRB5_SUPPORTED_ENCTYPES); |
| 196 | |||
| 197 | k5mech = gss_mech_get_by_name("krb5"); | ||
| 198 | if (k5mech == NULL) | ||
| 199 | goto out; | ||
| 200 | if (k5mech->gm_upcall_enctypes != NULL) | ||
| 201 | seq_printf(m, k5mech->gm_upcall_enctypes); | ||
| 202 | gss_mech_put(k5mech); | ||
| 203 | out: | ||
| 204 | return 0; | 197 | return 0; |
| 205 | } | 198 | } |
| 206 | 199 | ||
| @@ -215,7 +208,7 @@ static struct file_operations supported_enctypes_ops = { | |||
| 215 | .llseek = seq_lseek, | 208 | .llseek = seq_lseek, |
| 216 | .release = single_release, | 209 | .release = single_release, |
| 217 | }; | 210 | }; |
| 218 | #endif /* CONFIG_SUNRPC_GSS */ | 211 | #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ |
| 219 | 212 | ||
| 220 | extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); | 213 | extern int nfsd_pool_stats_open(struct inode *inode, struct file *file); |
| 221 | extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); | 214 | extern int nfsd_pool_stats_release(struct inode *inode, struct file *file); |
| @@ -1427,9 +1420,9 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) | |||
| 1427 | [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, | 1420 | [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, |
| 1428 | [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, | 1421 | [NFSD_Ports] = {"portlist", &transaction_ops, S_IWUSR|S_IRUGO}, |
| 1429 | [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, | 1422 | [NFSD_MaxBlkSize] = {"max_block_size", &transaction_ops, S_IWUSR|S_IRUGO}, |
| 1430 | #ifdef CONFIG_SUNRPC_GSS | 1423 | #if defined(CONFIG_SUNRPC_GSS) || defined(CONFIG_SUNRPC_GSS_MODULE) |
| 1431 | [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, | 1424 | [NFSD_SupportedEnctypes] = {"supported_krb5_enctypes", &supported_enctypes_ops, S_IRUGO}, |
| 1432 | #endif /* CONFIG_SUNRPC_GSS */ | 1425 | #endif /* CONFIG_SUNRPC_GSS or CONFIG_SUNRPC_GSS_MODULE */ |
| 1433 | #ifdef CONFIG_NFSD_V4 | 1426 | #ifdef CONFIG_NFSD_V4 |
| 1434 | [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, | 1427 | [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, |
| 1435 | [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, | 1428 | [NFSD_Gracetime] = {"nfsv4gracetime", &transaction_ops, S_IWUSR|S_IRUSR}, |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index d5718273bb32..fd0acca5370a 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
| @@ -696,7 +696,15 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access, u32 *suppor | |||
| 696 | } | 696 | } |
| 697 | #endif /* CONFIG_NFSD_V3 */ | 697 | #endif /* CONFIG_NFSD_V3 */ |
| 698 | 698 | ||
| 699 | static int nfsd_open_break_lease(struct inode *inode, int access) | ||
| 700 | { | ||
| 701 | unsigned int mode; | ||
| 699 | 702 | ||
| 703 | if (access & NFSD_MAY_NOT_BREAK_LEASE) | ||
| 704 | return 0; | ||
| 705 | mode = (access & NFSD_MAY_WRITE) ? O_WRONLY : O_RDONLY; | ||
| 706 | return break_lease(inode, mode | O_NONBLOCK); | ||
| 707 | } | ||
| 700 | 708 | ||
| 701 | /* | 709 | /* |
| 702 | * Open an existing file or directory. | 710 | * Open an existing file or directory. |
| @@ -744,12 +752,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, | |||
| 744 | if (!inode->i_fop) | 752 | if (!inode->i_fop) |
| 745 | goto out; | 753 | goto out; |
| 746 | 754 | ||
| 747 | /* | 755 | host_err = nfsd_open_break_lease(inode, access); |
| 748 | * Check to see if there are any leases on this file. | ||
| 749 | * This may block while leases are broken. | ||
| 750 | */ | ||
| 751 | if (!(access & NFSD_MAY_NOT_BREAK_LEASE)) | ||
| 752 | host_err = break_lease(inode, O_NONBLOCK | ((access & NFSD_MAY_WRITE) ? O_WRONLY : 0)); | ||
| 753 | if (host_err) /* NOMEM or WOULDBLOCK */ | 756 | if (host_err) /* NOMEM or WOULDBLOCK */ |
| 754 | goto out_nfserr; | 757 | goto out_nfserr; |
| 755 | 758 | ||
| @@ -1660,8 +1663,10 @@ nfsd_link(struct svc_rqst *rqstp, struct svc_fh *ffhp, | |||
| 1660 | if (!dold->d_inode) | 1663 | if (!dold->d_inode) |
| 1661 | goto out_drop_write; | 1664 | goto out_drop_write; |
| 1662 | host_err = nfsd_break_lease(dold->d_inode); | 1665 | host_err = nfsd_break_lease(dold->d_inode); |
| 1663 | if (host_err) | 1666 | if (host_err) { |
| 1667 | err = nfserrno(host_err); | ||
| 1664 | goto out_drop_write; | 1668 | goto out_drop_write; |
| 1669 | } | ||
| 1665 | host_err = vfs_link(dold, dirp, dnew); | 1670 | host_err = vfs_link(dold, dirp, dnew); |
| 1666 | if (!host_err) { | 1671 | if (!host_err) { |
| 1667 | err = nfserrno(commit_metadata(ffhp)); | 1672 | err = nfserrno(commit_metadata(ffhp)); |
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c index b954878ad6ce..b9b45fc2903e 100644 --- a/fs/nilfs2/inode.c +++ b/fs/nilfs2/inode.c | |||
| @@ -801,12 +801,7 @@ out_err: | |||
| 801 | 801 | ||
| 802 | int nilfs_permission(struct inode *inode, int mask, unsigned int flags) | 802 | int nilfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 803 | { | 803 | { |
| 804 | struct nilfs_root *root; | 804 | struct nilfs_root *root = NILFS_I(inode)->i_root; |
| 805 | |||
| 806 | if (flags & IPERM_FLAG_RCU) | ||
| 807 | return -ECHILD; | ||
| 808 | |||
| 809 | root = NILFS_I(inode)->i_root; | ||
| 810 | if ((mask & MAY_WRITE) && root && | 805 | if ((mask & MAY_WRITE) && root && |
| 811 | root->cno != NILFS_CPTREE_CURRENT_CNO) | 806 | root->cno != NILFS_CPTREE_CURRENT_CNO) |
| 812 | return -EROFS; /* snapshot is not writable */ | 807 | return -EROFS; /* snapshot is not writable */ |
diff --git a/fs/omfs/file.c b/fs/omfs/file.c index d738a7e493dd..2c6d95257a4d 100644 --- a/fs/omfs/file.c +++ b/fs/omfs/file.c | |||
| @@ -4,7 +4,6 @@ | |||
| 4 | * Released under GPL v2. | 4 | * Released under GPL v2. |
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <linux/version.h> | ||
| 8 | #include <linux/module.h> | 7 | #include <linux/module.h> |
| 9 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
| 10 | #include <linux/buffer_head.h> | 9 | #include <linux/buffer_head.h> |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 14def991d9dd..fc5bc2767692 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -2169,11 +2169,7 @@ static const struct file_operations proc_fd_operations = { | |||
| 2169 | */ | 2169 | */ |
| 2170 | static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags) | 2170 | static int proc_fd_permission(struct inode *inode, int mask, unsigned int flags) |
| 2171 | { | 2171 | { |
| 2172 | int rv; | 2172 | int rv = generic_permission(inode, mask, flags, NULL); |
| 2173 | |||
| 2174 | if (flags & IPERM_FLAG_RCU) | ||
| 2175 | return -ECHILD; | ||
| 2176 | rv = generic_permission(inode, mask, flags, NULL); | ||
| 2177 | if (rv == 0) | 2173 | if (rv == 0) |
| 2178 | return 0; | 2174 | return 0; |
| 2179 | if (task_pid(current) == proc_pid(inode)) | 2175 | if (task_pid(current) == proc_pid(inode)) |
| @@ -2712,6 +2708,9 @@ static int do_io_accounting(struct task_struct *task, char *buffer, int whole) | |||
| 2712 | struct task_io_accounting acct = task->ioac; | 2708 | struct task_io_accounting acct = task->ioac; |
| 2713 | unsigned long flags; | 2709 | unsigned long flags; |
| 2714 | 2710 | ||
| 2711 | if (!ptrace_may_access(task, PTRACE_MODE_READ)) | ||
| 2712 | return -EACCES; | ||
| 2713 | |||
| 2715 | if (whole && lock_task_sighand(task, &flags)) { | 2714 | if (whole && lock_task_sighand(task, &flags)) { |
| 2716 | struct task_struct *t = task; | 2715 | struct task_struct *t = task; |
| 2717 | 2716 | ||
| @@ -2843,7 +2842,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2843 | REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), | 2842 | REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations), |
| 2844 | #endif | 2843 | #endif |
| 2845 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 2844 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 2846 | INF("io", S_IRUGO, proc_tgid_io_accounting), | 2845 | INF("io", S_IRUSR, proc_tgid_io_accounting), |
| 2847 | #endif | 2846 | #endif |
| 2848 | #ifdef CONFIG_HARDWALL | 2847 | #ifdef CONFIG_HARDWALL |
| 2849 | INF("hardwall", S_IRUGO, proc_pid_hardwall), | 2848 | INF("hardwall", S_IRUGO, proc_pid_hardwall), |
| @@ -3185,7 +3184,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 3185 | REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), | 3184 | REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations), |
| 3186 | #endif | 3185 | #endif |
| 3187 | #ifdef CONFIG_TASK_IO_ACCOUNTING | 3186 | #ifdef CONFIG_TASK_IO_ACCOUNTING |
| 3188 | INF("io", S_IRUGO, proc_tid_io_accounting), | 3187 | INF("io", S_IRUSR, proc_tid_io_accounting), |
| 3189 | #endif | 3188 | #endif |
| 3190 | #ifdef CONFIG_HARDWALL | 3189 | #ifdef CONFIG_HARDWALL |
| 3191 | INF("hardwall", S_IRUGO, proc_pid_hardwall), | 3190 | INF("hardwall", S_IRUGO, proc_pid_hardwall), |
diff --git a/fs/proc/namespaces.c b/fs/proc/namespaces.c index 781dec5bd682..be177f702acb 100644 --- a/fs/proc/namespaces.c +++ b/fs/proc/namespaces.c | |||
| @@ -38,18 +38,21 @@ static struct dentry *proc_ns_instantiate(struct inode *dir, | |||
| 38 | struct inode *inode; | 38 | struct inode *inode; |
| 39 | struct proc_inode *ei; | 39 | struct proc_inode *ei; |
| 40 | struct dentry *error = ERR_PTR(-ENOENT); | 40 | struct dentry *error = ERR_PTR(-ENOENT); |
| 41 | void *ns; | ||
| 41 | 42 | ||
| 42 | inode = proc_pid_make_inode(dir->i_sb, task); | 43 | inode = proc_pid_make_inode(dir->i_sb, task); |
| 43 | if (!inode) | 44 | if (!inode) |
| 44 | goto out; | 45 | goto out; |
| 45 | 46 | ||
| 47 | ns = ns_ops->get(task); | ||
| 48 | if (!ns) | ||
| 49 | goto out_iput; | ||
| 50 | |||
| 46 | ei = PROC_I(inode); | 51 | ei = PROC_I(inode); |
| 47 | inode->i_mode = S_IFREG|S_IRUSR; | 52 | inode->i_mode = S_IFREG|S_IRUSR; |
| 48 | inode->i_fop = &ns_file_operations; | 53 | inode->i_fop = &ns_file_operations; |
| 49 | ei->ns_ops = ns_ops; | 54 | ei->ns_ops = ns_ops; |
| 50 | ei->ns = ns_ops->get(task); | 55 | ei->ns = ns; |
| 51 | if (!ei->ns) | ||
| 52 | goto out_iput; | ||
| 53 | 56 | ||
| 54 | dentry->d_op = &pid_dentry_operations; | 57 | dentry->d_op = &pid_dentry_operations; |
| 55 | d_add(dentry, inode); | 58 | d_add(dentry, inode); |
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index f50133c11c24..d167de365a8d 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
| @@ -304,9 +304,6 @@ static int proc_sys_permission(struct inode *inode, int mask,unsigned int flags) | |||
| 304 | struct ctl_table *table; | 304 | struct ctl_table *table; |
| 305 | int error; | 305 | int error; |
| 306 | 306 | ||
| 307 | if (flags & IPERM_FLAG_RCU) | ||
| 308 | return -ECHILD; | ||
| 309 | |||
| 310 | /* Executable files are not allowed under /proc/sys/ */ | 307 | /* Executable files are not allowed under /proc/sys/ */ |
| 311 | if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) | 308 | if ((mask & MAY_EXEC) && S_ISREG(inode->i_mode)) |
| 312 | return -EACCES; | 309 | return -EACCES; |
diff --git a/fs/proc/root.c b/fs/proc/root.c index a9000e9cfee5..d6c3b416529b 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
| @@ -28,11 +28,12 @@ static int proc_test_super(struct super_block *sb, void *data) | |||
| 28 | 28 | ||
| 29 | static int proc_set_super(struct super_block *sb, void *data) | 29 | static int proc_set_super(struct super_block *sb, void *data) |
| 30 | { | 30 | { |
| 31 | struct pid_namespace *ns; | 31 | int err = set_anon_super(sb, NULL); |
| 32 | 32 | if (!err) { | |
| 33 | ns = (struct pid_namespace *)data; | 33 | struct pid_namespace *ns = (struct pid_namespace *)data; |
| 34 | sb->s_fs_info = get_pid_ns(ns); | 34 | sb->s_fs_info = get_pid_ns(ns); |
| 35 | return set_anon_super(sb, NULL); | 35 | } |
| 36 | return err; | ||
| 36 | } | 37 | } |
| 37 | 38 | ||
| 38 | static struct dentry *proc_mount(struct file_system_type *fs_type, | 39 | static struct dentry *proc_mount(struct file_system_type *fs_type, |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index e8a62f41b458..d78089690965 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
| @@ -954,8 +954,6 @@ static int xattr_mount_check(struct super_block *s) | |||
| 954 | 954 | ||
| 955 | int reiserfs_permission(struct inode *inode, int mask, unsigned int flags) | 955 | int reiserfs_permission(struct inode *inode, int mask, unsigned int flags) |
| 956 | { | 956 | { |
| 957 | if (flags & IPERM_FLAG_RCU) | ||
| 958 | return -ECHILD; | ||
| 959 | /* | 957 | /* |
| 960 | * We don't do permission checks on the internal objects. | 958 | * We don't do permission checks on the internal objects. |
| 961 | * Permissions are determined by the "owning" object. | 959 | * Permissions are determined by the "owning" object. |
diff --git a/fs/romfs/mmap-nommu.c b/fs/romfs/mmap-nommu.c index f0511e816967..eed99428f104 100644 --- a/fs/romfs/mmap-nommu.c +++ b/fs/romfs/mmap-nommu.c | |||
| @@ -27,14 +27,18 @@ static unsigned long romfs_get_unmapped_area(struct file *file, | |||
| 27 | { | 27 | { |
| 28 | struct inode *inode = file->f_mapping->host; | 28 | struct inode *inode = file->f_mapping->host; |
| 29 | struct mtd_info *mtd = inode->i_sb->s_mtd; | 29 | struct mtd_info *mtd = inode->i_sb->s_mtd; |
| 30 | unsigned long isize, offset; | 30 | unsigned long isize, offset, maxpages, lpages; |
| 31 | 31 | ||
| 32 | if (!mtd) | 32 | if (!mtd) |
| 33 | goto cant_map_directly; | 33 | goto cant_map_directly; |
| 34 | 34 | ||
| 35 | /* the mapping mustn't extend beyond the EOF */ | ||
| 36 | lpages = (len + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 35 | isize = i_size_read(inode); | 37 | isize = i_size_read(inode); |
| 36 | offset = pgoff << PAGE_SHIFT; | 38 | offset = pgoff << PAGE_SHIFT; |
| 37 | if (offset > isize || len > isize || offset > isize - len) | 39 | |
| 40 | maxpages = (isize + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
| 41 | if ((pgoff >= maxpages) || (maxpages - pgoff < lpages)) | ||
| 38 | return (unsigned long) -EINVAL; | 42 | return (unsigned long) -EINVAL; |
| 39 | 43 | ||
| 40 | /* we need to call down to the MTD layer to do the actual mapping */ | 44 | /* we need to call down to the MTD layer to do the actual mapping */ |
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index 266895783b47..e34f0d99ea4e 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
| @@ -95,6 +95,14 @@ static int sysfs_set_super(struct super_block *sb, void *data) | |||
| 95 | return error; | 95 | return error; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static void free_sysfs_super_info(struct sysfs_super_info *info) | ||
| 99 | { | ||
| 100 | int type; | ||
| 101 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) | ||
| 102 | kobj_ns_drop(type, info->ns[type]); | ||
| 103 | kfree(info); | ||
| 104 | } | ||
| 105 | |||
| 98 | static struct dentry *sysfs_mount(struct file_system_type *fs_type, | 106 | static struct dentry *sysfs_mount(struct file_system_type *fs_type, |
| 99 | int flags, const char *dev_name, void *data) | 107 | int flags, const char *dev_name, void *data) |
| 100 | { | 108 | { |
| @@ -108,11 +116,11 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, | |||
| 108 | return ERR_PTR(-ENOMEM); | 116 | return ERR_PTR(-ENOMEM); |
| 109 | 117 | ||
| 110 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) | 118 | for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++) |
| 111 | info->ns[type] = kobj_ns_current(type); | 119 | info->ns[type] = kobj_ns_grab_current(type); |
| 112 | 120 | ||
| 113 | sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info); | 121 | sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info); |
| 114 | if (IS_ERR(sb) || sb->s_fs_info != info) | 122 | if (IS_ERR(sb) || sb->s_fs_info != info) |
| 115 | kfree(info); | 123 | free_sysfs_super_info(info); |
| 116 | if (IS_ERR(sb)) | 124 | if (IS_ERR(sb)) |
| 117 | return ERR_CAST(sb); | 125 | return ERR_CAST(sb); |
| 118 | if (!sb->s_root) { | 126 | if (!sb->s_root) { |
| @@ -131,12 +139,11 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type, | |||
| 131 | static void sysfs_kill_sb(struct super_block *sb) | 139 | static void sysfs_kill_sb(struct super_block *sb) |
| 132 | { | 140 | { |
| 133 | struct sysfs_super_info *info = sysfs_info(sb); | 141 | struct sysfs_super_info *info = sysfs_info(sb); |
| 134 | |||
| 135 | /* Remove the superblock from fs_supers/s_instances | 142 | /* Remove the superblock from fs_supers/s_instances |
| 136 | * so we can't find it, before freeing sysfs_super_info. | 143 | * so we can't find it, before freeing sysfs_super_info. |
| 137 | */ | 144 | */ |
| 138 | kill_anon_super(sb); | 145 | kill_anon_super(sb); |
| 139 | kfree(info); | 146 | free_sysfs_super_info(info); |
| 140 | } | 147 | } |
| 141 | 148 | ||
| 142 | static struct file_system_type sysfs_fs_type = { | 149 | static struct file_system_type sysfs_fs_type = { |
| @@ -145,28 +152,6 @@ static struct file_system_type sysfs_fs_type = { | |||
| 145 | .kill_sb = sysfs_kill_sb, | 152 | .kill_sb = sysfs_kill_sb, |
| 146 | }; | 153 | }; |
| 147 | 154 | ||
| 148 | void sysfs_exit_ns(enum kobj_ns_type type, const void *ns) | ||
| 149 | { | ||
| 150 | struct super_block *sb; | ||
| 151 | |||
| 152 | mutex_lock(&sysfs_mutex); | ||
| 153 | spin_lock(&sb_lock); | ||
| 154 | list_for_each_entry(sb, &sysfs_fs_type.fs_supers, s_instances) { | ||
| 155 | struct sysfs_super_info *info = sysfs_info(sb); | ||
| 156 | /* | ||
| 157 | * If we see a superblock on the fs_supers/s_instances | ||
| 158 | * list the unmount has not completed and sb->s_fs_info | ||
| 159 | * points to a valid struct sysfs_super_info. | ||
| 160 | */ | ||
| 161 | /* Ignore superblocks with the wrong ns */ | ||
| 162 | if (info->ns[type] != ns) | ||
| 163 | continue; | ||
| 164 | info->ns[type] = NULL; | ||
| 165 | } | ||
| 166 | spin_unlock(&sb_lock); | ||
| 167 | mutex_unlock(&sysfs_mutex); | ||
| 168 | } | ||
| 169 | |||
| 170 | int __init sysfs_init(void) | 155 | int __init sysfs_init(void) |
| 171 | { | 156 | { |
| 172 | int err = -ENOMEM; | 157 | int err = -ENOMEM; |
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h index 3d28af31d863..2ed2404f3113 100644 --- a/fs/sysfs/sysfs.h +++ b/fs/sysfs/sysfs.h | |||
| @@ -136,7 +136,7 @@ struct sysfs_addrm_cxt { | |||
| 136 | * instance). | 136 | * instance). |
| 137 | */ | 137 | */ |
| 138 | struct sysfs_super_info { | 138 | struct sysfs_super_info { |
| 139 | const void *ns[KOBJ_NS_TYPES]; | 139 | void *ns[KOBJ_NS_TYPES]; |
| 140 | }; | 140 | }; |
| 141 | #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) | 141 | #define sysfs_info(SB) ((struct sysfs_super_info *)(SB->s_fs_info)) |
| 142 | extern struct sysfs_dirent sysfs_root; | 142 | extern struct sysfs_dirent sysfs_root; |
diff --git a/fs/timerfd.c b/fs/timerfd.c index f67acbdda5e8..dffeb3795af1 100644 --- a/fs/timerfd.c +++ b/fs/timerfd.c | |||
| @@ -61,7 +61,9 @@ static enum hrtimer_restart timerfd_tmrproc(struct hrtimer *htmr) | |||
| 61 | 61 | ||
| 62 | /* | 62 | /* |
| 63 | * Called when the clock was set to cancel the timers in the cancel | 63 | * Called when the clock was set to cancel the timers in the cancel |
| 64 | * list. | 64 | * list. This will wake up processes waiting on these timers. The |
| 65 | * wake-up requires ctx->ticks to be non zero, therefore we increment | ||
| 66 | * it before calling wake_up_locked(). | ||
| 65 | */ | 67 | */ |
| 66 | void timerfd_clock_was_set(void) | 68 | void timerfd_clock_was_set(void) |
| 67 | { | 69 | { |
| @@ -76,6 +78,7 @@ void timerfd_clock_was_set(void) | |||
| 76 | spin_lock_irqsave(&ctx->wqh.lock, flags); | 78 | spin_lock_irqsave(&ctx->wqh.lock, flags); |
| 77 | if (ctx->moffs.tv64 != moffs.tv64) { | 79 | if (ctx->moffs.tv64 != moffs.tv64) { |
| 78 | ctx->moffs.tv64 = KTIME_MAX; | 80 | ctx->moffs.tv64 = KTIME_MAX; |
| 81 | ctx->ticks++; | ||
| 79 | wake_up_locked(&ctx->wqh); | 82 | wake_up_locked(&ctx->wqh); |
| 80 | } | 83 | } |
| 81 | spin_unlock_irqrestore(&ctx->wqh.lock, flags); | 84 | spin_unlock_irqrestore(&ctx->wqh.lock, flags); |
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index b5aeb5a8ebed..529be0582029 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c | |||
| @@ -1848,7 +1848,6 @@ static void ubifs_put_super(struct super_block *sb) | |||
| 1848 | bdi_destroy(&c->bdi); | 1848 | bdi_destroy(&c->bdi); |
| 1849 | ubi_close_volume(c->ubi); | 1849 | ubi_close_volume(c->ubi); |
| 1850 | mutex_unlock(&c->umount_mutex); | 1850 | mutex_unlock(&c->umount_mutex); |
| 1851 | kfree(c); | ||
| 1852 | } | 1851 | } |
| 1853 | 1852 | ||
| 1854 | static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) | 1853 | static int ubifs_remount_fs(struct super_block *sb, int *flags, char *data) |
| @@ -1971,61 +1970,65 @@ static struct ubi_volume_desc *open_ubi(const char *name, int mode) | |||
| 1971 | return ERR_PTR(-EINVAL); | 1970 | return ERR_PTR(-EINVAL); |
| 1972 | } | 1971 | } |
| 1973 | 1972 | ||
| 1974 | static int ubifs_fill_super(struct super_block *sb, void *data, int silent) | 1973 | static struct ubifs_info *alloc_ubifs_info(struct ubi_volume_desc *ubi) |
| 1975 | { | 1974 | { |
| 1976 | struct ubi_volume_desc *ubi = sb->s_fs_info; | ||
| 1977 | struct ubifs_info *c; | 1975 | struct ubifs_info *c; |
| 1978 | struct inode *root; | ||
| 1979 | int err; | ||
| 1980 | 1976 | ||
| 1981 | c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); | 1977 | c = kzalloc(sizeof(struct ubifs_info), GFP_KERNEL); |
| 1982 | if (!c) | 1978 | if (c) { |
| 1983 | return -ENOMEM; | 1979 | spin_lock_init(&c->cnt_lock); |
| 1980 | spin_lock_init(&c->cs_lock); | ||
| 1981 | spin_lock_init(&c->buds_lock); | ||
| 1982 | spin_lock_init(&c->space_lock); | ||
| 1983 | spin_lock_init(&c->orphan_lock); | ||
| 1984 | init_rwsem(&c->commit_sem); | ||
| 1985 | mutex_init(&c->lp_mutex); | ||
| 1986 | mutex_init(&c->tnc_mutex); | ||
| 1987 | mutex_init(&c->log_mutex); | ||
| 1988 | mutex_init(&c->mst_mutex); | ||
| 1989 | mutex_init(&c->umount_mutex); | ||
| 1990 | mutex_init(&c->bu_mutex); | ||
| 1991 | mutex_init(&c->write_reserve_mutex); | ||
| 1992 | init_waitqueue_head(&c->cmt_wq); | ||
| 1993 | c->buds = RB_ROOT; | ||
| 1994 | c->old_idx = RB_ROOT; | ||
| 1995 | c->size_tree = RB_ROOT; | ||
| 1996 | c->orph_tree = RB_ROOT; | ||
| 1997 | INIT_LIST_HEAD(&c->infos_list); | ||
| 1998 | INIT_LIST_HEAD(&c->idx_gc); | ||
| 1999 | INIT_LIST_HEAD(&c->replay_list); | ||
| 2000 | INIT_LIST_HEAD(&c->replay_buds); | ||
| 2001 | INIT_LIST_HEAD(&c->uncat_list); | ||
| 2002 | INIT_LIST_HEAD(&c->empty_list); | ||
| 2003 | INIT_LIST_HEAD(&c->freeable_list); | ||
| 2004 | INIT_LIST_HEAD(&c->frdi_idx_list); | ||
| 2005 | INIT_LIST_HEAD(&c->unclean_leb_list); | ||
| 2006 | INIT_LIST_HEAD(&c->old_buds); | ||
| 2007 | INIT_LIST_HEAD(&c->orph_list); | ||
| 2008 | INIT_LIST_HEAD(&c->orph_new); | ||
| 2009 | c->no_chk_data_crc = 1; | ||
| 2010 | |||
| 2011 | c->highest_inum = UBIFS_FIRST_INO; | ||
| 2012 | c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; | ||
| 2013 | |||
| 2014 | ubi_get_volume_info(ubi, &c->vi); | ||
| 2015 | ubi_get_device_info(c->vi.ubi_num, &c->di); | ||
| 2016 | } | ||
| 2017 | return c; | ||
| 2018 | } | ||
| 1984 | 2019 | ||
| 1985 | spin_lock_init(&c->cnt_lock); | 2020 | static int ubifs_fill_super(struct super_block *sb, void *data, int silent) |
| 1986 | spin_lock_init(&c->cs_lock); | 2021 | { |
| 1987 | spin_lock_init(&c->buds_lock); | 2022 | struct ubifs_info *c = sb->s_fs_info; |
| 1988 | spin_lock_init(&c->space_lock); | 2023 | struct inode *root; |
| 1989 | spin_lock_init(&c->orphan_lock); | 2024 | int err; |
| 1990 | init_rwsem(&c->commit_sem); | ||
| 1991 | mutex_init(&c->lp_mutex); | ||
| 1992 | mutex_init(&c->tnc_mutex); | ||
| 1993 | mutex_init(&c->log_mutex); | ||
| 1994 | mutex_init(&c->mst_mutex); | ||
| 1995 | mutex_init(&c->umount_mutex); | ||
| 1996 | mutex_init(&c->bu_mutex); | ||
| 1997 | mutex_init(&c->write_reserve_mutex); | ||
| 1998 | init_waitqueue_head(&c->cmt_wq); | ||
| 1999 | c->buds = RB_ROOT; | ||
| 2000 | c->old_idx = RB_ROOT; | ||
| 2001 | c->size_tree = RB_ROOT; | ||
| 2002 | c->orph_tree = RB_ROOT; | ||
| 2003 | INIT_LIST_HEAD(&c->infos_list); | ||
| 2004 | INIT_LIST_HEAD(&c->idx_gc); | ||
| 2005 | INIT_LIST_HEAD(&c->replay_list); | ||
| 2006 | INIT_LIST_HEAD(&c->replay_buds); | ||
| 2007 | INIT_LIST_HEAD(&c->uncat_list); | ||
| 2008 | INIT_LIST_HEAD(&c->empty_list); | ||
| 2009 | INIT_LIST_HEAD(&c->freeable_list); | ||
| 2010 | INIT_LIST_HEAD(&c->frdi_idx_list); | ||
| 2011 | INIT_LIST_HEAD(&c->unclean_leb_list); | ||
| 2012 | INIT_LIST_HEAD(&c->old_buds); | ||
| 2013 | INIT_LIST_HEAD(&c->orph_list); | ||
| 2014 | INIT_LIST_HEAD(&c->orph_new); | ||
| 2015 | c->no_chk_data_crc = 1; | ||
| 2016 | 2025 | ||
| 2017 | c->vfs_sb = sb; | 2026 | c->vfs_sb = sb; |
| 2018 | c->highest_inum = UBIFS_FIRST_INO; | ||
| 2019 | c->lhead_lnum = c->ltail_lnum = UBIFS_LOG_LNUM; | ||
| 2020 | |||
| 2021 | ubi_get_volume_info(ubi, &c->vi); | ||
| 2022 | ubi_get_device_info(c->vi.ubi_num, &c->di); | ||
| 2023 | |||
| 2024 | /* Re-open the UBI device in read-write mode */ | 2027 | /* Re-open the UBI device in read-write mode */ |
| 2025 | c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE); | 2028 | c->ubi = ubi_open_volume(c->vi.ubi_num, c->vi.vol_id, UBI_READWRITE); |
| 2026 | if (IS_ERR(c->ubi)) { | 2029 | if (IS_ERR(c->ubi)) { |
| 2027 | err = PTR_ERR(c->ubi); | 2030 | err = PTR_ERR(c->ubi); |
| 2028 | goto out_free; | 2031 | goto out; |
| 2029 | } | 2032 | } |
| 2030 | 2033 | ||
| 2031 | /* | 2034 | /* |
| @@ -2091,24 +2094,29 @@ out_bdi: | |||
| 2091 | bdi_destroy(&c->bdi); | 2094 | bdi_destroy(&c->bdi); |
| 2092 | out_close: | 2095 | out_close: |
| 2093 | ubi_close_volume(c->ubi); | 2096 | ubi_close_volume(c->ubi); |
| 2094 | out_free: | 2097 | out: |
| 2095 | kfree(c); | ||
| 2096 | return err; | 2098 | return err; |
| 2097 | } | 2099 | } |
| 2098 | 2100 | ||
| 2099 | static int sb_test(struct super_block *sb, void *data) | 2101 | static int sb_test(struct super_block *sb, void *data) |
| 2100 | { | 2102 | { |
| 2101 | dev_t *dev = data; | 2103 | struct ubifs_info *c1 = data; |
| 2102 | struct ubifs_info *c = sb->s_fs_info; | 2104 | struct ubifs_info *c = sb->s_fs_info; |
| 2103 | 2105 | ||
| 2104 | return c->vi.cdev == *dev; | 2106 | return c->vi.cdev == c1->vi.cdev; |
| 2107 | } | ||
| 2108 | |||
| 2109 | static int sb_set(struct super_block *sb, void *data) | ||
| 2110 | { | ||
| 2111 | sb->s_fs_info = data; | ||
| 2112 | return set_anon_super(sb, NULL); | ||
| 2105 | } | 2113 | } |
| 2106 | 2114 | ||
| 2107 | static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, | 2115 | static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, |
| 2108 | const char *name, void *data) | 2116 | const char *name, void *data) |
| 2109 | { | 2117 | { |
| 2110 | struct ubi_volume_desc *ubi; | 2118 | struct ubi_volume_desc *ubi; |
| 2111 | struct ubi_volume_info vi; | 2119 | struct ubifs_info *c; |
| 2112 | struct super_block *sb; | 2120 | struct super_block *sb; |
| 2113 | int err; | 2121 | int err; |
| 2114 | 2122 | ||
| @@ -2125,19 +2133,25 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, | |||
| 2125 | name, (int)PTR_ERR(ubi)); | 2133 | name, (int)PTR_ERR(ubi)); |
| 2126 | return ERR_CAST(ubi); | 2134 | return ERR_CAST(ubi); |
| 2127 | } | 2135 | } |
| 2128 | ubi_get_volume_info(ubi, &vi); | ||
| 2129 | 2136 | ||
| 2130 | dbg_gen("opened ubi%d_%d", vi.ubi_num, vi.vol_id); | 2137 | c = alloc_ubifs_info(ubi); |
| 2138 | if (!c) { | ||
| 2139 | err = -ENOMEM; | ||
| 2140 | goto out_close; | ||
| 2141 | } | ||
| 2142 | |||
| 2143 | dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id); | ||
| 2131 | 2144 | ||
| 2132 | sb = sget(fs_type, &sb_test, &set_anon_super, &vi.cdev); | 2145 | sb = sget(fs_type, sb_test, sb_set, c); |
| 2133 | if (IS_ERR(sb)) { | 2146 | if (IS_ERR(sb)) { |
| 2134 | err = PTR_ERR(sb); | 2147 | err = PTR_ERR(sb); |
| 2148 | kfree(c); | ||
| 2135 | goto out_close; | 2149 | goto out_close; |
| 2136 | } | 2150 | } |
| 2137 | 2151 | ||
| 2138 | if (sb->s_root) { | 2152 | if (sb->s_root) { |
| 2139 | struct ubifs_info *c1 = sb->s_fs_info; | 2153 | struct ubifs_info *c1 = sb->s_fs_info; |
| 2140 | 2154 | kfree(c); | |
| 2141 | /* A new mount point for already mounted UBIFS */ | 2155 | /* A new mount point for already mounted UBIFS */ |
| 2142 | dbg_gen("this ubi volume is already mounted"); | 2156 | dbg_gen("this ubi volume is already mounted"); |
| 2143 | if (!!(flags & MS_RDONLY) != c1->ro_mount) { | 2157 | if (!!(flags & MS_RDONLY) != c1->ro_mount) { |
| @@ -2146,11 +2160,6 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags, | |||
| 2146 | } | 2160 | } |
| 2147 | } else { | 2161 | } else { |
| 2148 | sb->s_flags = flags; | 2162 | sb->s_flags = flags; |
| 2149 | /* | ||
| 2150 | * Pass 'ubi' to 'fill_super()' in sb->s_fs_info where it is | ||
| 2151 | * replaced by 'c'. | ||
| 2152 | */ | ||
| 2153 | sb->s_fs_info = ubi; | ||
| 2154 | err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | 2163 | err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); |
| 2155 | if (err) | 2164 | if (err) |
| 2156 | goto out_deact; | 2165 | goto out_deact; |
| @@ -2170,11 +2179,18 @@ out_close: | |||
| 2170 | return ERR_PTR(err); | 2179 | return ERR_PTR(err); |
| 2171 | } | 2180 | } |
| 2172 | 2181 | ||
| 2182 | static void kill_ubifs_super(struct super_block *s) | ||
| 2183 | { | ||
| 2184 | struct ubifs_info *c = s->s_fs_info; | ||
| 2185 | kill_anon_super(s); | ||
| 2186 | kfree(c); | ||
| 2187 | } | ||
| 2188 | |||
| 2173 | static struct file_system_type ubifs_fs_type = { | 2189 | static struct file_system_type ubifs_fs_type = { |
| 2174 | .name = "ubifs", | 2190 | .name = "ubifs", |
| 2175 | .owner = THIS_MODULE, | 2191 | .owner = THIS_MODULE, |
| 2176 | .mount = ubifs_mount, | 2192 | .mount = ubifs_mount, |
| 2177 | .kill_sb = kill_anon_super, | 2193 | .kill_sb = kill_ubifs_super, |
| 2178 | }; | 2194 | }; |
| 2179 | 2195 | ||
| 2180 | /* | 2196 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index f4213ba1ff85..7f782af286bf 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
| @@ -131,19 +131,34 @@ xfs_file_fsync( | |||
| 131 | { | 131 | { |
| 132 | struct inode *inode = file->f_mapping->host; | 132 | struct inode *inode = file->f_mapping->host; |
| 133 | struct xfs_inode *ip = XFS_I(inode); | 133 | struct xfs_inode *ip = XFS_I(inode); |
| 134 | struct xfs_mount *mp = ip->i_mount; | ||
| 134 | struct xfs_trans *tp; | 135 | struct xfs_trans *tp; |
| 135 | int error = 0; | 136 | int error = 0; |
| 136 | int log_flushed = 0; | 137 | int log_flushed = 0; |
| 137 | 138 | ||
| 138 | trace_xfs_file_fsync(ip); | 139 | trace_xfs_file_fsync(ip); |
| 139 | 140 | ||
| 140 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 141 | if (XFS_FORCED_SHUTDOWN(mp)) |
| 141 | return -XFS_ERROR(EIO); | 142 | return -XFS_ERROR(EIO); |
| 142 | 143 | ||
| 143 | xfs_iflags_clear(ip, XFS_ITRUNCATED); | 144 | xfs_iflags_clear(ip, XFS_ITRUNCATED); |
| 144 | 145 | ||
| 145 | xfs_ioend_wait(ip); | 146 | xfs_ioend_wait(ip); |
| 146 | 147 | ||
| 148 | if (mp->m_flags & XFS_MOUNT_BARRIER) { | ||
| 149 | /* | ||
| 150 | * If we have an RT and/or log subvolume we need to make sure | ||
| 151 | * to flush the write cache the device used for file data | ||
| 152 | * first. This is to ensure newly written file data make | ||
| 153 | * it to disk before logging the new inode size in case of | ||
| 154 | * an extending write. | ||
| 155 | */ | ||
| 156 | if (XFS_IS_REALTIME_INODE(ip)) | ||
| 157 | xfs_blkdev_issue_flush(mp->m_rtdev_targp); | ||
| 158 | else if (mp->m_logdev_targp != mp->m_ddev_targp) | ||
| 159 | xfs_blkdev_issue_flush(mp->m_ddev_targp); | ||
| 160 | } | ||
| 161 | |||
| 147 | /* | 162 | /* |
| 148 | * We always need to make sure that the required inode state is safe on | 163 | * We always need to make sure that the required inode state is safe on |
| 149 | * disk. The inode might be clean but we still might need to force the | 164 | * disk. The inode might be clean but we still might need to force the |
| @@ -175,9 +190,9 @@ xfs_file_fsync( | |||
| 175 | * updates. The sync transaction will also force the log. | 190 | * updates. The sync transaction will also force the log. |
| 176 | */ | 191 | */ |
| 177 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 192 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
| 178 | tp = xfs_trans_alloc(ip->i_mount, XFS_TRANS_FSYNC_TS); | 193 | tp = xfs_trans_alloc(mp, XFS_TRANS_FSYNC_TS); |
| 179 | error = xfs_trans_reserve(tp, 0, | 194 | error = xfs_trans_reserve(tp, 0, |
| 180 | XFS_FSYNC_TS_LOG_RES(ip->i_mount), 0, 0, 0); | 195 | XFS_FSYNC_TS_LOG_RES(mp), 0, 0, 0); |
| 181 | if (error) { | 196 | if (error) { |
| 182 | xfs_trans_cancel(tp, 0); | 197 | xfs_trans_cancel(tp, 0); |
| 183 | return -error; | 198 | return -error; |
| @@ -209,28 +224,25 @@ xfs_file_fsync( | |||
| 209 | * force the log. | 224 | * force the log. |
| 210 | */ | 225 | */ |
| 211 | if (xfs_ipincount(ip)) { | 226 | if (xfs_ipincount(ip)) { |
| 212 | error = _xfs_log_force_lsn(ip->i_mount, | 227 | error = _xfs_log_force_lsn(mp, |
| 213 | ip->i_itemp->ili_last_lsn, | 228 | ip->i_itemp->ili_last_lsn, |
| 214 | XFS_LOG_SYNC, &log_flushed); | 229 | XFS_LOG_SYNC, &log_flushed); |
| 215 | } | 230 | } |
| 216 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 231 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
| 217 | } | 232 | } |
| 218 | 233 | ||
| 219 | if (ip->i_mount->m_flags & XFS_MOUNT_BARRIER) { | 234 | /* |
| 220 | /* | 235 | * If we only have a single device, and the log force about was |
| 221 | * If the log write didn't issue an ordered tag we need | 236 | * a no-op we might have to flush the data device cache here. |
| 222 | * to flush the disk cache for the data device now. | 237 | * This can only happen for fdatasync/O_DSYNC if we were overwriting |
| 223 | */ | 238 | * an already allocated file and thus do not have any metadata to |
| 224 | if (!log_flushed) | 239 | * commit. |
| 225 | xfs_blkdev_issue_flush(ip->i_mount->m_ddev_targp); | 240 | */ |
| 226 | 241 | if ((mp->m_flags & XFS_MOUNT_BARRIER) && | |
| 227 | /* | 242 | mp->m_logdev_targp == mp->m_ddev_targp && |
| 228 | * If this inode is on the RT dev we need to flush that | 243 | !XFS_IS_REALTIME_INODE(ip) && |
| 229 | * cache as well. | 244 | !log_flushed) |
| 230 | */ | 245 | xfs_blkdev_issue_flush(mp->m_ddev_targp); |
| 231 | if (XFS_IS_REALTIME_INODE(ip)) | ||
| 232 | xfs_blkdev_issue_flush(ip->i_mount->m_rtdev_targp); | ||
| 233 | } | ||
| 234 | 246 | ||
| 235 | return -error; | 247 | return -error; |
| 236 | } | 248 | } |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index dd21784525a8..d44d92cd12b1 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
| @@ -182,7 +182,7 @@ xfs_vn_mknod( | |||
| 182 | if (IS_POSIXACL(dir)) { | 182 | if (IS_POSIXACL(dir)) { |
| 183 | default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT); | 183 | default_acl = xfs_get_acl(dir, ACL_TYPE_DEFAULT); |
| 184 | if (IS_ERR(default_acl)) | 184 | if (IS_ERR(default_acl)) |
| 185 | return -PTR_ERR(default_acl); | 185 | return PTR_ERR(default_acl); |
| 186 | 186 | ||
| 187 | if (!default_acl) | 187 | if (!default_acl) |
| 188 | mode &= ~current_umask(); | 188 | mode &= ~current_umask(); |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 1e3a7ce804dc..a1a881e68a9a 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
| @@ -627,68 +627,6 @@ xfs_blkdev_put( | |||
| 627 | blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); | 627 | blkdev_put(bdev, FMODE_READ|FMODE_WRITE|FMODE_EXCL); |
| 628 | } | 628 | } |
| 629 | 629 | ||
| 630 | /* | ||
| 631 | * Try to write out the superblock using barriers. | ||
| 632 | */ | ||
| 633 | STATIC int | ||
| 634 | xfs_barrier_test( | ||
| 635 | xfs_mount_t *mp) | ||
| 636 | { | ||
| 637 | xfs_buf_t *sbp = xfs_getsb(mp, 0); | ||
| 638 | int error; | ||
| 639 | |||
| 640 | XFS_BUF_UNDONE(sbp); | ||
| 641 | XFS_BUF_UNREAD(sbp); | ||
| 642 | XFS_BUF_UNDELAYWRITE(sbp); | ||
| 643 | XFS_BUF_WRITE(sbp); | ||
| 644 | XFS_BUF_UNASYNC(sbp); | ||
| 645 | XFS_BUF_ORDERED(sbp); | ||
| 646 | |||
| 647 | xfsbdstrat(mp, sbp); | ||
| 648 | error = xfs_buf_iowait(sbp); | ||
| 649 | |||
| 650 | /* | ||
| 651 | * Clear all the flags we set and possible error state in the | ||
| 652 | * buffer. We only did the write to try out whether barriers | ||
| 653 | * worked and shouldn't leave any traces in the superblock | ||
| 654 | * buffer. | ||
| 655 | */ | ||
| 656 | XFS_BUF_DONE(sbp); | ||
| 657 | XFS_BUF_ERROR(sbp, 0); | ||
| 658 | XFS_BUF_UNORDERED(sbp); | ||
| 659 | |||
| 660 | xfs_buf_relse(sbp); | ||
| 661 | return error; | ||
| 662 | } | ||
| 663 | |||
| 664 | STATIC void | ||
| 665 | xfs_mountfs_check_barriers(xfs_mount_t *mp) | ||
| 666 | { | ||
| 667 | int error; | ||
| 668 | |||
| 669 | if (mp->m_logdev_targp != mp->m_ddev_targp) { | ||
| 670 | xfs_notice(mp, | ||
| 671 | "Disabling barriers, not supported with external log device"); | ||
| 672 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
| 673 | return; | ||
| 674 | } | ||
| 675 | |||
| 676 | if (xfs_readonly_buftarg(mp->m_ddev_targp)) { | ||
| 677 | xfs_notice(mp, | ||
| 678 | "Disabling barriers, underlying device is readonly"); | ||
| 679 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
| 680 | return; | ||
| 681 | } | ||
| 682 | |||
| 683 | error = xfs_barrier_test(mp); | ||
| 684 | if (error) { | ||
| 685 | xfs_notice(mp, | ||
| 686 | "Disabling barriers, trial barrier write failed"); | ||
| 687 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | ||
| 688 | return; | ||
| 689 | } | ||
| 690 | } | ||
| 691 | |||
| 692 | void | 630 | void |
| 693 | xfs_blkdev_issue_flush( | 631 | xfs_blkdev_issue_flush( |
| 694 | xfs_buftarg_t *buftarg) | 632 | xfs_buftarg_t *buftarg) |
| @@ -1240,14 +1178,6 @@ xfs_fs_remount( | |||
| 1240 | switch (token) { | 1178 | switch (token) { |
| 1241 | case Opt_barrier: | 1179 | case Opt_barrier: |
| 1242 | mp->m_flags |= XFS_MOUNT_BARRIER; | 1180 | mp->m_flags |= XFS_MOUNT_BARRIER; |
| 1243 | |||
| 1244 | /* | ||
| 1245 | * Test if barriers are actually working if we can, | ||
| 1246 | * else delay this check until the filesystem is | ||
| 1247 | * marked writeable. | ||
| 1248 | */ | ||
| 1249 | if (!(mp->m_flags & XFS_MOUNT_RDONLY)) | ||
| 1250 | xfs_mountfs_check_barriers(mp); | ||
| 1251 | break; | 1181 | break; |
| 1252 | case Opt_nobarrier: | 1182 | case Opt_nobarrier: |
| 1253 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | 1183 | mp->m_flags &= ~XFS_MOUNT_BARRIER; |
| @@ -1282,8 +1212,6 @@ xfs_fs_remount( | |||
| 1282 | /* ro -> rw */ | 1212 | /* ro -> rw */ |
| 1283 | if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { | 1213 | if ((mp->m_flags & XFS_MOUNT_RDONLY) && !(*flags & MS_RDONLY)) { |
| 1284 | mp->m_flags &= ~XFS_MOUNT_RDONLY; | 1214 | mp->m_flags &= ~XFS_MOUNT_RDONLY; |
| 1285 | if (mp->m_flags & XFS_MOUNT_BARRIER) | ||
| 1286 | xfs_mountfs_check_barriers(mp); | ||
| 1287 | 1215 | ||
| 1288 | /* | 1216 | /* |
| 1289 | * If this is the first remount to writeable state we | 1217 | * If this is the first remount to writeable state we |
| @@ -1465,9 +1393,6 @@ xfs_fs_fill_super( | |||
| 1465 | if (error) | 1393 | if (error) |
| 1466 | goto out_free_sb; | 1394 | goto out_free_sb; |
| 1467 | 1395 | ||
| 1468 | if (mp->m_flags & XFS_MOUNT_BARRIER) | ||
| 1469 | xfs_mountfs_check_barriers(mp); | ||
| 1470 | |||
| 1471 | error = xfs_filestream_mount(mp); | 1396 | error = xfs_filestream_mount(mp); |
| 1472 | if (error) | 1397 | if (error) |
| 1473 | goto out_free_sb; | 1398 | goto out_free_sb; |
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index c86375378810..01d2072fb6d4 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
| @@ -490,6 +490,13 @@ xfs_attr_remove_int(xfs_inode_t *dp, struct xfs_name *name, int flags) | |||
| 490 | args.whichfork = XFS_ATTR_FORK; | 490 | args.whichfork = XFS_ATTR_FORK; |
| 491 | 491 | ||
| 492 | /* | 492 | /* |
| 493 | * we have no control over the attribute names that userspace passes us | ||
| 494 | * to remove, so we have to allow the name lookup prior to attribute | ||
| 495 | * removal to fail. | ||
| 496 | */ | ||
| 497 | args.op_flags = XFS_DA_OP_OKNOENT; | ||
| 498 | |||
| 499 | /* | ||
| 493 | * Attach the dquots to the inode. | 500 | * Attach the dquots to the inode. |
| 494 | */ | 501 | */ |
| 495 | error = xfs_qm_dqattach(dp, 0); | 502 | error = xfs_qm_dqattach(dp, 0); |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index cb9b6d1469f7..3631783b2b53 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
| @@ -253,16 +253,21 @@ xfs_iget_cache_hit( | |||
| 253 | rcu_read_lock(); | 253 | rcu_read_lock(); |
| 254 | spin_lock(&ip->i_flags_lock); | 254 | spin_lock(&ip->i_flags_lock); |
| 255 | 255 | ||
| 256 | ip->i_flags &= ~XFS_INEW; | 256 | ip->i_flags &= ~(XFS_INEW | XFS_IRECLAIM); |
| 257 | ip->i_flags |= XFS_IRECLAIMABLE; | 257 | ASSERT(ip->i_flags & XFS_IRECLAIMABLE); |
| 258 | __xfs_inode_set_reclaim_tag(pag, ip); | ||
| 259 | trace_xfs_iget_reclaim_fail(ip); | 258 | trace_xfs_iget_reclaim_fail(ip); |
| 260 | goto out_error; | 259 | goto out_error; |
| 261 | } | 260 | } |
| 262 | 261 | ||
| 263 | spin_lock(&pag->pag_ici_lock); | 262 | spin_lock(&pag->pag_ici_lock); |
| 264 | spin_lock(&ip->i_flags_lock); | 263 | spin_lock(&ip->i_flags_lock); |
| 265 | ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM); | 264 | |
| 265 | /* | ||
| 266 | * Clear the per-lifetime state in the inode as we are now | ||
| 267 | * effectively a new inode and need to return to the initial | ||
| 268 | * state before reuse occurs. | ||
| 269 | */ | ||
| 270 | ip->i_flags &= ~XFS_IRECLAIM_RESET_FLAGS; | ||
| 266 | ip->i_flags |= XFS_INEW; | 271 | ip->i_flags |= XFS_INEW; |
| 267 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); | 272 | __xfs_inode_clear_reclaim_tag(mp, pag, ip); |
| 268 | inode->i_state = I_NEW; | 273 | inode->i_state = I_NEW; |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 3ae6d58e5473..964cfea77686 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
| @@ -384,6 +384,16 @@ static inline void xfs_ifunlock(xfs_inode_t *ip) | |||
| 384 | #define XFS_IDIRTY_RELEASE 0x0040 /* dirty release already seen */ | 384 | #define XFS_IDIRTY_RELEASE 0x0040 /* dirty release already seen */ |
| 385 | 385 | ||
| 386 | /* | 386 | /* |
| 387 | * Per-lifetime flags need to be reset when re-using a reclaimable inode during | ||
| 388 | * inode lookup. Thi prevents unintended behaviour on the new inode from | ||
| 389 | * ocurring. | ||
| 390 | */ | ||
| 391 | #define XFS_IRECLAIM_RESET_FLAGS \ | ||
| 392 | (XFS_IRECLAIMABLE | XFS_IRECLAIM | \ | ||
| 393 | XFS_IDIRTY_RELEASE | XFS_ITRUNCATED | \ | ||
| 394 | XFS_IFILESTREAM); | ||
| 395 | |||
| 396 | /* | ||
| 387 | * Flags for inode locking. | 397 | * Flags for inode locking. |
| 388 | * Bit ranges: 1<<1 - 1<<16-1 -- iolock/ilock modes (bitfield) | 398 | * Bit ranges: 1<<1 - 1<<16-1 -- iolock/ilock modes (bitfield) |
| 389 | * 1<<16 - 1<<32-1 -- lockdep annotation (integers) | 399 | * 1<<16 - 1<<32-1 -- lockdep annotation (integers) |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 211930246f20..41d5b8f2bf92 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
| @@ -1372,8 +1372,17 @@ xlog_sync(xlog_t *log, | |||
| 1372 | XFS_BUF_ASYNC(bp); | 1372 | XFS_BUF_ASYNC(bp); |
| 1373 | bp->b_flags |= XBF_LOG_BUFFER; | 1373 | bp->b_flags |= XBF_LOG_BUFFER; |
| 1374 | 1374 | ||
| 1375 | if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) | 1375 | if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) { |
| 1376 | /* | ||
| 1377 | * If we have an external log device, flush the data device | ||
| 1378 | * before flushing the log to make sure all meta data | ||
| 1379 | * written back from the AIL actually made it to disk | ||
| 1380 | * before writing out the new log tail LSN in the log buffer. | ||
| 1381 | */ | ||
| 1382 | if (log->l_mp->m_logdev_targp != log->l_mp->m_ddev_targp) | ||
| 1383 | xfs_blkdev_issue_flush(log->l_mp->m_ddev_targp); | ||
| 1376 | XFS_BUF_ORDERED(bp); | 1384 | XFS_BUF_ORDERED(bp); |
| 1385 | } | ||
| 1377 | 1386 | ||
| 1378 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); | 1387 | ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); |
| 1379 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); | 1388 | ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index b7a5fe7c52c8..619720705bc6 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
| @@ -960,8 +960,11 @@ xfs_release( | |||
| 960 | * be exposed to that problem. | 960 | * be exposed to that problem. |
| 961 | */ | 961 | */ |
| 962 | truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); | 962 | truncated = xfs_iflags_test_and_clear(ip, XFS_ITRUNCATED); |
| 963 | if (truncated && VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) | 963 | if (truncated) { |
| 964 | xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE); | 964 | xfs_iflags_clear(ip, XFS_IDIRTY_RELEASE); |
| 965 | if (VN_DIRTY(VFS_I(ip)) && ip->i_delayed_blks > 0) | ||
| 966 | xfs_flush_pages(ip, 0, -1, XBF_ASYNC, FI_NONE); | ||
| 967 | } | ||
| 965 | } | 968 | } |
| 966 | 969 | ||
| 967 | if (ip->i_d.di_nlink == 0) | 970 | if (ip->i_d.di_nlink == 0) |
