diff options
Diffstat (limited to 'fs')
49 files changed, 535 insertions, 274 deletions
| @@ -75,6 +75,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) | |||
| 75 | unsigned int sz = sizeof(struct bio) + extra_size; | 75 | unsigned int sz = sizeof(struct bio) + extra_size; |
| 76 | struct kmem_cache *slab = NULL; | 76 | struct kmem_cache *slab = NULL; |
| 77 | struct bio_slab *bslab, *new_bio_slabs; | 77 | struct bio_slab *bslab, *new_bio_slabs; |
| 78 | unsigned int new_bio_slab_max; | ||
| 78 | unsigned int i, entry = -1; | 79 | unsigned int i, entry = -1; |
| 79 | 80 | ||
| 80 | mutex_lock(&bio_slab_lock); | 81 | mutex_lock(&bio_slab_lock); |
| @@ -97,12 +98,13 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) | |||
| 97 | goto out_unlock; | 98 | goto out_unlock; |
| 98 | 99 | ||
| 99 | if (bio_slab_nr == bio_slab_max && entry == -1) { | 100 | if (bio_slab_nr == bio_slab_max && entry == -1) { |
| 100 | bio_slab_max <<= 1; | 101 | new_bio_slab_max = bio_slab_max << 1; |
| 101 | new_bio_slabs = krealloc(bio_slabs, | 102 | new_bio_slabs = krealloc(bio_slabs, |
| 102 | bio_slab_max * sizeof(struct bio_slab), | 103 | new_bio_slab_max * sizeof(struct bio_slab), |
| 103 | GFP_KERNEL); | 104 | GFP_KERNEL); |
| 104 | if (!new_bio_slabs) | 105 | if (!new_bio_slabs) |
| 105 | goto out_unlock; | 106 | goto out_unlock; |
| 107 | bio_slab_max = new_bio_slab_max; | ||
| 106 | bio_slabs = new_bio_slabs; | 108 | bio_slabs = new_bio_slabs; |
| 107 | } | 109 | } |
| 108 | if (entry == -1) | 110 | if (entry == -1) |
diff --git a/fs/block_dev.c b/fs/block_dev.c index b3c1d3dae77d..1a1e5e3b1eaf 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -1661,6 +1661,39 @@ static int blkdev_mmap(struct file *file, struct vm_area_struct *vma) | |||
| 1661 | return ret; | 1661 | return ret; |
| 1662 | } | 1662 | } |
| 1663 | 1663 | ||
| 1664 | static ssize_t blkdev_splice_read(struct file *file, loff_t *ppos, | ||
| 1665 | struct pipe_inode_info *pipe, size_t len, | ||
| 1666 | unsigned int flags) | ||
| 1667 | { | ||
| 1668 | ssize_t ret; | ||
| 1669 | struct block_device *bdev = I_BDEV(file->f_mapping->host); | ||
| 1670 | |||
| 1671 | percpu_down_read(&bdev->bd_block_size_semaphore); | ||
| 1672 | |||
| 1673 | ret = generic_file_splice_read(file, ppos, pipe, len, flags); | ||
| 1674 | |||
| 1675 | percpu_up_read(&bdev->bd_block_size_semaphore); | ||
| 1676 | |||
| 1677 | return ret; | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | static ssize_t blkdev_splice_write(struct pipe_inode_info *pipe, | ||
| 1681 | struct file *file, loff_t *ppos, size_t len, | ||
| 1682 | unsigned int flags) | ||
| 1683 | { | ||
| 1684 | ssize_t ret; | ||
| 1685 | struct block_device *bdev = I_BDEV(file->f_mapping->host); | ||
| 1686 | |||
| 1687 | percpu_down_read(&bdev->bd_block_size_semaphore); | ||
| 1688 | |||
| 1689 | ret = generic_file_splice_write(pipe, file, ppos, len, flags); | ||
| 1690 | |||
| 1691 | percpu_up_read(&bdev->bd_block_size_semaphore); | ||
| 1692 | |||
| 1693 | return ret; | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | |||
| 1664 | /* | 1697 | /* |
| 1665 | * Try to release a page associated with block device when the system | 1698 | * Try to release a page associated with block device when the system |
| 1666 | * is under memory pressure. | 1699 | * is under memory pressure. |
| @@ -1699,8 +1732,8 @@ const struct file_operations def_blk_fops = { | |||
| 1699 | #ifdef CONFIG_COMPAT | 1732 | #ifdef CONFIG_COMPAT |
| 1700 | .compat_ioctl = compat_blkdev_ioctl, | 1733 | .compat_ioctl = compat_blkdev_ioctl, |
| 1701 | #endif | 1734 | #endif |
| 1702 | .splice_read = generic_file_splice_read, | 1735 | .splice_read = blkdev_splice_read, |
| 1703 | .splice_write = generic_file_splice_write, | 1736 | .splice_write = blkdev_splice_write, |
| 1704 | }; | 1737 | }; |
| 1705 | 1738 | ||
| 1706 | int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) | 1739 | int ioctl_by_bdev(struct block_device *bdev, unsigned cmd, unsigned long arg) |
diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index f3187938e081..208d8aa5b07e 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c | |||
| @@ -283,9 +283,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info, | |||
| 283 | goto out; | 283 | goto out; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | rcu_read_lock(); | 286 | root_level = btrfs_old_root_level(root, time_seq); |
| 287 | root_level = btrfs_header_level(root->node); | ||
| 288 | rcu_read_unlock(); | ||
| 289 | 287 | ||
| 290 | if (root_level + 1 == level) | 288 | if (root_level + 1 == level) |
| 291 | goto out; | 289 | goto out; |
| @@ -1177,16 +1175,15 @@ int btrfs_find_one_extref(struct btrfs_root *root, u64 inode_objectid, | |||
| 1177 | return ret; | 1175 | return ret; |
| 1178 | } | 1176 | } |
| 1179 | 1177 | ||
| 1180 | static char *ref_to_path(struct btrfs_root *fs_root, | 1178 | char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, |
| 1181 | struct btrfs_path *path, | 1179 | u32 name_len, unsigned long name_off, |
| 1182 | u32 name_len, unsigned long name_off, | 1180 | struct extent_buffer *eb_in, u64 parent, |
| 1183 | struct extent_buffer *eb_in, u64 parent, | 1181 | char *dest, u32 size) |
| 1184 | char *dest, u32 size) | ||
| 1185 | { | 1182 | { |
| 1186 | int slot; | 1183 | int slot; |
| 1187 | u64 next_inum; | 1184 | u64 next_inum; |
| 1188 | int ret; | 1185 | int ret; |
| 1189 | s64 bytes_left = size - 1; | 1186 | s64 bytes_left = ((s64)size) - 1; |
| 1190 | struct extent_buffer *eb = eb_in; | 1187 | struct extent_buffer *eb = eb_in; |
| 1191 | struct btrfs_key found_key; | 1188 | struct btrfs_key found_key; |
| 1192 | int leave_spinning = path->leave_spinning; | 1189 | int leave_spinning = path->leave_spinning; |
| @@ -1266,10 +1263,10 @@ char *btrfs_iref_to_path(struct btrfs_root *fs_root, | |||
| 1266 | struct extent_buffer *eb_in, u64 parent, | 1263 | struct extent_buffer *eb_in, u64 parent, |
| 1267 | char *dest, u32 size) | 1264 | char *dest, u32 size) |
| 1268 | { | 1265 | { |
| 1269 | return ref_to_path(fs_root, path, | 1266 | return btrfs_ref_to_path(fs_root, path, |
| 1270 | btrfs_inode_ref_name_len(eb_in, iref), | 1267 | btrfs_inode_ref_name_len(eb_in, iref), |
| 1271 | (unsigned long)(iref + 1), | 1268 | (unsigned long)(iref + 1), |
| 1272 | eb_in, parent, dest, size); | 1269 | eb_in, parent, dest, size); |
| 1273 | } | 1270 | } |
| 1274 | 1271 | ||
| 1275 | /* | 1272 | /* |
| @@ -1715,9 +1712,8 @@ static int inode_to_path(u64 inum, u32 name_len, unsigned long name_off, | |||
| 1715 | ipath->fspath->bytes_left - s_ptr : 0; | 1712 | ipath->fspath->bytes_left - s_ptr : 0; |
| 1716 | 1713 | ||
| 1717 | fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; | 1714 | fspath_min = (char *)ipath->fspath->val + (i + 1) * s_ptr; |
| 1718 | fspath = ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, | 1715 | fspath = btrfs_ref_to_path(ipath->fs_root, ipath->btrfs_path, name_len, |
| 1719 | name_off, eb, inum, fspath_min, | 1716 | name_off, eb, inum, fspath_min, bytes_left); |
| 1720 | bytes_left); | ||
| 1721 | if (IS_ERR(fspath)) | 1717 | if (IS_ERR(fspath)) |
| 1722 | return PTR_ERR(fspath); | 1718 | return PTR_ERR(fspath); |
| 1723 | 1719 | ||
diff --git a/fs/btrfs/backref.h b/fs/btrfs/backref.h index e75533043a5f..d61feca79455 100644 --- a/fs/btrfs/backref.h +++ b/fs/btrfs/backref.h | |||
| @@ -62,6 +62,10 @@ int btrfs_find_all_roots(struct btrfs_trans_handle *trans, | |||
| 62 | char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | 62 | char *btrfs_iref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, |
| 63 | struct btrfs_inode_ref *iref, struct extent_buffer *eb, | 63 | struct btrfs_inode_ref *iref, struct extent_buffer *eb, |
| 64 | u64 parent, char *dest, u32 size); | 64 | u64 parent, char *dest, u32 size); |
| 65 | char *btrfs_ref_to_path(struct btrfs_root *fs_root, struct btrfs_path *path, | ||
| 66 | u32 name_len, unsigned long name_off, | ||
| 67 | struct extent_buffer *eb_in, u64 parent, | ||
| 68 | char *dest, u32 size); | ||
| 65 | 69 | ||
| 66 | struct btrfs_data_container *init_data_container(u32 total_bytes); | 70 | struct btrfs_data_container *init_data_container(u32 total_bytes); |
| 67 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, | 71 | struct inode_fs_paths *init_ipath(s32 total_bytes, struct btrfs_root *fs_root, |
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index b33436211000..cdfb4c49a806 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
| @@ -596,6 +596,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info, | |||
| 596 | if (tree_mod_dont_log(fs_info, eb)) | 596 | if (tree_mod_dont_log(fs_info, eb)) |
| 597 | return 0; | 597 | return 0; |
| 598 | 598 | ||
| 599 | /* | ||
| 600 | * When we override something during the move, we log these removals. | ||
| 601 | * This can only happen when we move towards the beginning of the | ||
| 602 | * buffer, i.e. dst_slot < src_slot. | ||
| 603 | */ | ||
| 599 | for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { | 604 | for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) { |
| 600 | ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot, | 605 | ret = tree_mod_log_insert_key_locked(fs_info, eb, i + dst_slot, |
| 601 | MOD_LOG_KEY_REMOVE_WHILE_MOVING); | 606 | MOD_LOG_KEY_REMOVE_WHILE_MOVING); |
| @@ -647,8 +652,6 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info, | |||
| 647 | if (tree_mod_dont_log(fs_info, NULL)) | 652 | if (tree_mod_dont_log(fs_info, NULL)) |
| 648 | return 0; | 653 | return 0; |
| 649 | 654 | ||
| 650 | __tree_mod_log_free_eb(fs_info, old_root); | ||
| 651 | |||
| 652 | ret = tree_mod_alloc(fs_info, flags, &tm); | 655 | ret = tree_mod_alloc(fs_info, flags, &tm); |
| 653 | if (ret < 0) | 656 | if (ret < 0) |
| 654 | goto out; | 657 | goto out; |
| @@ -926,12 +929,7 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans, | |||
| 926 | ret = btrfs_dec_ref(trans, root, buf, 1, 1); | 929 | ret = btrfs_dec_ref(trans, root, buf, 1, 1); |
| 927 | BUG_ON(ret); /* -ENOMEM */ | 930 | BUG_ON(ret); /* -ENOMEM */ |
| 928 | } | 931 | } |
| 929 | /* | 932 | tree_mod_log_free_eb(root->fs_info, buf); |
| 930 | * don't log freeing in case we're freeing the root node, this | ||
| 931 | * is done by tree_mod_log_set_root_pointer later | ||
| 932 | */ | ||
| 933 | if (buf != root->node && btrfs_header_level(buf) != 0) | ||
| 934 | tree_mod_log_free_eb(root->fs_info, buf); | ||
| 935 | clean_tree_block(trans, root, buf); | 933 | clean_tree_block(trans, root, buf); |
| 936 | *last_ref = 1; | 934 | *last_ref = 1; |
| 937 | } | 935 | } |
| @@ -1225,6 +1223,8 @@ tree_mod_log_rewind(struct btrfs_fs_info *fs_info, struct extent_buffer *eb, | |||
| 1225 | free_extent_buffer(eb); | 1223 | free_extent_buffer(eb); |
| 1226 | 1224 | ||
| 1227 | __tree_mod_log_rewind(eb_rewin, time_seq, tm); | 1225 | __tree_mod_log_rewind(eb_rewin, time_seq, tm); |
| 1226 | WARN_ON(btrfs_header_nritems(eb_rewin) > | ||
| 1227 | BTRFS_NODEPTRS_PER_BLOCK(fs_info->fs_root)); | ||
| 1228 | 1228 | ||
| 1229 | return eb_rewin; | 1229 | return eb_rewin; |
| 1230 | } | 1230 | } |
| @@ -1241,9 +1241,11 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
| 1241 | { | 1241 | { |
| 1242 | struct tree_mod_elem *tm; | 1242 | struct tree_mod_elem *tm; |
| 1243 | struct extent_buffer *eb; | 1243 | struct extent_buffer *eb; |
| 1244 | struct extent_buffer *old; | ||
| 1244 | struct tree_mod_root *old_root = NULL; | 1245 | struct tree_mod_root *old_root = NULL; |
| 1245 | u64 old_generation = 0; | 1246 | u64 old_generation = 0; |
| 1246 | u64 logical; | 1247 | u64 logical; |
| 1248 | u32 blocksize; | ||
| 1247 | 1249 | ||
| 1248 | eb = btrfs_read_lock_root_node(root); | 1250 | eb = btrfs_read_lock_root_node(root); |
| 1249 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); | 1251 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); |
| @@ -1259,14 +1261,32 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
| 1259 | } | 1261 | } |
| 1260 | 1262 | ||
| 1261 | tm = tree_mod_log_search(root->fs_info, logical, time_seq); | 1263 | tm = tree_mod_log_search(root->fs_info, logical, time_seq); |
| 1262 | if (old_root) | 1264 | if (old_root && tm && tm->op != MOD_LOG_KEY_REMOVE_WHILE_FREEING) { |
| 1265 | btrfs_tree_read_unlock(root->node); | ||
| 1266 | free_extent_buffer(root->node); | ||
| 1267 | blocksize = btrfs_level_size(root, old_root->level); | ||
| 1268 | old = read_tree_block(root, logical, blocksize, 0); | ||
| 1269 | if (!old) { | ||
| 1270 | pr_warn("btrfs: failed to read tree block %llu from get_old_root\n", | ||
| 1271 | logical); | ||
| 1272 | WARN_ON(1); | ||
| 1273 | } else { | ||
| 1274 | eb = btrfs_clone_extent_buffer(old); | ||
| 1275 | free_extent_buffer(old); | ||
| 1276 | } | ||
| 1277 | } else if (old_root) { | ||
| 1278 | btrfs_tree_read_unlock(root->node); | ||
| 1279 | free_extent_buffer(root->node); | ||
| 1263 | eb = alloc_dummy_extent_buffer(logical, root->nodesize); | 1280 | eb = alloc_dummy_extent_buffer(logical, root->nodesize); |
| 1264 | else | 1281 | } else { |
| 1265 | eb = btrfs_clone_extent_buffer(root->node); | 1282 | eb = btrfs_clone_extent_buffer(root->node); |
| 1266 | btrfs_tree_read_unlock(root->node); | 1283 | btrfs_tree_read_unlock(root->node); |
| 1267 | free_extent_buffer(root->node); | 1284 | free_extent_buffer(root->node); |
| 1285 | } | ||
| 1286 | |||
| 1268 | if (!eb) | 1287 | if (!eb) |
| 1269 | return NULL; | 1288 | return NULL; |
| 1289 | extent_buffer_get(eb); | ||
| 1270 | btrfs_tree_read_lock(eb); | 1290 | btrfs_tree_read_lock(eb); |
| 1271 | if (old_root) { | 1291 | if (old_root) { |
| 1272 | btrfs_set_header_bytenr(eb, eb->start); | 1292 | btrfs_set_header_bytenr(eb, eb->start); |
| @@ -1279,11 +1299,28 @@ get_old_root(struct btrfs_root *root, u64 time_seq) | |||
| 1279 | __tree_mod_log_rewind(eb, time_seq, tm); | 1299 | __tree_mod_log_rewind(eb, time_seq, tm); |
| 1280 | else | 1300 | else |
| 1281 | WARN_ON(btrfs_header_level(eb) != 0); | 1301 | WARN_ON(btrfs_header_level(eb) != 0); |
| 1282 | extent_buffer_get(eb); | 1302 | WARN_ON(btrfs_header_nritems(eb) > BTRFS_NODEPTRS_PER_BLOCK(root)); |
| 1283 | 1303 | ||
| 1284 | return eb; | 1304 | return eb; |
| 1285 | } | 1305 | } |
| 1286 | 1306 | ||
| 1307 | int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq) | ||
| 1308 | { | ||
| 1309 | struct tree_mod_elem *tm; | ||
| 1310 | int level; | ||
| 1311 | |||
| 1312 | tm = __tree_mod_log_oldest_root(root->fs_info, root, time_seq); | ||
| 1313 | if (tm && tm->op == MOD_LOG_ROOT_REPLACE) { | ||
| 1314 | level = tm->old_root.level; | ||
| 1315 | } else { | ||
| 1316 | rcu_read_lock(); | ||
| 1317 | level = btrfs_header_level(root->node); | ||
| 1318 | rcu_read_unlock(); | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | return level; | ||
| 1322 | } | ||
| 1323 | |||
| 1287 | static inline int should_cow_block(struct btrfs_trans_handle *trans, | 1324 | static inline int should_cow_block(struct btrfs_trans_handle *trans, |
| 1288 | struct btrfs_root *root, | 1325 | struct btrfs_root *root, |
| 1289 | struct extent_buffer *buf) | 1326 | struct extent_buffer *buf) |
| @@ -1725,6 +1762,7 @@ static noinline int balance_level(struct btrfs_trans_handle *trans, | |||
| 1725 | goto enospc; | 1762 | goto enospc; |
| 1726 | } | 1763 | } |
| 1727 | 1764 | ||
| 1765 | tree_mod_log_free_eb(root->fs_info, root->node); | ||
| 1728 | tree_mod_log_set_root_pointer(root, child); | 1766 | tree_mod_log_set_root_pointer(root, child); |
| 1729 | rcu_assign_pointer(root->node, child); | 1767 | rcu_assign_pointer(root->node, child); |
| 1730 | 1768 | ||
| @@ -2970,8 +3008,10 @@ static int push_node_left(struct btrfs_trans_handle *trans, | |||
| 2970 | push_items * sizeof(struct btrfs_key_ptr)); | 3008 | push_items * sizeof(struct btrfs_key_ptr)); |
| 2971 | 3009 | ||
| 2972 | if (push_items < src_nritems) { | 3010 | if (push_items < src_nritems) { |
| 2973 | tree_mod_log_eb_move(root->fs_info, src, 0, push_items, | 3011 | /* |
| 2974 | src_nritems - push_items); | 3012 | * don't call tree_mod_log_eb_move here, key removal was already |
| 3013 | * fully logged by tree_mod_log_eb_copy above. | ||
| 3014 | */ | ||
| 2975 | memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), | 3015 | memmove_extent_buffer(src, btrfs_node_key_ptr_offset(0), |
| 2976 | btrfs_node_key_ptr_offset(push_items), | 3016 | btrfs_node_key_ptr_offset(push_items), |
| 2977 | (src_nritems - push_items) * | 3017 | (src_nritems - push_items) * |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 926c9ffc66d9..c72ead869507 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -3120,6 +3120,7 @@ static inline u64 btrfs_inc_tree_mod_seq(struct btrfs_fs_info *fs_info) | |||
| 3120 | { | 3120 | { |
| 3121 | return atomic_inc_return(&fs_info->tree_mod_seq); | 3121 | return atomic_inc_return(&fs_info->tree_mod_seq); |
| 3122 | } | 3122 | } |
| 3123 | int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq); | ||
| 3123 | 3124 | ||
| 3124 | /* root-item.c */ | 3125 | /* root-item.c */ |
| 3125 | int btrfs_find_root_ref(struct btrfs_root *tree_root, | 3126 | int btrfs_find_root_ref(struct btrfs_root *tree_root, |
| @@ -3338,6 +3339,8 @@ struct extent_map *btrfs_get_extent(struct inode *inode, struct page *page, | |||
| 3338 | int btrfs_update_inode(struct btrfs_trans_handle *trans, | 3339 | int btrfs_update_inode(struct btrfs_trans_handle *trans, |
| 3339 | struct btrfs_root *root, | 3340 | struct btrfs_root *root, |
| 3340 | struct inode *inode); | 3341 | struct inode *inode); |
| 3342 | int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | ||
| 3343 | struct btrfs_root *root, struct inode *inode); | ||
| 3341 | int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); | 3344 | int btrfs_orphan_add(struct btrfs_trans_handle *trans, struct inode *inode); |
| 3342 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); | 3345 | int btrfs_orphan_del(struct btrfs_trans_handle *trans, struct inode *inode); |
| 3343 | int btrfs_orphan_cleanup(struct btrfs_root *root); | 3346 | int btrfs_orphan_cleanup(struct btrfs_root *root); |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 8036d3a84853..472873a94d96 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -4110,8 +4110,8 @@ struct extent_buffer *alloc_dummy_extent_buffer(u64 start, unsigned long len) | |||
| 4110 | 4110 | ||
| 4111 | return eb; | 4111 | return eb; |
| 4112 | err: | 4112 | err: |
| 4113 | for (i--; i >= 0; i--) | 4113 | for (; i > 0; i--) |
| 4114 | __free_page(eb->pages[i]); | 4114 | __free_page(eb->pages[i - 1]); |
| 4115 | __free_extent_buffer(eb); | 4115 | __free_extent_buffer(eb); |
| 4116 | return NULL; | 4116 | return NULL; |
| 4117 | } | 4117 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 85a1e5053fe6..95542a1b3dfc 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -94,8 +94,6 @@ static noinline int cow_file_range(struct inode *inode, | |||
| 94 | struct page *locked_page, | 94 | struct page *locked_page, |
| 95 | u64 start, u64 end, int *page_started, | 95 | u64 start, u64 end, int *page_started, |
| 96 | unsigned long *nr_written, int unlock); | 96 | unsigned long *nr_written, int unlock); |
| 97 | static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | ||
| 98 | struct btrfs_root *root, struct inode *inode); | ||
| 99 | 97 | ||
| 100 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, | 98 | static int btrfs_init_inode_security(struct btrfs_trans_handle *trans, |
| 101 | struct inode *inode, struct inode *dir, | 99 | struct inode *inode, struct inode *dir, |
| @@ -2746,8 +2744,9 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans, | |||
| 2746 | return btrfs_update_inode_item(trans, root, inode); | 2744 | return btrfs_update_inode_item(trans, root, inode); |
| 2747 | } | 2745 | } |
| 2748 | 2746 | ||
| 2749 | static noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, | 2747 | noinline int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans, |
| 2750 | struct btrfs_root *root, struct inode *inode) | 2748 | struct btrfs_root *root, |
| 2749 | struct inode *inode) | ||
| 2751 | { | 2750 | { |
| 2752 | int ret; | 2751 | int ret; |
| 2753 | 2752 | ||
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 61168805f175..8fcf9a59c28d 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -343,7 +343,8 @@ static noinline int btrfs_ioctl_fitrim(struct file *file, void __user *arg) | |||
| 343 | return -EOPNOTSUPP; | 343 | return -EOPNOTSUPP; |
| 344 | if (copy_from_user(&range, arg, sizeof(range))) | 344 | if (copy_from_user(&range, arg, sizeof(range))) |
| 345 | return -EFAULT; | 345 | return -EFAULT; |
| 346 | if (range.start > total_bytes) | 346 | if (range.start > total_bytes || |
| 347 | range.len < fs_info->sb->s_blocksize) | ||
| 347 | return -EINVAL; | 348 | return -EINVAL; |
| 348 | 349 | ||
| 349 | range.len = min(range.len, total_bytes - range.start); | 350 | range.len = min(range.len, total_bytes - range.start); |
| @@ -570,7 +571,8 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 570 | ret = btrfs_commit_transaction(trans, | 571 | ret = btrfs_commit_transaction(trans, |
| 571 | root->fs_info->extent_root); | 572 | root->fs_info->extent_root); |
| 572 | } | 573 | } |
| 573 | BUG_ON(ret); | 574 | if (ret) |
| 575 | goto fail; | ||
| 574 | 576 | ||
| 575 | ret = pending_snapshot->error; | 577 | ret = pending_snapshot->error; |
| 576 | if (ret) | 578 | if (ret) |
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c index 5039686df6ae..fe9d02c45f8e 100644 --- a/fs/btrfs/qgroup.c +++ b/fs/btrfs/qgroup.c | |||
| @@ -790,8 +790,10 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, | |||
| 790 | } | 790 | } |
| 791 | 791 | ||
| 792 | path = btrfs_alloc_path(); | 792 | path = btrfs_alloc_path(); |
| 793 | if (!path) | 793 | if (!path) { |
| 794 | return -ENOMEM; | 794 | ret = -ENOMEM; |
| 795 | goto out_free_root; | ||
| 796 | } | ||
| 795 | 797 | ||
| 796 | key.objectid = 0; | 798 | key.objectid = 0; |
| 797 | key.type = BTRFS_QGROUP_STATUS_KEY; | 799 | key.type = BTRFS_QGROUP_STATUS_KEY; |
| @@ -800,7 +802,7 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, | |||
| 800 | ret = btrfs_insert_empty_item(trans, quota_root, path, &key, | 802 | ret = btrfs_insert_empty_item(trans, quota_root, path, &key, |
| 801 | sizeof(*ptr)); | 803 | sizeof(*ptr)); |
| 802 | if (ret) | 804 | if (ret) |
| 803 | goto out; | 805 | goto out_free_path; |
| 804 | 806 | ||
| 805 | leaf = path->nodes[0]; | 807 | leaf = path->nodes[0]; |
| 806 | ptr = btrfs_item_ptr(leaf, path->slots[0], | 808 | ptr = btrfs_item_ptr(leaf, path->slots[0], |
| @@ -818,8 +820,15 @@ int btrfs_quota_enable(struct btrfs_trans_handle *trans, | |||
| 818 | fs_info->quota_root = quota_root; | 820 | fs_info->quota_root = quota_root; |
| 819 | fs_info->pending_quota_state = 1; | 821 | fs_info->pending_quota_state = 1; |
| 820 | spin_unlock(&fs_info->qgroup_lock); | 822 | spin_unlock(&fs_info->qgroup_lock); |
| 821 | out: | 823 | out_free_path: |
| 822 | btrfs_free_path(path); | 824 | btrfs_free_path(path); |
| 825 | out_free_root: | ||
| 826 | if (ret) { | ||
| 827 | free_extent_buffer(quota_root->node); | ||
| 828 | free_extent_buffer(quota_root->commit_root); | ||
| 829 | kfree(quota_root); | ||
| 830 | } | ||
| 831 | out: | ||
| 823 | return ret; | 832 | return ret; |
| 824 | } | 833 | } |
| 825 | 834 | ||
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index c7beb543a4a8..e78b297b0b00 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c | |||
| @@ -745,31 +745,36 @@ typedef int (*iterate_inode_ref_t)(int num, u64 dir, int index, | |||
| 745 | void *ctx); | 745 | void *ctx); |
| 746 | 746 | ||
| 747 | /* | 747 | /* |
| 748 | * Helper function to iterate the entries in ONE btrfs_inode_ref. | 748 | * Helper function to iterate the entries in ONE btrfs_inode_ref or |
| 749 | * btrfs_inode_extref. | ||
| 749 | * The iterate callback may return a non zero value to stop iteration. This can | 750 | * The iterate callback may return a non zero value to stop iteration. This can |
| 750 | * be a negative value for error codes or 1 to simply stop it. | 751 | * be a negative value for error codes or 1 to simply stop it. |
| 751 | * | 752 | * |
| 752 | * path must point to the INODE_REF when called. | 753 | * path must point to the INODE_REF or INODE_EXTREF when called. |
| 753 | */ | 754 | */ |
| 754 | static int iterate_inode_ref(struct send_ctx *sctx, | 755 | static int iterate_inode_ref(struct send_ctx *sctx, |
| 755 | struct btrfs_root *root, struct btrfs_path *path, | 756 | struct btrfs_root *root, struct btrfs_path *path, |
| 756 | struct btrfs_key *found_key, int resolve, | 757 | struct btrfs_key *found_key, int resolve, |
| 757 | iterate_inode_ref_t iterate, void *ctx) | 758 | iterate_inode_ref_t iterate, void *ctx) |
| 758 | { | 759 | { |
| 759 | struct extent_buffer *eb; | 760 | struct extent_buffer *eb = path->nodes[0]; |
| 760 | struct btrfs_item *item; | 761 | struct btrfs_item *item; |
| 761 | struct btrfs_inode_ref *iref; | 762 | struct btrfs_inode_ref *iref; |
| 763 | struct btrfs_inode_extref *extref; | ||
| 762 | struct btrfs_path *tmp_path; | 764 | struct btrfs_path *tmp_path; |
| 763 | struct fs_path *p; | 765 | struct fs_path *p; |
| 764 | u32 cur; | 766 | u32 cur = 0; |
| 765 | u32 len; | ||
| 766 | u32 total; | 767 | u32 total; |
| 767 | int slot; | 768 | int slot = path->slots[0]; |
| 768 | u32 name_len; | 769 | u32 name_len; |
| 769 | char *start; | 770 | char *start; |
| 770 | int ret = 0; | 771 | int ret = 0; |
| 771 | int num; | 772 | int num = 0; |
| 772 | int index; | 773 | int index; |
| 774 | u64 dir; | ||
| 775 | unsigned long name_off; | ||
| 776 | unsigned long elem_size; | ||
| 777 | unsigned long ptr; | ||
| 773 | 778 | ||
| 774 | p = fs_path_alloc_reversed(sctx); | 779 | p = fs_path_alloc_reversed(sctx); |
| 775 | if (!p) | 780 | if (!p) |
| @@ -781,24 +786,40 @@ static int iterate_inode_ref(struct send_ctx *sctx, | |||
| 781 | return -ENOMEM; | 786 | return -ENOMEM; |
| 782 | } | 787 | } |
| 783 | 788 | ||
| 784 | eb = path->nodes[0]; | ||
| 785 | slot = path->slots[0]; | ||
| 786 | item = btrfs_item_nr(eb, slot); | ||
| 787 | iref = btrfs_item_ptr(eb, slot, struct btrfs_inode_ref); | ||
| 788 | cur = 0; | ||
| 789 | len = 0; | ||
| 790 | total = btrfs_item_size(eb, item); | ||
| 791 | 789 | ||
| 792 | num = 0; | 790 | if (found_key->type == BTRFS_INODE_REF_KEY) { |
| 791 | ptr = (unsigned long)btrfs_item_ptr(eb, slot, | ||
| 792 | struct btrfs_inode_ref); | ||
| 793 | item = btrfs_item_nr(eb, slot); | ||
| 794 | total = btrfs_item_size(eb, item); | ||
| 795 | elem_size = sizeof(*iref); | ||
| 796 | } else { | ||
| 797 | ptr = btrfs_item_ptr_offset(eb, slot); | ||
| 798 | total = btrfs_item_size_nr(eb, slot); | ||
| 799 | elem_size = sizeof(*extref); | ||
| 800 | } | ||
| 801 | |||
| 793 | while (cur < total) { | 802 | while (cur < total) { |
| 794 | fs_path_reset(p); | 803 | fs_path_reset(p); |
| 795 | 804 | ||
| 796 | name_len = btrfs_inode_ref_name_len(eb, iref); | 805 | if (found_key->type == BTRFS_INODE_REF_KEY) { |
| 797 | index = btrfs_inode_ref_index(eb, iref); | 806 | iref = (struct btrfs_inode_ref *)(ptr + cur); |
| 807 | name_len = btrfs_inode_ref_name_len(eb, iref); | ||
| 808 | name_off = (unsigned long)(iref + 1); | ||
| 809 | index = btrfs_inode_ref_index(eb, iref); | ||
| 810 | dir = found_key->offset; | ||
| 811 | } else { | ||
| 812 | extref = (struct btrfs_inode_extref *)(ptr + cur); | ||
| 813 | name_len = btrfs_inode_extref_name_len(eb, extref); | ||
| 814 | name_off = (unsigned long)&extref->name; | ||
| 815 | index = btrfs_inode_extref_index(eb, extref); | ||
| 816 | dir = btrfs_inode_extref_parent(eb, extref); | ||
| 817 | } | ||
| 818 | |||
| 798 | if (resolve) { | 819 | if (resolve) { |
| 799 | start = btrfs_iref_to_path(root, tmp_path, iref, eb, | 820 | start = btrfs_ref_to_path(root, tmp_path, name_len, |
| 800 | found_key->offset, p->buf, | 821 | name_off, eb, dir, |
| 801 | p->buf_len); | 822 | p->buf, p->buf_len); |
| 802 | if (IS_ERR(start)) { | 823 | if (IS_ERR(start)) { |
| 803 | ret = PTR_ERR(start); | 824 | ret = PTR_ERR(start); |
| 804 | goto out; | 825 | goto out; |
| @@ -809,9 +830,10 @@ static int iterate_inode_ref(struct send_ctx *sctx, | |||
| 809 | p->buf_len + p->buf - start); | 830 | p->buf_len + p->buf - start); |
| 810 | if (ret < 0) | 831 | if (ret < 0) |
| 811 | goto out; | 832 | goto out; |
| 812 | start = btrfs_iref_to_path(root, tmp_path, iref, | 833 | start = btrfs_ref_to_path(root, tmp_path, |
| 813 | eb, found_key->offset, p->buf, | 834 | name_len, name_off, |
| 814 | p->buf_len); | 835 | eb, dir, |
| 836 | p->buf, p->buf_len); | ||
| 815 | if (IS_ERR(start)) { | 837 | if (IS_ERR(start)) { |
| 816 | ret = PTR_ERR(start); | 838 | ret = PTR_ERR(start); |
| 817 | goto out; | 839 | goto out; |
| @@ -820,21 +842,16 @@ static int iterate_inode_ref(struct send_ctx *sctx, | |||
| 820 | } | 842 | } |
| 821 | p->start = start; | 843 | p->start = start; |
| 822 | } else { | 844 | } else { |
| 823 | ret = fs_path_add_from_extent_buffer(p, eb, | 845 | ret = fs_path_add_from_extent_buffer(p, eb, name_off, |
| 824 | (unsigned long)(iref + 1), name_len); | 846 | name_len); |
| 825 | if (ret < 0) | 847 | if (ret < 0) |
| 826 | goto out; | 848 | goto out; |
| 827 | } | 849 | } |
| 828 | 850 | ||
| 829 | 851 | cur += elem_size + name_len; | |
| 830 | len = sizeof(*iref) + name_len; | 852 | ret = iterate(num, dir, index, p, ctx); |
| 831 | iref = (struct btrfs_inode_ref *)((char *)iref + len); | ||
| 832 | cur += len; | ||
| 833 | |||
| 834 | ret = iterate(num, found_key->offset, index, p, ctx); | ||
| 835 | if (ret) | 853 | if (ret) |
| 836 | goto out; | 854 | goto out; |
| 837 | |||
| 838 | num++; | 855 | num++; |
| 839 | } | 856 | } |
| 840 | 857 | ||
| @@ -998,7 +1015,8 @@ static int get_inode_path(struct send_ctx *sctx, struct btrfs_root *root, | |||
| 998 | } | 1015 | } |
| 999 | btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); | 1016 | btrfs_item_key_to_cpu(p->nodes[0], &found_key, p->slots[0]); |
| 1000 | if (found_key.objectid != ino || | 1017 | if (found_key.objectid != ino || |
| 1001 | found_key.type != BTRFS_INODE_REF_KEY) { | 1018 | (found_key.type != BTRFS_INODE_REF_KEY && |
| 1019 | found_key.type != BTRFS_INODE_EXTREF_KEY)) { | ||
| 1002 | ret = -ENOENT; | 1020 | ret = -ENOENT; |
| 1003 | goto out; | 1021 | goto out; |
| 1004 | } | 1022 | } |
| @@ -1551,8 +1569,8 @@ static int get_first_ref(struct send_ctx *sctx, | |||
| 1551 | struct btrfs_key key; | 1569 | struct btrfs_key key; |
| 1552 | struct btrfs_key found_key; | 1570 | struct btrfs_key found_key; |
| 1553 | struct btrfs_path *path; | 1571 | struct btrfs_path *path; |
| 1554 | struct btrfs_inode_ref *iref; | ||
| 1555 | int len; | 1572 | int len; |
| 1573 | u64 parent_dir; | ||
| 1556 | 1574 | ||
| 1557 | path = alloc_path_for_send(); | 1575 | path = alloc_path_for_send(); |
| 1558 | if (!path) | 1576 | if (!path) |
| @@ -1568,27 +1586,41 @@ static int get_first_ref(struct send_ctx *sctx, | |||
| 1568 | if (!ret) | 1586 | if (!ret) |
| 1569 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, | 1587 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, |
| 1570 | path->slots[0]); | 1588 | path->slots[0]); |
| 1571 | if (ret || found_key.objectid != key.objectid || | 1589 | if (ret || found_key.objectid != ino || |
| 1572 | found_key.type != key.type) { | 1590 | (found_key.type != BTRFS_INODE_REF_KEY && |
| 1591 | found_key.type != BTRFS_INODE_EXTREF_KEY)) { | ||
| 1573 | ret = -ENOENT; | 1592 | ret = -ENOENT; |
| 1574 | goto out; | 1593 | goto out; |
| 1575 | } | 1594 | } |
| 1576 | 1595 | ||
| 1577 | iref = btrfs_item_ptr(path->nodes[0], path->slots[0], | 1596 | if (key.type == BTRFS_INODE_REF_KEY) { |
| 1578 | struct btrfs_inode_ref); | 1597 | struct btrfs_inode_ref *iref; |
| 1579 | len = btrfs_inode_ref_name_len(path->nodes[0], iref); | 1598 | iref = btrfs_item_ptr(path->nodes[0], path->slots[0], |
| 1580 | ret = fs_path_add_from_extent_buffer(name, path->nodes[0], | 1599 | struct btrfs_inode_ref); |
| 1581 | (unsigned long)(iref + 1), len); | 1600 | len = btrfs_inode_ref_name_len(path->nodes[0], iref); |
| 1601 | ret = fs_path_add_from_extent_buffer(name, path->nodes[0], | ||
| 1602 | (unsigned long)(iref + 1), | ||
| 1603 | len); | ||
| 1604 | parent_dir = found_key.offset; | ||
| 1605 | } else { | ||
| 1606 | struct btrfs_inode_extref *extref; | ||
| 1607 | extref = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
| 1608 | struct btrfs_inode_extref); | ||
| 1609 | len = btrfs_inode_extref_name_len(path->nodes[0], extref); | ||
| 1610 | ret = fs_path_add_from_extent_buffer(name, path->nodes[0], | ||
| 1611 | (unsigned long)&extref->name, len); | ||
| 1612 | parent_dir = btrfs_inode_extref_parent(path->nodes[0], extref); | ||
| 1613 | } | ||
| 1582 | if (ret < 0) | 1614 | if (ret < 0) |
| 1583 | goto out; | 1615 | goto out; |
| 1584 | btrfs_release_path(path); | 1616 | btrfs_release_path(path); |
| 1585 | 1617 | ||
| 1586 | ret = get_inode_info(root, found_key.offset, NULL, dir_gen, NULL, NULL, | 1618 | ret = get_inode_info(root, parent_dir, NULL, dir_gen, NULL, NULL, |
| 1587 | NULL, NULL); | 1619 | NULL, NULL); |
| 1588 | if (ret < 0) | 1620 | if (ret < 0) |
| 1589 | goto out; | 1621 | goto out; |
| 1590 | 1622 | ||
| 1591 | *dir = found_key.offset; | 1623 | *dir = parent_dir; |
| 1592 | 1624 | ||
| 1593 | out: | 1625 | out: |
| 1594 | btrfs_free_path(path); | 1626 | btrfs_free_path(path); |
| @@ -2430,7 +2462,8 @@ verbose_printk("btrfs: send_create_inode %llu\n", ino); | |||
| 2430 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p); | 2462 | TLV_PUT_PATH(sctx, BTRFS_SEND_A_PATH_LINK, p); |
| 2431 | } else if (S_ISCHR(mode) || S_ISBLK(mode) || | 2463 | } else if (S_ISCHR(mode) || S_ISBLK(mode) || |
| 2432 | S_ISFIFO(mode) || S_ISSOCK(mode)) { | 2464 | S_ISFIFO(mode) || S_ISSOCK(mode)) { |
| 2433 | TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, rdev); | 2465 | TLV_PUT_U64(sctx, BTRFS_SEND_A_RDEV, new_encode_dev(rdev)); |
| 2466 | TLV_PUT_U64(sctx, BTRFS_SEND_A_MODE, mode); | ||
| 2434 | } | 2467 | } |
| 2435 | 2468 | ||
| 2436 | ret = send_cmd(sctx); | 2469 | ret = send_cmd(sctx); |
| @@ -3226,7 +3259,8 @@ static int process_all_refs(struct send_ctx *sctx, | |||
| 3226 | btrfs_item_key_to_cpu(eb, &found_key, slot); | 3259 | btrfs_item_key_to_cpu(eb, &found_key, slot); |
| 3227 | 3260 | ||
| 3228 | if (found_key.objectid != key.objectid || | 3261 | if (found_key.objectid != key.objectid || |
| 3229 | found_key.type != key.type) | 3262 | (found_key.type != BTRFS_INODE_REF_KEY && |
| 3263 | found_key.type != BTRFS_INODE_EXTREF_KEY)) | ||
| 3230 | break; | 3264 | break; |
| 3231 | 3265 | ||
| 3232 | ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, | 3266 | ret = iterate_inode_ref(sctx, root, path, &found_key, 0, cb, |
| @@ -3987,7 +4021,7 @@ static int process_recorded_refs_if_needed(struct send_ctx *sctx, int at_end) | |||
| 3987 | if (sctx->cur_ino == 0) | 4021 | if (sctx->cur_ino == 0) |
| 3988 | goto out; | 4022 | goto out; |
| 3989 | if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && | 4023 | if (!at_end && sctx->cur_ino == sctx->cmp_key->objectid && |
| 3990 | sctx->cmp_key->type <= BTRFS_INODE_REF_KEY) | 4024 | sctx->cmp_key->type <= BTRFS_INODE_EXTREF_KEY) |
| 3991 | goto out; | 4025 | goto out; |
| 3992 | if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) | 4026 | if (list_empty(&sctx->new_refs) && list_empty(&sctx->deleted_refs)) |
| 3993 | goto out; | 4027 | goto out; |
| @@ -4033,22 +4067,21 @@ static int finish_inode_if_needed(struct send_ctx *sctx, int at_end) | |||
| 4033 | if (ret < 0) | 4067 | if (ret < 0) |
| 4034 | goto out; | 4068 | goto out; |
| 4035 | 4069 | ||
| 4036 | if (!S_ISLNK(sctx->cur_inode_mode)) { | 4070 | if (!sctx->parent_root || sctx->cur_inode_new) { |
| 4037 | if (!sctx->parent_root || sctx->cur_inode_new) { | 4071 | need_chown = 1; |
| 4072 | if (!S_ISLNK(sctx->cur_inode_mode)) | ||
| 4038 | need_chmod = 1; | 4073 | need_chmod = 1; |
| 4039 | need_chown = 1; | 4074 | } else { |
| 4040 | } else { | 4075 | ret = get_inode_info(sctx->parent_root, sctx->cur_ino, |
| 4041 | ret = get_inode_info(sctx->parent_root, sctx->cur_ino, | 4076 | NULL, NULL, &right_mode, &right_uid, |
| 4042 | NULL, NULL, &right_mode, &right_uid, | 4077 | &right_gid, NULL); |
| 4043 | &right_gid, NULL); | 4078 | if (ret < 0) |
| 4044 | if (ret < 0) | 4079 | goto out; |
| 4045 | goto out; | ||
| 4046 | 4080 | ||
| 4047 | if (left_uid != right_uid || left_gid != right_gid) | 4081 | if (left_uid != right_uid || left_gid != right_gid) |
| 4048 | need_chown = 1; | 4082 | need_chown = 1; |
| 4049 | if (left_mode != right_mode) | 4083 | if (!S_ISLNK(sctx->cur_inode_mode) && left_mode != right_mode) |
| 4050 | need_chmod = 1; | 4084 | need_chmod = 1; |
| 4051 | } | ||
| 4052 | } | 4085 | } |
| 4053 | 4086 | ||
| 4054 | if (S_ISREG(sctx->cur_inode_mode)) { | 4087 | if (S_ISREG(sctx->cur_inode_mode)) { |
| @@ -4335,7 +4368,8 @@ static int changed_cb(struct btrfs_root *left_root, | |||
| 4335 | 4368 | ||
| 4336 | if (key->type == BTRFS_INODE_ITEM_KEY) | 4369 | if (key->type == BTRFS_INODE_ITEM_KEY) |
| 4337 | ret = changed_inode(sctx, result); | 4370 | ret = changed_inode(sctx, result); |
| 4338 | else if (key->type == BTRFS_INODE_REF_KEY) | 4371 | else if (key->type == BTRFS_INODE_REF_KEY || |
| 4372 | key->type == BTRFS_INODE_EXTREF_KEY) | ||
| 4339 | ret = changed_ref(sctx, result); | 4373 | ret = changed_ref(sctx, result); |
| 4340 | else if (key->type == BTRFS_XATTR_ITEM_KEY) | 4374 | else if (key->type == BTRFS_XATTR_ITEM_KEY) |
| 4341 | ret = changed_xattr(sctx, result); | 4375 | ret = changed_xattr(sctx, result); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 77db875b5116..04bbfb1052eb 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -1200,7 +1200,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 1200 | btrfs_i_size_write(parent_inode, parent_inode->i_size + | 1200 | btrfs_i_size_write(parent_inode, parent_inode->i_size + |
| 1201 | dentry->d_name.len * 2); | 1201 | dentry->d_name.len * 2); |
| 1202 | parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; | 1202 | parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME; |
| 1203 | ret = btrfs_update_inode(trans, parent_root, parent_inode); | 1203 | ret = btrfs_update_inode_fallback(trans, parent_root, parent_inode); |
| 1204 | if (ret) | 1204 | if (ret) |
| 1205 | btrfs_abort_transaction(trans, root, ret); | 1205 | btrfs_abort_transaction(trans, root, ret); |
| 1206 | fail: | 1206 | fail: |
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 029b903a4ae3..0f5ebb72a5ea 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -1819,6 +1819,13 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) | |||
| 1819 | "Failed to relocate sys chunks after " | 1819 | "Failed to relocate sys chunks after " |
| 1820 | "device initialization. This can be fixed " | 1820 | "device initialization. This can be fixed " |
| 1821 | "using the \"btrfs balance\" command."); | 1821 | "using the \"btrfs balance\" command."); |
| 1822 | trans = btrfs_attach_transaction(root); | ||
| 1823 | if (IS_ERR(trans)) { | ||
| 1824 | if (PTR_ERR(trans) == -ENOENT) | ||
| 1825 | return 0; | ||
| 1826 | return PTR_ERR(trans); | ||
| 1827 | } | ||
| 1828 | ret = btrfs_commit_transaction(trans, root); | ||
| 1822 | } | 1829 | } |
| 1823 | 1830 | ||
| 1824 | return ret; | 1831 | return ret; |
diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 02ce90972d81..9349bb37a2fe 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c | |||
| @@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len, | |||
| 90 | *max_len = handle_length; | 90 | *max_len = handle_length; |
| 91 | type = 255; | 91 | type = 255; |
| 92 | } | 92 | } |
| 93 | if (dentry) | ||
| 94 | dput(dentry); | ||
| 93 | return type; | 95 | return type; |
| 94 | } | 96 | } |
| 95 | 97 | ||
diff --git a/fs/char_dev.c b/fs/char_dev.c index 3f152b92a94a..afc2bb691780 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
| @@ -471,9 +471,19 @@ static int exact_lock(dev_t dev, void *data) | |||
| 471 | */ | 471 | */ |
| 472 | int cdev_add(struct cdev *p, dev_t dev, unsigned count) | 472 | int cdev_add(struct cdev *p, dev_t dev, unsigned count) |
| 473 | { | 473 | { |
| 474 | int error; | ||
| 475 | |||
| 474 | p->dev = dev; | 476 | p->dev = dev; |
| 475 | p->count = count; | 477 | p->count = count; |
| 476 | return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p); | 478 | |
| 479 | error = kobj_map(cdev_map, dev, count, NULL, | ||
| 480 | exact_match, exact_lock, p); | ||
| 481 | if (error) | ||
| 482 | return error; | ||
| 483 | |||
| 484 | kobject_get(p->kobj.parent); | ||
| 485 | |||
| 486 | return 0; | ||
| 477 | } | 487 | } |
| 478 | 488 | ||
| 479 | static void cdev_unmap(dev_t dev, unsigned count) | 489 | static void cdev_unmap(dev_t dev, unsigned count) |
| @@ -498,14 +508,20 @@ void cdev_del(struct cdev *p) | |||
| 498 | static void cdev_default_release(struct kobject *kobj) | 508 | static void cdev_default_release(struct kobject *kobj) |
| 499 | { | 509 | { |
| 500 | struct cdev *p = container_of(kobj, struct cdev, kobj); | 510 | struct cdev *p = container_of(kobj, struct cdev, kobj); |
| 511 | struct kobject *parent = kobj->parent; | ||
| 512 | |||
| 501 | cdev_purge(p); | 513 | cdev_purge(p); |
| 514 | kobject_put(parent); | ||
| 502 | } | 515 | } |
| 503 | 516 | ||
| 504 | static void cdev_dynamic_release(struct kobject *kobj) | 517 | static void cdev_dynamic_release(struct kobject *kobj) |
| 505 | { | 518 | { |
| 506 | struct cdev *p = container_of(kobj, struct cdev, kobj); | 519 | struct cdev *p = container_of(kobj, struct cdev, kobj); |
| 520 | struct kobject *parent = kobj->parent; | ||
| 521 | |||
| 507 | cdev_purge(p); | 522 | cdev_purge(p); |
| 508 | kfree(p); | 523 | kfree(p); |
| 524 | kobject_put(parent); | ||
| 509 | } | 525 | } |
| 510 | 526 | ||
| 511 | static struct kobj_type ktype_cdev_default = { | 527 | static struct kobj_type ktype_cdev_default = { |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index f5054025f9da..4c6285fff598 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -210,6 +210,8 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, | |||
| 210 | 210 | ||
| 211 | err = get_user(palp, &up->palette); | 211 | err = get_user(palp, &up->palette); |
| 212 | err |= get_user(length, &up->length); | 212 | err |= get_user(length, &up->length); |
| 213 | if (err) | ||
| 214 | return -EFAULT; | ||
| 213 | 215 | ||
| 214 | up_native = compat_alloc_user_space(sizeof(struct video_spu_palette)); | 216 | up_native = compat_alloc_user_space(sizeof(struct video_spu_palette)); |
| 215 | err = put_user(compat_ptr(palp), &up_native->palette); | 217 | err = put_user(compat_ptr(palp), &up_native->palette); |
diff --git a/fs/coredump.c b/fs/coredump.c index fd37facac8dc..ce47379bfa61 100644 --- a/fs/coredump.c +++ b/fs/coredump.c | |||
| @@ -450,11 +450,12 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) | |||
| 450 | 450 | ||
| 451 | cp->file = files[1]; | 451 | cp->file = files[1]; |
| 452 | 452 | ||
| 453 | replace_fd(0, files[0], 0); | 453 | err = replace_fd(0, files[0], 0); |
| 454 | fput(files[0]); | ||
| 454 | /* and disallow core files too */ | 455 | /* and disallow core files too */ |
| 455 | current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; | 456 | current->signal->rlim[RLIMIT_CORE] = (struct rlimit){1, 1}; |
| 456 | 457 | ||
| 457 | return 0; | 458 | return err; |
| 458 | } | 459 | } |
| 459 | 460 | ||
| 460 | void do_coredump(siginfo_t *siginfo, struct pt_regs *regs) | 461 | void do_coredump(siginfo_t *siginfo, struct pt_regs *regs) |
| @@ -1083,7 +1083,8 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
| 1083 | bprm->mm = NULL; /* We're using it now */ | 1083 | bprm->mm = NULL; /* We're using it now */ |
| 1084 | 1084 | ||
| 1085 | set_fs(USER_DS); | 1085 | set_fs(USER_DS); |
| 1086 | current->flags &= ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD); | 1086 | current->flags &= |
| 1087 | ~(PF_RANDOMIZE | PF_FORKNOEXEC | PF_KTHREAD | PF_NOFREEZE); | ||
| 1087 | flush_thread(); | 1088 | flush_thread(); |
| 1088 | current->personality &= ~bprm->per_clear; | 1089 | current->personality &= ~bprm->per_clear; |
| 1089 | 1090 | ||
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 6c205d0c565b..fa04d023177e 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
| @@ -469,7 +469,7 @@ static int parse_options(char *options, struct super_block *sb) | |||
| 469 | uid = make_kuid(current_user_ns(), option); | 469 | uid = make_kuid(current_user_ns(), option); |
| 470 | if (!uid_valid(uid)) { | 470 | if (!uid_valid(uid)) { |
| 471 | ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option); | 471 | ext2_msg(sb, KERN_ERR, "Invalid uid value %d", option); |
| 472 | return -1; | 472 | return 0; |
| 473 | 473 | ||
| 474 | } | 474 | } |
| 475 | sbi->s_resuid = uid; | 475 | sbi->s_resuid = uid; |
| @@ -480,7 +480,7 @@ static int parse_options(char *options, struct super_block *sb) | |||
| 480 | gid = make_kgid(current_user_ns(), option); | 480 | gid = make_kgid(current_user_ns(), option); |
| 481 | if (!gid_valid(gid)) { | 481 | if (!gid_valid(gid)) { |
| 482 | ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option); | 482 | ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option); |
| 483 | return -1; | 483 | return 0; |
| 484 | } | 484 | } |
| 485 | sbi->s_resgid = gid; | 485 | sbi->s_resgid = gid; |
| 486 | break; | 486 | break; |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 8f4fddac01a6..890b8947c546 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
| @@ -46,8 +46,7 @@ static struct buffer_head *ext3_append(handle_t *handle, | |||
| 46 | 46 | ||
| 47 | *block = inode->i_size >> inode->i_sb->s_blocksize_bits; | 47 | *block = inode->i_size >> inode->i_sb->s_blocksize_bits; |
| 48 | 48 | ||
| 49 | bh = ext3_bread(handle, inode, *block, 1, err); | 49 | if ((bh = ext3_dir_bread(handle, inode, *block, 1, err))) { |
| 50 | if (bh) { | ||
| 51 | inode->i_size += inode->i_sb->s_blocksize; | 50 | inode->i_size += inode->i_sb->s_blocksize; |
| 52 | EXT3_I(inode)->i_disksize = inode->i_size; | 51 | EXT3_I(inode)->i_disksize = inode->i_size; |
| 53 | *err = ext3_journal_get_write_access(handle, bh); | 52 | *err = ext3_journal_get_write_access(handle, bh); |
| @@ -339,8 +338,10 @@ dx_probe(struct qstr *entry, struct inode *dir, | |||
| 339 | u32 hash; | 338 | u32 hash; |
| 340 | 339 | ||
| 341 | frame->bh = NULL; | 340 | frame->bh = NULL; |
| 342 | if (!(bh = ext3_bread (NULL,dir, 0, 0, err))) | 341 | if (!(bh = ext3_dir_bread(NULL, dir, 0, 0, err))) { |
| 342 | *err = ERR_BAD_DX_DIR; | ||
| 343 | goto fail; | 343 | goto fail; |
| 344 | } | ||
| 344 | root = (struct dx_root *) bh->b_data; | 345 | root = (struct dx_root *) bh->b_data; |
| 345 | if (root->info.hash_version != DX_HASH_TEA && | 346 | if (root->info.hash_version != DX_HASH_TEA && |
| 346 | root->info.hash_version != DX_HASH_HALF_MD4 && | 347 | root->info.hash_version != DX_HASH_HALF_MD4 && |
| @@ -436,8 +437,10 @@ dx_probe(struct qstr *entry, struct inode *dir, | |||
| 436 | frame->entries = entries; | 437 | frame->entries = entries; |
| 437 | frame->at = at; | 438 | frame->at = at; |
| 438 | if (!indirect--) return frame; | 439 | if (!indirect--) return frame; |
| 439 | if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0, err))) | 440 | if (!(bh = ext3_dir_bread(NULL, dir, dx_get_block(at), 0, err))) { |
| 441 | *err = ERR_BAD_DX_DIR; | ||
| 440 | goto fail2; | 442 | goto fail2; |
| 443 | } | ||
| 441 | at = entries = ((struct dx_node *) bh->b_data)->entries; | 444 | at = entries = ((struct dx_node *) bh->b_data)->entries; |
| 442 | if (dx_get_limit(entries) != dx_node_limit (dir)) { | 445 | if (dx_get_limit(entries) != dx_node_limit (dir)) { |
| 443 | ext3_warning(dir->i_sb, __func__, | 446 | ext3_warning(dir->i_sb, __func__, |
| @@ -535,8 +538,8 @@ static int ext3_htree_next_block(struct inode *dir, __u32 hash, | |||
| 535 | * block so no check is necessary | 538 | * block so no check is necessary |
| 536 | */ | 539 | */ |
| 537 | while (num_frames--) { | 540 | while (num_frames--) { |
| 538 | if (!(bh = ext3_bread(NULL, dir, dx_get_block(p->at), | 541 | if (!(bh = ext3_dir_bread(NULL, dir, dx_get_block(p->at), |
| 539 | 0, &err))) | 542 | 0, &err))) |
| 540 | return err; /* Failure */ | 543 | return err; /* Failure */ |
| 541 | p++; | 544 | p++; |
| 542 | brelse (p->bh); | 545 | brelse (p->bh); |
| @@ -559,10 +562,11 @@ static int htree_dirblock_to_tree(struct file *dir_file, | |||
| 559 | { | 562 | { |
| 560 | struct buffer_head *bh; | 563 | struct buffer_head *bh; |
| 561 | struct ext3_dir_entry_2 *de, *top; | 564 | struct ext3_dir_entry_2 *de, *top; |
| 562 | int err, count = 0; | 565 | int err = 0, count = 0; |
| 563 | 566 | ||
| 564 | dxtrace(printk("In htree dirblock_to_tree: block %d\n", block)); | 567 | dxtrace(printk("In htree dirblock_to_tree: block %d\n", block)); |
| 565 | if (!(bh = ext3_bread (NULL, dir, block, 0, &err))) | 568 | |
| 569 | if (!(bh = ext3_dir_bread(NULL, dir, block, 0, &err))) | ||
| 566 | return err; | 570 | return err; |
| 567 | 571 | ||
| 568 | de = (struct ext3_dir_entry_2 *) bh->b_data; | 572 | de = (struct ext3_dir_entry_2 *) bh->b_data; |
| @@ -976,7 +980,7 @@ static struct buffer_head * ext3_dx_find_entry(struct inode *dir, | |||
| 976 | return NULL; | 980 | return NULL; |
| 977 | do { | 981 | do { |
| 978 | block = dx_get_block(frame->at); | 982 | block = dx_get_block(frame->at); |
| 979 | if (!(bh = ext3_bread (NULL,dir, block, 0, err))) | 983 | if (!(bh = ext3_dir_bread (NULL, dir, block, 0, err))) |
| 980 | goto errout; | 984 | goto errout; |
| 981 | 985 | ||
| 982 | retval = search_dirblock(bh, dir, entry, | 986 | retval = search_dirblock(bh, dir, entry, |
| @@ -1458,9 +1462,9 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry, | |||
| 1458 | } | 1462 | } |
| 1459 | blocks = dir->i_size >> sb->s_blocksize_bits; | 1463 | blocks = dir->i_size >> sb->s_blocksize_bits; |
| 1460 | for (block = 0; block < blocks; block++) { | 1464 | for (block = 0; block < blocks; block++) { |
| 1461 | bh = ext3_bread(handle, dir, block, 0, &retval); | 1465 | if (!(bh = ext3_dir_bread(handle, dir, block, 0, &retval))) |
| 1462 | if(!bh) | ||
| 1463 | return retval; | 1466 | return retval; |
| 1467 | |||
| 1464 | retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh); | 1468 | retval = add_dirent_to_buf(handle, dentry, inode, NULL, bh); |
| 1465 | if (retval != -ENOSPC) | 1469 | if (retval != -ENOSPC) |
| 1466 | return retval; | 1470 | return retval; |
| @@ -1500,7 +1504,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, | |||
| 1500 | entries = frame->entries; | 1504 | entries = frame->entries; |
| 1501 | at = frame->at; | 1505 | at = frame->at; |
| 1502 | 1506 | ||
| 1503 | if (!(bh = ext3_bread(handle,dir, dx_get_block(frame->at), 0, &err))) | 1507 | if (!(bh = ext3_dir_bread(handle, dir, dx_get_block(frame->at), 0, &err))) |
| 1504 | goto cleanup; | 1508 | goto cleanup; |
| 1505 | 1509 | ||
| 1506 | BUFFER_TRACE(bh, "get_write_access"); | 1510 | BUFFER_TRACE(bh, "get_write_access"); |
| @@ -1790,8 +1794,7 @@ retry: | |||
| 1790 | inode->i_op = &ext3_dir_inode_operations; | 1794 | inode->i_op = &ext3_dir_inode_operations; |
| 1791 | inode->i_fop = &ext3_dir_operations; | 1795 | inode->i_fop = &ext3_dir_operations; |
| 1792 | inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; | 1796 | inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; |
| 1793 | dir_block = ext3_bread (handle, inode, 0, 1, &err); | 1797 | if (!(dir_block = ext3_dir_bread(handle, inode, 0, 1, &err))) |
| 1794 | if (!dir_block) | ||
| 1795 | goto out_clear_inode; | 1798 | goto out_clear_inode; |
| 1796 | 1799 | ||
| 1797 | BUFFER_TRACE(dir_block, "get_write_access"); | 1800 | BUFFER_TRACE(dir_block, "get_write_access"); |
| @@ -1859,7 +1862,7 @@ static int empty_dir (struct inode * inode) | |||
| 1859 | 1862 | ||
| 1860 | sb = inode->i_sb; | 1863 | sb = inode->i_sb; |
| 1861 | if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) || | 1864 | if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) || |
| 1862 | !(bh = ext3_bread (NULL, inode, 0, 0, &err))) { | 1865 | !(bh = ext3_dir_bread(NULL, inode, 0, 0, &err))) { |
| 1863 | if (err) | 1866 | if (err) |
| 1864 | ext3_error(inode->i_sb, __func__, | 1867 | ext3_error(inode->i_sb, __func__, |
| 1865 | "error %d reading directory #%lu offset 0", | 1868 | "error %d reading directory #%lu offset 0", |
| @@ -1890,9 +1893,8 @@ static int empty_dir (struct inode * inode) | |||
| 1890 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { | 1893 | (void *) de >= (void *) (bh->b_data+sb->s_blocksize)) { |
| 1891 | err = 0; | 1894 | err = 0; |
| 1892 | brelse (bh); | 1895 | brelse (bh); |
| 1893 | bh = ext3_bread (NULL, inode, | 1896 | if (!(bh = ext3_dir_bread (NULL, inode, |
| 1894 | offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err); | 1897 | offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err))) { |
| 1895 | if (!bh) { | ||
| 1896 | if (err) | 1898 | if (err) |
| 1897 | ext3_error(sb, __func__, | 1899 | ext3_error(sb, __func__, |
| 1898 | "error %d reading directory" | 1900 | "error %d reading directory" |
| @@ -2388,7 +2390,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, | |||
| 2388 | goto end_rename; | 2390 | goto end_rename; |
| 2389 | } | 2391 | } |
| 2390 | retval = -EIO; | 2392 | retval = -EIO; |
| 2391 | dir_bh = ext3_bread (handle, old_inode, 0, 0, &retval); | 2393 | dir_bh = ext3_dir_bread(handle, old_inode, 0, 0, &retval); |
| 2392 | if (!dir_bh) | 2394 | if (!dir_bh) |
| 2393 | goto end_rename; | 2395 | goto end_rename; |
| 2394 | if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) | 2396 | if (le32_to_cpu(PARENT_INO(dir_bh->b_data)) != old_dir->i_ino) |
diff --git a/fs/ext3/namei.h b/fs/ext3/namei.h index f2ce2b0065c9..46304d8c9f0a 100644 --- a/fs/ext3/namei.h +++ b/fs/ext3/namei.h | |||
| @@ -6,3 +6,22 @@ | |||
| 6 | */ | 6 | */ |
| 7 | 7 | ||
| 8 | extern struct dentry *ext3_get_parent(struct dentry *child); | 8 | extern struct dentry *ext3_get_parent(struct dentry *child); |
| 9 | |||
| 10 | static inline struct buffer_head *ext3_dir_bread(handle_t *handle, | ||
| 11 | struct inode *inode, | ||
| 12 | int block, int create, | ||
| 13 | int *err) | ||
| 14 | { | ||
| 15 | struct buffer_head *bh; | ||
| 16 | |||
| 17 | bh = ext3_bread(handle, inode, block, create, err); | ||
| 18 | |||
| 19 | if (!bh && !(*err)) { | ||
| 20 | *err = -EIO; | ||
| 21 | ext3_error(inode->i_sb, __func__, | ||
| 22 | "Directory hole detected on inode %lu\n", | ||
| 23 | inode->i_ino); | ||
| 24 | return NULL; | ||
| 25 | } | ||
| 26 | return bh; | ||
| 27 | } | ||
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 29e79713c7eb..5366393528df 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
| @@ -1001,7 +1001,7 @@ static int parse_options (char *options, struct super_block *sb, | |||
| 1001 | uid = make_kuid(current_user_ns(), option); | 1001 | uid = make_kuid(current_user_ns(), option); |
| 1002 | if (!uid_valid(uid)) { | 1002 | if (!uid_valid(uid)) { |
| 1003 | ext3_msg(sb, KERN_ERR, "Invalid uid value %d", option); | 1003 | ext3_msg(sb, KERN_ERR, "Invalid uid value %d", option); |
| 1004 | return -1; | 1004 | return 0; |
| 1005 | 1005 | ||
| 1006 | } | 1006 | } |
| 1007 | sbi->s_resuid = uid; | 1007 | sbi->s_resuid = uid; |
| @@ -1012,7 +1012,7 @@ static int parse_options (char *options, struct super_block *sb, | |||
| 1012 | gid = make_kgid(current_user_ns(), option); | 1012 | gid = make_kgid(current_user_ns(), option); |
| 1013 | if (!gid_valid(gid)) { | 1013 | if (!gid_valid(gid)) { |
| 1014 | ext3_msg(sb, KERN_ERR, "Invalid gid value %d", option); | 1014 | ext3_msg(sb, KERN_ERR, "Invalid gid value %d", option); |
| 1015 | return -1; | 1015 | return 0; |
| 1016 | } | 1016 | } |
| 1017 | sbi->s_resgid = gid; | 1017 | sbi->s_resgid = gid; |
| 1018 | break; | 1018 | break; |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 1b5089067d01..cf1821784a16 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -174,8 +174,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
| 174 | ext4_free_inodes_set(sb, gdp, 0); | 174 | ext4_free_inodes_set(sb, gdp, 0); |
| 175 | ext4_itable_unused_set(sb, gdp, 0); | 175 | ext4_itable_unused_set(sb, gdp, 0); |
| 176 | memset(bh->b_data, 0xff, sb->s_blocksize); | 176 | memset(bh->b_data, 0xff, sb->s_blocksize); |
| 177 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, | 177 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bh); |
| 178 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | ||
| 179 | return; | 178 | return; |
| 180 | } | 179 | } |
| 181 | memset(bh->b_data, 0, sb->s_blocksize); | 180 | memset(bh->b_data, 0, sb->s_blocksize); |
| @@ -212,8 +211,7 @@ void ext4_init_block_bitmap(struct super_block *sb, struct buffer_head *bh, | |||
| 212 | */ | 211 | */ |
| 213 | ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group), | 212 | ext4_mark_bitmap_end(num_clusters_in_group(sb, block_group), |
| 214 | sb->s_blocksize * 8, bh->b_data); | 213 | sb->s_blocksize * 8, bh->b_data); |
| 215 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bh, | 214 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bh); |
| 216 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | ||
| 217 | ext4_group_desc_csum_set(sb, block_group, gdp); | 215 | ext4_group_desc_csum_set(sb, block_group, gdp); |
| 218 | } | 216 | } |
| 219 | 217 | ||
| @@ -350,7 +348,7 @@ void ext4_validate_block_bitmap(struct super_block *sb, | |||
| 350 | return; | 348 | return; |
| 351 | } | 349 | } |
| 352 | if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, | 350 | if (unlikely(!ext4_block_bitmap_csum_verify(sb, block_group, |
| 353 | desc, bh, EXT4_BLOCKS_PER_GROUP(sb) / 8))) { | 351 | desc, bh))) { |
| 354 | ext4_unlock_group(sb, block_group); | 352 | ext4_unlock_group(sb, block_group); |
| 355 | ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); | 353 | ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); |
| 356 | return; | 354 | return; |
diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c index 5c2d1813ebe9..3285aa5a706a 100644 --- a/fs/ext4/bitmap.c +++ b/fs/ext4/bitmap.c | |||
| @@ -58,11 +58,12 @@ void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group, | |||
| 58 | 58 | ||
| 59 | int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, | 59 | int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, |
| 60 | struct ext4_group_desc *gdp, | 60 | struct ext4_group_desc *gdp, |
| 61 | struct buffer_head *bh, int sz) | 61 | struct buffer_head *bh) |
| 62 | { | 62 | { |
| 63 | __u32 hi; | 63 | __u32 hi; |
| 64 | __u32 provided, calculated; | 64 | __u32 provided, calculated; |
| 65 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 65 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 66 | int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8; | ||
| 66 | 67 | ||
| 67 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, | 68 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, |
| 68 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | 69 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) |
| @@ -84,8 +85,9 @@ int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, | |||
| 84 | 85 | ||
| 85 | void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, | 86 | void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, |
| 86 | struct ext4_group_desc *gdp, | 87 | struct ext4_group_desc *gdp, |
| 87 | struct buffer_head *bh, int sz) | 88 | struct buffer_head *bh) |
| 88 | { | 89 | { |
| 90 | int sz = EXT4_CLUSTERS_PER_GROUP(sb) / 8; | ||
| 89 | __u32 csum; | 91 | __u32 csum; |
| 90 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 92 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 91 | 93 | ||
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 3ab2539b7b2e..3c20de1d59d0 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
| @@ -1882,10 +1882,10 @@ int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, | |||
| 1882 | struct buffer_head *bh, int sz); | 1882 | struct buffer_head *bh, int sz); |
| 1883 | void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, | 1883 | void ext4_block_bitmap_csum_set(struct super_block *sb, ext4_group_t group, |
| 1884 | struct ext4_group_desc *gdp, | 1884 | struct ext4_group_desc *gdp, |
| 1885 | struct buffer_head *bh, int sz); | 1885 | struct buffer_head *bh); |
| 1886 | int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, | 1886 | int ext4_block_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, |
| 1887 | struct ext4_group_desc *gdp, | 1887 | struct ext4_group_desc *gdp, |
| 1888 | struct buffer_head *bh, int sz); | 1888 | struct buffer_head *bh); |
| 1889 | 1889 | ||
| 1890 | /* balloc.c */ | 1890 | /* balloc.c */ |
| 1891 | extern void ext4_validate_block_bitmap(struct super_block *sb, | 1891 | extern void ext4_validate_block_bitmap(struct super_block *sb, |
| @@ -2063,8 +2063,7 @@ extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); | |||
| 2063 | extern int ext4_calculate_overhead(struct super_block *sb); | 2063 | extern int ext4_calculate_overhead(struct super_block *sb); |
| 2064 | extern int ext4_superblock_csum_verify(struct super_block *sb, | 2064 | extern int ext4_superblock_csum_verify(struct super_block *sb, |
| 2065 | struct ext4_super_block *es); | 2065 | struct ext4_super_block *es); |
| 2066 | extern void ext4_superblock_csum_set(struct super_block *sb, | 2066 | extern void ext4_superblock_csum_set(struct super_block *sb); |
| 2067 | struct ext4_super_block *es); | ||
| 2068 | extern void *ext4_kvmalloc(size_t size, gfp_t flags); | 2067 | extern void *ext4_kvmalloc(size_t size, gfp_t flags); |
| 2069 | extern void *ext4_kvzalloc(size_t size, gfp_t flags); | 2068 | extern void *ext4_kvzalloc(size_t size, gfp_t flags); |
| 2070 | extern void ext4_kvfree(void *ptr); | 2069 | extern void ext4_kvfree(void *ptr); |
diff --git a/fs/ext4/ext4_jbd2.c b/fs/ext4/ext4_jbd2.c index bfa65b49d424..b4323ba846b5 100644 --- a/fs/ext4/ext4_jbd2.c +++ b/fs/ext4/ext4_jbd2.c | |||
| @@ -143,17 +143,13 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line, | |||
| 143 | struct buffer_head *bh = EXT4_SB(sb)->s_sbh; | 143 | struct buffer_head *bh = EXT4_SB(sb)->s_sbh; |
| 144 | int err = 0; | 144 | int err = 0; |
| 145 | 145 | ||
| 146 | ext4_superblock_csum_set(sb); | ||
| 146 | if (ext4_handle_valid(handle)) { | 147 | if (ext4_handle_valid(handle)) { |
| 147 | ext4_superblock_csum_set(sb, | ||
| 148 | (struct ext4_super_block *)bh->b_data); | ||
| 149 | err = jbd2_journal_dirty_metadata(handle, bh); | 148 | err = jbd2_journal_dirty_metadata(handle, bh); |
| 150 | if (err) | 149 | if (err) |
| 151 | ext4_journal_abort_handle(where, line, __func__, | 150 | ext4_journal_abort_handle(where, line, __func__, |
| 152 | bh, handle, err); | 151 | bh, handle, err); |
| 153 | } else { | 152 | } else |
| 154 | ext4_superblock_csum_set(sb, | ||
| 155 | (struct ext4_super_block *)bh->b_data); | ||
| 156 | mark_buffer_dirty(bh); | 153 | mark_buffer_dirty(bh); |
| 157 | } | ||
| 158 | return err; | 154 | return err; |
| 159 | } | 155 | } |
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index 1c94cca35ed1..7011ac967208 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
| @@ -52,6 +52,9 @@ | |||
| 52 | #define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ | 52 | #define EXT4_EXT_MARK_UNINIT1 0x2 /* mark first half uninitialized */ |
| 53 | #define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ | 53 | #define EXT4_EXT_MARK_UNINIT2 0x4 /* mark second half uninitialized */ |
| 54 | 54 | ||
| 55 | #define EXT4_EXT_DATA_VALID1 0x8 /* first half contains valid data */ | ||
| 56 | #define EXT4_EXT_DATA_VALID2 0x10 /* second half contains valid data */ | ||
| 57 | |||
| 55 | static __le32 ext4_extent_block_csum(struct inode *inode, | 58 | static __le32 ext4_extent_block_csum(struct inode *inode, |
| 56 | struct ext4_extent_header *eh) | 59 | struct ext4_extent_header *eh) |
| 57 | { | 60 | { |
| @@ -2914,6 +2917,9 @@ static int ext4_split_extent_at(handle_t *handle, | |||
| 2914 | unsigned int ee_len, depth; | 2917 | unsigned int ee_len, depth; |
| 2915 | int err = 0; | 2918 | int err = 0; |
| 2916 | 2919 | ||
| 2920 | BUG_ON((split_flag & (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)) == | ||
| 2921 | (EXT4_EXT_DATA_VALID1 | EXT4_EXT_DATA_VALID2)); | ||
| 2922 | |||
| 2917 | ext_debug("ext4_split_extents_at: inode %lu, logical" | 2923 | ext_debug("ext4_split_extents_at: inode %lu, logical" |
| 2918 | "block %llu\n", inode->i_ino, (unsigned long long)split); | 2924 | "block %llu\n", inode->i_ino, (unsigned long long)split); |
| 2919 | 2925 | ||
| @@ -2972,7 +2978,14 @@ static int ext4_split_extent_at(handle_t *handle, | |||
| 2972 | 2978 | ||
| 2973 | err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); | 2979 | err = ext4_ext_insert_extent(handle, inode, path, &newex, flags); |
| 2974 | if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { | 2980 | if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) { |
| 2975 | err = ext4_ext_zeroout(inode, &orig_ex); | 2981 | if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) { |
| 2982 | if (split_flag & EXT4_EXT_DATA_VALID1) | ||
| 2983 | err = ext4_ext_zeroout(inode, ex2); | ||
| 2984 | else | ||
| 2985 | err = ext4_ext_zeroout(inode, ex); | ||
| 2986 | } else | ||
| 2987 | err = ext4_ext_zeroout(inode, &orig_ex); | ||
| 2988 | |||
| 2976 | if (err) | 2989 | if (err) |
| 2977 | goto fix_extent_len; | 2990 | goto fix_extent_len; |
| 2978 | /* update the extent length and mark as initialized */ | 2991 | /* update the extent length and mark as initialized */ |
| @@ -3025,12 +3038,13 @@ static int ext4_split_extent(handle_t *handle, | |||
| 3025 | uninitialized = ext4_ext_is_uninitialized(ex); | 3038 | uninitialized = ext4_ext_is_uninitialized(ex); |
| 3026 | 3039 | ||
| 3027 | if (map->m_lblk + map->m_len < ee_block + ee_len) { | 3040 | if (map->m_lblk + map->m_len < ee_block + ee_len) { |
| 3028 | split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? | 3041 | split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT; |
| 3029 | EXT4_EXT_MAY_ZEROOUT : 0; | ||
| 3030 | flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; | 3042 | flags1 = flags | EXT4_GET_BLOCKS_PRE_IO; |
| 3031 | if (uninitialized) | 3043 | if (uninitialized) |
| 3032 | split_flag1 |= EXT4_EXT_MARK_UNINIT1 | | 3044 | split_flag1 |= EXT4_EXT_MARK_UNINIT1 | |
| 3033 | EXT4_EXT_MARK_UNINIT2; | 3045 | EXT4_EXT_MARK_UNINIT2; |
| 3046 | if (split_flag & EXT4_EXT_DATA_VALID2) | ||
| 3047 | split_flag1 |= EXT4_EXT_DATA_VALID1; | ||
| 3034 | err = ext4_split_extent_at(handle, inode, path, | 3048 | err = ext4_split_extent_at(handle, inode, path, |
| 3035 | map->m_lblk + map->m_len, split_flag1, flags1); | 3049 | map->m_lblk + map->m_len, split_flag1, flags1); |
| 3036 | if (err) | 3050 | if (err) |
| @@ -3043,8 +3057,8 @@ static int ext4_split_extent(handle_t *handle, | |||
| 3043 | return PTR_ERR(path); | 3057 | return PTR_ERR(path); |
| 3044 | 3058 | ||
| 3045 | if (map->m_lblk >= ee_block) { | 3059 | if (map->m_lblk >= ee_block) { |
| 3046 | split_flag1 = split_flag & EXT4_EXT_MAY_ZEROOUT ? | 3060 | split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT | |
| 3047 | EXT4_EXT_MAY_ZEROOUT : 0; | 3061 | EXT4_EXT_DATA_VALID2); |
| 3048 | if (uninitialized) | 3062 | if (uninitialized) |
| 3049 | split_flag1 |= EXT4_EXT_MARK_UNINIT1; | 3063 | split_flag1 |= EXT4_EXT_MARK_UNINIT1; |
| 3050 | if (split_flag & EXT4_EXT_MARK_UNINIT2) | 3064 | if (split_flag & EXT4_EXT_MARK_UNINIT2) |
| @@ -3323,26 +3337,47 @@ static int ext4_split_unwritten_extents(handle_t *handle, | |||
| 3323 | 3337 | ||
| 3324 | split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; | 3338 | split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0; |
| 3325 | split_flag |= EXT4_EXT_MARK_UNINIT2; | 3339 | split_flag |= EXT4_EXT_MARK_UNINIT2; |
| 3326 | 3340 | if (flags & EXT4_GET_BLOCKS_CONVERT) | |
| 3341 | split_flag |= EXT4_EXT_DATA_VALID2; | ||
| 3327 | flags |= EXT4_GET_BLOCKS_PRE_IO; | 3342 | flags |= EXT4_GET_BLOCKS_PRE_IO; |
| 3328 | return ext4_split_extent(handle, inode, path, map, split_flag, flags); | 3343 | return ext4_split_extent(handle, inode, path, map, split_flag, flags); |
| 3329 | } | 3344 | } |
| 3330 | 3345 | ||
| 3331 | static int ext4_convert_unwritten_extents_endio(handle_t *handle, | 3346 | static int ext4_convert_unwritten_extents_endio(handle_t *handle, |
| 3332 | struct inode *inode, | 3347 | struct inode *inode, |
| 3333 | struct ext4_ext_path *path) | 3348 | struct ext4_map_blocks *map, |
| 3349 | struct ext4_ext_path *path) | ||
| 3334 | { | 3350 | { |
| 3335 | struct ext4_extent *ex; | 3351 | struct ext4_extent *ex; |
| 3352 | ext4_lblk_t ee_block; | ||
| 3353 | unsigned int ee_len; | ||
| 3336 | int depth; | 3354 | int depth; |
| 3337 | int err = 0; | 3355 | int err = 0; |
| 3338 | 3356 | ||
| 3339 | depth = ext_depth(inode); | 3357 | depth = ext_depth(inode); |
| 3340 | ex = path[depth].p_ext; | 3358 | ex = path[depth].p_ext; |
| 3359 | ee_block = le32_to_cpu(ex->ee_block); | ||
| 3360 | ee_len = ext4_ext_get_actual_len(ex); | ||
| 3341 | 3361 | ||
| 3342 | ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" | 3362 | ext_debug("ext4_convert_unwritten_extents_endio: inode %lu, logical" |
| 3343 | "block %llu, max_blocks %u\n", inode->i_ino, | 3363 | "block %llu, max_blocks %u\n", inode->i_ino, |
| 3344 | (unsigned long long)le32_to_cpu(ex->ee_block), | 3364 | (unsigned long long)ee_block, ee_len); |
| 3345 | ext4_ext_get_actual_len(ex)); | 3365 | |
| 3366 | /* If extent is larger than requested then split is required */ | ||
| 3367 | if (ee_block != map->m_lblk || ee_len > map->m_len) { | ||
| 3368 | err = ext4_split_unwritten_extents(handle, inode, map, path, | ||
| 3369 | EXT4_GET_BLOCKS_CONVERT); | ||
| 3370 | if (err < 0) | ||
| 3371 | goto out; | ||
| 3372 | ext4_ext_drop_refs(path); | ||
| 3373 | path = ext4_ext_find_extent(inode, map->m_lblk, path); | ||
| 3374 | if (IS_ERR(path)) { | ||
| 3375 | err = PTR_ERR(path); | ||
| 3376 | goto out; | ||
| 3377 | } | ||
| 3378 | depth = ext_depth(inode); | ||
| 3379 | ex = path[depth].p_ext; | ||
| 3380 | } | ||
| 3346 | 3381 | ||
| 3347 | err = ext4_ext_get_access(handle, inode, path + depth); | 3382 | err = ext4_ext_get_access(handle, inode, path + depth); |
| 3348 | if (err) | 3383 | if (err) |
| @@ -3652,7 +3687,7 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode, | |||
| 3652 | } | 3687 | } |
| 3653 | /* IO end_io complete, convert the filled extent to written */ | 3688 | /* IO end_io complete, convert the filled extent to written */ |
| 3654 | if ((flags & EXT4_GET_BLOCKS_CONVERT)) { | 3689 | if ((flags & EXT4_GET_BLOCKS_CONVERT)) { |
| 3655 | ret = ext4_convert_unwritten_extents_endio(handle, inode, | 3690 | ret = ext4_convert_unwritten_extents_endio(handle, inode, map, |
| 3656 | path); | 3691 | path); |
| 3657 | if (ret >= 0) { | 3692 | if (ret >= 0) { |
| 3658 | ext4_update_inode_fsync_trans(handle, inode, 1); | 3693 | ext4_update_inode_fsync_trans(handle, inode, 1); |
| @@ -4428,6 +4463,9 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) | |||
| 4428 | */ | 4463 | */ |
| 4429 | if (len <= EXT_UNINIT_MAX_LEN << blkbits) | 4464 | if (len <= EXT_UNINIT_MAX_LEN << blkbits) |
| 4430 | flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; | 4465 | flags |= EXT4_GET_BLOCKS_NO_NORMALIZE; |
| 4466 | |||
| 4467 | /* Prevent race condition between unwritten */ | ||
| 4468 | ext4_flush_unwritten_io(inode); | ||
| 4431 | retry: | 4469 | retry: |
| 4432 | while (ret >= 0 && ret < max_blocks) { | 4470 | while (ret >= 0 && ret < max_blocks) { |
| 4433 | map.m_lblk = map.m_lblk + ret; | 4471 | map.m_lblk = map.m_lblk + ret; |
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index fa36372f3fdf..3a100e7a62a8 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
| @@ -725,6 +725,10 @@ repeat_in_this_group: | |||
| 725 | "inode=%lu", ino + 1); | 725 | "inode=%lu", ino + 1); |
| 726 | continue; | 726 | continue; |
| 727 | } | 727 | } |
| 728 | BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); | ||
| 729 | err = ext4_journal_get_write_access(handle, inode_bitmap_bh); | ||
| 730 | if (err) | ||
| 731 | goto fail; | ||
| 728 | ext4_lock_group(sb, group); | 732 | ext4_lock_group(sb, group); |
| 729 | ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); | 733 | ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); |
| 730 | ext4_unlock_group(sb, group); | 734 | ext4_unlock_group(sb, group); |
| @@ -738,6 +742,11 @@ repeat_in_this_group: | |||
| 738 | goto out; | 742 | goto out; |
| 739 | 743 | ||
| 740 | got: | 744 | got: |
| 745 | BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); | ||
| 746 | err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); | ||
| 747 | if (err) | ||
| 748 | goto fail; | ||
| 749 | |||
| 741 | /* We may have to initialize the block bitmap if it isn't already */ | 750 | /* We may have to initialize the block bitmap if it isn't already */ |
| 742 | if (ext4_has_group_desc_csum(sb) && | 751 | if (ext4_has_group_desc_csum(sb) && |
| 743 | gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 752 | gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { |
| @@ -762,9 +771,7 @@ got: | |||
| 762 | ext4_free_group_clusters_set(sb, gdp, | 771 | ext4_free_group_clusters_set(sb, gdp, |
| 763 | ext4_free_clusters_after_init(sb, group, gdp)); | 772 | ext4_free_clusters_after_init(sb, group, gdp)); |
| 764 | ext4_block_bitmap_csum_set(sb, group, gdp, | 773 | ext4_block_bitmap_csum_set(sb, group, gdp, |
| 765 | block_bitmap_bh, | 774 | block_bitmap_bh); |
| 766 | EXT4_BLOCKS_PER_GROUP(sb) / | ||
| 767 | 8); | ||
| 768 | ext4_group_desc_csum_set(sb, group, gdp); | 775 | ext4_group_desc_csum_set(sb, group, gdp); |
| 769 | } | 776 | } |
| 770 | ext4_unlock_group(sb, group); | 777 | ext4_unlock_group(sb, group); |
| @@ -773,11 +780,6 @@ got: | |||
| 773 | goto fail; | 780 | goto fail; |
| 774 | } | 781 | } |
| 775 | 782 | ||
| 776 | BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); | ||
| 777 | err = ext4_journal_get_write_access(handle, inode_bitmap_bh); | ||
| 778 | if (err) | ||
| 779 | goto fail; | ||
| 780 | |||
| 781 | BUFFER_TRACE(group_desc_bh, "get_write_access"); | 783 | BUFFER_TRACE(group_desc_bh, "get_write_access"); |
| 782 | err = ext4_journal_get_write_access(handle, group_desc_bh); | 784 | err = ext4_journal_get_write_access(handle, group_desc_bh); |
| 783 | if (err) | 785 | if (err) |
| @@ -825,11 +827,6 @@ got: | |||
| 825 | } | 827 | } |
| 826 | ext4_unlock_group(sb, group); | 828 | ext4_unlock_group(sb, group); |
| 827 | 829 | ||
| 828 | BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); | ||
| 829 | err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); | ||
| 830 | if (err) | ||
| 831 | goto fail; | ||
| 832 | |||
| 833 | BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); | 830 | BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); |
| 834 | err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); | 831 | err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); |
| 835 | if (err) | 832 | if (err) |
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index f8b27bf80aca..526e55358606 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
| @@ -2805,8 +2805,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, | |||
| 2805 | } | 2805 | } |
| 2806 | len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len; | 2806 | len = ext4_free_group_clusters(sb, gdp) - ac->ac_b_ex.fe_len; |
| 2807 | ext4_free_group_clusters_set(sb, gdp, len); | 2807 | ext4_free_group_clusters_set(sb, gdp, len); |
| 2808 | ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh, | 2808 | ext4_block_bitmap_csum_set(sb, ac->ac_b_ex.fe_group, gdp, bitmap_bh); |
| 2809 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | ||
| 2810 | ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp); | 2809 | ext4_group_desc_csum_set(sb, ac->ac_b_ex.fe_group, gdp); |
| 2811 | 2810 | ||
| 2812 | ext4_unlock_group(sb, ac->ac_b_ex.fe_group); | 2811 | ext4_unlock_group(sb, ac->ac_b_ex.fe_group); |
| @@ -4666,8 +4665,7 @@ do_more: | |||
| 4666 | 4665 | ||
| 4667 | ret = ext4_free_group_clusters(sb, gdp) + count_clusters; | 4666 | ret = ext4_free_group_clusters(sb, gdp) + count_clusters; |
| 4668 | ext4_free_group_clusters_set(sb, gdp, ret); | 4667 | ext4_free_group_clusters_set(sb, gdp, ret); |
| 4669 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh, | 4668 | ext4_block_bitmap_csum_set(sb, block_group, gdp, bitmap_bh); |
| 4670 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | ||
| 4671 | ext4_group_desc_csum_set(sb, block_group, gdp); | 4669 | ext4_group_desc_csum_set(sb, block_group, gdp); |
| 4672 | ext4_unlock_group(sb, block_group); | 4670 | ext4_unlock_group(sb, block_group); |
| 4673 | percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters); | 4671 | percpu_counter_add(&sbi->s_freeclusters_counter, count_clusters); |
| @@ -4811,8 +4809,7 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb, | |||
| 4811 | mb_free_blocks(NULL, &e4b, bit, count); | 4809 | mb_free_blocks(NULL, &e4b, bit, count); |
| 4812 | blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc); | 4810 | blk_free_count = blocks_freed + ext4_free_group_clusters(sb, desc); |
| 4813 | ext4_free_group_clusters_set(sb, desc, blk_free_count); | 4811 | ext4_free_group_clusters_set(sb, desc, blk_free_count); |
| 4814 | ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh, | 4812 | ext4_block_bitmap_csum_set(sb, block_group, desc, bitmap_bh); |
| 4815 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | ||
| 4816 | ext4_group_desc_csum_set(sb, block_group, desc); | 4813 | ext4_group_desc_csum_set(sb, block_group, desc); |
| 4817 | ext4_unlock_group(sb, block_group); | 4814 | ext4_unlock_group(sb, block_group); |
| 4818 | percpu_counter_add(&sbi->s_freeclusters_counter, | 4815 | percpu_counter_add(&sbi->s_freeclusters_counter, |
| @@ -4993,8 +4990,9 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) | |||
| 4993 | minlen = EXT4_NUM_B2C(EXT4_SB(sb), | 4990 | minlen = EXT4_NUM_B2C(EXT4_SB(sb), |
| 4994 | range->minlen >> sb->s_blocksize_bits); | 4991 | range->minlen >> sb->s_blocksize_bits); |
| 4995 | 4992 | ||
| 4996 | if (unlikely(minlen > EXT4_CLUSTERS_PER_GROUP(sb)) || | 4993 | if (minlen > EXT4_CLUSTERS_PER_GROUP(sb) || |
| 4997 | unlikely(start >= max_blks)) | 4994 | start >= max_blks || |
| 4995 | range->len < sb->s_blocksize) | ||
| 4998 | return -EINVAL; | 4996 | return -EINVAL; |
| 4999 | if (end >= max_blks) | 4997 | if (end >= max_blks) |
| 5000 | end = max_blks - 1; | 4998 | end = max_blks - 1; |
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 7a75e1086961..47bf06a2765d 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c | |||
| @@ -1212,8 +1212,7 @@ static int ext4_set_bitmap_checksums(struct super_block *sb, | |||
| 1212 | bh = ext4_get_bitmap(sb, group_data->block_bitmap); | 1212 | bh = ext4_get_bitmap(sb, group_data->block_bitmap); |
| 1213 | if (!bh) | 1213 | if (!bh) |
| 1214 | return -EIO; | 1214 | return -EIO; |
| 1215 | ext4_block_bitmap_csum_set(sb, group, gdp, bh, | 1215 | ext4_block_bitmap_csum_set(sb, group, gdp, bh); |
| 1216 | EXT4_BLOCKS_PER_GROUP(sb) / 8); | ||
| 1217 | brelse(bh); | 1216 | brelse(bh); |
| 1218 | 1217 | ||
| 1219 | return 0; | 1218 | return 0; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 7265a0367476..80928f716850 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -143,9 +143,10 @@ int ext4_superblock_csum_verify(struct super_block *sb, | |||
| 143 | return es->s_checksum == ext4_superblock_csum(sb, es); | 143 | return es->s_checksum == ext4_superblock_csum(sb, es); |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | void ext4_superblock_csum_set(struct super_block *sb, | 146 | void ext4_superblock_csum_set(struct super_block *sb) |
| 147 | struct ext4_super_block *es) | ||
| 148 | { | 147 | { |
| 148 | struct ext4_super_block *es = EXT4_SB(sb)->s_es; | ||
| 149 | |||
| 149 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, | 150 | if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, |
| 150 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) | 151 | EXT4_FEATURE_RO_COMPAT_METADATA_CSUM)) |
| 151 | return; | 152 | return; |
| @@ -1963,7 +1964,7 @@ static int ext4_fill_flex_info(struct super_block *sb) | |||
| 1963 | sbi->s_log_groups_per_flex = 0; | 1964 | sbi->s_log_groups_per_flex = 0; |
| 1964 | return 1; | 1965 | return 1; |
| 1965 | } | 1966 | } |
| 1966 | groups_per_flex = 1 << sbi->s_log_groups_per_flex; | 1967 | groups_per_flex = 1U << sbi->s_log_groups_per_flex; |
| 1967 | 1968 | ||
| 1968 | err = ext4_alloc_flex_bg_array(sb, sbi->s_groups_count); | 1969 | err = ext4_alloc_flex_bg_array(sb, sbi->s_groups_count); |
| 1969 | if (err) | 1970 | if (err) |
| @@ -4381,7 +4382,7 @@ static int ext4_commit_super(struct super_block *sb, int sync) | |||
| 4381 | cpu_to_le32(percpu_counter_sum_positive( | 4382 | cpu_to_le32(percpu_counter_sum_positive( |
| 4382 | &EXT4_SB(sb)->s_freeinodes_counter)); | 4383 | &EXT4_SB(sb)->s_freeinodes_counter)); |
| 4383 | BUFFER_TRACE(sbh, "marking dirty"); | 4384 | BUFFER_TRACE(sbh, "marking dirty"); |
| 4384 | ext4_superblock_csum_set(sb, es); | 4385 | ext4_superblock_csum_set(sb); |
| 4385 | mark_buffer_dirty(sbh); | 4386 | mark_buffer_dirty(sbh); |
| 4386 | if (sync) { | 4387 | if (sync) { |
| 4387 | error = sync_dirty_buffer(sbh); | 4388 | error = sync_dirty_buffer(sbh); |
diff --git a/fs/jfs/jfs_discard.c b/fs/jfs/jfs_discard.c index 9947563e4175..dfcd50304559 100644 --- a/fs/jfs/jfs_discard.c +++ b/fs/jfs/jfs_discard.c | |||
| @@ -83,7 +83,7 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range) | |||
| 83 | struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; | 83 | struct bmap *bmp = JFS_SBI(ip->i_sb)->bmap; |
| 84 | struct super_block *sb = ipbmap->i_sb; | 84 | struct super_block *sb = ipbmap->i_sb; |
| 85 | int agno, agno_end; | 85 | int agno, agno_end; |
| 86 | s64 start, end, minlen; | 86 | u64 start, end, minlen; |
| 87 | u64 trimmed = 0; | 87 | u64 trimmed = 0; |
| 88 | 88 | ||
| 89 | /** | 89 | /** |
| @@ -93,15 +93,19 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range) | |||
| 93 | * minlen: minimum extent length in Bytes | 93 | * minlen: minimum extent length in Bytes |
| 94 | */ | 94 | */ |
| 95 | start = range->start >> sb->s_blocksize_bits; | 95 | start = range->start >> sb->s_blocksize_bits; |
| 96 | if (start < 0) | ||
| 97 | start = 0; | ||
| 98 | end = start + (range->len >> sb->s_blocksize_bits) - 1; | 96 | end = start + (range->len >> sb->s_blocksize_bits) - 1; |
| 99 | if (end >= bmp->db_mapsize) | ||
| 100 | end = bmp->db_mapsize - 1; | ||
| 101 | minlen = range->minlen >> sb->s_blocksize_bits; | 97 | minlen = range->minlen >> sb->s_blocksize_bits; |
| 102 | if (minlen <= 0) | 98 | if (minlen == 0) |
| 103 | minlen = 1; | 99 | minlen = 1; |
| 104 | 100 | ||
| 101 | if (minlen > bmp->db_agsize || | ||
| 102 | start >= bmp->db_mapsize || | ||
| 103 | range->len < sb->s_blocksize) | ||
| 104 | return -EINVAL; | ||
| 105 | |||
| 106 | if (end >= bmp->db_mapsize) | ||
| 107 | end = bmp->db_mapsize - 1; | ||
| 108 | |||
| 105 | /** | 109 | /** |
| 106 | * we trim all ag's within the range | 110 | * we trim all ag's within the range |
| 107 | */ | 111 | */ |
diff --git a/fs/lockd/clntxdr.c b/fs/lockd/clntxdr.c index d269ada7670e..982d2676e1f8 100644 --- a/fs/lockd/clntxdr.c +++ b/fs/lockd/clntxdr.c | |||
| @@ -223,7 +223,7 @@ static void encode_nlm_stat(struct xdr_stream *xdr, | |||
| 223 | { | 223 | { |
| 224 | __be32 *p; | 224 | __be32 *p; |
| 225 | 225 | ||
| 226 | BUG_ON(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); | 226 | WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD); |
| 227 | p = xdr_reserve_space(xdr, 4); | 227 | p = xdr_reserve_space(xdr, 4); |
| 228 | *p = stat; | 228 | *p = stat; |
| 229 | } | 229 | } |
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index e4fb3ba5a58a..3d7e09bcc0e9 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c | |||
| @@ -85,29 +85,38 @@ static struct rpc_clnt *nsm_create(struct net *net) | |||
| 85 | return rpc_create(&args); | 85 | return rpc_create(&args); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static struct rpc_clnt *nsm_client_set(struct lockd_net *ln, | ||
| 89 | struct rpc_clnt *clnt) | ||
| 90 | { | ||
| 91 | spin_lock(&ln->nsm_clnt_lock); | ||
| 92 | if (ln->nsm_users == 0) { | ||
| 93 | if (clnt == NULL) | ||
| 94 | goto out; | ||
| 95 | ln->nsm_clnt = clnt; | ||
| 96 | } | ||
| 97 | clnt = ln->nsm_clnt; | ||
| 98 | ln->nsm_users++; | ||
| 99 | out: | ||
| 100 | spin_unlock(&ln->nsm_clnt_lock); | ||
| 101 | return clnt; | ||
| 102 | } | ||
| 103 | |||
| 88 | static struct rpc_clnt *nsm_client_get(struct net *net) | 104 | static struct rpc_clnt *nsm_client_get(struct net *net) |
| 89 | { | 105 | { |
| 90 | static DEFINE_MUTEX(nsm_create_mutex); | 106 | struct rpc_clnt *clnt, *new; |
| 91 | struct rpc_clnt *clnt; | ||
| 92 | struct lockd_net *ln = net_generic(net, lockd_net_id); | 107 | struct lockd_net *ln = net_generic(net, lockd_net_id); |
| 93 | 108 | ||
| 94 | spin_lock(&ln->nsm_clnt_lock); | 109 | clnt = nsm_client_set(ln, NULL); |
| 95 | if (ln->nsm_users) { | 110 | if (clnt != NULL) |
| 96 | ln->nsm_users++; | ||
| 97 | clnt = ln->nsm_clnt; | ||
| 98 | spin_unlock(&ln->nsm_clnt_lock); | ||
| 99 | goto out; | 111 | goto out; |
| 100 | } | ||
| 101 | spin_unlock(&ln->nsm_clnt_lock); | ||
| 102 | 112 | ||
| 103 | mutex_lock(&nsm_create_mutex); | 113 | clnt = new = nsm_create(net); |
| 104 | clnt = nsm_create(net); | 114 | if (IS_ERR(clnt)) |
| 105 | if (!IS_ERR(clnt)) { | 115 | goto out; |
| 106 | ln->nsm_clnt = clnt; | 116 | |
| 107 | smp_wmb(); | 117 | clnt = nsm_client_set(ln, new); |
| 108 | ln->nsm_users = 1; | 118 | if (clnt != new) |
| 109 | } | 119 | rpc_shutdown_client(new); |
| 110 | mutex_unlock(&nsm_create_mutex); | ||
| 111 | out: | 120 | out: |
| 112 | return clnt; | 121 | return clnt; |
| 113 | } | 122 | } |
| @@ -115,18 +124,16 @@ out: | |||
| 115 | static void nsm_client_put(struct net *net) | 124 | static void nsm_client_put(struct net *net) |
| 116 | { | 125 | { |
| 117 | struct lockd_net *ln = net_generic(net, lockd_net_id); | 126 | struct lockd_net *ln = net_generic(net, lockd_net_id); |
| 118 | struct rpc_clnt *clnt = ln->nsm_clnt; | 127 | struct rpc_clnt *clnt = NULL; |
| 119 | int shutdown = 0; | ||
| 120 | 128 | ||
| 121 | spin_lock(&ln->nsm_clnt_lock); | 129 | spin_lock(&ln->nsm_clnt_lock); |
| 122 | if (ln->nsm_users) { | 130 | ln->nsm_users--; |
| 123 | if (--ln->nsm_users) | 131 | if (ln->nsm_users == 0) { |
| 124 | ln->nsm_clnt = NULL; | 132 | clnt = ln->nsm_clnt; |
| 125 | shutdown = !ln->nsm_users; | 133 | ln->nsm_clnt = NULL; |
| 126 | } | 134 | } |
| 127 | spin_unlock(&ln->nsm_clnt_lock); | 135 | spin_unlock(&ln->nsm_clnt_lock); |
| 128 | 136 | if (clnt != NULL) | |
| 129 | if (shutdown) | ||
| 130 | rpc_shutdown_client(clnt); | 137 | rpc_shutdown_client(clnt); |
| 131 | } | 138 | } |
| 132 | 139 | ||
diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 3009a365e082..21171f0c6477 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c | |||
| @@ -68,7 +68,8 @@ nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, | |||
| 68 | 68 | ||
| 69 | /* Obtain file pointer. Not used by FREE_ALL call. */ | 69 | /* Obtain file pointer. Not used by FREE_ALL call. */ |
| 70 | if (filp != NULL) { | 70 | if (filp != NULL) { |
| 71 | if ((error = nlm_lookup_file(rqstp, &file, &lock->fh)) != 0) | 71 | error = cast_status(nlm_lookup_file(rqstp, &file, &lock->fh)); |
| 72 | if (error != 0) | ||
| 72 | goto no_locks; | 73 | goto no_locks; |
| 73 | *filp = file; | 74 | *filp = file; |
| 74 | 75 | ||
diff --git a/fs/namei.c b/fs/namei.c index d1895f308156..937f9d50c84b 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -705,8 +705,8 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki | |||
| 705 | path_put(link); | 705 | path_put(link); |
| 706 | } | 706 | } |
| 707 | 707 | ||
| 708 | int sysctl_protected_symlinks __read_mostly = 1; | 708 | int sysctl_protected_symlinks __read_mostly = 0; |
| 709 | int sysctl_protected_hardlinks __read_mostly = 1; | 709 | int sysctl_protected_hardlinks __read_mostly = 0; |
| 710 | 710 | ||
| 711 | /** | 711 | /** |
| 712 | * may_follow_link - Check symlink following for unsafe situations | 712 | * may_follow_link - Check symlink following for unsafe situations |
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c index 9a521fb39869..5088b57b078a 100644 --- a/fs/nfs/callback.c +++ b/fs/nfs/callback.c | |||
| @@ -241,7 +241,7 @@ static int nfs_callback_start_svc(int minorversion, struct rpc_xprt *xprt, | |||
| 241 | svc_exit_thread(cb_info->rqst); | 241 | svc_exit_thread(cb_info->rqst); |
| 242 | cb_info->rqst = NULL; | 242 | cb_info->rqst = NULL; |
| 243 | cb_info->task = NULL; | 243 | cb_info->task = NULL; |
| 244 | return PTR_ERR(cb_info->task); | 244 | return ret; |
| 245 | } | 245 | } |
| 246 | dprintk("nfs_callback_up: service started\n"); | 246 | dprintk("nfs_callback_up: service started\n"); |
| 247 | return 0; | 247 | return 0; |
diff --git a/fs/nfs/nfs4filelayout.c b/fs/nfs/nfs4filelayout.c index 52d847212066..2e45fd9c02a3 100644 --- a/fs/nfs/nfs4filelayout.c +++ b/fs/nfs/nfs4filelayout.c | |||
| @@ -122,12 +122,21 @@ static void filelayout_reset_read(struct nfs_read_data *data) | |||
| 122 | } | 122 | } |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo) | ||
| 126 | { | ||
| 127 | if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags)) | ||
| 128 | return; | ||
| 129 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags); | ||
| 130 | pnfs_return_layout(inode); | ||
| 131 | } | ||
| 132 | |||
| 125 | static int filelayout_async_handle_error(struct rpc_task *task, | 133 | static int filelayout_async_handle_error(struct rpc_task *task, |
| 126 | struct nfs4_state *state, | 134 | struct nfs4_state *state, |
| 127 | struct nfs_client *clp, | 135 | struct nfs_client *clp, |
| 128 | struct pnfs_layout_segment *lseg) | 136 | struct pnfs_layout_segment *lseg) |
| 129 | { | 137 | { |
| 130 | struct inode *inode = lseg->pls_layout->plh_inode; | 138 | struct pnfs_layout_hdr *lo = lseg->pls_layout; |
| 139 | struct inode *inode = lo->plh_inode; | ||
| 131 | struct nfs_server *mds_server = NFS_SERVER(inode); | 140 | struct nfs_server *mds_server = NFS_SERVER(inode); |
| 132 | struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); | 141 | struct nfs4_deviceid_node *devid = FILELAYOUT_DEVID_NODE(lseg); |
| 133 | struct nfs_client *mds_client = mds_server->nfs_client; | 142 | struct nfs_client *mds_client = mds_server->nfs_client; |
| @@ -204,10 +213,8 @@ static int filelayout_async_handle_error(struct rpc_task *task, | |||
| 204 | dprintk("%s DS connection error %d\n", __func__, | 213 | dprintk("%s DS connection error %d\n", __func__, |
| 205 | task->tk_status); | 214 | task->tk_status); |
| 206 | nfs4_mark_deviceid_unavailable(devid); | 215 | nfs4_mark_deviceid_unavailable(devid); |
| 207 | clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags); | 216 | set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags); |
| 208 | _pnfs_return_layout(inode); | ||
| 209 | rpc_wake_up(&tbl->slot_tbl_waitq); | 217 | rpc_wake_up(&tbl->slot_tbl_waitq); |
| 210 | nfs4_ds_disconnect(clp); | ||
| 211 | /* fall through */ | 218 | /* fall through */ |
| 212 | default: | 219 | default: |
| 213 | reset: | 220 | reset: |
| @@ -331,7 +338,9 @@ static void filelayout_read_count_stats(struct rpc_task *task, void *data) | |||
| 331 | static void filelayout_read_release(void *data) | 338 | static void filelayout_read_release(void *data) |
| 332 | { | 339 | { |
| 333 | struct nfs_read_data *rdata = data; | 340 | struct nfs_read_data *rdata = data; |
| 341 | struct pnfs_layout_hdr *lo = rdata->header->lseg->pls_layout; | ||
| 334 | 342 | ||
| 343 | filelayout_fenceme(lo->plh_inode, lo); | ||
| 335 | nfs_put_client(rdata->ds_clp); | 344 | nfs_put_client(rdata->ds_clp); |
| 336 | rdata->header->mds_ops->rpc_release(data); | 345 | rdata->header->mds_ops->rpc_release(data); |
| 337 | } | 346 | } |
| @@ -429,7 +438,9 @@ static void filelayout_write_count_stats(struct rpc_task *task, void *data) | |||
| 429 | static void filelayout_write_release(void *data) | 438 | static void filelayout_write_release(void *data) |
| 430 | { | 439 | { |
| 431 | struct nfs_write_data *wdata = data; | 440 | struct nfs_write_data *wdata = data; |
| 441 | struct pnfs_layout_hdr *lo = wdata->header->lseg->pls_layout; | ||
| 432 | 442 | ||
| 443 | filelayout_fenceme(lo->plh_inode, lo); | ||
| 433 | nfs_put_client(wdata->ds_clp); | 444 | nfs_put_client(wdata->ds_clp); |
| 434 | wdata->header->mds_ops->rpc_release(data); | 445 | wdata->header->mds_ops->rpc_release(data); |
| 435 | } | 446 | } |
| @@ -739,7 +750,7 @@ filelayout_decode_layout(struct pnfs_layout_hdr *flo, | |||
| 739 | goto out_err; | 750 | goto out_err; |
| 740 | 751 | ||
| 741 | if (fl->num_fh > 0) { | 752 | if (fl->num_fh > 0) { |
| 742 | fl->fh_array = kzalloc(fl->num_fh * sizeof(struct nfs_fh *), | 753 | fl->fh_array = kcalloc(fl->num_fh, sizeof(fl->fh_array[0]), |
| 743 | gfp_flags); | 754 | gfp_flags); |
| 744 | if (!fl->fh_array) | 755 | if (!fl->fh_array) |
| 745 | goto out_err; | 756 | goto out_err; |
diff --git a/fs/nfs/nfs4filelayout.h b/fs/nfs/nfs4filelayout.h index dca47d786710..8c07241fe52b 100644 --- a/fs/nfs/nfs4filelayout.h +++ b/fs/nfs/nfs4filelayout.h | |||
| @@ -149,6 +149,5 @@ extern void nfs4_fl_put_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | |||
| 149 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); | 149 | extern void nfs4_fl_free_deviceid(struct nfs4_file_layout_dsaddr *dsaddr); |
| 150 | struct nfs4_file_layout_dsaddr * | 150 | struct nfs4_file_layout_dsaddr * |
| 151 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); | 151 | filelayout_get_device_info(struct inode *inode, struct nfs4_deviceid *dev_id, gfp_t gfp_flags); |
| 152 | void nfs4_ds_disconnect(struct nfs_client *clp); | ||
| 153 | 152 | ||
| 154 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ | 153 | #endif /* FS_NFS_NFS4FILELAYOUT_H */ |
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c index 3336d5eaf879..a8eaa9b7bb0f 100644 --- a/fs/nfs/nfs4filelayoutdev.c +++ b/fs/nfs/nfs4filelayoutdev.c | |||
| @@ -149,28 +149,6 @@ _data_server_lookup_locked(const struct list_head *dsaddrs) | |||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | /* | 151 | /* |
| 152 | * Lookup DS by nfs_client pointer. Zero data server client pointer | ||
| 153 | */ | ||
| 154 | void nfs4_ds_disconnect(struct nfs_client *clp) | ||
| 155 | { | ||
| 156 | struct nfs4_pnfs_ds *ds; | ||
| 157 | struct nfs_client *found = NULL; | ||
| 158 | |||
| 159 | dprintk("%s clp %p\n", __func__, clp); | ||
| 160 | spin_lock(&nfs4_ds_cache_lock); | ||
| 161 | list_for_each_entry(ds, &nfs4_data_server_cache, ds_node) | ||
| 162 | if (ds->ds_clp && ds->ds_clp == clp) { | ||
| 163 | found = ds->ds_clp; | ||
| 164 | ds->ds_clp = NULL; | ||
| 165 | } | ||
| 166 | spin_unlock(&nfs4_ds_cache_lock); | ||
| 167 | if (found) { | ||
| 168 | set_bit(NFS_CS_STOP_RENEW, &clp->cl_res_state); | ||
| 169 | nfs_put_client(clp); | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | /* | ||
| 174 | * Create an rpc connection to the nfs4_pnfs_ds data server | 152 | * Create an rpc connection to the nfs4_pnfs_ds data server |
| 175 | * Currently only supports IPv4 and IPv6 addresses | 153 | * Currently only supports IPv4 and IPv6 addresses |
| 176 | */ | 154 | */ |
diff --git a/fs/nfs/nfs4getroot.c b/fs/nfs/nfs4getroot.c index 6a83780e0ce6..549462e5b9b0 100644 --- a/fs/nfs/nfs4getroot.c +++ b/fs/nfs/nfs4getroot.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <linux/nfs_fs.h> | 6 | #include <linux/nfs_fs.h> |
| 7 | #include "nfs4_fs.h" | 7 | #include "nfs4_fs.h" |
| 8 | #include "internal.h" | ||
| 8 | 9 | ||
| 9 | #define NFSDBG_FACILITY NFSDBG_CLIENT | 10 | #define NFSDBG_FACILITY NFSDBG_CLIENT |
| 10 | 11 | ||
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c index be731e6b7b9c..c6f990656f89 100644 --- a/fs/nfs/objlayout/objio_osd.c +++ b/fs/nfs/objlayout/objio_osd.c | |||
| @@ -369,7 +369,7 @@ void objio_free_result(struct objlayout_io_res *oir) | |||
| 369 | kfree(objios); | 369 | kfree(objios); |
| 370 | } | 370 | } |
| 371 | 371 | ||
| 372 | enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep) | 372 | static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep) |
| 373 | { | 373 | { |
| 374 | switch (oep) { | 374 | switch (oep) { |
| 375 | case OSD_ERR_PRI_NO_ERROR: | 375 | case OSD_ERR_PRI_NO_ERROR: |
| @@ -574,7 +574,7 @@ static bool objio_pg_test(struct nfs_pageio_descriptor *pgio, | |||
| 574 | (unsigned long)pgio->pg_layout_private; | 574 | (unsigned long)pgio->pg_layout_private; |
| 575 | } | 575 | } |
| 576 | 576 | ||
| 577 | void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | 577 | static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) |
| 578 | { | 578 | { |
| 579 | pnfs_generic_pg_init_read(pgio, req); | 579 | pnfs_generic_pg_init_read(pgio, req); |
| 580 | if (unlikely(pgio->pg_lseg == NULL)) | 580 | if (unlikely(pgio->pg_lseg == NULL)) |
| @@ -604,7 +604,7 @@ static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout, | |||
| 604 | return false; | 604 | return false; |
| 605 | } | 605 | } |
| 606 | 606 | ||
| 607 | void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) | 607 | static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req) |
| 608 | { | 608 | { |
| 609 | unsigned long stripe_end = 0; | 609 | unsigned long stripe_end = 0; |
| 610 | u64 wb_size; | 610 | u64 wb_size; |
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h index 2d722dba1111..dbf7bba52da0 100644 --- a/fs/nfs/pnfs.h +++ b/fs/nfs/pnfs.h | |||
| @@ -62,6 +62,7 @@ enum { | |||
| 62 | NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */ | 62 | NFS_LAYOUT_RW_FAILED, /* get rw layout failed stop trying */ |
| 63 | NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */ | 63 | NFS_LAYOUT_BULK_RECALL, /* bulk recall affecting layout */ |
| 64 | NFS_LAYOUT_ROC, /* some lseg had roc bit set */ | 64 | NFS_LAYOUT_ROC, /* some lseg had roc bit set */ |
| 65 | NFS_LAYOUT_RETURN, /* Return this layout ASAP */ | ||
| 65 | }; | 66 | }; |
| 66 | 67 | ||
| 67 | enum layoutdriver_policy_flags { | 68 | enum layoutdriver_policy_flags { |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index cceaab07ad54..43973b084abf 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
| @@ -12,6 +12,7 @@ | |||
| 12 | #include <linux/sched.h> | 12 | #include <linux/sched.h> |
| 13 | #include <linux/proc_fs.h> | 13 | #include <linux/proc_fs.h> |
| 14 | struct ctl_table_header; | 14 | struct ctl_table_header; |
| 15 | struct mempolicy; | ||
| 15 | 16 | ||
| 16 | extern struct proc_dir_entry proc_root; | 17 | extern struct proc_dir_entry proc_root; |
| 17 | #ifdef CONFIG_PROC_SYSCTL | 18 | #ifdef CONFIG_PROC_SYSCTL |
| @@ -74,6 +75,9 @@ struct proc_maps_private { | |||
| 74 | #ifdef CONFIG_MMU | 75 | #ifdef CONFIG_MMU |
| 75 | struct vm_area_struct *tail_vma; | 76 | struct vm_area_struct *tail_vma; |
| 76 | #endif | 77 | #endif |
| 78 | #ifdef CONFIG_NUMA | ||
| 79 | struct mempolicy *task_mempolicy; | ||
| 80 | #endif | ||
| 77 | }; | 81 | }; |
| 78 | 82 | ||
| 79 | void proc_init_inodecache(void); | 83 | void proc_init_inodecache(void); |
diff --git a/fs/proc/stat.c b/fs/proc/stat.c index 64c3b3172367..e296572c73ed 100644 --- a/fs/proc/stat.c +++ b/fs/proc/stat.c | |||
| @@ -45,10 +45,13 @@ static cputime64_t get_iowait_time(int cpu) | |||
| 45 | 45 | ||
| 46 | static u64 get_idle_time(int cpu) | 46 | static u64 get_idle_time(int cpu) |
| 47 | { | 47 | { |
| 48 | u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL); | 48 | u64 idle, idle_time = -1ULL; |
| 49 | |||
| 50 | if (cpu_online(cpu)) | ||
| 51 | idle_time = get_cpu_idle_time_us(cpu, NULL); | ||
| 49 | 52 | ||
| 50 | if (idle_time == -1ULL) | 53 | if (idle_time == -1ULL) |
| 51 | /* !NO_HZ so we can rely on cpustat.idle */ | 54 | /* !NO_HZ or cpu offline so we can rely on cpustat.idle */ |
| 52 | idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE]; | 55 | idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE]; |
| 53 | else | 56 | else |
| 54 | idle = usecs_to_cputime64(idle_time); | 57 | idle = usecs_to_cputime64(idle_time); |
| @@ -58,10 +61,13 @@ static u64 get_idle_time(int cpu) | |||
| 58 | 61 | ||
| 59 | static u64 get_iowait_time(int cpu) | 62 | static u64 get_iowait_time(int cpu) |
| 60 | { | 63 | { |
| 61 | u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL); | 64 | u64 iowait, iowait_time = -1ULL; |
| 65 | |||
| 66 | if (cpu_online(cpu)) | ||
| 67 | iowait_time = get_cpu_iowait_time_us(cpu, NULL); | ||
| 62 | 68 | ||
| 63 | if (iowait_time == -1ULL) | 69 | if (iowait_time == -1ULL) |
| 64 | /* !NO_HZ so we can rely on cpustat.iowait */ | 70 | /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */ |
| 65 | iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT]; | 71 | iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT]; |
| 66 | else | 72 | else |
| 67 | iowait = usecs_to_cputime64(iowait_time); | 73 | iowait = usecs_to_cputime64(iowait_time); |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 79827ce03e3b..90c63f9392a5 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -90,10 +90,55 @@ static void pad_len_spaces(struct seq_file *m, int len) | |||
| 90 | seq_printf(m, "%*c", len, ' '); | 90 | seq_printf(m, "%*c", len, ' '); |
| 91 | } | 91 | } |
| 92 | 92 | ||
| 93 | #ifdef CONFIG_NUMA | ||
| 94 | /* | ||
| 95 | * These functions are for numa_maps but called in generic **maps seq_file | ||
| 96 | * ->start(), ->stop() ops. | ||
| 97 | * | ||
| 98 | * numa_maps scans all vmas under mmap_sem and checks their mempolicy. | ||
| 99 | * Each mempolicy object is controlled by reference counting. The problem here | ||
| 100 | * is how to avoid accessing dead mempolicy object. | ||
| 101 | * | ||
| 102 | * Because we're holding mmap_sem while reading seq_file, it's safe to access | ||
| 103 | * each vma's mempolicy, no vma objects will never drop refs to mempolicy. | ||
| 104 | * | ||
| 105 | * A task's mempolicy (task->mempolicy) has different behavior. task->mempolicy | ||
| 106 | * is set and replaced under mmap_sem but unrefed and cleared under task_lock(). | ||
| 107 | * So, without task_lock(), we cannot trust get_vma_policy() because we cannot | ||
| 108 | * gurantee the task never exits under us. But taking task_lock() around | ||
| 109 | * get_vma_plicy() causes lock order problem. | ||
| 110 | * | ||
| 111 | * To access task->mempolicy without lock, we hold a reference count of an | ||
| 112 | * object pointed by task->mempolicy and remember it. This will guarantee | ||
| 113 | * that task->mempolicy points to an alive object or NULL in numa_maps accesses. | ||
| 114 | */ | ||
| 115 | static void hold_task_mempolicy(struct proc_maps_private *priv) | ||
| 116 | { | ||
| 117 | struct task_struct *task = priv->task; | ||
| 118 | |||
| 119 | task_lock(task); | ||
| 120 | priv->task_mempolicy = task->mempolicy; | ||
| 121 | mpol_get(priv->task_mempolicy); | ||
| 122 | task_unlock(task); | ||
| 123 | } | ||
| 124 | static void release_task_mempolicy(struct proc_maps_private *priv) | ||
| 125 | { | ||
| 126 | mpol_put(priv->task_mempolicy); | ||
| 127 | } | ||
| 128 | #else | ||
| 129 | static void hold_task_mempolicy(struct proc_maps_private *priv) | ||
| 130 | { | ||
| 131 | } | ||
| 132 | static void release_task_mempolicy(struct proc_maps_private *priv) | ||
| 133 | { | ||
| 134 | } | ||
| 135 | #endif | ||
| 136 | |||
| 93 | static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma) | 137 | static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma) |
| 94 | { | 138 | { |
| 95 | if (vma && vma != priv->tail_vma) { | 139 | if (vma && vma != priv->tail_vma) { |
| 96 | struct mm_struct *mm = vma->vm_mm; | 140 | struct mm_struct *mm = vma->vm_mm; |
| 141 | release_task_mempolicy(priv); | ||
| 97 | up_read(&mm->mmap_sem); | 142 | up_read(&mm->mmap_sem); |
| 98 | mmput(mm); | 143 | mmput(mm); |
| 99 | } | 144 | } |
| @@ -132,7 +177,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) | |||
| 132 | 177 | ||
| 133 | tail_vma = get_gate_vma(priv->task->mm); | 178 | tail_vma = get_gate_vma(priv->task->mm); |
| 134 | priv->tail_vma = tail_vma; | 179 | priv->tail_vma = tail_vma; |
| 135 | 180 | hold_task_mempolicy(priv); | |
| 136 | /* Start with last addr hint */ | 181 | /* Start with last addr hint */ |
| 137 | vma = find_vma(mm, last_addr); | 182 | vma = find_vma(mm, last_addr); |
| 138 | if (last_addr && vma) { | 183 | if (last_addr && vma) { |
| @@ -159,6 +204,7 @@ out: | |||
| 159 | if (vma) | 204 | if (vma) |
| 160 | return vma; | 205 | return vma; |
| 161 | 206 | ||
| 207 | release_task_mempolicy(priv); | ||
| 162 | /* End of vmas has been reached */ | 208 | /* End of vmas has been reached */ |
| 163 | m->version = (tail_vma != NULL)? 0: -1UL; | 209 | m->version = (tail_vma != NULL)? 0: -1UL; |
| 164 | up_read(&mm->mmap_sem); | 210 | up_read(&mm->mmap_sem); |
| @@ -1158,6 +1204,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) | |||
| 1158 | struct vm_area_struct *vma = v; | 1204 | struct vm_area_struct *vma = v; |
| 1159 | struct numa_maps *md = &numa_priv->md; | 1205 | struct numa_maps *md = &numa_priv->md; |
| 1160 | struct file *file = vma->vm_file; | 1206 | struct file *file = vma->vm_file; |
| 1207 | struct task_struct *task = proc_priv->task; | ||
| 1161 | struct mm_struct *mm = vma->vm_mm; | 1208 | struct mm_struct *mm = vma->vm_mm; |
| 1162 | struct mm_walk walk = {}; | 1209 | struct mm_walk walk = {}; |
| 1163 | struct mempolicy *pol; | 1210 | struct mempolicy *pol; |
| @@ -1177,7 +1224,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) | |||
| 1177 | walk.private = md; | 1224 | walk.private = md; |
| 1178 | walk.mm = mm; | 1225 | walk.mm = mm; |
| 1179 | 1226 | ||
| 1180 | pol = get_vma_policy(proc_priv->task, vma, vma->vm_start); | 1227 | pol = get_vma_policy(task, vma, vma->vm_start); |
| 1181 | mpol_to_str(buffer, sizeof(buffer), pol, 0); | 1228 | mpol_to_str(buffer, sizeof(buffer), pol, 0); |
| 1182 | mpol_cond_put(pol); | 1229 | mpol_cond_put(pol); |
| 1183 | 1230 | ||
| @@ -1189,7 +1236,7 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) | |||
| 1189 | } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { | 1236 | } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { |
| 1190 | seq_printf(m, " heap"); | 1237 | seq_printf(m, " heap"); |
| 1191 | } else { | 1238 | } else { |
| 1192 | pid_t tid = vm_is_stack(proc_priv->task, vma, is_pid); | 1239 | pid_t tid = vm_is_stack(task, vma, is_pid); |
| 1193 | if (tid != 0) { | 1240 | if (tid != 0) { |
| 1194 | /* | 1241 | /* |
| 1195 | * Thread stack in /proc/PID/task/TID/maps or | 1242 | * Thread stack in /proc/PID/task/TID/maps or |
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 557a9c20a215..05ae3c97f7a5 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c | |||
| @@ -1160,6 +1160,8 @@ static int need_print_warning(struct dquot_warn *warn) | |||
| 1160 | return uid_eq(current_fsuid(), warn->w_dq_id.uid); | 1160 | return uid_eq(current_fsuid(), warn->w_dq_id.uid); |
| 1161 | case GRPQUOTA: | 1161 | case GRPQUOTA: |
| 1162 | return in_group_p(warn->w_dq_id.gid); | 1162 | return in_group_p(warn->w_dq_id.gid); |
| 1163 | case PRJQUOTA: /* Never taken... Just make gcc happy */ | ||
| 1164 | return 0; | ||
| 1163 | } | 1165 | } |
| 1164 | return 0; | 1166 | return 0; |
| 1165 | } | 1167 | } |
diff --git a/fs/sysfs/dir.c b/fs/sysfs/dir.c index 6b0bb00d4d2b..2fbdff6be25c 100644 --- a/fs/sysfs/dir.c +++ b/fs/sysfs/dir.c | |||
| @@ -485,20 +485,18 @@ int __sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
| 485 | /** | 485 | /** |
| 486 | * sysfs_pathname - return full path to sysfs dirent | 486 | * sysfs_pathname - return full path to sysfs dirent |
| 487 | * @sd: sysfs_dirent whose path we want | 487 | * @sd: sysfs_dirent whose path we want |
| 488 | * @path: caller allocated buffer | 488 | * @path: caller allocated buffer of size PATH_MAX |
| 489 | * | 489 | * |
| 490 | * Gives the name "/" to the sysfs_root entry; any path returned | 490 | * Gives the name "/" to the sysfs_root entry; any path returned |
| 491 | * is relative to wherever sysfs is mounted. | 491 | * is relative to wherever sysfs is mounted. |
| 492 | * | ||
| 493 | * XXX: does no error checking on @path size | ||
| 494 | */ | 492 | */ |
| 495 | static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) | 493 | static char *sysfs_pathname(struct sysfs_dirent *sd, char *path) |
| 496 | { | 494 | { |
| 497 | if (sd->s_parent) { | 495 | if (sd->s_parent) { |
| 498 | sysfs_pathname(sd->s_parent, path); | 496 | sysfs_pathname(sd->s_parent, path); |
| 499 | strcat(path, "/"); | 497 | strlcat(path, "/", PATH_MAX); |
| 500 | } | 498 | } |
| 501 | strcat(path, sd->s_name); | 499 | strlcat(path, sd->s_name, PATH_MAX); |
| 502 | return path; | 500 | return path; |
| 503 | } | 501 | } |
| 504 | 502 | ||
| @@ -531,9 +529,11 @@ int sysfs_add_one(struct sysfs_addrm_cxt *acxt, struct sysfs_dirent *sd) | |||
| 531 | char *path = kzalloc(PATH_MAX, GFP_KERNEL); | 529 | char *path = kzalloc(PATH_MAX, GFP_KERNEL); |
| 532 | WARN(1, KERN_WARNING | 530 | WARN(1, KERN_WARNING |
| 533 | "sysfs: cannot create duplicate filename '%s'\n", | 531 | "sysfs: cannot create duplicate filename '%s'\n", |
| 534 | (path == NULL) ? sd->s_name : | 532 | (path == NULL) ? sd->s_name |
| 535 | strcat(strcat(sysfs_pathname(acxt->parent_sd, path), "/"), | 533 | : (sysfs_pathname(acxt->parent_sd, path), |
| 536 | sd->s_name)); | 534 | strlcat(path, "/", PATH_MAX), |
| 535 | strlcat(path, sd->s_name, PATH_MAX), | ||
| 536 | path)); | ||
| 537 | kfree(path); | 537 | kfree(path); |
| 538 | } | 538 | } |
| 539 | 539 | ||
diff --git a/fs/xattr.c b/fs/xattr.c index e164dddb8e96..e21c119f4f99 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
| @@ -846,7 +846,7 @@ static int __simple_xattr_set(struct simple_xattrs *xattrs, const char *name, | |||
| 846 | const void *value, size_t size, int flags) | 846 | const void *value, size_t size, int flags) |
| 847 | { | 847 | { |
| 848 | struct simple_xattr *xattr; | 848 | struct simple_xattr *xattr; |
| 849 | struct simple_xattr *uninitialized_var(new_xattr); | 849 | struct simple_xattr *new_xattr = NULL; |
| 850 | int err = 0; | 850 | int err = 0; |
| 851 | 851 | ||
| 852 | /* value == NULL means remove */ | 852 | /* value == NULL means remove */ |
