diff options
Diffstat (limited to 'fs')
38 files changed, 647 insertions, 372 deletions
diff --git a/fs/btrfs/btrfs_inode.h b/fs/btrfs/btrfs_inode.h index 5a5d325a3935..634608d2a6d0 100644 --- a/fs/btrfs/btrfs_inode.h +++ b/fs/btrfs/btrfs_inode.h | |||
@@ -147,14 +147,12 @@ struct btrfs_inode { | |||
147 | * the btrfs file release call will add this inode to the | 147 | * the btrfs file release call will add this inode to the |
148 | * ordered operations list so that we make sure to flush out any | 148 | * ordered operations list so that we make sure to flush out any |
149 | * new data the application may have written before commit. | 149 | * new data the application may have written before commit. |
150 | * | ||
151 | * yes, its silly to have a single bitflag, but we might grow more | ||
152 | * of these. | ||
153 | */ | 150 | */ |
154 | unsigned ordered_data_close:1; | 151 | unsigned ordered_data_close:1; |
155 | unsigned orphan_meta_reserved:1; | 152 | unsigned orphan_meta_reserved:1; |
156 | unsigned dummy_inode:1; | 153 | unsigned dummy_inode:1; |
157 | unsigned in_defrag:1; | 154 | unsigned in_defrag:1; |
155 | unsigned delalloc_meta_reserved:1; | ||
158 | 156 | ||
159 | /* | 157 | /* |
160 | * always compress this one file | 158 | * always compress this one file |
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 3a1b939c9ae2..5b163572e0ca 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c | |||
@@ -617,12 +617,14 @@ static void btrfs_delayed_item_release_metadata(struct btrfs_root *root, | |||
617 | static int btrfs_delayed_inode_reserve_metadata( | 617 | static int btrfs_delayed_inode_reserve_metadata( |
618 | struct btrfs_trans_handle *trans, | 618 | struct btrfs_trans_handle *trans, |
619 | struct btrfs_root *root, | 619 | struct btrfs_root *root, |
620 | struct inode *inode, | ||
620 | struct btrfs_delayed_node *node) | 621 | struct btrfs_delayed_node *node) |
621 | { | 622 | { |
622 | struct btrfs_block_rsv *src_rsv; | 623 | struct btrfs_block_rsv *src_rsv; |
623 | struct btrfs_block_rsv *dst_rsv; | 624 | struct btrfs_block_rsv *dst_rsv; |
624 | u64 num_bytes; | 625 | u64 num_bytes; |
625 | int ret; | 626 | int ret; |
627 | int release = false; | ||
626 | 628 | ||
627 | src_rsv = trans->block_rsv; | 629 | src_rsv = trans->block_rsv; |
628 | dst_rsv = &root->fs_info->delayed_block_rsv; | 630 | dst_rsv = &root->fs_info->delayed_block_rsv; |
@@ -652,12 +654,65 @@ static int btrfs_delayed_inode_reserve_metadata( | |||
652 | if (!ret) | 654 | if (!ret) |
653 | node->bytes_reserved = num_bytes; | 655 | node->bytes_reserved = num_bytes; |
654 | return ret; | 656 | return ret; |
657 | } else if (src_rsv == &root->fs_info->delalloc_block_rsv) { | ||
658 | spin_lock(&BTRFS_I(inode)->lock); | ||
659 | if (BTRFS_I(inode)->delalloc_meta_reserved) { | ||
660 | BTRFS_I(inode)->delalloc_meta_reserved = 0; | ||
661 | spin_unlock(&BTRFS_I(inode)->lock); | ||
662 | release = true; | ||
663 | goto migrate; | ||
664 | } | ||
665 | spin_unlock(&BTRFS_I(inode)->lock); | ||
666 | |||
667 | /* Ok we didn't have space pre-reserved. This shouldn't happen | ||
668 | * too often but it can happen if we do delalloc to an existing | ||
669 | * inode which gets dirtied because of the time update, and then | ||
670 | * isn't touched again until after the transaction commits and | ||
671 | * then we try to write out the data. First try to be nice and | ||
672 | * reserve something strictly for us. If not be a pain and try | ||
673 | * to steal from the delalloc block rsv. | ||
674 | */ | ||
675 | ret = btrfs_block_rsv_add_noflush(root, dst_rsv, num_bytes); | ||
676 | if (!ret) | ||
677 | goto out; | ||
678 | |||
679 | ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); | ||
680 | if (!ret) | ||
681 | goto out; | ||
682 | |||
683 | /* | ||
684 | * Ok this is a problem, let's just steal from the global rsv | ||
685 | * since this really shouldn't happen that often. | ||
686 | */ | ||
687 | WARN_ON(1); | ||
688 | ret = btrfs_block_rsv_migrate(&root->fs_info->global_block_rsv, | ||
689 | dst_rsv, num_bytes); | ||
690 | goto out; | ||
655 | } | 691 | } |
656 | 692 | ||
693 | migrate: | ||
657 | ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); | 694 | ret = btrfs_block_rsv_migrate(src_rsv, dst_rsv, num_bytes); |
695 | |||
696 | out: | ||
697 | /* | ||
698 | * Migrate only takes a reservation, it doesn't touch the size of the | ||
699 | * block_rsv. This is to simplify people who don't normally have things | ||
700 | * migrated from their block rsv. If they go to release their | ||
701 | * reservation, that will decrease the size as well, so if migrate | ||
702 | * reduced size we'd end up with a negative size. But for the | ||
703 | * delalloc_meta_reserved stuff we will only know to drop 1 reservation, | ||
704 | * but we could in fact do this reserve/migrate dance several times | ||
705 | * between the time we did the original reservation and we'd clean it | ||
706 | * up. So to take care of this, release the space for the meta | ||
707 | * reservation here. I think it may be time for a documentation page on | ||
708 | * how block rsvs. work. | ||
709 | */ | ||
658 | if (!ret) | 710 | if (!ret) |
659 | node->bytes_reserved = num_bytes; | 711 | node->bytes_reserved = num_bytes; |
660 | 712 | ||
713 | if (release) | ||
714 | btrfs_block_rsv_release(root, src_rsv, num_bytes); | ||
715 | |||
661 | return ret; | 716 | return ret; |
662 | } | 717 | } |
663 | 718 | ||
@@ -1708,7 +1763,8 @@ int btrfs_delayed_update_inode(struct btrfs_trans_handle *trans, | |||
1708 | goto release_node; | 1763 | goto release_node; |
1709 | } | 1764 | } |
1710 | 1765 | ||
1711 | ret = btrfs_delayed_inode_reserve_metadata(trans, root, delayed_node); | 1766 | ret = btrfs_delayed_inode_reserve_metadata(trans, root, inode, |
1767 | delayed_node); | ||
1712 | if (ret) | 1768 | if (ret) |
1713 | goto release_node; | 1769 | goto release_node; |
1714 | 1770 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 102c176fc29c..62afe5c5694e 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -1890,31 +1890,32 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1890 | u64 features; | 1890 | u64 features; |
1891 | struct btrfs_key location; | 1891 | struct btrfs_key location; |
1892 | struct buffer_head *bh; | 1892 | struct buffer_head *bh; |
1893 | struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root), | 1893 | struct btrfs_super_block *disk_super; |
1894 | GFP_NOFS); | ||
1895 | struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root), | ||
1896 | GFP_NOFS); | ||
1897 | struct btrfs_root *tree_root = btrfs_sb(sb); | 1894 | struct btrfs_root *tree_root = btrfs_sb(sb); |
1898 | struct btrfs_fs_info *fs_info = NULL; | 1895 | struct btrfs_fs_info *fs_info = tree_root->fs_info; |
1899 | struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root), | 1896 | struct btrfs_root *extent_root; |
1900 | GFP_NOFS); | 1897 | struct btrfs_root *csum_root; |
1901 | struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root), | 1898 | struct btrfs_root *chunk_root; |
1902 | GFP_NOFS); | 1899 | struct btrfs_root *dev_root; |
1903 | struct btrfs_root *log_tree_root; | 1900 | struct btrfs_root *log_tree_root; |
1904 | |||
1905 | int ret; | 1901 | int ret; |
1906 | int err = -EINVAL; | 1902 | int err = -EINVAL; |
1907 | int num_backups_tried = 0; | 1903 | int num_backups_tried = 0; |
1908 | int backup_index = 0; | 1904 | int backup_index = 0; |
1909 | 1905 | ||
1910 | struct btrfs_super_block *disk_super; | 1906 | extent_root = fs_info->extent_root = |
1907 | kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
1908 | csum_root = fs_info->csum_root = | ||
1909 | kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
1910 | chunk_root = fs_info->chunk_root = | ||
1911 | kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
1912 | dev_root = fs_info->dev_root = | ||
1913 | kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
1911 | 1914 | ||
1912 | if (!extent_root || !tree_root || !tree_root->fs_info || | 1915 | if (!extent_root || !csum_root || !chunk_root || !dev_root) { |
1913 | !chunk_root || !dev_root || !csum_root) { | ||
1914 | err = -ENOMEM; | 1916 | err = -ENOMEM; |
1915 | goto fail; | 1917 | goto fail; |
1916 | } | 1918 | } |
1917 | fs_info = tree_root->fs_info; | ||
1918 | 1919 | ||
1919 | ret = init_srcu_struct(&fs_info->subvol_srcu); | 1920 | ret = init_srcu_struct(&fs_info->subvol_srcu); |
1920 | if (ret) { | 1921 | if (ret) { |
@@ -1954,12 +1955,6 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1954 | mutex_init(&fs_info->reloc_mutex); | 1955 | mutex_init(&fs_info->reloc_mutex); |
1955 | 1956 | ||
1956 | init_completion(&fs_info->kobj_unregister); | 1957 | init_completion(&fs_info->kobj_unregister); |
1957 | fs_info->tree_root = tree_root; | ||
1958 | fs_info->extent_root = extent_root; | ||
1959 | fs_info->csum_root = csum_root; | ||
1960 | fs_info->chunk_root = chunk_root; | ||
1961 | fs_info->dev_root = dev_root; | ||
1962 | fs_info->fs_devices = fs_devices; | ||
1963 | INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots); | 1958 | INIT_LIST_HEAD(&fs_info->dirty_cowonly_roots); |
1964 | INIT_LIST_HEAD(&fs_info->space_info); | 1959 | INIT_LIST_HEAD(&fs_info->space_info); |
1965 | btrfs_mapping_init(&fs_info->mapping_tree); | 1960 | btrfs_mapping_init(&fs_info->mapping_tree); |
@@ -2465,21 +2460,20 @@ fail_sb_buffer: | |||
2465 | btrfs_stop_workers(&fs_info->caching_workers); | 2460 | btrfs_stop_workers(&fs_info->caching_workers); |
2466 | fail_alloc: | 2461 | fail_alloc: |
2467 | fail_iput: | 2462 | fail_iput: |
2463 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | ||
2464 | |||
2468 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); | 2465 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); |
2469 | iput(fs_info->btree_inode); | 2466 | iput(fs_info->btree_inode); |
2470 | |||
2471 | btrfs_close_devices(fs_info->fs_devices); | ||
2472 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | ||
2473 | fail_bdi: | 2467 | fail_bdi: |
2474 | bdi_destroy(&fs_info->bdi); | 2468 | bdi_destroy(&fs_info->bdi); |
2475 | fail_srcu: | 2469 | fail_srcu: |
2476 | cleanup_srcu_struct(&fs_info->subvol_srcu); | 2470 | cleanup_srcu_struct(&fs_info->subvol_srcu); |
2477 | fail: | 2471 | fail: |
2472 | btrfs_close_devices(fs_info->fs_devices); | ||
2478 | free_fs_info(fs_info); | 2473 | free_fs_info(fs_info); |
2479 | return ERR_PTR(err); | 2474 | return ERR_PTR(err); |
2480 | 2475 | ||
2481 | recovery_tree_root: | 2476 | recovery_tree_root: |
2482 | |||
2483 | if (!btrfs_test_opt(tree_root, RECOVERY)) | 2477 | if (!btrfs_test_opt(tree_root, RECOVERY)) |
2484 | goto fail_tree_roots; | 2478 | goto fail_tree_roots; |
2485 | 2479 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 9879bd474632..b232150b5b6b 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -3797,16 +3797,16 @@ void btrfs_free_block_rsv(struct btrfs_root *root, | |||
3797 | kfree(rsv); | 3797 | kfree(rsv); |
3798 | } | 3798 | } |
3799 | 3799 | ||
3800 | int btrfs_block_rsv_add(struct btrfs_root *root, | 3800 | static inline int __block_rsv_add(struct btrfs_root *root, |
3801 | struct btrfs_block_rsv *block_rsv, | 3801 | struct btrfs_block_rsv *block_rsv, |
3802 | u64 num_bytes) | 3802 | u64 num_bytes, int flush) |
3803 | { | 3803 | { |
3804 | int ret; | 3804 | int ret; |
3805 | 3805 | ||
3806 | if (num_bytes == 0) | 3806 | if (num_bytes == 0) |
3807 | return 0; | 3807 | return 0; |
3808 | 3808 | ||
3809 | ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 1); | 3809 | ret = reserve_metadata_bytes(root, block_rsv, num_bytes, flush); |
3810 | if (!ret) { | 3810 | if (!ret) { |
3811 | block_rsv_add_bytes(block_rsv, num_bytes, 1); | 3811 | block_rsv_add_bytes(block_rsv, num_bytes, 1); |
3812 | return 0; | 3812 | return 0; |
@@ -3815,22 +3815,18 @@ int btrfs_block_rsv_add(struct btrfs_root *root, | |||
3815 | return ret; | 3815 | return ret; |
3816 | } | 3816 | } |
3817 | 3817 | ||
3818 | int btrfs_block_rsv_add(struct btrfs_root *root, | ||
3819 | struct btrfs_block_rsv *block_rsv, | ||
3820 | u64 num_bytes) | ||
3821 | { | ||
3822 | return __block_rsv_add(root, block_rsv, num_bytes, 1); | ||
3823 | } | ||
3824 | |||
3818 | int btrfs_block_rsv_add_noflush(struct btrfs_root *root, | 3825 | int btrfs_block_rsv_add_noflush(struct btrfs_root *root, |
3819 | struct btrfs_block_rsv *block_rsv, | 3826 | struct btrfs_block_rsv *block_rsv, |
3820 | u64 num_bytes) | 3827 | u64 num_bytes) |
3821 | { | 3828 | { |
3822 | int ret; | 3829 | return __block_rsv_add(root, block_rsv, num_bytes, 0); |
3823 | |||
3824 | if (num_bytes == 0) | ||
3825 | return 0; | ||
3826 | |||
3827 | ret = reserve_metadata_bytes(root, block_rsv, num_bytes, 0); | ||
3828 | if (!ret) { | ||
3829 | block_rsv_add_bytes(block_rsv, num_bytes, 1); | ||
3830 | return 0; | ||
3831 | } | ||
3832 | |||
3833 | return ret; | ||
3834 | } | 3830 | } |
3835 | 3831 | ||
3836 | int btrfs_block_rsv_check(struct btrfs_root *root, | 3832 | int btrfs_block_rsv_check(struct btrfs_root *root, |
@@ -4064,23 +4060,30 @@ int btrfs_snap_reserve_metadata(struct btrfs_trans_handle *trans, | |||
4064 | */ | 4060 | */ |
4065 | static unsigned drop_outstanding_extent(struct inode *inode) | 4061 | static unsigned drop_outstanding_extent(struct inode *inode) |
4066 | { | 4062 | { |
4063 | unsigned drop_inode_space = 0; | ||
4067 | unsigned dropped_extents = 0; | 4064 | unsigned dropped_extents = 0; |
4068 | 4065 | ||
4069 | BUG_ON(!BTRFS_I(inode)->outstanding_extents); | 4066 | BUG_ON(!BTRFS_I(inode)->outstanding_extents); |
4070 | BTRFS_I(inode)->outstanding_extents--; | 4067 | BTRFS_I(inode)->outstanding_extents--; |
4071 | 4068 | ||
4069 | if (BTRFS_I(inode)->outstanding_extents == 0 && | ||
4070 | BTRFS_I(inode)->delalloc_meta_reserved) { | ||
4071 | drop_inode_space = 1; | ||
4072 | BTRFS_I(inode)->delalloc_meta_reserved = 0; | ||
4073 | } | ||
4074 | |||
4072 | /* | 4075 | /* |
4073 | * If we have more or the same amount of outsanding extents than we have | 4076 | * If we have more or the same amount of outsanding extents than we have |
4074 | * reserved then we need to leave the reserved extents count alone. | 4077 | * reserved then we need to leave the reserved extents count alone. |
4075 | */ | 4078 | */ |
4076 | if (BTRFS_I(inode)->outstanding_extents >= | 4079 | if (BTRFS_I(inode)->outstanding_extents >= |
4077 | BTRFS_I(inode)->reserved_extents) | 4080 | BTRFS_I(inode)->reserved_extents) |
4078 | return 0; | 4081 | return drop_inode_space; |
4079 | 4082 | ||
4080 | dropped_extents = BTRFS_I(inode)->reserved_extents - | 4083 | dropped_extents = BTRFS_I(inode)->reserved_extents - |
4081 | BTRFS_I(inode)->outstanding_extents; | 4084 | BTRFS_I(inode)->outstanding_extents; |
4082 | BTRFS_I(inode)->reserved_extents -= dropped_extents; | 4085 | BTRFS_I(inode)->reserved_extents -= dropped_extents; |
4083 | return dropped_extents; | 4086 | return dropped_extents + drop_inode_space; |
4084 | } | 4087 | } |
4085 | 4088 | ||
4086 | /** | 4089 | /** |
@@ -4166,9 +4169,18 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes) | |||
4166 | nr_extents = BTRFS_I(inode)->outstanding_extents - | 4169 | nr_extents = BTRFS_I(inode)->outstanding_extents - |
4167 | BTRFS_I(inode)->reserved_extents; | 4170 | BTRFS_I(inode)->reserved_extents; |
4168 | BTRFS_I(inode)->reserved_extents += nr_extents; | 4171 | BTRFS_I(inode)->reserved_extents += nr_extents; |
4172 | } | ||
4169 | 4173 | ||
4170 | to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); | 4174 | /* |
4175 | * Add an item to reserve for updating the inode when we complete the | ||
4176 | * delalloc io. | ||
4177 | */ | ||
4178 | if (!BTRFS_I(inode)->delalloc_meta_reserved) { | ||
4179 | nr_extents++; | ||
4180 | BTRFS_I(inode)->delalloc_meta_reserved = 1; | ||
4171 | } | 4181 | } |
4182 | |||
4183 | to_reserve = btrfs_calc_trans_metadata_size(root, nr_extents); | ||
4172 | to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); | 4184 | to_reserve += calc_csum_metadata_size(inode, num_bytes, 1); |
4173 | spin_unlock(&BTRFS_I(inode)->lock); | 4185 | spin_unlock(&BTRFS_I(inode)->lock); |
4174 | 4186 | ||
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 7a15fcfb3e1f..181760f9d2ab 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -537,6 +537,13 @@ static int io_ctl_read_entry(struct io_ctl *io_ctl, | |||
537 | struct btrfs_free_space *entry, u8 *type) | 537 | struct btrfs_free_space *entry, u8 *type) |
538 | { | 538 | { |
539 | struct btrfs_free_space_entry *e; | 539 | struct btrfs_free_space_entry *e; |
540 | int ret; | ||
541 | |||
542 | if (!io_ctl->cur) { | ||
543 | ret = io_ctl_check_crc(io_ctl, io_ctl->index); | ||
544 | if (ret) | ||
545 | return ret; | ||
546 | } | ||
540 | 547 | ||
541 | e = io_ctl->cur; | 548 | e = io_ctl->cur; |
542 | entry->offset = le64_to_cpu(e->offset); | 549 | entry->offset = le64_to_cpu(e->offset); |
@@ -550,10 +557,7 @@ static int io_ctl_read_entry(struct io_ctl *io_ctl, | |||
550 | 557 | ||
551 | io_ctl_unmap_page(io_ctl); | 558 | io_ctl_unmap_page(io_ctl); |
552 | 559 | ||
553 | if (io_ctl->index >= io_ctl->num_pages) | 560 | return 0; |
554 | return 0; | ||
555 | |||
556 | return io_ctl_check_crc(io_ctl, io_ctl->index); | ||
557 | } | 561 | } |
558 | 562 | ||
559 | static int io_ctl_read_bitmap(struct io_ctl *io_ctl, | 563 | static int io_ctl_read_bitmap(struct io_ctl *io_ctl, |
@@ -561,9 +565,6 @@ static int io_ctl_read_bitmap(struct io_ctl *io_ctl, | |||
561 | { | 565 | { |
562 | int ret; | 566 | int ret; |
563 | 567 | ||
564 | if (io_ctl->cur && io_ctl->cur != io_ctl->orig) | ||
565 | io_ctl_unmap_page(io_ctl); | ||
566 | |||
567 | ret = io_ctl_check_crc(io_ctl, io_ctl->index); | 568 | ret = io_ctl_check_crc(io_ctl, io_ctl->index); |
568 | if (ret) | 569 | if (ret) |
569 | return ret; | 570 | return ret; |
@@ -699,6 +700,8 @@ int __load_free_space_cache(struct btrfs_root *root, struct inode *inode, | |||
699 | num_entries--; | 700 | num_entries--; |
700 | } | 701 | } |
701 | 702 | ||
703 | io_ctl_unmap_page(&io_ctl); | ||
704 | |||
702 | /* | 705 | /* |
703 | * We add the bitmaps at the end of the entries in order that | 706 | * We add the bitmaps at the end of the entries in order that |
704 | * the bitmap entries are added to the cache. | 707 | * the bitmap entries are added to the cache. |
diff --git a/fs/btrfs/inode-map.c b/fs/btrfs/inode-map.c index 53dcbdf446cd..f8962a957d65 100644 --- a/fs/btrfs/inode-map.c +++ b/fs/btrfs/inode-map.c | |||
@@ -398,6 +398,8 @@ int btrfs_save_ino_cache(struct btrfs_root *root, | |||
398 | struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; | 398 | struct btrfs_free_space_ctl *ctl = root->free_ino_ctl; |
399 | struct btrfs_path *path; | 399 | struct btrfs_path *path; |
400 | struct inode *inode; | 400 | struct inode *inode; |
401 | struct btrfs_block_rsv *rsv; | ||
402 | u64 num_bytes; | ||
401 | u64 alloc_hint = 0; | 403 | u64 alloc_hint = 0; |
402 | int ret; | 404 | int ret; |
403 | int prealloc; | 405 | int prealloc; |
@@ -421,11 +423,26 @@ int btrfs_save_ino_cache(struct btrfs_root *root, | |||
421 | if (!path) | 423 | if (!path) |
422 | return -ENOMEM; | 424 | return -ENOMEM; |
423 | 425 | ||
426 | rsv = trans->block_rsv; | ||
427 | trans->block_rsv = &root->fs_info->trans_block_rsv; | ||
428 | |||
429 | num_bytes = trans->bytes_reserved; | ||
430 | /* | ||
431 | * 1 item for inode item insertion if need | ||
432 | * 3 items for inode item update (in the worst case) | ||
433 | * 1 item for free space object | ||
434 | * 3 items for pre-allocation | ||
435 | */ | ||
436 | trans->bytes_reserved = btrfs_calc_trans_metadata_size(root, 8); | ||
437 | ret = btrfs_block_rsv_add_noflush(root, trans->block_rsv, | ||
438 | trans->bytes_reserved); | ||
439 | if (ret) | ||
440 | goto out; | ||
424 | again: | 441 | again: |
425 | inode = lookup_free_ino_inode(root, path); | 442 | inode = lookup_free_ino_inode(root, path); |
426 | if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { | 443 | if (IS_ERR(inode) && PTR_ERR(inode) != -ENOENT) { |
427 | ret = PTR_ERR(inode); | 444 | ret = PTR_ERR(inode); |
428 | goto out; | 445 | goto out_release; |
429 | } | 446 | } |
430 | 447 | ||
431 | if (IS_ERR(inode)) { | 448 | if (IS_ERR(inode)) { |
@@ -434,7 +451,7 @@ again: | |||
434 | 451 | ||
435 | ret = create_free_ino_inode(root, trans, path); | 452 | ret = create_free_ino_inode(root, trans, path); |
436 | if (ret) | 453 | if (ret) |
437 | goto out; | 454 | goto out_release; |
438 | goto again; | 455 | goto again; |
439 | } | 456 | } |
440 | 457 | ||
@@ -477,11 +494,14 @@ again: | |||
477 | } | 494 | } |
478 | btrfs_free_reserved_data_space(inode, prealloc); | 495 | btrfs_free_reserved_data_space(inode, prealloc); |
479 | 496 | ||
497 | ret = btrfs_write_out_ino_cache(root, trans, path); | ||
480 | out_put: | 498 | out_put: |
481 | iput(inode); | 499 | iput(inode); |
500 | out_release: | ||
501 | btrfs_block_rsv_release(root, trans->block_rsv, trans->bytes_reserved); | ||
482 | out: | 502 | out: |
483 | if (ret == 0) | 503 | trans->block_rsv = rsv; |
484 | ret = btrfs_write_out_ino_cache(root, trans, path); | 504 | trans->bytes_reserved = num_bytes; |
485 | 505 | ||
486 | btrfs_free_path(path); | 506 | btrfs_free_path(path); |
487 | return ret; | 507 | return ret; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 966ddcc4c63d..116ab67a06df 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -93,6 +93,8 @@ static noinline int cow_file_range(struct inode *inode, | |||
93 | struct page *locked_page, | 93 | struct page *locked_page, |
94 | u64 start, u64 end, int *page_started, | 94 | u64 start, u64 end, int *page_started, |
95 | unsigned long *nr_written, int unlock); | 95 | unsigned long *nr_written, int unlock); |
96 | static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | ||
97 | struct btrfs_root *root, struct inode *inode); | ||
96 | 98 | ||
97 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | 99 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, |
98 | struct inode *inode, struct inode *dir, | 100 | struct inode *inode, struct inode *dir, |
@@ -1741,7 +1743,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1741 | trans = btrfs_join_transaction(root); | 1743 | trans = btrfs_join_transaction(root); |
1742 | BUG_ON(IS_ERR(trans)); | 1744 | BUG_ON(IS_ERR(trans)); |
1743 | trans->block_rsv = &root->fs_info->delalloc_block_rsv; | 1745 | trans->block_rsv = &root->fs_info->delalloc_block_rsv; |
1744 | ret = btrfs_update_inode(trans, root, inode); | 1746 | ret = btrfs_update_inode_fallback(trans, root, inode); |
1745 | BUG_ON(ret); | 1747 | BUG_ON(ret); |
1746 | } | 1748 | } |
1747 | goto out; | 1749 | goto out; |
@@ -1791,7 +1793,7 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
1791 | 1793 | ||
1792 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); | 1794 | ret = btrfs_ordered_update_i_size(inode, 0, ordered_extent); |
1793 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { | 1795 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) { |
1794 | ret = btrfs_update_inode(trans, root, inode); | 1796 | ret = btrfs_update_inode_fallback(trans, root, inode); |
1795 | BUG_ON(ret); | 1797 | BUG_ON(ret); |
1796 | } | 1798 | } |
1797 | ret = 0; | 1799 | ret = 0; |
@@ -2199,6 +2201,9 @@ int btrfs_orphan_cleanup(struct btrfs_root *root) | |||
2199 | if (ret) | 2201 | if (ret) |
2200 | goto out; | 2202 | goto out; |
2201 | } | 2203 | } |
2204 | /* release the path since we're done with it */ | ||
2205 | btrfs_release_path(path); | ||
2206 | |||
2202 | root->orphan_cleanup_state = ORPHAN_CLEANUP_DONE; | 2207 | root->orphan_cleanup_state = ORPHAN_CLEANUP_DONE; |
2203 | 2208 | ||
2204 | if (root->orphan_block_rsv) | 2209 | if (root->orphan_block_rsv) |
@@ -2426,7 +2431,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans, | |||
2426 | /* | 2431 | /* |
2427 | * copy everything in the in-memory inode into the btree. | 2432 | * copy everything in the in-memory inode into the btree. |
2428 | */ | 2433 | */ |
2429 | noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | 2434 | static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans, |
2430 | struct btrfs_root *root, struct inode *inode) | 2435 | struct btrfs_root *root, struct inode *inode) |
2431 | { | 2436 | { |
2432 | struct btrfs_inode_item *inode_item; | 2437 | struct btrfs_inode_item *inode_item; |
@@ -2434,21 +2439,6 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
2434 | struct extent_buffer *leaf; | 2439 | struct extent_buffer *leaf; |
2435 | int ret; | 2440 | int ret; |
2436 | 2441 | ||
2437 | /* | ||
2438 | * If the inode is a free space inode, we can deadlock during commit | ||
2439 | * if we put it into the delayed code. | ||
2440 | * | ||
2441 | * The data relocation inode should also be directly updated | ||
2442 | * without delay | ||
2443 | */ | ||
2444 | if (!btrfs_is_free_space_inode(root, inode) | ||
2445 | && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { | ||
2446 | ret = btrfs_delayed_update_inode(trans, root, inode); | ||
2447 | if (!ret) | ||
2448 | btrfs_set_inode_last_trans(trans, inode); | ||
2449 | return ret; | ||
2450 | } | ||
2451 | |||
2452 | path = btrfs_alloc_path(); | 2442 | path = btrfs_alloc_path(); |
2453 | if (!path) | 2443 | if (!path) |
2454 | return -ENOMEM; | 2444 | return -ENOMEM; |
@@ -2477,6 +2467,43 @@ failed: | |||
2477 | } | 2467 | } |
2478 | 2468 | ||
2479 | /* | 2469 | /* |
2470 | * copy everything in the in-memory inode into the btree. | ||
2471 | */ | ||
2472 | noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | ||
2473 | struct btrfs_root *root, struct inode *inode) | ||
2474 | { | ||
2475 | int ret; | ||
2476 | |||
2477 | /* | ||
2478 | * If the inode is a free space inode, we can deadlock during commit | ||
2479 | * if we put it into the delayed code. | ||
2480 | * | ||
2481 | * The data relocation inode should also be directly updated | ||
2482 | * without delay | ||
2483 | */ | ||
2484 | if (!btrfs_is_free_space_inode(root, inode) | ||
2485 | && root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID) { | ||
2486 | ret = btrfs_delayed_update_inode(trans, root, inode); | ||
2487 | if (!ret) | ||
2488 | btrfs_set_inode_last_trans(trans, inode); | ||
2489 | return ret; | ||
2490 | } | ||
2491 | |||
2492 | return btrfs_update_inode_item(trans, root, inode); | ||
2493 | } | ||
2494 | |||
2495 | static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | ||
2496 | struct btrfs_root *root, struct inode *inode) | ||
2497 | { | ||
2498 | int ret; | ||
2499 | |||
2500 | ret = btrfs_update_inode(trans, root, inode); | ||
2501 | if (ret == -ENOSPC) | ||
2502 | return btrfs_update_inode_item(trans, root, inode); | ||
2503 | return ret; | ||
2504 | } | ||
2505 | |||
2506 | /* | ||
2480 | * unlink helper that gets used here in inode.c and in the tree logging | 2507 | * unlink helper that gets used here in inode.c and in the tree logging |
2481 | * recovery code. It remove a link in a directory with a given name, and | 2508 | * recovery code. It remove a link in a directory with a given name, and |
2482 | * also drops the back refs in the inode to the directory | 2509 | * also drops the back refs in the inode to the directory |
@@ -5632,7 +5659,7 @@ again: | |||
5632 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) { | 5659 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags)) { |
5633 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); | 5660 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); |
5634 | if (!ret) | 5661 | if (!ret) |
5635 | err = btrfs_update_inode(trans, root, inode); | 5662 | err = btrfs_update_inode_fallback(trans, root, inode); |
5636 | goto out; | 5663 | goto out; |
5637 | } | 5664 | } |
5638 | 5665 | ||
@@ -5670,7 +5697,7 @@ again: | |||
5670 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); | 5697 | add_pending_csums(trans, inode, ordered->file_offset, &ordered->list); |
5671 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); | 5698 | ret = btrfs_ordered_update_i_size(inode, 0, ordered); |
5672 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) | 5699 | if (!ret || !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) |
5673 | btrfs_update_inode(trans, root, inode); | 5700 | btrfs_update_inode_fallback(trans, root, inode); |
5674 | ret = 0; | 5701 | ret = 0; |
5675 | out_unlock: | 5702 | out_unlock: |
5676 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, | 5703 | unlock_extent_cached(&BTRFS_I(inode)->io_tree, ordered->file_offset, |
@@ -6529,14 +6556,16 @@ end_trans: | |||
6529 | ret = btrfs_orphan_del(NULL, inode); | 6556 | ret = btrfs_orphan_del(NULL, inode); |
6530 | } | 6557 | } |
6531 | 6558 | ||
6532 | trans->block_rsv = &root->fs_info->trans_block_rsv; | 6559 | if (trans) { |
6533 | ret = btrfs_update_inode(trans, root, inode); | 6560 | trans->block_rsv = &root->fs_info->trans_block_rsv; |
6534 | if (ret && !err) | 6561 | ret = btrfs_update_inode(trans, root, inode); |
6535 | err = ret; | 6562 | if (ret && !err) |
6563 | err = ret; | ||
6536 | 6564 | ||
6537 | nr = trans->blocks_used; | 6565 | nr = trans->blocks_used; |
6538 | ret = btrfs_end_transaction_throttle(trans, root); | 6566 | ret = btrfs_end_transaction_throttle(trans, root); |
6539 | btrfs_btree_balance_dirty(root, nr); | 6567 | btrfs_btree_balance_dirty(root, nr); |
6568 | } | ||
6540 | 6569 | ||
6541 | out: | 6570 | out: |
6542 | btrfs_free_block_rsv(root, rsv); | 6571 | btrfs_free_block_rsv(root, rsv); |
@@ -6605,6 +6634,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb) | |||
6605 | ei->orphan_meta_reserved = 0; | 6634 | ei->orphan_meta_reserved = 0; |
6606 | ei->dummy_inode = 0; | 6635 | ei->dummy_inode = 0; |
6607 | ei->in_defrag = 0; | 6636 | ei->in_defrag = 0; |
6637 | ei->delalloc_meta_reserved = 0; | ||
6608 | ei->force_compress = BTRFS_COMPRESS_NONE; | 6638 | ei->force_compress = BTRFS_COMPRESS_NONE; |
6609 | 6639 | ||
6610 | ei->delayed_node = NULL; | 6640 | ei->delayed_node = NULL; |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 24d654ce7a06..dff29d5e151a 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -1174,6 +1174,8 @@ static int clone_backref_node(struct btrfs_trans_handle *trans, | |||
1174 | list_add_tail(&new_edge->list[UPPER], | 1174 | list_add_tail(&new_edge->list[UPPER], |
1175 | &new_node->lower); | 1175 | &new_node->lower); |
1176 | } | 1176 | } |
1177 | } else { | ||
1178 | list_add_tail(&new_node->lower, &cache->leaves); | ||
1177 | } | 1179 | } |
1178 | 1180 | ||
1179 | rb_node = tree_insert(&cache->rb_root, new_node->bytenr, | 1181 | rb_node = tree_insert(&cache->rb_root, new_node->bytenr, |
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c index ed11d3866afd..f4190f22edfb 100644 --- a/fs/btrfs/scrub.c +++ b/fs/btrfs/scrub.c | |||
@@ -944,50 +944,18 @@ static int scrub_checksum_super(struct scrub_bio *sbio, void *buffer) | |||
944 | static int scrub_submit(struct scrub_dev *sdev) | 944 | static int scrub_submit(struct scrub_dev *sdev) |
945 | { | 945 | { |
946 | struct scrub_bio *sbio; | 946 | struct scrub_bio *sbio; |
947 | struct bio *bio; | ||
948 | int i; | ||
949 | 947 | ||
950 | if (sdev->curr == -1) | 948 | if (sdev->curr == -1) |
951 | return 0; | 949 | return 0; |
952 | 950 | ||
953 | sbio = sdev->bios[sdev->curr]; | 951 | sbio = sdev->bios[sdev->curr]; |
954 | |||
955 | bio = bio_alloc(GFP_NOFS, sbio->count); | ||
956 | if (!bio) | ||
957 | goto nomem; | ||
958 | |||
959 | bio->bi_private = sbio; | ||
960 | bio->bi_end_io = scrub_bio_end_io; | ||
961 | bio->bi_bdev = sdev->dev->bdev; | ||
962 | bio->bi_sector = sbio->physical >> 9; | ||
963 | |||
964 | for (i = 0; i < sbio->count; ++i) { | ||
965 | struct page *page; | ||
966 | int ret; | ||
967 | |||
968 | page = alloc_page(GFP_NOFS); | ||
969 | if (!page) | ||
970 | goto nomem; | ||
971 | |||
972 | ret = bio_add_page(bio, page, PAGE_SIZE, 0); | ||
973 | if (!ret) { | ||
974 | __free_page(page); | ||
975 | goto nomem; | ||
976 | } | ||
977 | } | ||
978 | |||
979 | sbio->err = 0; | 952 | sbio->err = 0; |
980 | sdev->curr = -1; | 953 | sdev->curr = -1; |
981 | atomic_inc(&sdev->in_flight); | 954 | atomic_inc(&sdev->in_flight); |
982 | 955 | ||
983 | submit_bio(READ, bio); | 956 | submit_bio(READ, sbio->bio); |
984 | 957 | ||
985 | return 0; | 958 | return 0; |
986 | |||
987 | nomem: | ||
988 | scrub_free_bio(bio); | ||
989 | |||
990 | return -ENOMEM; | ||
991 | } | 959 | } |
992 | 960 | ||
993 | static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, | 961 | static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, |
@@ -995,6 +963,8 @@ static int scrub_page(struct scrub_dev *sdev, u64 logical, u64 len, | |||
995 | u8 *csum, int force) | 963 | u8 *csum, int force) |
996 | { | 964 | { |
997 | struct scrub_bio *sbio; | 965 | struct scrub_bio *sbio; |
966 | struct page *page; | ||
967 | int ret; | ||
998 | 968 | ||
999 | again: | 969 | again: |
1000 | /* | 970 | /* |
@@ -1015,12 +985,22 @@ again: | |||
1015 | } | 985 | } |
1016 | sbio = sdev->bios[sdev->curr]; | 986 | sbio = sdev->bios[sdev->curr]; |
1017 | if (sbio->count == 0) { | 987 | if (sbio->count == 0) { |
988 | struct bio *bio; | ||
989 | |||
1018 | sbio->physical = physical; | 990 | sbio->physical = physical; |
1019 | sbio->logical = logical; | 991 | sbio->logical = logical; |
992 | bio = bio_alloc(GFP_NOFS, SCRUB_PAGES_PER_BIO); | ||
993 | if (!bio) | ||
994 | return -ENOMEM; | ||
995 | |||
996 | bio->bi_private = sbio; | ||
997 | bio->bi_end_io = scrub_bio_end_io; | ||
998 | bio->bi_bdev = sdev->dev->bdev; | ||
999 | bio->bi_sector = sbio->physical >> 9; | ||
1000 | sbio->err = 0; | ||
1001 | sbio->bio = bio; | ||
1020 | } else if (sbio->physical + sbio->count * PAGE_SIZE != physical || | 1002 | } else if (sbio->physical + sbio->count * PAGE_SIZE != physical || |
1021 | sbio->logical + sbio->count * PAGE_SIZE != logical) { | 1003 | sbio->logical + sbio->count * PAGE_SIZE != logical) { |
1022 | int ret; | ||
1023 | |||
1024 | ret = scrub_submit(sdev); | 1004 | ret = scrub_submit(sdev); |
1025 | if (ret) | 1005 | if (ret) |
1026 | return ret; | 1006 | return ret; |
@@ -1030,6 +1010,20 @@ again: | |||
1030 | sbio->spag[sbio->count].generation = gen; | 1010 | sbio->spag[sbio->count].generation = gen; |
1031 | sbio->spag[sbio->count].have_csum = 0; | 1011 | sbio->spag[sbio->count].have_csum = 0; |
1032 | sbio->spag[sbio->count].mirror_num = mirror_num; | 1012 | sbio->spag[sbio->count].mirror_num = mirror_num; |
1013 | |||
1014 | page = alloc_page(GFP_NOFS); | ||
1015 | if (!page) | ||
1016 | return -ENOMEM; | ||
1017 | |||
1018 | ret = bio_add_page(sbio->bio, page, PAGE_SIZE, 0); | ||
1019 | if (!ret) { | ||
1020 | __free_page(page); | ||
1021 | ret = scrub_submit(sdev); | ||
1022 | if (ret) | ||
1023 | return ret; | ||
1024 | goto again; | ||
1025 | } | ||
1026 | |||
1033 | if (csum) { | 1027 | if (csum) { |
1034 | sbio->spag[sbio->count].have_csum = 1; | 1028 | sbio->spag[sbio->count].have_csum = 1; |
1035 | memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size); | 1029 | memcpy(sbio->spag[sbio->count].csum, csum, sdev->csum_size); |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 57080dffdfc6..8bd9d6d0e07a 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -197,7 +197,7 @@ static match_table_t tokens = { | |||
197 | {Opt_subvolrootid, "subvolrootid=%d"}, | 197 | {Opt_subvolrootid, "subvolrootid=%d"}, |
198 | {Opt_defrag, "autodefrag"}, | 198 | {Opt_defrag, "autodefrag"}, |
199 | {Opt_inode_cache, "inode_cache"}, | 199 | {Opt_inode_cache, "inode_cache"}, |
200 | {Opt_no_space_cache, "no_space_cache"}, | 200 | {Opt_no_space_cache, "nospace_cache"}, |
201 | {Opt_recovery, "recovery"}, | 201 | {Opt_recovery, "recovery"}, |
202 | {Opt_err, NULL}, | 202 | {Opt_err, NULL}, |
203 | }; | 203 | }; |
@@ -448,6 +448,7 @@ static int btrfs_parse_early_options(const char *options, fmode_t flags, | |||
448 | token = match_token(p, tokens, args); | 448 | token = match_token(p, tokens, args); |
449 | switch (token) { | 449 | switch (token) { |
450 | case Opt_subvol: | 450 | case Opt_subvol: |
451 | kfree(*subvol_name); | ||
451 | *subvol_name = match_strdup(&args[0]); | 452 | *subvol_name = match_strdup(&args[0]); |
452 | break; | 453 | break; |
453 | case Opt_subvolid: | 454 | case Opt_subvolid: |
@@ -710,7 +711,7 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
710 | if (btrfs_test_opt(root, SPACE_CACHE)) | 711 | if (btrfs_test_opt(root, SPACE_CACHE)) |
711 | seq_puts(seq, ",space_cache"); | 712 | seq_puts(seq, ",space_cache"); |
712 | else | 713 | else |
713 | seq_puts(seq, ",no_space_cache"); | 714 | seq_puts(seq, ",nospace_cache"); |
714 | if (btrfs_test_opt(root, CLEAR_CACHE)) | 715 | if (btrfs_test_opt(root, CLEAR_CACHE)) |
715 | seq_puts(seq, ",clear_cache"); | 716 | seq_puts(seq, ",clear_cache"); |
716 | if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) | 717 | if (btrfs_test_opt(root, USER_SUBVOL_RM_ALLOWED)) |
@@ -890,7 +891,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
890 | struct super_block *s; | 891 | struct super_block *s; |
891 | struct dentry *root; | 892 | struct dentry *root; |
892 | struct btrfs_fs_devices *fs_devices = NULL; | 893 | struct btrfs_fs_devices *fs_devices = NULL; |
893 | struct btrfs_root *tree_root = NULL; | ||
894 | struct btrfs_fs_info *fs_info = NULL; | 894 | struct btrfs_fs_info *fs_info = NULL; |
895 | fmode_t mode = FMODE_READ; | 895 | fmode_t mode = FMODE_READ; |
896 | char *subvol_name = NULL; | 896 | char *subvol_name = NULL; |
@@ -904,8 +904,10 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
904 | error = btrfs_parse_early_options(data, mode, fs_type, | 904 | error = btrfs_parse_early_options(data, mode, fs_type, |
905 | &subvol_name, &subvol_objectid, | 905 | &subvol_name, &subvol_objectid, |
906 | &subvol_rootid, &fs_devices); | 906 | &subvol_rootid, &fs_devices); |
907 | if (error) | 907 | if (error) { |
908 | kfree(subvol_name); | ||
908 | return ERR_PTR(error); | 909 | return ERR_PTR(error); |
910 | } | ||
909 | 911 | ||
910 | if (subvol_name) { | 912 | if (subvol_name) { |
911 | root = mount_subvol(subvol_name, flags, device_name, data); | 913 | root = mount_subvol(subvol_name, flags, device_name, data); |
@@ -917,15 +919,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
917 | if (error) | 919 | if (error) |
918 | return ERR_PTR(error); | 920 | return ERR_PTR(error); |
919 | 921 | ||
920 | error = btrfs_open_devices(fs_devices, mode, fs_type); | ||
921 | if (error) | ||
922 | return ERR_PTR(error); | ||
923 | |||
924 | if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) { | ||
925 | error = -EACCES; | ||
926 | goto error_close_devices; | ||
927 | } | ||
928 | |||
929 | /* | 922 | /* |
930 | * Setup a dummy root and fs_info for test/set super. This is because | 923 | * Setup a dummy root and fs_info for test/set super. This is because |
931 | * we don't actually fill this stuff out until open_ctree, but we need | 924 | * we don't actually fill this stuff out until open_ctree, but we need |
@@ -933,24 +926,36 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
933 | * then open_ctree will properly initialize everything later. | 926 | * then open_ctree will properly initialize everything later. |
934 | */ | 927 | */ |
935 | fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); | 928 | fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); |
936 | tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | 929 | if (!fs_info) |
937 | if (!fs_info || !tree_root) { | 930 | return ERR_PTR(-ENOMEM); |
931 | |||
932 | fs_info->tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
933 | if (!fs_info->tree_root) { | ||
938 | error = -ENOMEM; | 934 | error = -ENOMEM; |
939 | goto error_close_devices; | 935 | goto error_fs_info; |
940 | } | 936 | } |
941 | fs_info->tree_root = tree_root; | 937 | fs_info->tree_root->fs_info = fs_info; |
942 | fs_info->fs_devices = fs_devices; | 938 | fs_info->fs_devices = fs_devices; |
943 | tree_root->fs_info = fs_info; | ||
944 | 939 | ||
945 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); | 940 | fs_info->super_copy = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); |
946 | fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); | 941 | fs_info->super_for_commit = kzalloc(BTRFS_SUPER_INFO_SIZE, GFP_NOFS); |
947 | if (!fs_info->super_copy || !fs_info->super_for_commit) { | 942 | if (!fs_info->super_copy || !fs_info->super_for_commit) { |
948 | error = -ENOMEM; | 943 | error = -ENOMEM; |
944 | goto error_fs_info; | ||
945 | } | ||
946 | |||
947 | error = btrfs_open_devices(fs_devices, mode, fs_type); | ||
948 | if (error) | ||
949 | goto error_fs_info; | ||
950 | |||
951 | if (!(flags & MS_RDONLY) && fs_devices->rw_devices == 0) { | ||
952 | error = -EACCES; | ||
949 | goto error_close_devices; | 953 | goto error_close_devices; |
950 | } | 954 | } |
951 | 955 | ||
952 | bdev = fs_devices->latest_bdev; | 956 | bdev = fs_devices->latest_bdev; |
953 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root); | 957 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, |
958 | fs_info->tree_root); | ||
954 | if (IS_ERR(s)) { | 959 | if (IS_ERR(s)) { |
955 | error = PTR_ERR(s); | 960 | error = PTR_ERR(s); |
956 | goto error_close_devices; | 961 | goto error_close_devices; |
@@ -959,12 +964,12 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
959 | if (s->s_root) { | 964 | if (s->s_root) { |
960 | if ((flags ^ s->s_flags) & MS_RDONLY) { | 965 | if ((flags ^ s->s_flags) & MS_RDONLY) { |
961 | deactivate_locked_super(s); | 966 | deactivate_locked_super(s); |
962 | return ERR_PTR(-EBUSY); | 967 | error = -EBUSY; |
968 | goto error_close_devices; | ||
963 | } | 969 | } |
964 | 970 | ||
965 | btrfs_close_devices(fs_devices); | 971 | btrfs_close_devices(fs_devices); |
966 | free_fs_info(fs_info); | 972 | free_fs_info(fs_info); |
967 | kfree(tree_root); | ||
968 | } else { | 973 | } else { |
969 | char b[BDEVNAME_SIZE]; | 974 | char b[BDEVNAME_SIZE]; |
970 | 975 | ||
@@ -991,8 +996,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
991 | 996 | ||
992 | error_close_devices: | 997 | error_close_devices: |
993 | btrfs_close_devices(fs_devices); | 998 | btrfs_close_devices(fs_devices); |
999 | error_fs_info: | ||
994 | free_fs_info(fs_info); | 1000 | free_fs_info(fs_info); |
995 | kfree(tree_root); | ||
996 | return ERR_PTR(error); | 1001 | return ERR_PTR(error); |
997 | } | 1002 | } |
998 | 1003 | ||
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 960835eaf4da..6a0574e923bc 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -882,8 +882,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
882 | btrfs_reloc_pre_snapshot(trans, pending, &to_reserve); | 882 | btrfs_reloc_pre_snapshot(trans, pending, &to_reserve); |
883 | 883 | ||
884 | if (to_reserve > 0) { | 884 | if (to_reserve > 0) { |
885 | ret = btrfs_block_rsv_add(root, &pending->block_rsv, | 885 | ret = btrfs_block_rsv_add_noflush(root, &pending->block_rsv, |
886 | to_reserve); | 886 | to_reserve); |
887 | if (ret) { | 887 | if (ret) { |
888 | pending->error = ret; | 888 | pending->error = ret; |
889 | goto fail; | 889 | goto fail; |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index f8e2943101a1..c37433d3cd82 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
@@ -999,7 +999,7 @@ static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, | |||
999 | key.objectid = device->devid; | 999 | key.objectid = device->devid; |
1000 | key.offset = start; | 1000 | key.offset = start; |
1001 | key.type = BTRFS_DEV_EXTENT_KEY; | 1001 | key.type = BTRFS_DEV_EXTENT_KEY; |
1002 | 1002 | again: | |
1003 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 1003 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
1004 | if (ret > 0) { | 1004 | if (ret > 0) { |
1005 | ret = btrfs_previous_item(root, path, key.objectid, | 1005 | ret = btrfs_previous_item(root, path, key.objectid, |
@@ -1012,6 +1012,9 @@ static int btrfs_free_dev_extent(struct btrfs_trans_handle *trans, | |||
1012 | struct btrfs_dev_extent); | 1012 | struct btrfs_dev_extent); |
1013 | BUG_ON(found_key.offset > start || found_key.offset + | 1013 | BUG_ON(found_key.offset > start || found_key.offset + |
1014 | btrfs_dev_extent_length(leaf, extent) < start); | 1014 | btrfs_dev_extent_length(leaf, extent) < start); |
1015 | key = found_key; | ||
1016 | btrfs_release_path(path); | ||
1017 | goto again; | ||
1015 | } else if (ret == 0) { | 1018 | } else if (ret == 0) { |
1016 | leaf = path->nodes[0]; | 1019 | leaf = path->nodes[0]; |
1017 | extent = btrfs_item_ptr(leaf, path->slots[0], | 1020 | extent = btrfs_item_ptr(leaf, path->slots[0], |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index c1f063cd1b0c..cf0b1539b321 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -645,20 +645,20 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
645 | } | 645 | } |
646 | 646 | ||
647 | static struct cifsLockInfo * | 647 | static struct cifsLockInfo * |
648 | cifs_lock_init(__u64 len, __u64 offset, __u8 type, __u16 netfid) | 648 | cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid) |
649 | { | 649 | { |
650 | struct cifsLockInfo *li = | 650 | struct cifsLockInfo *lock = |
651 | kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); | 651 | kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); |
652 | if (!li) | 652 | if (!lock) |
653 | return li; | 653 | return lock; |
654 | li->netfid = netfid; | 654 | lock->offset = offset; |
655 | li->offset = offset; | 655 | lock->length = length; |
656 | li->length = len; | 656 | lock->type = type; |
657 | li->type = type; | 657 | lock->netfid = netfid; |
658 | li->pid = current->tgid; | 658 | lock->pid = current->tgid; |
659 | INIT_LIST_HEAD(&li->blist); | 659 | INIT_LIST_HEAD(&lock->blist); |
660 | init_waitqueue_head(&li->block_q); | 660 | init_waitqueue_head(&lock->block_q); |
661 | return li; | 661 | return lock; |
662 | } | 662 | } |
663 | 663 | ||
664 | static void | 664 | static void |
@@ -672,7 +672,7 @@ cifs_del_lock_waiters(struct cifsLockInfo *lock) | |||
672 | } | 672 | } |
673 | 673 | ||
674 | static bool | 674 | static bool |
675 | cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, | 675 | __cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, |
676 | __u64 length, __u8 type, __u16 netfid, | 676 | __u64 length, __u8 type, __u16 netfid, |
677 | struct cifsLockInfo **conf_lock) | 677 | struct cifsLockInfo **conf_lock) |
678 | { | 678 | { |
@@ -694,6 +694,14 @@ cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, | |||
694 | return false; | 694 | return false; |
695 | } | 695 | } |
696 | 696 | ||
697 | static bool | ||
698 | cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, | ||
699 | struct cifsLockInfo **conf_lock) | ||
700 | { | ||
701 | return __cifs_find_lock_conflict(cinode, lock->offset, lock->length, | ||
702 | lock->type, lock->netfid, conf_lock); | ||
703 | } | ||
704 | |||
697 | static int | 705 | static int |
698 | cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | 706 | cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, |
699 | __u8 type, __u16 netfid, struct file_lock *flock) | 707 | __u8 type, __u16 netfid, struct file_lock *flock) |
@@ -704,8 +712,8 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | |||
704 | 712 | ||
705 | mutex_lock(&cinode->lock_mutex); | 713 | mutex_lock(&cinode->lock_mutex); |
706 | 714 | ||
707 | exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid, | 715 | exist = __cifs_find_lock_conflict(cinode, offset, length, type, netfid, |
708 | &conf_lock); | 716 | &conf_lock); |
709 | if (exist) { | 717 | if (exist) { |
710 | flock->fl_start = conf_lock->offset; | 718 | flock->fl_start = conf_lock->offset; |
711 | flock->fl_end = conf_lock->offset + conf_lock->length - 1; | 719 | flock->fl_end = conf_lock->offset + conf_lock->length - 1; |
@@ -723,40 +731,27 @@ cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | |||
723 | return rc; | 731 | return rc; |
724 | } | 732 | } |
725 | 733 | ||
726 | static int | 734 | static void |
727 | cifs_lock_add(struct cifsInodeInfo *cinode, __u64 len, __u64 offset, | 735 | cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) |
728 | __u8 type, __u16 netfid) | ||
729 | { | 736 | { |
730 | struct cifsLockInfo *li; | ||
731 | |||
732 | li = cifs_lock_init(len, offset, type, netfid); | ||
733 | if (!li) | ||
734 | return -ENOMEM; | ||
735 | |||
736 | mutex_lock(&cinode->lock_mutex); | 737 | mutex_lock(&cinode->lock_mutex); |
737 | list_add_tail(&li->llist, &cinode->llist); | 738 | list_add_tail(&lock->llist, &cinode->llist); |
738 | mutex_unlock(&cinode->lock_mutex); | 739 | mutex_unlock(&cinode->lock_mutex); |
739 | return 0; | ||
740 | } | 740 | } |
741 | 741 | ||
742 | static int | 742 | static int |
743 | cifs_lock_add_if(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, | 743 | cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, |
744 | __u8 type, __u16 netfid, bool wait) | 744 | bool wait) |
745 | { | 745 | { |
746 | struct cifsLockInfo *lock, *conf_lock; | 746 | struct cifsLockInfo *conf_lock; |
747 | bool exist; | 747 | bool exist; |
748 | int rc = 0; | 748 | int rc = 0; |
749 | 749 | ||
750 | lock = cifs_lock_init(length, offset, type, netfid); | ||
751 | if (!lock) | ||
752 | return -ENOMEM; | ||
753 | |||
754 | try_again: | 750 | try_again: |
755 | exist = false; | 751 | exist = false; |
756 | mutex_lock(&cinode->lock_mutex); | 752 | mutex_lock(&cinode->lock_mutex); |
757 | 753 | ||
758 | exist = cifs_find_lock_conflict(cinode, offset, length, type, netfid, | 754 | exist = cifs_find_lock_conflict(cinode, lock, &conf_lock); |
759 | &conf_lock); | ||
760 | if (!exist && cinode->can_cache_brlcks) { | 755 | if (!exist && cinode->can_cache_brlcks) { |
761 | list_add_tail(&lock->llist, &cinode->llist); | 756 | list_add_tail(&lock->llist, &cinode->llist); |
762 | mutex_unlock(&cinode->lock_mutex); | 757 | mutex_unlock(&cinode->lock_mutex); |
@@ -775,13 +770,10 @@ try_again: | |||
775 | (lock->blist.next == &lock->blist)); | 770 | (lock->blist.next == &lock->blist)); |
776 | if (!rc) | 771 | if (!rc) |
777 | goto try_again; | 772 | goto try_again; |
778 | else { | 773 | mutex_lock(&cinode->lock_mutex); |
779 | mutex_lock(&cinode->lock_mutex); | 774 | list_del_init(&lock->blist); |
780 | list_del_init(&lock->blist); | ||
781 | } | ||
782 | } | 775 | } |
783 | 776 | ||
784 | kfree(lock); | ||
785 | mutex_unlock(&cinode->lock_mutex); | 777 | mutex_unlock(&cinode->lock_mutex); |
786 | return rc; | 778 | return rc; |
787 | } | 779 | } |
@@ -933,7 +925,7 @@ cifs_push_posix_locks(struct cifsFileInfo *cfile) | |||
933 | else | 925 | else |
934 | type = CIFS_WRLCK; | 926 | type = CIFS_WRLCK; |
935 | 927 | ||
936 | lck = cifs_lock_init(length, flock->fl_start, type, | 928 | lck = cifs_lock_init(flock->fl_start, length, type, |
937 | cfile->netfid); | 929 | cfile->netfid); |
938 | if (!lck) { | 930 | if (!lck) { |
939 | rc = -ENOMEM; | 931 | rc = -ENOMEM; |
@@ -1070,14 +1062,12 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1070 | if (rc != 0) | 1062 | if (rc != 0) |
1071 | cERROR(1, "Error unlocking previously locked " | 1063 | cERROR(1, "Error unlocking previously locked " |
1072 | "range %d during test of lock", rc); | 1064 | "range %d during test of lock", rc); |
1073 | rc = 0; | 1065 | return 0; |
1074 | return rc; | ||
1075 | } | 1066 | } |
1076 | 1067 | ||
1077 | if (type & LOCKING_ANDX_SHARED_LOCK) { | 1068 | if (type & LOCKING_ANDX_SHARED_LOCK) { |
1078 | flock->fl_type = F_WRLCK; | 1069 | flock->fl_type = F_WRLCK; |
1079 | rc = 0; | 1070 | return 0; |
1080 | return rc; | ||
1081 | } | 1071 | } |
1082 | 1072 | ||
1083 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, | 1073 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, |
@@ -1095,8 +1085,7 @@ cifs_getlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1095 | } else | 1085 | } else |
1096 | flock->fl_type = F_WRLCK; | 1086 | flock->fl_type = F_WRLCK; |
1097 | 1087 | ||
1098 | rc = 0; | 1088 | return 0; |
1099 | return rc; | ||
1100 | } | 1089 | } |
1101 | 1090 | ||
1102 | static void | 1091 | static void |
@@ -1254,20 +1243,26 @@ cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, | |||
1254 | } | 1243 | } |
1255 | 1244 | ||
1256 | if (lock) { | 1245 | if (lock) { |
1257 | rc = cifs_lock_add_if(cinode, flock->fl_start, length, | 1246 | struct cifsLockInfo *lock; |
1258 | type, netfid, wait_flag); | 1247 | |
1248 | lock = cifs_lock_init(flock->fl_start, length, type, netfid); | ||
1249 | if (!lock) | ||
1250 | return -ENOMEM; | ||
1251 | |||
1252 | rc = cifs_lock_add_if(cinode, lock, wait_flag); | ||
1259 | if (rc < 0) | 1253 | if (rc < 0) |
1260 | return rc; | 1254 | kfree(lock); |
1261 | else if (!rc) | 1255 | if (rc <= 0) |
1262 | goto out; | 1256 | goto out; |
1263 | 1257 | ||
1264 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, | 1258 | rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, |
1265 | flock->fl_start, 0, 1, type, wait_flag, 0); | 1259 | flock->fl_start, 0, 1, type, wait_flag, 0); |
1266 | if (rc == 0) { | 1260 | if (rc) { |
1267 | /* For Windows locks we must store them. */ | 1261 | kfree(lock); |
1268 | rc = cifs_lock_add(cinode, length, flock->fl_start, | 1262 | goto out; |
1269 | type, netfid); | ||
1270 | } | 1263 | } |
1264 | |||
1265 | cifs_lock_add(cinode, lock); | ||
1271 | } else if (unlock) | 1266 | } else if (unlock) |
1272 | rc = cifs_unlock_range(cfile, flock, xid); | 1267 | rc = cifs_unlock_range(cfile, flock, xid); |
1273 | 1268 | ||
diff --git a/fs/dcache.c b/fs/dcache.c index 274f13e2f094..a901c6901bce 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -546,9 +546,11 @@ int d_invalidate(struct dentry * dentry) | |||
546 | * would make it unreachable from the root, | 546 | * would make it unreachable from the root, |
547 | * we might still populate it if it was a | 547 | * we might still populate it if it was a |
548 | * working directory or similar). | 548 | * working directory or similar). |
549 | * We also need to leave mountpoints alone, | ||
550 | * directory or not. | ||
549 | */ | 551 | */ |
550 | if (dentry->d_count > 1) { | 552 | if (dentry->d_count > 1 && dentry->d_inode) { |
551 | if (dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)) { | 553 | if (S_ISDIR(dentry->d_inode->i_mode) || d_mountpoint(dentry)) { |
552 | spin_unlock(&dentry->d_lock); | 554 | spin_unlock(&dentry->d_lock); |
553 | return -EBUSY; | 555 | return -EBUSY; |
554 | } | 556 | } |
diff --git a/fs/hfs/trans.c b/fs/hfs/trans.c index e673a88b8ae7..b1ce4c7ad3fb 100644 --- a/fs/hfs/trans.c +++ b/fs/hfs/trans.c | |||
@@ -40,6 +40,8 @@ int hfs_mac2asc(struct super_block *sb, char *out, const struct hfs_name *in) | |||
40 | 40 | ||
41 | src = in->name; | 41 | src = in->name; |
42 | srclen = in->len; | 42 | srclen = in->len; |
43 | if (srclen > HFS_NAMELEN) | ||
44 | srclen = HFS_NAMELEN; | ||
43 | dst = out; | 45 | dst = out; |
44 | dstlen = HFS_MAX_NAMELEN; | 46 | dstlen = HFS_MAX_NAMELEN; |
45 | if (nls_io) { | 47 | if (nls_io) { |
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index de4247021d25..5b6c9d1a2fb9 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c | |||
@@ -53,6 +53,78 @@ static int jffs2_is_best_compression(struct jffs2_compressor *this, | |||
53 | return 0; | 53 | return 0; |
54 | } | 54 | } |
55 | 55 | ||
56 | /* | ||
57 | * jffs2_selected_compress: | ||
58 | * @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB). | ||
59 | * If 0, just take the first available compression mode. | ||
60 | * @data_in: Pointer to uncompressed data | ||
61 | * @cpage_out: Pointer to returned pointer to buffer for compressed data | ||
62 | * @datalen: On entry, holds the amount of data available for compression. | ||
63 | * On exit, expected to hold the amount of data actually compressed. | ||
64 | * @cdatalen: On entry, holds the amount of space available for compressed | ||
65 | * data. On exit, expected to hold the actual size of the compressed | ||
66 | * data. | ||
67 | * | ||
68 | * Returns: the compression type used. Zero is used to show that the data | ||
69 | * could not be compressed; probably because we couldn't find the requested | ||
70 | * compression mode. | ||
71 | */ | ||
72 | static int jffs2_selected_compress(u8 compr, unsigned char *data_in, | ||
73 | unsigned char **cpage_out, u32 *datalen, u32 *cdatalen) | ||
74 | { | ||
75 | struct jffs2_compressor *this; | ||
76 | int err, ret = JFFS2_COMPR_NONE; | ||
77 | uint32_t orig_slen, orig_dlen; | ||
78 | char *output_buf; | ||
79 | |||
80 | output_buf = kmalloc(*cdatalen, GFP_KERNEL); | ||
81 | if (!output_buf) { | ||
82 | printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n"); | ||
83 | return ret; | ||
84 | } | ||
85 | orig_slen = *datalen; | ||
86 | orig_dlen = *cdatalen; | ||
87 | spin_lock(&jffs2_compressor_list_lock); | ||
88 | list_for_each_entry(this, &jffs2_compressor_list, list) { | ||
89 | /* Skip decompress-only and disabled modules */ | ||
90 | if (!this->compress || this->disabled) | ||
91 | continue; | ||
92 | |||
93 | /* Skip if not the desired compression type */ | ||
94 | if (compr && (compr != this->compr)) | ||
95 | continue; | ||
96 | |||
97 | /* | ||
98 | * Either compression type was unspecified, or we found our | ||
99 | * compressor; either way, we're good to go. | ||
100 | */ | ||
101 | this->usecount++; | ||
102 | spin_unlock(&jffs2_compressor_list_lock); | ||
103 | |||
104 | *datalen = orig_slen; | ||
105 | *cdatalen = orig_dlen; | ||
106 | err = this->compress(data_in, output_buf, datalen, cdatalen); | ||
107 | |||
108 | spin_lock(&jffs2_compressor_list_lock); | ||
109 | this->usecount--; | ||
110 | if (!err) { | ||
111 | /* Success */ | ||
112 | ret = this->compr; | ||
113 | this->stat_compr_blocks++; | ||
114 | this->stat_compr_orig_size += *datalen; | ||
115 | this->stat_compr_new_size += *cdatalen; | ||
116 | break; | ||
117 | } | ||
118 | } | ||
119 | spin_unlock(&jffs2_compressor_list_lock); | ||
120 | if (ret == JFFS2_COMPR_NONE) | ||
121 | kfree(output_buf); | ||
122 | else | ||
123 | *cpage_out = output_buf; | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
56 | /* jffs2_compress: | 128 | /* jffs2_compress: |
57 | * @data_in: Pointer to uncompressed data | 129 | * @data_in: Pointer to uncompressed data |
58 | * @cpage_out: Pointer to returned pointer to buffer for compressed data | 130 | * @cpage_out: Pointer to returned pointer to buffer for compressed data |
@@ -76,47 +148,23 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
76 | uint32_t *datalen, uint32_t *cdatalen) | 148 | uint32_t *datalen, uint32_t *cdatalen) |
77 | { | 149 | { |
78 | int ret = JFFS2_COMPR_NONE; | 150 | int ret = JFFS2_COMPR_NONE; |
79 | int compr_ret; | 151 | int mode, compr_ret; |
80 | struct jffs2_compressor *this, *best=NULL; | 152 | struct jffs2_compressor *this, *best=NULL; |
81 | unsigned char *output_buf = NULL, *tmp_buf; | 153 | unsigned char *output_buf = NULL, *tmp_buf; |
82 | uint32_t orig_slen, orig_dlen; | 154 | uint32_t orig_slen, orig_dlen; |
83 | uint32_t best_slen=0, best_dlen=0; | 155 | uint32_t best_slen=0, best_dlen=0; |
84 | 156 | ||
85 | switch (jffs2_compression_mode) { | 157 | if (c->mount_opts.override_compr) |
158 | mode = c->mount_opts.compr; | ||
159 | else | ||
160 | mode = jffs2_compression_mode; | ||
161 | |||
162 | switch (mode) { | ||
86 | case JFFS2_COMPR_MODE_NONE: | 163 | case JFFS2_COMPR_MODE_NONE: |
87 | break; | 164 | break; |
88 | case JFFS2_COMPR_MODE_PRIORITY: | 165 | case JFFS2_COMPR_MODE_PRIORITY: |
89 | output_buf = kmalloc(*cdatalen,GFP_KERNEL); | 166 | ret = jffs2_selected_compress(0, data_in, cpage_out, datalen, |
90 | if (!output_buf) { | 167 | cdatalen); |
91 | printk(KERN_WARNING "JFFS2: No memory for compressor allocation. Compression failed.\n"); | ||
92 | goto out; | ||
93 | } | ||
94 | orig_slen = *datalen; | ||
95 | orig_dlen = *cdatalen; | ||
96 | spin_lock(&jffs2_compressor_list_lock); | ||
97 | list_for_each_entry(this, &jffs2_compressor_list, list) { | ||
98 | /* Skip decompress-only backwards-compatibility and disabled modules */ | ||
99 | if ((!this->compress)||(this->disabled)) | ||
100 | continue; | ||
101 | |||
102 | this->usecount++; | ||
103 | spin_unlock(&jffs2_compressor_list_lock); | ||
104 | *datalen = orig_slen; | ||
105 | *cdatalen = orig_dlen; | ||
106 | compr_ret = this->compress(data_in, output_buf, datalen, cdatalen); | ||
107 | spin_lock(&jffs2_compressor_list_lock); | ||
108 | this->usecount--; | ||
109 | if (!compr_ret) { | ||
110 | ret = this->compr; | ||
111 | this->stat_compr_blocks++; | ||
112 | this->stat_compr_orig_size += *datalen; | ||
113 | this->stat_compr_new_size += *cdatalen; | ||
114 | break; | ||
115 | } | ||
116 | } | ||
117 | spin_unlock(&jffs2_compressor_list_lock); | ||
118 | if (ret == JFFS2_COMPR_NONE) | ||
119 | kfree(output_buf); | ||
120 | break; | 168 | break; |
121 | case JFFS2_COMPR_MODE_SIZE: | 169 | case JFFS2_COMPR_MODE_SIZE: |
122 | case JFFS2_COMPR_MODE_FAVOURLZO: | 170 | case JFFS2_COMPR_MODE_FAVOURLZO: |
@@ -174,22 +222,28 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
174 | best->stat_compr_orig_size += best_slen; | 222 | best->stat_compr_orig_size += best_slen; |
175 | best->stat_compr_new_size += best_dlen; | 223 | best->stat_compr_new_size += best_dlen; |
176 | ret = best->compr; | 224 | ret = best->compr; |
225 | *cpage_out = output_buf; | ||
177 | } | 226 | } |
178 | spin_unlock(&jffs2_compressor_list_lock); | 227 | spin_unlock(&jffs2_compressor_list_lock); |
179 | break; | 228 | break; |
229 | case JFFS2_COMPR_MODE_FORCELZO: | ||
230 | ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in, | ||
231 | cpage_out, datalen, cdatalen); | ||
232 | break; | ||
233 | case JFFS2_COMPR_MODE_FORCEZLIB: | ||
234 | ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in, | ||
235 | cpage_out, datalen, cdatalen); | ||
236 | break; | ||
180 | default: | 237 | default: |
181 | printk(KERN_ERR "JFFS2: unknown compression mode.\n"); | 238 | printk(KERN_ERR "JFFS2: unknown compression mode.\n"); |
182 | } | 239 | } |
183 | out: | 240 | |
184 | if (ret == JFFS2_COMPR_NONE) { | 241 | if (ret == JFFS2_COMPR_NONE) { |
185 | *cpage_out = data_in; | 242 | *cpage_out = data_in; |
186 | *datalen = *cdatalen; | 243 | *datalen = *cdatalen; |
187 | none_stat_compr_blocks++; | 244 | none_stat_compr_blocks++; |
188 | none_stat_compr_size += *datalen; | 245 | none_stat_compr_size += *datalen; |
189 | } | 246 | } |
190 | else { | ||
191 | *cpage_out = output_buf; | ||
192 | } | ||
193 | return ret; | 247 | return ret; |
194 | } | 248 | } |
195 | 249 | ||
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index 13bb7597ab39..5e91d578f4ed 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h | |||
@@ -40,6 +40,8 @@ | |||
40 | #define JFFS2_COMPR_MODE_PRIORITY 1 | 40 | #define JFFS2_COMPR_MODE_PRIORITY 1 |
41 | #define JFFS2_COMPR_MODE_SIZE 2 | 41 | #define JFFS2_COMPR_MODE_SIZE 2 |
42 | #define JFFS2_COMPR_MODE_FAVOURLZO 3 | 42 | #define JFFS2_COMPR_MODE_FAVOURLZO 3 |
43 | #define JFFS2_COMPR_MODE_FORCELZO 4 | ||
44 | #define JFFS2_COMPR_MODE_FORCEZLIB 5 | ||
43 | 45 | ||
44 | #define FAVOUR_LZO_PERCENT 80 | 46 | #define FAVOUR_LZO_PERCENT 80 |
45 | 47 | ||
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 7286e44ac665..4b8afe39a87f 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -379,7 +379,7 @@ void jffs2_dirty_inode(struct inode *inode, int flags) | |||
379 | jffs2_do_setattr(inode, &iattr); | 379 | jffs2_do_setattr(inode, &iattr); |
380 | } | 380 | } |
381 | 381 | ||
382 | int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) | 382 | int jffs2_do_remount_fs(struct super_block *sb, int *flags, char *data) |
383 | { | 383 | { |
384 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 384 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
385 | 385 | ||
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 0bc6a6c80a56..55a0c1dceadf 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
@@ -29,6 +29,11 @@ | |||
29 | 29 | ||
30 | struct jffs2_inodirty; | 30 | struct jffs2_inodirty; |
31 | 31 | ||
32 | struct jffs2_mount_opts { | ||
33 | bool override_compr; | ||
34 | unsigned int compr; | ||
35 | }; | ||
36 | |||
32 | /* A struct for the overall file system control. Pointers to | 37 | /* A struct for the overall file system control. Pointers to |
33 | jffs2_sb_info structs are named `c' in the source code. | 38 | jffs2_sb_info structs are named `c' in the source code. |
34 | Nee jffs_control | 39 | Nee jffs_control |
@@ -126,6 +131,7 @@ struct jffs2_sb_info { | |||
126 | #endif | 131 | #endif |
127 | 132 | ||
128 | struct jffs2_summary *summary; /* Summary information */ | 133 | struct jffs2_summary *summary; /* Summary information */ |
134 | struct jffs2_mount_opts mount_opts; | ||
129 | 135 | ||
130 | #ifdef CONFIG_JFFS2_FS_XATTR | 136 | #ifdef CONFIG_JFFS2_FS_XATTR |
131 | #define XATTRINDEX_HASHSIZE (57) | 137 | #define XATTRINDEX_HASHSIZE (57) |
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 6c1755c59c0f..ab65ee3ec858 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
@@ -176,7 +176,7 @@ void jffs2_dirty_inode(struct inode *inode, int flags); | |||
176 | struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, | 176 | struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, |
177 | struct jffs2_raw_inode *ri); | 177 | struct jffs2_raw_inode *ri); |
178 | int jffs2_statfs (struct dentry *, struct kstatfs *); | 178 | int jffs2_statfs (struct dentry *, struct kstatfs *); |
179 | int jffs2_remount_fs (struct super_block *, int *, char *); | 179 | int jffs2_do_remount_fs(struct super_block *, int *, char *); |
180 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); | 180 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); |
181 | void jffs2_gc_release_inode(struct jffs2_sb_info *c, | 181 | void jffs2_gc_release_inode(struct jffs2_sb_info *c, |
182 | struct jffs2_inode_info *f); | 182 | struct jffs2_inode_info *f); |
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 8d8cd3419d02..28107ca136e4 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -275,9 +275,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) | |||
275 | else | 275 | else |
276 | c->mtd->unpoint(c->mtd, 0, c->mtd->size); | 276 | c->mtd->unpoint(c->mtd, 0, c->mtd->size); |
277 | #endif | 277 | #endif |
278 | if (s) | 278 | kfree(s); |
279 | kfree(s); | ||
280 | |||
281 | return ret; | 279 | return ret; |
282 | } | 280 | } |
283 | 281 | ||
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 853b8e300084..e7e974454115 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
@@ -17,11 +17,13 @@ | |||
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/mount.h> | 19 | #include <linux/mount.h> |
20 | #include <linux/parser.h> | ||
20 | #include <linux/jffs2.h> | 21 | #include <linux/jffs2.h> |
21 | #include <linux/pagemap.h> | 22 | #include <linux/pagemap.h> |
22 | #include <linux/mtd/super.h> | 23 | #include <linux/mtd/super.h> |
23 | #include <linux/ctype.h> | 24 | #include <linux/ctype.h> |
24 | #include <linux/namei.h> | 25 | #include <linux/namei.h> |
26 | #include <linux/seq_file.h> | ||
25 | #include <linux/exportfs.h> | 27 | #include <linux/exportfs.h> |
26 | #include "compr.h" | 28 | #include "compr.h" |
27 | #include "nodelist.h" | 29 | #include "nodelist.h" |
@@ -75,6 +77,37 @@ static void jffs2_write_super(struct super_block *sb) | |||
75 | unlock_super(sb); | 77 | unlock_super(sb); |
76 | } | 78 | } |
77 | 79 | ||
80 | static const char *jffs2_compr_name(unsigned int compr) | ||
81 | { | ||
82 | switch (compr) { | ||
83 | case JFFS2_COMPR_MODE_NONE: | ||
84 | return "none"; | ||
85 | #ifdef CONFIG_JFFS2_LZO | ||
86 | case JFFS2_COMPR_MODE_FORCELZO: | ||
87 | return "lzo"; | ||
88 | #endif | ||
89 | #ifdef CONFIG_JFFS2_ZLIB | ||
90 | case JFFS2_COMPR_MODE_FORCEZLIB: | ||
91 | return "zlib"; | ||
92 | #endif | ||
93 | default: | ||
94 | /* should never happen; programmer error */ | ||
95 | WARN_ON(1); | ||
96 | return ""; | ||
97 | } | ||
98 | } | ||
99 | |||
100 | static int jffs2_show_options(struct seq_file *s, struct vfsmount *mnt) | ||
101 | { | ||
102 | struct jffs2_sb_info *c = JFFS2_SB_INFO(mnt->mnt_sb); | ||
103 | struct jffs2_mount_opts *opts = &c->mount_opts; | ||
104 | |||
105 | if (opts->override_compr) | ||
106 | seq_printf(s, ",compr=%s", jffs2_compr_name(opts->compr)); | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
78 | static int jffs2_sync_fs(struct super_block *sb, int wait) | 111 | static int jffs2_sync_fs(struct super_block *sb, int wait) |
79 | { | 112 | { |
80 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 113 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
@@ -133,6 +166,85 @@ static const struct export_operations jffs2_export_ops = { | |||
133 | .fh_to_parent = jffs2_fh_to_parent, | 166 | .fh_to_parent = jffs2_fh_to_parent, |
134 | }; | 167 | }; |
135 | 168 | ||
169 | /* | ||
170 | * JFFS2 mount options. | ||
171 | * | ||
172 | * Opt_override_compr: override default compressor | ||
173 | * Opt_err: just end of array marker | ||
174 | */ | ||
175 | enum { | ||
176 | Opt_override_compr, | ||
177 | Opt_err, | ||
178 | }; | ||
179 | |||
180 | static const match_table_t tokens = { | ||
181 | {Opt_override_compr, "compr=%s"}, | ||
182 | {Opt_err, NULL}, | ||
183 | }; | ||
184 | |||
185 | static int jffs2_parse_options(struct jffs2_sb_info *c, char *data) | ||
186 | { | ||
187 | substring_t args[MAX_OPT_ARGS]; | ||
188 | char *p, *name; | ||
189 | |||
190 | if (!data) | ||
191 | return 0; | ||
192 | |||
193 | while ((p = strsep(&data, ","))) { | ||
194 | int token; | ||
195 | |||
196 | if (!*p) | ||
197 | continue; | ||
198 | |||
199 | token = match_token(p, tokens, args); | ||
200 | switch (token) { | ||
201 | case Opt_override_compr: | ||
202 | name = match_strdup(&args[0]); | ||
203 | |||
204 | if (!name) | ||
205 | return -ENOMEM; | ||
206 | if (!strcmp(name, "none")) | ||
207 | c->mount_opts.compr = JFFS2_COMPR_MODE_NONE; | ||
208 | #ifdef CONFIG_JFFS2_LZO | ||
209 | else if (!strcmp(name, "lzo")) | ||
210 | c->mount_opts.compr = JFFS2_COMPR_MODE_FORCELZO; | ||
211 | #endif | ||
212 | #ifdef CONFIG_JFFS2_ZLIB | ||
213 | else if (!strcmp(name, "zlib")) | ||
214 | c->mount_opts.compr = | ||
215 | JFFS2_COMPR_MODE_FORCEZLIB; | ||
216 | #endif | ||
217 | else { | ||
218 | printk(KERN_ERR "JFFS2 Error: unknown compressor \"%s\"", | ||
219 | name); | ||
220 | kfree(name); | ||
221 | return -EINVAL; | ||
222 | } | ||
223 | kfree(name); | ||
224 | c->mount_opts.override_compr = true; | ||
225 | break; | ||
226 | default: | ||
227 | printk(KERN_ERR "JFFS2 Error: unrecognized mount option '%s' or missing value\n", | ||
228 | p); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | } | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | static int jffs2_remount_fs(struct super_block *sb, int *flags, char *data) | ||
237 | { | ||
238 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | ||
239 | int err; | ||
240 | |||
241 | err = jffs2_parse_options(c, data); | ||
242 | if (err) | ||
243 | return -EINVAL; | ||
244 | |||
245 | return jffs2_do_remount_fs(sb, flags, data); | ||
246 | } | ||
247 | |||
136 | static const struct super_operations jffs2_super_operations = | 248 | static const struct super_operations jffs2_super_operations = |
137 | { | 249 | { |
138 | .alloc_inode = jffs2_alloc_inode, | 250 | .alloc_inode = jffs2_alloc_inode, |
@@ -143,6 +255,7 @@ static const struct super_operations jffs2_super_operations = | |||
143 | .remount_fs = jffs2_remount_fs, | 255 | .remount_fs = jffs2_remount_fs, |
144 | .evict_inode = jffs2_evict_inode, | 256 | .evict_inode = jffs2_evict_inode, |
145 | .dirty_inode = jffs2_dirty_inode, | 257 | .dirty_inode = jffs2_dirty_inode, |
258 | .show_options = jffs2_show_options, | ||
146 | .sync_fs = jffs2_sync_fs, | 259 | .sync_fs = jffs2_sync_fs, |
147 | }; | 260 | }; |
148 | 261 | ||
@@ -166,6 +279,12 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent) | |||
166 | c->os_priv = sb; | 279 | c->os_priv = sb; |
167 | sb->s_fs_info = c; | 280 | sb->s_fs_info = c; |
168 | 281 | ||
282 | ret = jffs2_parse_options(c, data); | ||
283 | if (ret) { | ||
284 | kfree(c); | ||
285 | return -EINVAL; | ||
286 | } | ||
287 | |||
169 | /* Initialize JFFS2 superblock locks, the further initialization will | 288 | /* Initialize JFFS2 superblock locks, the further initialization will |
170 | * be done later */ | 289 | * be done later */ |
171 | mutex_init(&c->alloc_sem); | 290 | mutex_init(&c->alloc_sem); |
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 4515bea0268f..b09e51d2f81f 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
@@ -578,8 +578,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
578 | if (!jffs2_is_writebuffered(c)) | 578 | if (!jffs2_is_writebuffered(c)) |
579 | return 0; | 579 | return 0; |
580 | 580 | ||
581 | if (mutex_trylock(&c->alloc_sem)) { | 581 | if (!mutex_is_locked(&c->alloc_sem)) { |
582 | mutex_unlock(&c->alloc_sem); | ||
583 | printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n"); | 582 | printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n"); |
584 | BUG(); | 583 | BUG(); |
585 | } | 584 | } |
@@ -1026,7 +1025,7 @@ int jffs2_check_oob_empty(struct jffs2_sb_info *c, | |||
1026 | int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); | 1025 | int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); |
1027 | struct mtd_oob_ops ops; | 1026 | struct mtd_oob_ops ops; |
1028 | 1027 | ||
1029 | ops.mode = MTD_OOB_AUTO; | 1028 | ops.mode = MTD_OPS_AUTO_OOB; |
1030 | ops.ooblen = NR_OOB_SCAN_PAGES * c->oobavail; | 1029 | ops.ooblen = NR_OOB_SCAN_PAGES * c->oobavail; |
1031 | ops.oobbuf = c->oobbuf; | 1030 | ops.oobbuf = c->oobbuf; |
1032 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; | 1031 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; |
@@ -1069,7 +1068,7 @@ int jffs2_check_nand_cleanmarker(struct jffs2_sb_info *c, | |||
1069 | struct mtd_oob_ops ops; | 1068 | struct mtd_oob_ops ops; |
1070 | int ret, cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); | 1069 | int ret, cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); |
1071 | 1070 | ||
1072 | ops.mode = MTD_OOB_AUTO; | 1071 | ops.mode = MTD_OPS_AUTO_OOB; |
1073 | ops.ooblen = cmlen; | 1072 | ops.ooblen = cmlen; |
1074 | ops.oobbuf = c->oobbuf; | 1073 | ops.oobbuf = c->oobbuf; |
1075 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; | 1074 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; |
@@ -1095,7 +1094,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, | |||
1095 | struct mtd_oob_ops ops; | 1094 | struct mtd_oob_ops ops; |
1096 | int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); | 1095 | int cmlen = min_t(int, c->oobavail, OOB_CM_SIZE); |
1097 | 1096 | ||
1098 | ops.mode = MTD_OOB_AUTO; | 1097 | ops.mode = MTD_OPS_AUTO_OOB; |
1099 | ops.ooblen = cmlen; | 1098 | ops.ooblen = cmlen; |
1100 | ops.oobbuf = (uint8_t *)&oob_cleanmarker; | 1099 | ops.oobbuf = (uint8_t *)&oob_cleanmarker; |
1101 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; | 1100 | ops.len = ops.ooboffs = ops.retlen = ops.oobretlen = 0; |
diff --git a/fs/namei.c b/fs/namei.c index ac6d214da827..5008f01787f5 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -852,7 +852,7 @@ static int follow_managed(struct path *path, unsigned flags) | |||
852 | mntput(path->mnt); | 852 | mntput(path->mnt); |
853 | if (ret == -EISDIR) | 853 | if (ret == -EISDIR) |
854 | ret = 0; | 854 | ret = 0; |
855 | return ret; | 855 | return ret < 0 ? ret : need_mntput; |
856 | } | 856 | } |
857 | 857 | ||
858 | int follow_down_one(struct path *path) | 858 | int follow_down_one(struct path *path) |
@@ -900,6 +900,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
900 | break; | 900 | break; |
901 | path->mnt = mounted; | 901 | path->mnt = mounted; |
902 | path->dentry = mounted->mnt_root; | 902 | path->dentry = mounted->mnt_root; |
903 | nd->flags |= LOOKUP_JUMPED; | ||
903 | nd->seq = read_seqcount_begin(&path->dentry->d_seq); | 904 | nd->seq = read_seqcount_begin(&path->dentry->d_seq); |
904 | /* | 905 | /* |
905 | * Update the inode too. We don't need to re-check the | 906 | * Update the inode too. We don't need to re-check the |
@@ -1213,6 +1214,8 @@ retry: | |||
1213 | path_put_conditional(path, nd); | 1214 | path_put_conditional(path, nd); |
1214 | return err; | 1215 | return err; |
1215 | } | 1216 | } |
1217 | if (err) | ||
1218 | nd->flags |= LOOKUP_JUMPED; | ||
1216 | *inode = path->dentry->d_inode; | 1219 | *inode = path->dentry->d_inode; |
1217 | return 0; | 1220 | return 0; |
1218 | } | 1221 | } |
@@ -2146,6 +2149,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2146 | } | 2149 | } |
2147 | 2150 | ||
2148 | /* create side of things */ | 2151 | /* create side of things */ |
2152 | /* | ||
2153 | * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED has been | ||
2154 | * cleared when we got to the last component we are about to look up | ||
2155 | */ | ||
2149 | error = complete_walk(nd); | 2156 | error = complete_walk(nd); |
2150 | if (error) | 2157 | if (error) |
2151 | return ERR_PTR(error); | 2158 | return ERR_PTR(error); |
@@ -2214,6 +2221,9 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2214 | if (error < 0) | 2221 | if (error < 0) |
2215 | goto exit_dput; | 2222 | goto exit_dput; |
2216 | 2223 | ||
2224 | if (error) | ||
2225 | nd->flags |= LOOKUP_JUMPED; | ||
2226 | |||
2217 | error = -ENOENT; | 2227 | error = -ENOENT; |
2218 | if (!path->dentry->d_inode) | 2228 | if (!path->dentry->d_inode) |
2219 | goto exit_dput; | 2229 | goto exit_dput; |
@@ -2223,6 +2233,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path, | |||
2223 | 2233 | ||
2224 | path_to_nameidata(path, nd); | 2234 | path_to_nameidata(path, nd); |
2225 | nd->inode = path->dentry->d_inode; | 2235 | nd->inode = path->dentry->d_inode; |
2236 | /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */ | ||
2237 | error = complete_walk(nd); | ||
2238 | if (error) | ||
2239 | goto exit; | ||
2226 | error = -EISDIR; | 2240 | error = -EISDIR; |
2227 | if (S_ISDIR(nd->inode->i_mode)) | 2241 | if (S_ISDIR(nd->inode->i_mode)) |
2228 | goto exit; | 2242 | goto exit; |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 2db1bd3173b2..851ba3dcdc29 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1652,46 +1652,12 @@ out: | |||
1652 | return error; | 1652 | return error; |
1653 | } | 1653 | } |
1654 | 1654 | ||
1655 | static int proc_pid_fd_link_getattr(struct vfsmount *mnt, struct dentry *dentry, | ||
1656 | struct kstat *stat) | ||
1657 | { | ||
1658 | struct inode *inode = dentry->d_inode; | ||
1659 | struct task_struct *task = get_proc_task(inode); | ||
1660 | int rc; | ||
1661 | |||
1662 | if (task == NULL) | ||
1663 | return -ESRCH; | ||
1664 | |||
1665 | rc = -EACCES; | ||
1666 | if (lock_trace(task)) | ||
1667 | goto out_task; | ||
1668 | |||
1669 | generic_fillattr(inode, stat); | ||
1670 | unlock_trace(task); | ||
1671 | rc = 0; | ||
1672 | out_task: | ||
1673 | put_task_struct(task); | ||
1674 | return rc; | ||
1675 | } | ||
1676 | |||
1677 | static const struct inode_operations proc_pid_link_inode_operations = { | 1655 | static const struct inode_operations proc_pid_link_inode_operations = { |
1678 | .readlink = proc_pid_readlink, | 1656 | .readlink = proc_pid_readlink, |
1679 | .follow_link = proc_pid_follow_link, | 1657 | .follow_link = proc_pid_follow_link, |
1680 | .setattr = proc_setattr, | 1658 | .setattr = proc_setattr, |
1681 | }; | 1659 | }; |
1682 | 1660 | ||
1683 | static const struct inode_operations proc_fdinfo_link_inode_operations = { | ||
1684 | .setattr = proc_setattr, | ||
1685 | .getattr = proc_pid_fd_link_getattr, | ||
1686 | }; | ||
1687 | |||
1688 | static const struct inode_operations proc_fd_link_inode_operations = { | ||
1689 | .readlink = proc_pid_readlink, | ||
1690 | .follow_link = proc_pid_follow_link, | ||
1691 | .setattr = proc_setattr, | ||
1692 | .getattr = proc_pid_fd_link_getattr, | ||
1693 | }; | ||
1694 | |||
1695 | 1661 | ||
1696 | /* building an inode */ | 1662 | /* building an inode */ |
1697 | 1663 | ||
@@ -1923,61 +1889,49 @@ out: | |||
1923 | 1889 | ||
1924 | static int proc_fd_info(struct inode *inode, struct path *path, char *info) | 1890 | static int proc_fd_info(struct inode *inode, struct path *path, char *info) |
1925 | { | 1891 | { |
1926 | struct task_struct *task; | 1892 | struct task_struct *task = get_proc_task(inode); |
1927 | struct files_struct *files; | 1893 | struct files_struct *files = NULL; |
1928 | struct file *file; | 1894 | struct file *file; |
1929 | int fd = proc_fd(inode); | 1895 | int fd = proc_fd(inode); |
1930 | int rc; | ||
1931 | |||
1932 | task = get_proc_task(inode); | ||
1933 | if (!task) | ||
1934 | return -ENOENT; | ||
1935 | |||
1936 | rc = -EACCES; | ||
1937 | if (lock_trace(task)) | ||
1938 | goto out_task; | ||
1939 | |||
1940 | rc = -ENOENT; | ||
1941 | files = get_files_struct(task); | ||
1942 | if (files == NULL) | ||
1943 | goto out_unlock; | ||
1944 | 1896 | ||
1945 | /* | 1897 | if (task) { |
1946 | * We are not taking a ref to the file structure, so we must | 1898 | files = get_files_struct(task); |
1947 | * hold ->file_lock. | 1899 | put_task_struct(task); |
1948 | */ | 1900 | } |
1949 | spin_lock(&files->file_lock); | 1901 | if (files) { |
1950 | file = fcheck_files(files, fd); | 1902 | /* |
1951 | if (file) { | 1903 | * We are not taking a ref to the file structure, so we must |
1952 | unsigned int f_flags; | 1904 | * hold ->file_lock. |
1953 | struct fdtable *fdt; | 1905 | */ |
1954 | 1906 | spin_lock(&files->file_lock); | |
1955 | fdt = files_fdtable(files); | 1907 | file = fcheck_files(files, fd); |
1956 | f_flags = file->f_flags & ~O_CLOEXEC; | 1908 | if (file) { |
1957 | if (FD_ISSET(fd, fdt->close_on_exec)) | 1909 | unsigned int f_flags; |
1958 | f_flags |= O_CLOEXEC; | 1910 | struct fdtable *fdt; |
1959 | 1911 | ||
1960 | if (path) { | 1912 | fdt = files_fdtable(files); |
1961 | *path = file->f_path; | 1913 | f_flags = file->f_flags & ~O_CLOEXEC; |
1962 | path_get(&file->f_path); | 1914 | if (FD_ISSET(fd, fdt->close_on_exec)) |
1915 | f_flags |= O_CLOEXEC; | ||
1916 | |||
1917 | if (path) { | ||
1918 | *path = file->f_path; | ||
1919 | path_get(&file->f_path); | ||
1920 | } | ||
1921 | if (info) | ||
1922 | snprintf(info, PROC_FDINFO_MAX, | ||
1923 | "pos:\t%lli\n" | ||
1924 | "flags:\t0%o\n", | ||
1925 | (long long) file->f_pos, | ||
1926 | f_flags); | ||
1927 | spin_unlock(&files->file_lock); | ||
1928 | put_files_struct(files); | ||
1929 | return 0; | ||
1963 | } | 1930 | } |
1964 | if (info) | 1931 | spin_unlock(&files->file_lock); |
1965 | snprintf(info, PROC_FDINFO_MAX, | 1932 | put_files_struct(files); |
1966 | "pos:\t%lli\n" | 1933 | } |
1967 | "flags:\t0%o\n", | 1934 | return -ENOENT; |
1968 | (long long) file->f_pos, | ||
1969 | f_flags); | ||
1970 | rc = 0; | ||
1971 | } else | ||
1972 | rc = -ENOENT; | ||
1973 | spin_unlock(&files->file_lock); | ||
1974 | put_files_struct(files); | ||
1975 | |||
1976 | out_unlock: | ||
1977 | unlock_trace(task); | ||
1978 | out_task: | ||
1979 | put_task_struct(task); | ||
1980 | return rc; | ||
1981 | } | 1935 | } |
1982 | 1936 | ||
1983 | static int proc_fd_link(struct inode *inode, struct path *path) | 1937 | static int proc_fd_link(struct inode *inode, struct path *path) |
@@ -2072,7 +2026,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir, | |||
2072 | spin_unlock(&files->file_lock); | 2026 | spin_unlock(&files->file_lock); |
2073 | put_files_struct(files); | 2027 | put_files_struct(files); |
2074 | 2028 | ||
2075 | inode->i_op = &proc_fd_link_inode_operations; | 2029 | inode->i_op = &proc_pid_link_inode_operations; |
2076 | inode->i_size = 64; | 2030 | inode->i_size = 64; |
2077 | ei->op.proc_get_link = proc_fd_link; | 2031 | ei->op.proc_get_link = proc_fd_link; |
2078 | d_set_d_op(dentry, &tid_fd_dentry_operations); | 2032 | d_set_d_op(dentry, &tid_fd_dentry_operations); |
@@ -2104,12 +2058,7 @@ static struct dentry *proc_lookupfd_common(struct inode *dir, | |||
2104 | if (fd == ~0U) | 2058 | if (fd == ~0U) |
2105 | goto out; | 2059 | goto out; |
2106 | 2060 | ||
2107 | result = ERR_PTR(-EACCES); | ||
2108 | if (lock_trace(task)) | ||
2109 | goto out; | ||
2110 | |||
2111 | result = instantiate(dir, dentry, task, &fd); | 2061 | result = instantiate(dir, dentry, task, &fd); |
2112 | unlock_trace(task); | ||
2113 | out: | 2062 | out: |
2114 | put_task_struct(task); | 2063 | put_task_struct(task); |
2115 | out_no_task: | 2064 | out_no_task: |
@@ -2129,28 +2078,23 @@ static int proc_readfd_common(struct file * filp, void * dirent, | |||
2129 | retval = -ENOENT; | 2078 | retval = -ENOENT; |
2130 | if (!p) | 2079 | if (!p) |
2131 | goto out_no_task; | 2080 | goto out_no_task; |
2132 | |||
2133 | retval = -EACCES; | ||
2134 | if (lock_trace(p)) | ||
2135 | goto out; | ||
2136 | |||
2137 | retval = 0; | 2081 | retval = 0; |
2138 | 2082 | ||
2139 | fd = filp->f_pos; | 2083 | fd = filp->f_pos; |
2140 | switch (fd) { | 2084 | switch (fd) { |
2141 | case 0: | 2085 | case 0: |
2142 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) | 2086 | if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0) |
2143 | goto out_unlock; | 2087 | goto out; |
2144 | filp->f_pos++; | 2088 | filp->f_pos++; |
2145 | case 1: | 2089 | case 1: |
2146 | ino = parent_ino(dentry); | 2090 | ino = parent_ino(dentry); |
2147 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) | 2091 | if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0) |
2148 | goto out_unlock; | 2092 | goto out; |
2149 | filp->f_pos++; | 2093 | filp->f_pos++; |
2150 | default: | 2094 | default: |
2151 | files = get_files_struct(p); | 2095 | files = get_files_struct(p); |
2152 | if (!files) | 2096 | if (!files) |
2153 | goto out_unlock; | 2097 | goto out; |
2154 | rcu_read_lock(); | 2098 | rcu_read_lock(); |
2155 | for (fd = filp->f_pos-2; | 2099 | for (fd = filp->f_pos-2; |
2156 | fd < files_fdtable(files)->max_fds; | 2100 | fd < files_fdtable(files)->max_fds; |
@@ -2174,9 +2118,6 @@ static int proc_readfd_common(struct file * filp, void * dirent, | |||
2174 | rcu_read_unlock(); | 2118 | rcu_read_unlock(); |
2175 | put_files_struct(files); | 2119 | put_files_struct(files); |
2176 | } | 2120 | } |
2177 | |||
2178 | out_unlock: | ||
2179 | unlock_trace(p); | ||
2180 | out: | 2121 | out: |
2181 | put_task_struct(p); | 2122 | put_task_struct(p); |
2182 | out_no_task: | 2123 | out_no_task: |
@@ -2254,7 +2195,6 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir, | |||
2254 | ei->fd = fd; | 2195 | ei->fd = fd; |
2255 | inode->i_mode = S_IFREG | S_IRUSR; | 2196 | inode->i_mode = S_IFREG | S_IRUSR; |
2256 | inode->i_fop = &proc_fdinfo_file_operations; | 2197 | inode->i_fop = &proc_fdinfo_file_operations; |
2257 | inode->i_op = &proc_fdinfo_link_inode_operations; | ||
2258 | d_set_d_op(dentry, &tid_fd_dentry_operations); | 2198 | d_set_d_op(dentry, &tid_fd_dentry_operations); |
2259 | d_add(dentry, inode); | 2199 | d_add(dentry, inode); |
2260 | /* Close the race of the process dying before we return the dentry */ | 2200 | /* Close the race of the process dying before we return the dentry */ |
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c index eef109a1a927..b09ba2dd8b62 100644 --- a/fs/ubifs/debug.c +++ b/fs/ubifs/debug.c | |||
@@ -870,6 +870,22 @@ void dbg_dump_lpt_info(struct ubifs_info *c) | |||
870 | spin_unlock(&dbg_lock); | 870 | spin_unlock(&dbg_lock); |
871 | } | 871 | } |
872 | 872 | ||
873 | void dbg_dump_sleb(const struct ubifs_info *c, | ||
874 | const struct ubifs_scan_leb *sleb, int offs) | ||
875 | { | ||
876 | struct ubifs_scan_node *snod; | ||
877 | |||
878 | printk(KERN_DEBUG "(pid %d) start dumping scanned data from LEB %d:%d\n", | ||
879 | current->pid, sleb->lnum, offs); | ||
880 | |||
881 | list_for_each_entry(snod, &sleb->nodes, list) { | ||
882 | cond_resched(); | ||
883 | printk(KERN_DEBUG "Dumping node at LEB %d:%d len %d\n", sleb->lnum, | ||
884 | snod->offs, snod->len); | ||
885 | dbg_dump_node(c, snod->node); | ||
886 | } | ||
887 | } | ||
888 | |||
873 | void dbg_dump_leb(const struct ubifs_info *c, int lnum) | 889 | void dbg_dump_leb(const struct ubifs_info *c, int lnum) |
874 | { | 890 | { |
875 | struct ubifs_scan_leb *sleb; | 891 | struct ubifs_scan_leb *sleb; |
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h index feb361e252ac..8d9c46810189 100644 --- a/fs/ubifs/debug.h +++ b/fs/ubifs/debug.h | |||
@@ -269,6 +269,8 @@ void dbg_dump_lprop(const struct ubifs_info *c, const struct ubifs_lprops *lp); | |||
269 | void dbg_dump_lprops(struct ubifs_info *c); | 269 | void dbg_dump_lprops(struct ubifs_info *c); |
270 | void dbg_dump_lpt_info(struct ubifs_info *c); | 270 | void dbg_dump_lpt_info(struct ubifs_info *c); |
271 | void dbg_dump_leb(const struct ubifs_info *c, int lnum); | 271 | void dbg_dump_leb(const struct ubifs_info *c, int lnum); |
272 | void dbg_dump_sleb(const struct ubifs_info *c, | ||
273 | const struct ubifs_scan_leb *sleb, int offs); | ||
272 | void dbg_dump_znode(const struct ubifs_info *c, | 274 | void dbg_dump_znode(const struct ubifs_info *c, |
273 | const struct ubifs_znode *znode); | 275 | const struct ubifs_znode *znode); |
274 | void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat); | 276 | void dbg_dump_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat); |
@@ -387,6 +389,9 @@ static inline void dbg_dump_lpt_info(struct ubifs_info *c) { return; } | |||
387 | static inline void dbg_dump_leb(const struct ubifs_info *c, | 389 | static inline void dbg_dump_leb(const struct ubifs_info *c, |
388 | int lnum) { return; } | 390 | int lnum) { return; } |
389 | static inline void | 391 | static inline void |
392 | dbg_dump_sleb(const struct ubifs_info *c, | ||
393 | const struct ubifs_scan_leb *sleb, int offs) { return; } | ||
394 | static inline void | ||
390 | dbg_dump_znode(const struct ubifs_info *c, | 395 | dbg_dump_znode(const struct ubifs_info *c, |
391 | const struct ubifs_znode *znode) { return; } | 396 | const struct ubifs_znode *znode) { return; } |
392 | static inline void dbg_dump_heap(struct ubifs_info *c, | 397 | static inline void dbg_dump_heap(struct ubifs_info *c, |
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index af02790d9328..ee4f43f4bb99 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c | |||
@@ -983,7 +983,7 @@ int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf) | |||
983 | } | 983 | } |
984 | 984 | ||
985 | /** | 985 | /** |
986 | * clean_an_unclean_leb - read and write a LEB to remove corruption. | 986 | * clean_an_unclean_leb - read and write a LEB to remove corruption. |
987 | * @c: UBIFS file-system description object | 987 | * @c: UBIFS file-system description object |
988 | * @ucleb: unclean LEB information | 988 | * @ucleb: unclean LEB information |
989 | * @sbuf: LEB-sized buffer to use | 989 | * @sbuf: LEB-sized buffer to use |
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c index 93d938ad3d2a..6094c5a5d7a8 100644 --- a/fs/ubifs/sb.c +++ b/fs/ubifs/sb.c | |||
@@ -247,7 +247,7 @@ static int create_default_filesystem(struct ubifs_info *c) | |||
247 | mst->total_dirty = cpu_to_le64(tmp64); | 247 | mst->total_dirty = cpu_to_le64(tmp64); |
248 | 248 | ||
249 | /* The indexing LEB does not contribute to dark space */ | 249 | /* The indexing LEB does not contribute to dark space */ |
250 | tmp64 = (c->main_lebs - 1) * c->dark_wm; | 250 | tmp64 = ((long long)(c->main_lebs - 1) * c->dark_wm); |
251 | mst->total_dark = cpu_to_le64(tmp64); | 251 | mst->total_dark = cpu_to_le64(tmp64); |
252 | 252 | ||
253 | mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ); | 253 | mst->total_used = cpu_to_le64(UBIFS_INO_NODE_SZ); |
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 33b13310ee0c..574d4ee9b625 100644 --- a/fs/xfs/xfs_aops.c +++ b/fs/xfs/xfs_aops.c | |||
@@ -189,7 +189,7 @@ xfs_end_io( | |||
189 | int error = 0; | 189 | int error = 0; |
190 | 190 | ||
191 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { | 191 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
192 | error = -EIO; | 192 | ioend->io_error = -EIO; |
193 | goto done; | 193 | goto done; |
194 | } | 194 | } |
195 | if (ioend->io_error) | 195 | if (ioend->io_error) |
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 1a3513881bce..eac97ef81e2a 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -656,7 +656,7 @@ xfs_buf_item_committing( | |||
656 | /* | 656 | /* |
657 | * This is the ops vector shared by all buf log items. | 657 | * This is the ops vector shared by all buf log items. |
658 | */ | 658 | */ |
659 | static struct xfs_item_ops xfs_buf_item_ops = { | 659 | static const struct xfs_item_ops xfs_buf_item_ops = { |
660 | .iop_size = xfs_buf_item_size, | 660 | .iop_size = xfs_buf_item_size, |
661 | .iop_format = xfs_buf_item_format, | 661 | .iop_format = xfs_buf_item_format, |
662 | .iop_pin = xfs_buf_item_pin, | 662 | .iop_pin = xfs_buf_item_pin, |
diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c index bb3f71d236d2..0dee0b71029d 100644 --- a/fs/xfs/xfs_dquot_item.c +++ b/fs/xfs/xfs_dquot_item.c | |||
@@ -295,7 +295,7 @@ xfs_qm_dquot_logitem_committing( | |||
295 | /* | 295 | /* |
296 | * This is the ops vector for dquots | 296 | * This is the ops vector for dquots |
297 | */ | 297 | */ |
298 | static struct xfs_item_ops xfs_dquot_item_ops = { | 298 | static const struct xfs_item_ops xfs_dquot_item_ops = { |
299 | .iop_size = xfs_qm_dquot_logitem_size, | 299 | .iop_size = xfs_qm_dquot_logitem_size, |
300 | .iop_format = xfs_qm_dquot_logitem_format, | 300 | .iop_format = xfs_qm_dquot_logitem_format, |
301 | .iop_pin = xfs_qm_dquot_logitem_pin, | 301 | .iop_pin = xfs_qm_dquot_logitem_pin, |
@@ -483,7 +483,7 @@ xfs_qm_qoff_logitem_committing( | |||
483 | { | 483 | { |
484 | } | 484 | } |
485 | 485 | ||
486 | static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { | 486 | static const struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { |
487 | .iop_size = xfs_qm_qoff_logitem_size, | 487 | .iop_size = xfs_qm_qoff_logitem_size, |
488 | .iop_format = xfs_qm_qoff_logitem_format, | 488 | .iop_format = xfs_qm_qoff_logitem_format, |
489 | .iop_pin = xfs_qm_qoff_logitem_pin, | 489 | .iop_pin = xfs_qm_qoff_logitem_pin, |
@@ -498,7 +498,7 @@ static struct xfs_item_ops xfs_qm_qoffend_logitem_ops = { | |||
498 | /* | 498 | /* |
499 | * This is the ops vector shared by all quotaoff-start log items. | 499 | * This is the ops vector shared by all quotaoff-start log items. |
500 | */ | 500 | */ |
501 | static struct xfs_item_ops xfs_qm_qoff_logitem_ops = { | 501 | static const struct xfs_item_ops xfs_qm_qoff_logitem_ops = { |
502 | .iop_size = xfs_qm_qoff_logitem_size, | 502 | .iop_size = xfs_qm_qoff_logitem_size, |
503 | .iop_format = xfs_qm_qoff_logitem_format, | 503 | .iop_format = xfs_qm_qoff_logitem_format, |
504 | .iop_pin = xfs_qm_qoff_logitem_pin, | 504 | .iop_pin = xfs_qm_qoff_logitem_pin, |
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index d22e62623437..35c2aff38b20 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c | |||
@@ -217,7 +217,7 @@ xfs_efi_item_committing( | |||
217 | /* | 217 | /* |
218 | * This is the ops vector shared by all efi log items. | 218 | * This is the ops vector shared by all efi log items. |
219 | */ | 219 | */ |
220 | static struct xfs_item_ops xfs_efi_item_ops = { | 220 | static const struct xfs_item_ops xfs_efi_item_ops = { |
221 | .iop_size = xfs_efi_item_size, | 221 | .iop_size = xfs_efi_item_size, |
222 | .iop_format = xfs_efi_item_format, | 222 | .iop_format = xfs_efi_item_format, |
223 | .iop_pin = xfs_efi_item_pin, | 223 | .iop_pin = xfs_efi_item_pin, |
@@ -477,7 +477,7 @@ xfs_efd_item_committing( | |||
477 | /* | 477 | /* |
478 | * This is the ops vector shared by all efd log items. | 478 | * This is the ops vector shared by all efd log items. |
479 | */ | 479 | */ |
480 | static struct xfs_item_ops xfs_efd_item_ops = { | 480 | static const struct xfs_item_ops xfs_efd_item_ops = { |
481 | .iop_size = xfs_efd_item_size, | 481 | .iop_size = xfs_efd_item_size, |
482 | .iop_format = xfs_efd_item_format, | 482 | .iop_format = xfs_efd_item_format, |
483 | .iop_pin = xfs_efd_item_pin, | 483 | .iop_pin = xfs_efd_item_pin, |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index b7cf21ba240f..abaafdbb3e65 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -795,7 +795,7 @@ xfs_inode_item_committing( | |||
795 | /* | 795 | /* |
796 | * This is the ops vector shared by all buf log items. | 796 | * This is the ops vector shared by all buf log items. |
797 | */ | 797 | */ |
798 | static struct xfs_item_ops xfs_inode_item_ops = { | 798 | static const struct xfs_item_ops xfs_inode_item_ops = { |
799 | .iop_size = xfs_inode_item_size, | 799 | .iop_size = xfs_inode_item_size, |
800 | .iop_format = xfs_inode_item_format, | 800 | .iop_format = xfs_inode_item_format, |
801 | .iop_pin = xfs_inode_item_pin, | 801 | .iop_pin = xfs_inode_item_pin, |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 2758a6277c52..a14cd89fe465 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -626,7 +626,7 @@ xfs_log_item_init( | |||
626 | struct xfs_mount *mp, | 626 | struct xfs_mount *mp, |
627 | struct xfs_log_item *item, | 627 | struct xfs_log_item *item, |
628 | int type, | 628 | int type, |
629 | struct xfs_item_ops *ops) | 629 | const struct xfs_item_ops *ops) |
630 | { | 630 | { |
631 | item->li_mountp = mp; | 631 | item->li_mountp = mp; |
632 | item->li_ailp = mp->m_ail; | 632 | item->li_ailp = mp->m_ail; |
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 78c9039994af..3f7bf451c034 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h | |||
@@ -137,7 +137,7 @@ struct xfs_trans; | |||
137 | void xfs_log_item_init(struct xfs_mount *mp, | 137 | void xfs_log_item_init(struct xfs_mount *mp, |
138 | struct xfs_log_item *item, | 138 | struct xfs_log_item *item, |
139 | int type, | 139 | int type, |
140 | struct xfs_item_ops *ops); | 140 | const struct xfs_item_ops *ops); |
141 | 141 | ||
142 | xfs_lsn_t xfs_log_done(struct xfs_mount *mp, | 142 | xfs_lsn_t xfs_log_done(struct xfs_mount *mp, |
143 | struct xlog_ticket *ticket, | 143 | struct xlog_ticket *ticket, |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 603f3eb52041..3ae713c0abd9 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -326,7 +326,7 @@ typedef struct xfs_log_item { | |||
326 | struct xfs_log_item *); | 326 | struct xfs_log_item *); |
327 | /* buffer item iodone */ | 327 | /* buffer item iodone */ |
328 | /* callback func */ | 328 | /* callback func */ |
329 | struct xfs_item_ops *li_ops; /* function list */ | 329 | const struct xfs_item_ops *li_ops; /* function list */ |
330 | 330 | ||
331 | /* delayed logging */ | 331 | /* delayed logging */ |
332 | struct list_head li_cil; /* CIL pointers */ | 332 | struct list_head li_cil; /* CIL pointers */ |
@@ -341,7 +341,7 @@ typedef struct xfs_log_item { | |||
341 | { XFS_LI_IN_AIL, "IN_AIL" }, \ | 341 | { XFS_LI_IN_AIL, "IN_AIL" }, \ |
342 | { XFS_LI_ABORTED, "ABORTED" } | 342 | { XFS_LI_ABORTED, "ABORTED" } |
343 | 343 | ||
344 | typedef struct xfs_item_ops { | 344 | struct xfs_item_ops { |
345 | uint (*iop_size)(xfs_log_item_t *); | 345 | uint (*iop_size)(xfs_log_item_t *); |
346 | void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *); | 346 | void (*iop_format)(xfs_log_item_t *, struct xfs_log_iovec *); |
347 | void (*iop_pin)(xfs_log_item_t *); | 347 | void (*iop_pin)(xfs_log_item_t *); |
@@ -352,7 +352,7 @@ typedef struct xfs_item_ops { | |||
352 | void (*iop_push)(xfs_log_item_t *); | 352 | void (*iop_push)(xfs_log_item_t *); |
353 | bool (*iop_pushbuf)(xfs_log_item_t *); | 353 | bool (*iop_pushbuf)(xfs_log_item_t *); |
354 | void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t); | 354 | void (*iop_committing)(xfs_log_item_t *, xfs_lsn_t); |
355 | } xfs_item_ops_t; | 355 | }; |
356 | 356 | ||
357 | #define IOP_SIZE(ip) (*(ip)->li_ops->iop_size)(ip) | 357 | #define IOP_SIZE(ip) (*(ip)->li_ops->iop_size)(ip) |
358 | #define IOP_FORMAT(ip,vp) (*(ip)->li_ops->iop_format)(ip, vp) | 358 | #define IOP_FORMAT(ip,vp) (*(ip)->li_ops->iop_format)(ip, vp) |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 4ecf2a549060..ce9268a2f56b 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -112,7 +112,7 @@ xfs_readlink( | |||
112 | char *link) | 112 | char *link) |
113 | { | 113 | { |
114 | xfs_mount_t *mp = ip->i_mount; | 114 | xfs_mount_t *mp = ip->i_mount; |
115 | int pathlen; | 115 | xfs_fsize_t pathlen; |
116 | int error = 0; | 116 | int error = 0; |
117 | 117 | ||
118 | trace_xfs_readlink(ip); | 118 | trace_xfs_readlink(ip); |
@@ -122,13 +122,19 @@ xfs_readlink( | |||
122 | 122 | ||
123 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 123 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
124 | 124 | ||
125 | ASSERT(S_ISLNK(ip->i_d.di_mode)); | ||
126 | ASSERT(ip->i_d.di_size <= MAXPATHLEN); | ||
127 | |||
128 | pathlen = ip->i_d.di_size; | 125 | pathlen = ip->i_d.di_size; |
129 | if (!pathlen) | 126 | if (!pathlen) |
130 | goto out; | 127 | goto out; |
131 | 128 | ||
129 | if (pathlen < 0 || pathlen > MAXPATHLEN) { | ||
130 | xfs_alert(mp, "%s: inode (%llu) bad symlink length (%lld)", | ||
131 | __func__, (unsigned long long) ip->i_ino, | ||
132 | (long long) pathlen); | ||
133 | ASSERT(0); | ||
134 | return XFS_ERROR(EFSCORRUPTED); | ||
135 | } | ||
136 | |||
137 | |||
132 | if (ip->i_df.if_flags & XFS_IFINLINE) { | 138 | if (ip->i_df.if_flags & XFS_IFINLINE) { |
133 | memcpy(link, ip->i_df.if_u1.if_data, pathlen); | 139 | memcpy(link, ip->i_df.if_u1.if_data, pathlen); |
134 | link[pathlen] = '\0'; | 140 | link[pathlen] = '\0'; |