diff options
| author | Dave Airlie <airlied@redhat.com> | 2010-12-21 18:48:54 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2010-12-21 18:48:54 -0500 |
| commit | ae09f09e94d755ed45c58b695675636c0ec53f9e (patch) | |
| tree | 77cb9bac7d81f5b1250b8638a007e10c17b600af /fs | |
| parent | 1d99e5c57255d188773fb437391df24fe8faf575 (diff) | |
| parent | 5909a77ac62cc042f94bd262016cf468a2f96022 (diff) | |
Merge remote branch 'intel/drm-intel-next' of /ssd/git/drm-next into drm-core-next
* 'intel/drm-intel-next' of /ssd/git/drm-next: (771 commits)
drm/i915: Undo "Uncouple render/power ctx before suspending"
drm/i915: Allow the application to choose the constant addressing mode
drm/i915: dynamic render p-state support for Sandy Bridge
drm/i915: Enable EI mode for RCx decision making on Sandybridge
drm/i915/sdvo: Border and stall select became test bits in gen5
drm/i915: Add Guess-o-matic for pageflip timestamping.
drm/i915: Add support for precise vblank timestamping (v2)
drm/i915: Add frame buffer compression on Sandybridge
drm/i915: Add self-refresh support on Sandybridge
drm/i915: Wait for vblank before unpinning old fb
Revert "drm/i915: Avoid using PIPE_CONTROL on Ironlake"
drm/i915: Pass clock limits down to PLL matcher
drm/i915: Poll for seqno completion if IRQ is disabled
drm/i915/ringbuffer: Make IRQ refcnting atomic
agp/intel: Fix missed cached memory flags setting in i965_write_entry()
drm/i915/sdvo: Only use the SDVO pin if it is in the valid range
drm/i915: Enable RC6 autodownclocking on Sandybridge
drm/i915: Terminate the FORCE WAKE after we have finished reading
drm/i915/gtt: Clear the cachelines upon resume
drm/i915: Restore GTT mapping first upon resume
...
Diffstat (limited to 'fs')
59 files changed, 1062 insertions, 414 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index d5c1401f0031..d34896cfb19f 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
| @@ -980,19 +980,11 @@ static int autofs4_root_ioctl_unlocked(struct inode *inode, struct file *filp, | |||
| 980 | } | 980 | } |
| 981 | } | 981 | } |
| 982 | 982 | ||
| 983 | static DEFINE_MUTEX(autofs4_ioctl_mutex); | ||
| 984 | |||
| 985 | static long autofs4_root_ioctl(struct file *filp, | 983 | static long autofs4_root_ioctl(struct file *filp, |
| 986 | unsigned int cmd, unsigned long arg) | 984 | unsigned int cmd, unsigned long arg) |
| 987 | { | 985 | { |
| 988 | long ret; | ||
| 989 | struct inode *inode = filp->f_dentry->d_inode; | 986 | struct inode *inode = filp->f_dentry->d_inode; |
| 990 | 987 | return autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | |
| 991 | mutex_lock(&autofs4_ioctl_mutex); | ||
| 992 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | ||
| 993 | mutex_unlock(&autofs4_ioctl_mutex); | ||
| 994 | |||
| 995 | return ret; | ||
| 996 | } | 988 | } |
| 997 | 989 | ||
| 998 | #ifdef CONFIG_COMPAT | 990 | #ifdef CONFIG_COMPAT |
| @@ -1002,13 +994,11 @@ static long autofs4_root_compat_ioctl(struct file *filp, | |||
| 1002 | struct inode *inode = filp->f_path.dentry->d_inode; | 994 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 1003 | int ret; | 995 | int ret; |
| 1004 | 996 | ||
| 1005 | mutex_lock(&autofs4_ioctl_mutex); | ||
| 1006 | if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) | 997 | if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL) |
| 1007 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); | 998 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, arg); |
| 1008 | else | 999 | else |
| 1009 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, | 1000 | ret = autofs4_root_ioctl_unlocked(inode, filp, cmd, |
| 1010 | (unsigned long)compat_ptr(arg)); | 1001 | (unsigned long)compat_ptr(arg)); |
| 1011 | mutex_unlock(&autofs4_ioctl_mutex); | ||
| 1012 | 1002 | ||
| 1013 | return ret; | 1003 | return ret; |
| 1014 | } | 1004 | } |
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 7845d1f7d1d9..b50bc4bd5c56 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
| @@ -91,23 +91,10 @@ static inline int compressed_bio_size(struct btrfs_root *root, | |||
| 91 | static struct bio *compressed_bio_alloc(struct block_device *bdev, | 91 | static struct bio *compressed_bio_alloc(struct block_device *bdev, |
| 92 | u64 first_byte, gfp_t gfp_flags) | 92 | u64 first_byte, gfp_t gfp_flags) |
| 93 | { | 93 | { |
| 94 | struct bio *bio; | ||
| 95 | int nr_vecs; | 94 | int nr_vecs; |
| 96 | 95 | ||
| 97 | nr_vecs = bio_get_nr_vecs(bdev); | 96 | nr_vecs = bio_get_nr_vecs(bdev); |
| 98 | bio = bio_alloc(gfp_flags, nr_vecs); | 97 | return btrfs_bio_alloc(bdev, first_byte >> 9, nr_vecs, gfp_flags); |
| 99 | |||
| 100 | if (bio == NULL && (current->flags & PF_MEMALLOC)) { | ||
| 101 | while (!bio && (nr_vecs /= 2)) | ||
| 102 | bio = bio_alloc(gfp_flags, nr_vecs); | ||
| 103 | } | ||
| 104 | |||
| 105 | if (bio) { | ||
| 106 | bio->bi_size = 0; | ||
| 107 | bio->bi_bdev = bdev; | ||
| 108 | bio->bi_sector = first_byte >> 9; | ||
| 109 | } | ||
| 110 | return bio; | ||
| 111 | } | 98 | } |
| 112 | 99 | ||
| 113 | static int check_compressed_csum(struct inode *inode, | 100 | static int check_compressed_csum(struct inode *inode, |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 8db9234f6b41..af52f6d7a4d8 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -808,9 +808,9 @@ struct btrfs_block_group_cache { | |||
| 808 | int extents_thresh; | 808 | int extents_thresh; |
| 809 | int free_extents; | 809 | int free_extents; |
| 810 | int total_bitmaps; | 810 | int total_bitmaps; |
| 811 | int ro:1; | 811 | unsigned int ro:1; |
| 812 | int dirty:1; | 812 | unsigned int dirty:1; |
| 813 | int iref:1; | 813 | unsigned int iref:1; |
| 814 | 814 | ||
| 815 | int disk_cache_state; | 815 | int disk_cache_state; |
| 816 | 816 | ||
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index fb827d0d7181..c547cca26a26 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/freezer.h> | 28 | #include <linux/freezer.h> |
| 29 | #include <linux/crc32c.h> | 29 | #include <linux/crc32c.h> |
| 30 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| 31 | #include <linux/migrate.h> | ||
| 31 | #include "compat.h" | 32 | #include "compat.h" |
| 32 | #include "ctree.h" | 33 | #include "ctree.h" |
| 33 | #include "disk-io.h" | 34 | #include "disk-io.h" |
| @@ -355,6 +356,8 @@ static int csum_dirty_buffer(struct btrfs_root *root, struct page *page) | |||
| 355 | ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE, | 356 | ret = btree_read_extent_buffer_pages(root, eb, start + PAGE_CACHE_SIZE, |
| 356 | btrfs_header_generation(eb)); | 357 | btrfs_header_generation(eb)); |
| 357 | BUG_ON(ret); | 358 | BUG_ON(ret); |
| 359 | WARN_ON(!btrfs_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN)); | ||
| 360 | |||
| 358 | found_start = btrfs_header_bytenr(eb); | 361 | found_start = btrfs_header_bytenr(eb); |
| 359 | if (found_start != start) { | 362 | if (found_start != start) { |
| 360 | WARN_ON(1); | 363 | WARN_ON(1); |
| @@ -693,6 +696,29 @@ static int btree_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
| 693 | __btree_submit_bio_done); | 696 | __btree_submit_bio_done); |
| 694 | } | 697 | } |
| 695 | 698 | ||
| 699 | static int btree_migratepage(struct address_space *mapping, | ||
| 700 | struct page *newpage, struct page *page) | ||
| 701 | { | ||
| 702 | /* | ||
| 703 | * we can't safely write a btree page from here, | ||
| 704 | * we haven't done the locking hook | ||
| 705 | */ | ||
| 706 | if (PageDirty(page)) | ||
| 707 | return -EAGAIN; | ||
| 708 | /* | ||
| 709 | * Buffers may be managed in a filesystem specific way. | ||
| 710 | * We must have no buffers or drop them. | ||
| 711 | */ | ||
| 712 | if (page_has_private(page) && | ||
| 713 | !try_to_release_page(page, GFP_KERNEL)) | ||
| 714 | return -EAGAIN; | ||
| 715 | #ifdef CONFIG_MIGRATION | ||
| 716 | return migrate_page(mapping, newpage, page); | ||
| 717 | #else | ||
| 718 | return -ENOSYS; | ||
| 719 | #endif | ||
| 720 | } | ||
| 721 | |||
| 696 | static int btree_writepage(struct page *page, struct writeback_control *wbc) | 722 | static int btree_writepage(struct page *page, struct writeback_control *wbc) |
| 697 | { | 723 | { |
| 698 | struct extent_io_tree *tree; | 724 | struct extent_io_tree *tree; |
| @@ -707,8 +733,7 @@ static int btree_writepage(struct page *page, struct writeback_control *wbc) | |||
| 707 | } | 733 | } |
| 708 | 734 | ||
| 709 | redirty_page_for_writepage(wbc, page); | 735 | redirty_page_for_writepage(wbc, page); |
| 710 | eb = btrfs_find_tree_block(root, page_offset(page), | 736 | eb = btrfs_find_tree_block(root, page_offset(page), PAGE_CACHE_SIZE); |
| 711 | PAGE_CACHE_SIZE); | ||
| 712 | WARN_ON(!eb); | 737 | WARN_ON(!eb); |
| 713 | 738 | ||
| 714 | was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags); | 739 | was_dirty = test_and_set_bit(EXTENT_BUFFER_DIRTY, &eb->bflags); |
| @@ -799,6 +824,9 @@ static const struct address_space_operations btree_aops = { | |||
| 799 | .releasepage = btree_releasepage, | 824 | .releasepage = btree_releasepage, |
| 800 | .invalidatepage = btree_invalidatepage, | 825 | .invalidatepage = btree_invalidatepage, |
| 801 | .sync_page = block_sync_page, | 826 | .sync_page = block_sync_page, |
| 827 | #ifdef CONFIG_MIGRATION | ||
| 828 | .migratepage = btree_migratepage, | ||
| 829 | #endif | ||
| 802 | }; | 830 | }; |
| 803 | 831 | ||
| 804 | int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, | 832 | int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, |
| @@ -1538,10 +1566,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1538 | GFP_NOFS); | 1566 | GFP_NOFS); |
| 1539 | struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root), | 1567 | struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root), |
| 1540 | GFP_NOFS); | 1568 | GFP_NOFS); |
| 1541 | struct btrfs_root *tree_root = kzalloc(sizeof(struct btrfs_root), | 1569 | struct btrfs_root *tree_root = btrfs_sb(sb); |
| 1542 | GFP_NOFS); | 1570 | struct btrfs_fs_info *fs_info = tree_root->fs_info; |
| 1543 | struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info), | ||
| 1544 | GFP_NOFS); | ||
| 1545 | struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root), | 1571 | struct btrfs_root *chunk_root = kzalloc(sizeof(struct btrfs_root), |
| 1546 | GFP_NOFS); | 1572 | GFP_NOFS); |
| 1547 | struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root), | 1573 | struct btrfs_root *dev_root = kzalloc(sizeof(struct btrfs_root), |
diff --git a/fs/btrfs/export.c b/fs/btrfs/export.c index 951ef09b82f4..6f0444473594 100644 --- a/fs/btrfs/export.c +++ b/fs/btrfs/export.c | |||
| @@ -232,9 +232,85 @@ fail: | |||
| 232 | return ERR_PTR(ret); | 232 | return ERR_PTR(ret); |
| 233 | } | 233 | } |
| 234 | 234 | ||
| 235 | static int btrfs_get_name(struct dentry *parent, char *name, | ||
| 236 | struct dentry *child) | ||
| 237 | { | ||
| 238 | struct inode *inode = child->d_inode; | ||
| 239 | struct inode *dir = parent->d_inode; | ||
| 240 | struct btrfs_path *path; | ||
| 241 | struct btrfs_root *root = BTRFS_I(dir)->root; | ||
| 242 | struct btrfs_inode_ref *iref; | ||
| 243 | struct btrfs_root_ref *rref; | ||
| 244 | struct extent_buffer *leaf; | ||
| 245 | unsigned long name_ptr; | ||
| 246 | struct btrfs_key key; | ||
| 247 | int name_len; | ||
| 248 | int ret; | ||
| 249 | |||
| 250 | if (!dir || !inode) | ||
| 251 | return -EINVAL; | ||
| 252 | |||
| 253 | if (!S_ISDIR(dir->i_mode)) | ||
| 254 | return -EINVAL; | ||
| 255 | |||
| 256 | path = btrfs_alloc_path(); | ||
| 257 | if (!path) | ||
| 258 | return -ENOMEM; | ||
| 259 | path->leave_spinning = 1; | ||
| 260 | |||
| 261 | if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) { | ||
| 262 | key.objectid = BTRFS_I(inode)->root->root_key.objectid; | ||
| 263 | key.type = BTRFS_ROOT_BACKREF_KEY; | ||
| 264 | key.offset = (u64)-1; | ||
| 265 | root = root->fs_info->tree_root; | ||
| 266 | } else { | ||
| 267 | key.objectid = inode->i_ino; | ||
| 268 | key.offset = dir->i_ino; | ||
| 269 | key.type = BTRFS_INODE_REF_KEY; | ||
| 270 | } | ||
| 271 | |||
| 272 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | ||
| 273 | if (ret < 0) { | ||
| 274 | btrfs_free_path(path); | ||
| 275 | return ret; | ||
| 276 | } else if (ret > 0) { | ||
| 277 | if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) { | ||
| 278 | path->slots[0]--; | ||
| 279 | } else { | ||
| 280 | btrfs_free_path(path); | ||
| 281 | return -ENOENT; | ||
| 282 | } | ||
| 283 | } | ||
| 284 | leaf = path->nodes[0]; | ||
| 285 | |||
| 286 | if (inode->i_ino == BTRFS_FIRST_FREE_OBJECTID) { | ||
| 287 | rref = btrfs_item_ptr(leaf, path->slots[0], | ||
| 288 | struct btrfs_root_ref); | ||
| 289 | name_ptr = (unsigned long)(rref + 1); | ||
| 290 | name_len = btrfs_root_ref_name_len(leaf, rref); | ||
| 291 | } else { | ||
| 292 | iref = btrfs_item_ptr(leaf, path->slots[0], | ||
| 293 | struct btrfs_inode_ref); | ||
| 294 | name_ptr = (unsigned long)(iref + 1); | ||
| 295 | name_len = btrfs_inode_ref_name_len(leaf, iref); | ||
| 296 | } | ||
| 297 | |||
| 298 | read_extent_buffer(leaf, name, name_ptr, name_len); | ||
| 299 | btrfs_free_path(path); | ||
| 300 | |||
| 301 | /* | ||
| 302 | * have to add the null termination to make sure that reconnect_path | ||
| 303 | * gets the right len for strlen | ||
| 304 | */ | ||
| 305 | name[name_len] = '\0'; | ||
| 306 | |||
| 307 | return 0; | ||
| 308 | } | ||
| 309 | |||
| 235 | const struct export_operations btrfs_export_ops = { | 310 | const struct export_operations btrfs_export_ops = { |
| 236 | .encode_fh = btrfs_encode_fh, | 311 | .encode_fh = btrfs_encode_fh, |
| 237 | .fh_to_dentry = btrfs_fh_to_dentry, | 312 | .fh_to_dentry = btrfs_fh_to_dentry, |
| 238 | .fh_to_parent = btrfs_fh_to_parent, | 313 | .fh_to_parent = btrfs_fh_to_parent, |
| 239 | .get_parent = btrfs_get_parent, | 314 | .get_parent = btrfs_get_parent, |
| 315 | .get_name = btrfs_get_name, | ||
| 240 | }; | 316 | }; |
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0c097f3aec41..bcd59c7dfb57 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
| @@ -3412,7 +3412,7 @@ again: | |||
| 3412 | * our reservation. | 3412 | * our reservation. |
| 3413 | */ | 3413 | */ |
| 3414 | if (unused <= space_info->total_bytes) { | 3414 | if (unused <= space_info->total_bytes) { |
| 3415 | unused -= space_info->total_bytes; | 3415 | unused = space_info->total_bytes - unused; |
| 3416 | if (unused >= num_bytes) { | 3416 | if (unused >= num_bytes) { |
| 3417 | if (!reserved) | 3417 | if (!reserved) |
| 3418 | space_info->bytes_reserved += orig_bytes; | 3418 | space_info->bytes_reserved += orig_bytes; |
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index eac10e3260a9..3e86b9f36507 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -1828,9 +1828,9 @@ static void end_bio_extent_preparewrite(struct bio *bio, int err) | |||
| 1828 | bio_put(bio); | 1828 | bio_put(bio); |
| 1829 | } | 1829 | } |
| 1830 | 1830 | ||
| 1831 | static struct bio * | 1831 | struct bio * |
| 1832 | extent_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs, | 1832 | btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs, |
| 1833 | gfp_t gfp_flags) | 1833 | gfp_t gfp_flags) |
| 1834 | { | 1834 | { |
| 1835 | struct bio *bio; | 1835 | struct bio *bio; |
| 1836 | 1836 | ||
| @@ -1919,7 +1919,7 @@ static int submit_extent_page(int rw, struct extent_io_tree *tree, | |||
| 1919 | else | 1919 | else |
| 1920 | nr = bio_get_nr_vecs(bdev); | 1920 | nr = bio_get_nr_vecs(bdev); |
| 1921 | 1921 | ||
| 1922 | bio = extent_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH); | 1922 | bio = btrfs_bio_alloc(bdev, sector, nr, GFP_NOFS | __GFP_HIGH); |
| 1923 | 1923 | ||
| 1924 | bio_add_page(bio, page, page_size, offset); | 1924 | bio_add_page(bio, page, page_size, offset); |
| 1925 | bio->bi_end_io = end_io_func; | 1925 | bio->bi_end_io = end_io_func; |
| @@ -2901,21 +2901,53 @@ out: | |||
| 2901 | int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | 2901 | int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, |
| 2902 | __u64 start, __u64 len, get_extent_t *get_extent) | 2902 | __u64 start, __u64 len, get_extent_t *get_extent) |
| 2903 | { | 2903 | { |
| 2904 | int ret; | 2904 | int ret = 0; |
| 2905 | u64 off = start; | 2905 | u64 off = start; |
| 2906 | u64 max = start + len; | 2906 | u64 max = start + len; |
| 2907 | u32 flags = 0; | 2907 | u32 flags = 0; |
| 2908 | u32 found_type; | ||
| 2909 | u64 last; | ||
| 2908 | u64 disko = 0; | 2910 | u64 disko = 0; |
| 2911 | struct btrfs_key found_key; | ||
| 2909 | struct extent_map *em = NULL; | 2912 | struct extent_map *em = NULL; |
| 2910 | struct extent_state *cached_state = NULL; | 2913 | struct extent_state *cached_state = NULL; |
| 2914 | struct btrfs_path *path; | ||
| 2915 | struct btrfs_file_extent_item *item; | ||
| 2911 | int end = 0; | 2916 | int end = 0; |
| 2912 | u64 em_start = 0, em_len = 0; | 2917 | u64 em_start = 0, em_len = 0; |
| 2913 | unsigned long emflags; | 2918 | unsigned long emflags; |
| 2914 | ret = 0; | 2919 | int hole = 0; |
| 2915 | 2920 | ||
| 2916 | if (len == 0) | 2921 | if (len == 0) |
| 2917 | return -EINVAL; | 2922 | return -EINVAL; |
| 2918 | 2923 | ||
| 2924 | path = btrfs_alloc_path(); | ||
| 2925 | if (!path) | ||
| 2926 | return -ENOMEM; | ||
| 2927 | path->leave_spinning = 1; | ||
| 2928 | |||
| 2929 | ret = btrfs_lookup_file_extent(NULL, BTRFS_I(inode)->root, | ||
| 2930 | path, inode->i_ino, -1, 0); | ||
| 2931 | if (ret < 0) { | ||
| 2932 | btrfs_free_path(path); | ||
| 2933 | return ret; | ||
| 2934 | } | ||
| 2935 | WARN_ON(!ret); | ||
| 2936 | path->slots[0]--; | ||
| 2937 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
| 2938 | struct btrfs_file_extent_item); | ||
| 2939 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]); | ||
| 2940 | found_type = btrfs_key_type(&found_key); | ||
| 2941 | |||
| 2942 | /* No extents, just return */ | ||
| 2943 | if (found_key.objectid != inode->i_ino || | ||
| 2944 | found_type != BTRFS_EXTENT_DATA_KEY) { | ||
| 2945 | btrfs_free_path(path); | ||
| 2946 | return 0; | ||
| 2947 | } | ||
| 2948 | last = found_key.offset; | ||
| 2949 | btrfs_free_path(path); | ||
| 2950 | |||
| 2919 | lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0, | 2951 | lock_extent_bits(&BTRFS_I(inode)->io_tree, start, start + len, 0, |
| 2920 | &cached_state, GFP_NOFS); | 2952 | &cached_state, GFP_NOFS); |
| 2921 | em = get_extent(inode, NULL, 0, off, max - off, 0); | 2953 | em = get_extent(inode, NULL, 0, off, max - off, 0); |
| @@ -2925,11 +2957,18 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 2925 | ret = PTR_ERR(em); | 2957 | ret = PTR_ERR(em); |
| 2926 | goto out; | 2958 | goto out; |
| 2927 | } | 2959 | } |
| 2960 | |||
| 2928 | while (!end) { | 2961 | while (!end) { |
| 2962 | hole = 0; | ||
| 2929 | off = em->start + em->len; | 2963 | off = em->start + em->len; |
| 2930 | if (off >= max) | 2964 | if (off >= max) |
| 2931 | end = 1; | 2965 | end = 1; |
| 2932 | 2966 | ||
| 2967 | if (em->block_start == EXTENT_MAP_HOLE) { | ||
| 2968 | hole = 1; | ||
| 2969 | goto next; | ||
| 2970 | } | ||
| 2971 | |||
| 2933 | em_start = em->start; | 2972 | em_start = em->start; |
| 2934 | em_len = em->len; | 2973 | em_len = em->len; |
| 2935 | 2974 | ||
| @@ -2939,8 +2978,6 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 2939 | if (em->block_start == EXTENT_MAP_LAST_BYTE) { | 2978 | if (em->block_start == EXTENT_MAP_LAST_BYTE) { |
| 2940 | end = 1; | 2979 | end = 1; |
| 2941 | flags |= FIEMAP_EXTENT_LAST; | 2980 | flags |= FIEMAP_EXTENT_LAST; |
| 2942 | } else if (em->block_start == EXTENT_MAP_HOLE) { | ||
| 2943 | flags |= FIEMAP_EXTENT_UNWRITTEN; | ||
| 2944 | } else if (em->block_start == EXTENT_MAP_INLINE) { | 2981 | } else if (em->block_start == EXTENT_MAP_INLINE) { |
| 2945 | flags |= (FIEMAP_EXTENT_DATA_INLINE | | 2982 | flags |= (FIEMAP_EXTENT_DATA_INLINE | |
| 2946 | FIEMAP_EXTENT_NOT_ALIGNED); | 2983 | FIEMAP_EXTENT_NOT_ALIGNED); |
| @@ -2953,10 +2990,10 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 2953 | if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) | 2990 | if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) |
| 2954 | flags |= FIEMAP_EXTENT_ENCODED; | 2991 | flags |= FIEMAP_EXTENT_ENCODED; |
| 2955 | 2992 | ||
| 2993 | next: | ||
| 2956 | emflags = em->flags; | 2994 | emflags = em->flags; |
| 2957 | free_extent_map(em); | 2995 | free_extent_map(em); |
| 2958 | em = NULL; | 2996 | em = NULL; |
| 2959 | |||
| 2960 | if (!end) { | 2997 | if (!end) { |
| 2961 | em = get_extent(inode, NULL, 0, off, max - off, 0); | 2998 | em = get_extent(inode, NULL, 0, off, max - off, 0); |
| 2962 | if (!em) | 2999 | if (!em) |
| @@ -2967,15 +3004,23 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
| 2967 | } | 3004 | } |
| 2968 | emflags = em->flags; | 3005 | emflags = em->flags; |
| 2969 | } | 3006 | } |
| 3007 | |||
| 2970 | if (test_bit(EXTENT_FLAG_VACANCY, &emflags)) { | 3008 | if (test_bit(EXTENT_FLAG_VACANCY, &emflags)) { |
| 2971 | flags |= FIEMAP_EXTENT_LAST; | 3009 | flags |= FIEMAP_EXTENT_LAST; |
| 2972 | end = 1; | 3010 | end = 1; |
| 2973 | } | 3011 | } |
| 2974 | 3012 | ||
| 2975 | ret = fiemap_fill_next_extent(fieinfo, em_start, disko, | 3013 | if (em_start == last) { |
| 2976 | em_len, flags); | 3014 | flags |= FIEMAP_EXTENT_LAST; |
| 2977 | if (ret) | 3015 | end = 1; |
| 2978 | goto out_free; | 3016 | } |
| 3017 | |||
| 3018 | if (!hole) { | ||
| 3019 | ret = fiemap_fill_next_extent(fieinfo, em_start, disko, | ||
| 3020 | em_len, flags); | ||
| 3021 | if (ret) | ||
| 3022 | goto out_free; | ||
| 3023 | } | ||
| 2979 | } | 3024 | } |
| 2980 | out_free: | 3025 | out_free: |
| 2981 | free_extent_map(em); | 3026 | free_extent_map(em); |
| @@ -3836,8 +3881,10 @@ int try_release_extent_buffer(struct extent_io_tree *tree, struct page *page) | |||
| 3836 | 3881 | ||
| 3837 | spin_lock(&tree->buffer_lock); | 3882 | spin_lock(&tree->buffer_lock); |
| 3838 | eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT); | 3883 | eb = radix_tree_lookup(&tree->buffer, start >> PAGE_CACHE_SHIFT); |
| 3839 | if (!eb) | 3884 | if (!eb) { |
| 3840 | goto out; | 3885 | spin_unlock(&tree->buffer_lock); |
| 3886 | return ret; | ||
| 3887 | } | ||
| 3841 | 3888 | ||
| 3842 | if (test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) { | 3889 | if (test_bit(EXTENT_BUFFER_DIRTY, &eb->bflags)) { |
| 3843 | ret = 0; | 3890 | ret = 0; |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index 1c6d4f342ef7..4183c8178f01 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
| @@ -310,4 +310,7 @@ int extent_clear_unlock_delalloc(struct inode *inode, | |||
| 310 | struct extent_io_tree *tree, | 310 | struct extent_io_tree *tree, |
| 311 | u64 start, u64 end, struct page *locked_page, | 311 | u64 start, u64 end, struct page *locked_page, |
| 312 | unsigned long op); | 312 | unsigned long op); |
| 313 | struct bio * | ||
| 314 | btrfs_bio_alloc(struct block_device *bdev, u64 first_sector, int nr_vecs, | ||
| 315 | gfp_t gfp_flags); | ||
| 313 | #endif | 316 | #endif |
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index e354c33df082..c1faded5fca0 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c | |||
| @@ -1047,8 +1047,14 @@ out: | |||
| 1047 | 1047 | ||
| 1048 | if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { | 1048 | if ((file->f_flags & O_DSYNC) || IS_SYNC(inode)) { |
| 1049 | trans = btrfs_start_transaction(root, 0); | 1049 | trans = btrfs_start_transaction(root, 0); |
| 1050 | if (IS_ERR(trans)) { | ||
| 1051 | num_written = PTR_ERR(trans); | ||
| 1052 | goto done; | ||
| 1053 | } | ||
| 1054 | mutex_lock(&inode->i_mutex); | ||
| 1050 | ret = btrfs_log_dentry_safe(trans, root, | 1055 | ret = btrfs_log_dentry_safe(trans, root, |
| 1051 | file->f_dentry); | 1056 | file->f_dentry); |
| 1057 | mutex_unlock(&inode->i_mutex); | ||
| 1052 | if (ret == 0) { | 1058 | if (ret == 0) { |
| 1053 | ret = btrfs_sync_log(trans, root); | 1059 | ret = btrfs_sync_log(trans, root); |
| 1054 | if (ret == 0) | 1060 | if (ret == 0) |
| @@ -1067,6 +1073,7 @@ out: | |||
| 1067 | (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT); | 1073 | (start_pos + num_written - 1) >> PAGE_CACHE_SHIFT); |
| 1068 | } | 1074 | } |
| 1069 | } | 1075 | } |
| 1076 | done: | ||
| 1070 | current->backing_dev_info = NULL; | 1077 | current->backing_dev_info = NULL; |
| 1071 | return num_written ? num_written : err; | 1078 | return num_written ? num_written : err; |
| 1072 | } | 1079 | } |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 558cac2dfa54..8039390bd6a6 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -4501,6 +4501,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
| 4501 | BTRFS_I(inode)->index_cnt = 2; | 4501 | BTRFS_I(inode)->index_cnt = 2; |
| 4502 | BTRFS_I(inode)->root = root; | 4502 | BTRFS_I(inode)->root = root; |
| 4503 | BTRFS_I(inode)->generation = trans->transid; | 4503 | BTRFS_I(inode)->generation = trans->transid; |
| 4504 | inode->i_generation = BTRFS_I(inode)->generation; | ||
| 4504 | btrfs_set_inode_space_info(root, inode); | 4505 | btrfs_set_inode_space_info(root, inode); |
| 4505 | 4506 | ||
| 4506 | if (mode & S_IFDIR) | 4507 | if (mode & S_IFDIR) |
| @@ -4622,12 +4623,12 @@ int btrfs_add_link(struct btrfs_trans_handle *trans, | |||
| 4622 | } | 4623 | } |
| 4623 | 4624 | ||
| 4624 | static int btrfs_add_nondir(struct btrfs_trans_handle *trans, | 4625 | static int btrfs_add_nondir(struct btrfs_trans_handle *trans, |
| 4625 | struct dentry *dentry, struct inode *inode, | 4626 | struct inode *dir, struct dentry *dentry, |
| 4626 | int backref, u64 index) | 4627 | struct inode *inode, int backref, u64 index) |
| 4627 | { | 4628 | { |
| 4628 | int err = btrfs_add_link(trans, dentry->d_parent->d_inode, | 4629 | int err = btrfs_add_link(trans, dir, inode, |
| 4629 | inode, dentry->d_name.name, | 4630 | dentry->d_name.name, dentry->d_name.len, |
| 4630 | dentry->d_name.len, backref, index); | 4631 | backref, index); |
| 4631 | if (!err) { | 4632 | if (!err) { |
| 4632 | d_instantiate(dentry, inode); | 4633 | d_instantiate(dentry, inode); |
| 4633 | return 0; | 4634 | return 0; |
| @@ -4668,8 +4669,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
| 4668 | btrfs_set_trans_block_group(trans, dir); | 4669 | btrfs_set_trans_block_group(trans, dir); |
| 4669 | 4670 | ||
| 4670 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 4671 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
| 4671 | dentry->d_name.len, | 4672 | dentry->d_name.len, dir->i_ino, objectid, |
| 4672 | dentry->d_parent->d_inode->i_ino, objectid, | ||
| 4673 | BTRFS_I(dir)->block_group, mode, &index); | 4673 | BTRFS_I(dir)->block_group, mode, &index); |
| 4674 | err = PTR_ERR(inode); | 4674 | err = PTR_ERR(inode); |
| 4675 | if (IS_ERR(inode)) | 4675 | if (IS_ERR(inode)) |
| @@ -4682,7 +4682,7 @@ static int btrfs_mknod(struct inode *dir, struct dentry *dentry, | |||
| 4682 | } | 4682 | } |
| 4683 | 4683 | ||
| 4684 | btrfs_set_trans_block_group(trans, inode); | 4684 | btrfs_set_trans_block_group(trans, inode); |
| 4685 | err = btrfs_add_nondir(trans, dentry, inode, 0, index); | 4685 | err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); |
| 4686 | if (err) | 4686 | if (err) |
| 4687 | drop_inode = 1; | 4687 | drop_inode = 1; |
| 4688 | else { | 4688 | else { |
| @@ -4730,10 +4730,8 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
| 4730 | btrfs_set_trans_block_group(trans, dir); | 4730 | btrfs_set_trans_block_group(trans, dir); |
| 4731 | 4731 | ||
| 4732 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 4732 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
| 4733 | dentry->d_name.len, | 4733 | dentry->d_name.len, dir->i_ino, objectid, |
| 4734 | dentry->d_parent->d_inode->i_ino, | 4734 | BTRFS_I(dir)->block_group, mode, &index); |
| 4735 | objectid, BTRFS_I(dir)->block_group, mode, | ||
| 4736 | &index); | ||
| 4737 | err = PTR_ERR(inode); | 4735 | err = PTR_ERR(inode); |
| 4738 | if (IS_ERR(inode)) | 4736 | if (IS_ERR(inode)) |
| 4739 | goto out_unlock; | 4737 | goto out_unlock; |
| @@ -4745,7 +4743,7 @@ static int btrfs_create(struct inode *dir, struct dentry *dentry, | |||
| 4745 | } | 4743 | } |
| 4746 | 4744 | ||
| 4747 | btrfs_set_trans_block_group(trans, inode); | 4745 | btrfs_set_trans_block_group(trans, inode); |
| 4748 | err = btrfs_add_nondir(trans, dentry, inode, 0, index); | 4746 | err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); |
| 4749 | if (err) | 4747 | if (err) |
| 4750 | drop_inode = 1; | 4748 | drop_inode = 1; |
| 4751 | else { | 4749 | else { |
| @@ -4787,6 +4785,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 4787 | return -EPERM; | 4785 | return -EPERM; |
| 4788 | 4786 | ||
| 4789 | btrfs_inc_nlink(inode); | 4787 | btrfs_inc_nlink(inode); |
| 4788 | inode->i_ctime = CURRENT_TIME; | ||
| 4790 | 4789 | ||
| 4791 | err = btrfs_set_inode_index(dir, &index); | 4790 | err = btrfs_set_inode_index(dir, &index); |
| 4792 | if (err) | 4791 | if (err) |
| @@ -4805,15 +4804,17 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
| 4805 | btrfs_set_trans_block_group(trans, dir); | 4804 | btrfs_set_trans_block_group(trans, dir); |
| 4806 | ihold(inode); | 4805 | ihold(inode); |
| 4807 | 4806 | ||
| 4808 | err = btrfs_add_nondir(trans, dentry, inode, 1, index); | 4807 | err = btrfs_add_nondir(trans, dir, dentry, inode, 1, index); |
| 4809 | 4808 | ||
| 4810 | if (err) { | 4809 | if (err) { |
| 4811 | drop_inode = 1; | 4810 | drop_inode = 1; |
| 4812 | } else { | 4811 | } else { |
| 4812 | struct dentry *parent = dget_parent(dentry); | ||
| 4813 | btrfs_update_inode_block_group(trans, dir); | 4813 | btrfs_update_inode_block_group(trans, dir); |
| 4814 | err = btrfs_update_inode(trans, root, inode); | 4814 | err = btrfs_update_inode(trans, root, inode); |
| 4815 | BUG_ON(err); | 4815 | BUG_ON(err); |
| 4816 | btrfs_log_new_name(trans, inode, NULL, dentry->d_parent); | 4816 | btrfs_log_new_name(trans, inode, NULL, parent); |
| 4817 | dput(parent); | ||
| 4817 | } | 4818 | } |
| 4818 | 4819 | ||
| 4819 | nr = trans->blocks_used; | 4820 | nr = trans->blocks_used; |
| @@ -4853,8 +4854,7 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 4853 | btrfs_set_trans_block_group(trans, dir); | 4854 | btrfs_set_trans_block_group(trans, dir); |
| 4854 | 4855 | ||
| 4855 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 4856 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
| 4856 | dentry->d_name.len, | 4857 | dentry->d_name.len, dir->i_ino, objectid, |
| 4857 | dentry->d_parent->d_inode->i_ino, objectid, | ||
| 4858 | BTRFS_I(dir)->block_group, S_IFDIR | mode, | 4858 | BTRFS_I(dir)->block_group, S_IFDIR | mode, |
| 4859 | &index); | 4859 | &index); |
| 4860 | if (IS_ERR(inode)) { | 4860 | if (IS_ERR(inode)) { |
| @@ -4877,9 +4877,8 @@ static int btrfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
| 4877 | if (err) | 4877 | if (err) |
| 4878 | goto out_fail; | 4878 | goto out_fail; |
| 4879 | 4879 | ||
| 4880 | err = btrfs_add_link(trans, dentry->d_parent->d_inode, | 4880 | err = btrfs_add_link(trans, dir, inode, dentry->d_name.name, |
| 4881 | inode, dentry->d_name.name, | 4881 | dentry->d_name.len, 0, index); |
| 4882 | dentry->d_name.len, 0, index); | ||
| 4883 | if (err) | 4882 | if (err) |
| 4884 | goto out_fail; | 4883 | goto out_fail; |
| 4885 | 4884 | ||
| @@ -5535,13 +5534,21 @@ struct btrfs_dio_private { | |||
| 5535 | u64 bytes; | 5534 | u64 bytes; |
| 5536 | u32 *csums; | 5535 | u32 *csums; |
| 5537 | void *private; | 5536 | void *private; |
| 5537 | |||
| 5538 | /* number of bios pending for this dio */ | ||
| 5539 | atomic_t pending_bios; | ||
| 5540 | |||
| 5541 | /* IO errors */ | ||
| 5542 | int errors; | ||
| 5543 | |||
| 5544 | struct bio *orig_bio; | ||
| 5538 | }; | 5545 | }; |
| 5539 | 5546 | ||
| 5540 | static void btrfs_endio_direct_read(struct bio *bio, int err) | 5547 | static void btrfs_endio_direct_read(struct bio *bio, int err) |
| 5541 | { | 5548 | { |
| 5549 | struct btrfs_dio_private *dip = bio->bi_private; | ||
| 5542 | struct bio_vec *bvec_end = bio->bi_io_vec + bio->bi_vcnt - 1; | 5550 | struct bio_vec *bvec_end = bio->bi_io_vec + bio->bi_vcnt - 1; |
| 5543 | struct bio_vec *bvec = bio->bi_io_vec; | 5551 | struct bio_vec *bvec = bio->bi_io_vec; |
| 5544 | struct btrfs_dio_private *dip = bio->bi_private; | ||
| 5545 | struct inode *inode = dip->inode; | 5552 | struct inode *inode = dip->inode; |
| 5546 | struct btrfs_root *root = BTRFS_I(inode)->root; | 5553 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 5547 | u64 start; | 5554 | u64 start; |
| @@ -5595,15 +5602,18 @@ static void btrfs_endio_direct_write(struct bio *bio, int err) | |||
| 5595 | struct btrfs_trans_handle *trans; | 5602 | struct btrfs_trans_handle *trans; |
| 5596 | struct btrfs_ordered_extent *ordered = NULL; | 5603 | struct btrfs_ordered_extent *ordered = NULL; |
| 5597 | struct extent_state *cached_state = NULL; | 5604 | struct extent_state *cached_state = NULL; |
| 5605 | u64 ordered_offset = dip->logical_offset; | ||
| 5606 | u64 ordered_bytes = dip->bytes; | ||
| 5598 | int ret; | 5607 | int ret; |
| 5599 | 5608 | ||
| 5600 | if (err) | 5609 | if (err) |
| 5601 | goto out_done; | 5610 | goto out_done; |
| 5602 | 5611 | again: | |
| 5603 | ret = btrfs_dec_test_ordered_pending(inode, &ordered, | 5612 | ret = btrfs_dec_test_first_ordered_pending(inode, &ordered, |
| 5604 | dip->logical_offset, dip->bytes); | 5613 | &ordered_offset, |
| 5614 | ordered_bytes); | ||
| 5605 | if (!ret) | 5615 | if (!ret) |
| 5606 | goto out_done; | 5616 | goto out_test; |
| 5607 | 5617 | ||
| 5608 | BUG_ON(!ordered); | 5618 | BUG_ON(!ordered); |
| 5609 | 5619 | ||
| @@ -5663,8 +5673,20 @@ out_unlock: | |||
| 5663 | out: | 5673 | out: |
| 5664 | btrfs_delalloc_release_metadata(inode, ordered->len); | 5674 | btrfs_delalloc_release_metadata(inode, ordered->len); |
| 5665 | btrfs_end_transaction(trans, root); | 5675 | btrfs_end_transaction(trans, root); |
| 5676 | ordered_offset = ordered->file_offset + ordered->len; | ||
| 5666 | btrfs_put_ordered_extent(ordered); | 5677 | btrfs_put_ordered_extent(ordered); |
| 5667 | btrfs_put_ordered_extent(ordered); | 5678 | btrfs_put_ordered_extent(ordered); |
| 5679 | |||
| 5680 | out_test: | ||
| 5681 | /* | ||
| 5682 | * our bio might span multiple ordered extents. If we haven't | ||
| 5683 | * completed the accounting for the whole dio, go back and try again | ||
| 5684 | */ | ||
| 5685 | if (ordered_offset < dip->logical_offset + dip->bytes) { | ||
| 5686 | ordered_bytes = dip->logical_offset + dip->bytes - | ||
| 5687 | ordered_offset; | ||
| 5688 | goto again; | ||
| 5689 | } | ||
| 5668 | out_done: | 5690 | out_done: |
| 5669 | bio->bi_private = dip->private; | 5691 | bio->bi_private = dip->private; |
| 5670 | 5692 | ||
| @@ -5684,6 +5706,176 @@ static int __btrfs_submit_bio_start_direct_io(struct inode *inode, int rw, | |||
| 5684 | return 0; | 5706 | return 0; |
| 5685 | } | 5707 | } |
| 5686 | 5708 | ||
| 5709 | static void btrfs_end_dio_bio(struct bio *bio, int err) | ||
| 5710 | { | ||
| 5711 | struct btrfs_dio_private *dip = bio->bi_private; | ||
| 5712 | |||
| 5713 | if (err) { | ||
| 5714 | printk(KERN_ERR "btrfs direct IO failed ino %lu rw %lu " | ||
| 5715 | "disk_bytenr %lu len %u err no %d\n", | ||
| 5716 | dip->inode->i_ino, bio->bi_rw, bio->bi_sector, | ||
| 5717 | bio->bi_size, err); | ||
| 5718 | dip->errors = 1; | ||
| 5719 | |||
| 5720 | /* | ||
| 5721 | * before atomic variable goto zero, we must make sure | ||
| 5722 | * dip->errors is perceived to be set. | ||
| 5723 | */ | ||
| 5724 | smp_mb__before_atomic_dec(); | ||
| 5725 | } | ||
| 5726 | |||
| 5727 | /* if there are more bios still pending for this dio, just exit */ | ||
| 5728 | if (!atomic_dec_and_test(&dip->pending_bios)) | ||
| 5729 | goto out; | ||
| 5730 | |||
| 5731 | if (dip->errors) | ||
| 5732 | bio_io_error(dip->orig_bio); | ||
| 5733 | else { | ||
| 5734 | set_bit(BIO_UPTODATE, &dip->orig_bio->bi_flags); | ||
| 5735 | bio_endio(dip->orig_bio, 0); | ||
| 5736 | } | ||
| 5737 | out: | ||
| 5738 | bio_put(bio); | ||
| 5739 | } | ||
| 5740 | |||
| 5741 | static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev, | ||
| 5742 | u64 first_sector, gfp_t gfp_flags) | ||
| 5743 | { | ||
| 5744 | int nr_vecs = bio_get_nr_vecs(bdev); | ||
| 5745 | return btrfs_bio_alloc(bdev, first_sector, nr_vecs, gfp_flags); | ||
| 5746 | } | ||
| 5747 | |||
| 5748 | static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode, | ||
| 5749 | int rw, u64 file_offset, int skip_sum, | ||
| 5750 | u32 *csums) | ||
| 5751 | { | ||
| 5752 | int write = rw & REQ_WRITE; | ||
| 5753 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 5754 | int ret; | ||
| 5755 | |||
| 5756 | bio_get(bio); | ||
| 5757 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); | ||
| 5758 | if (ret) | ||
| 5759 | goto err; | ||
| 5760 | |||
| 5761 | if (write && !skip_sum) { | ||
| 5762 | ret = btrfs_wq_submit_bio(root->fs_info, | ||
| 5763 | inode, rw, bio, 0, 0, | ||
| 5764 | file_offset, | ||
| 5765 | __btrfs_submit_bio_start_direct_io, | ||
| 5766 | __btrfs_submit_bio_done); | ||
| 5767 | goto err; | ||
| 5768 | } else if (!skip_sum) | ||
| 5769 | btrfs_lookup_bio_sums_dio(root, inode, bio, | ||
| 5770 | file_offset, csums); | ||
| 5771 | |||
| 5772 | ret = btrfs_map_bio(root, rw, bio, 0, 1); | ||
| 5773 | err: | ||
| 5774 | bio_put(bio); | ||
| 5775 | return ret; | ||
| 5776 | } | ||
| 5777 | |||
| 5778 | static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip, | ||
| 5779 | int skip_sum) | ||
| 5780 | { | ||
| 5781 | struct inode *inode = dip->inode; | ||
| 5782 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 5783 | struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree; | ||
| 5784 | struct bio *bio; | ||
| 5785 | struct bio *orig_bio = dip->orig_bio; | ||
| 5786 | struct bio_vec *bvec = orig_bio->bi_io_vec; | ||
| 5787 | u64 start_sector = orig_bio->bi_sector; | ||
| 5788 | u64 file_offset = dip->logical_offset; | ||
| 5789 | u64 submit_len = 0; | ||
| 5790 | u64 map_length; | ||
| 5791 | int nr_pages = 0; | ||
| 5792 | u32 *csums = dip->csums; | ||
| 5793 | int ret = 0; | ||
| 5794 | |||
| 5795 | bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, start_sector, GFP_NOFS); | ||
| 5796 | if (!bio) | ||
| 5797 | return -ENOMEM; | ||
| 5798 | bio->bi_private = dip; | ||
| 5799 | bio->bi_end_io = btrfs_end_dio_bio; | ||
| 5800 | atomic_inc(&dip->pending_bios); | ||
| 5801 | |||
| 5802 | map_length = orig_bio->bi_size; | ||
| 5803 | ret = btrfs_map_block(map_tree, READ, start_sector << 9, | ||
| 5804 | &map_length, NULL, 0); | ||
| 5805 | if (ret) { | ||
| 5806 | bio_put(bio); | ||
| 5807 | return -EIO; | ||
| 5808 | } | ||
| 5809 | |||
| 5810 | while (bvec <= (orig_bio->bi_io_vec + orig_bio->bi_vcnt - 1)) { | ||
| 5811 | if (unlikely(map_length < submit_len + bvec->bv_len || | ||
| 5812 | bio_add_page(bio, bvec->bv_page, bvec->bv_len, | ||
| 5813 | bvec->bv_offset) < bvec->bv_len)) { | ||
| 5814 | /* | ||
| 5815 | * inc the count before we submit the bio so | ||
| 5816 | * we know the end IO handler won't happen before | ||
| 5817 | * we inc the count. Otherwise, the dip might get freed | ||
| 5818 | * before we're done setting it up | ||
| 5819 | */ | ||
| 5820 | atomic_inc(&dip->pending_bios); | ||
| 5821 | ret = __btrfs_submit_dio_bio(bio, inode, rw, | ||
| 5822 | file_offset, skip_sum, | ||
| 5823 | csums); | ||
| 5824 | if (ret) { | ||
| 5825 | bio_put(bio); | ||
| 5826 | atomic_dec(&dip->pending_bios); | ||
| 5827 | goto out_err; | ||
| 5828 | } | ||
| 5829 | |||
| 5830 | if (!skip_sum) | ||
| 5831 | csums = csums + nr_pages; | ||
| 5832 | start_sector += submit_len >> 9; | ||
| 5833 | file_offset += submit_len; | ||
| 5834 | |||
| 5835 | submit_len = 0; | ||
| 5836 | nr_pages = 0; | ||
| 5837 | |||
| 5838 | bio = btrfs_dio_bio_alloc(orig_bio->bi_bdev, | ||
| 5839 | start_sector, GFP_NOFS); | ||
| 5840 | if (!bio) | ||
| 5841 | goto out_err; | ||
| 5842 | bio->bi_private = dip; | ||
| 5843 | bio->bi_end_io = btrfs_end_dio_bio; | ||
| 5844 | |||
| 5845 | map_length = orig_bio->bi_size; | ||
| 5846 | ret = btrfs_map_block(map_tree, READ, start_sector << 9, | ||
| 5847 | &map_length, NULL, 0); | ||
| 5848 | if (ret) { | ||
| 5849 | bio_put(bio); | ||
| 5850 | goto out_err; | ||
| 5851 | } | ||
| 5852 | } else { | ||
| 5853 | submit_len += bvec->bv_len; | ||
| 5854 | nr_pages ++; | ||
| 5855 | bvec++; | ||
| 5856 | } | ||
| 5857 | } | ||
| 5858 | |||
| 5859 | ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum, | ||
| 5860 | csums); | ||
| 5861 | if (!ret) | ||
| 5862 | return 0; | ||
| 5863 | |||
| 5864 | bio_put(bio); | ||
| 5865 | out_err: | ||
| 5866 | dip->errors = 1; | ||
| 5867 | /* | ||
| 5868 | * before atomic variable goto zero, we must | ||
| 5869 | * make sure dip->errors is perceived to be set. | ||
| 5870 | */ | ||
| 5871 | smp_mb__before_atomic_dec(); | ||
| 5872 | if (atomic_dec_and_test(&dip->pending_bios)) | ||
| 5873 | bio_io_error(dip->orig_bio); | ||
| 5874 | |||
| 5875 | /* bio_end_io() will handle error, so we needn't return it */ | ||
| 5876 | return 0; | ||
| 5877 | } | ||
| 5878 | |||
| 5687 | static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, | 5879 | static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, |
| 5688 | loff_t file_offset) | 5880 | loff_t file_offset) |
| 5689 | { | 5881 | { |
| @@ -5723,36 +5915,18 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode, | |||
| 5723 | 5915 | ||
| 5724 | dip->disk_bytenr = (u64)bio->bi_sector << 9; | 5916 | dip->disk_bytenr = (u64)bio->bi_sector << 9; |
| 5725 | bio->bi_private = dip; | 5917 | bio->bi_private = dip; |
| 5918 | dip->errors = 0; | ||
| 5919 | dip->orig_bio = bio; | ||
| 5920 | atomic_set(&dip->pending_bios, 0); | ||
| 5726 | 5921 | ||
| 5727 | if (write) | 5922 | if (write) |
| 5728 | bio->bi_end_io = btrfs_endio_direct_write; | 5923 | bio->bi_end_io = btrfs_endio_direct_write; |
| 5729 | else | 5924 | else |
| 5730 | bio->bi_end_io = btrfs_endio_direct_read; | 5925 | bio->bi_end_io = btrfs_endio_direct_read; |
| 5731 | 5926 | ||
| 5732 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); | 5927 | ret = btrfs_submit_direct_hook(rw, dip, skip_sum); |
| 5733 | if (ret) | 5928 | if (!ret) |
| 5734 | goto out_err; | ||
| 5735 | |||
| 5736 | if (write && !skip_sum) { | ||
| 5737 | ret = btrfs_wq_submit_bio(BTRFS_I(inode)->root->fs_info, | ||
| 5738 | inode, rw, bio, 0, 0, | ||
| 5739 | dip->logical_offset, | ||
| 5740 | __btrfs_submit_bio_start_direct_io, | ||
| 5741 | __btrfs_submit_bio_done); | ||
| 5742 | if (ret) | ||
| 5743 | goto out_err; | ||
| 5744 | return; | 5929 | return; |
| 5745 | } else if (!skip_sum) | ||
| 5746 | btrfs_lookup_bio_sums_dio(root, inode, bio, | ||
| 5747 | dip->logical_offset, dip->csums); | ||
| 5748 | |||
| 5749 | ret = btrfs_map_bio(root, rw, bio, 0, 1); | ||
| 5750 | if (ret) | ||
| 5751 | goto out_err; | ||
| 5752 | return; | ||
| 5753 | out_err: | ||
| 5754 | kfree(dip->csums); | ||
| 5755 | kfree(dip); | ||
| 5756 | free_ordered: | 5930 | free_ordered: |
| 5757 | /* | 5931 | /* |
| 5758 | * If this is a write, we need to clean up the reserved space and kill | 5932 | * If this is a write, we need to clean up the reserved space and kill |
| @@ -6607,8 +6781,9 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 6607 | BUG_ON(ret); | 6781 | BUG_ON(ret); |
| 6608 | 6782 | ||
| 6609 | if (old_inode->i_ino != BTRFS_FIRST_FREE_OBJECTID) { | 6783 | if (old_inode->i_ino != BTRFS_FIRST_FREE_OBJECTID) { |
| 6610 | btrfs_log_new_name(trans, old_inode, old_dir, | 6784 | struct dentry *parent = dget_parent(new_dentry); |
| 6611 | new_dentry->d_parent); | 6785 | btrfs_log_new_name(trans, old_inode, old_dir, parent); |
| 6786 | dput(parent); | ||
| 6612 | btrfs_end_log_trans(root); | 6787 | btrfs_end_log_trans(root); |
| 6613 | } | 6788 | } |
| 6614 | out_fail: | 6789 | out_fail: |
| @@ -6758,8 +6933,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 6758 | btrfs_set_trans_block_group(trans, dir); | 6933 | btrfs_set_trans_block_group(trans, dir); |
| 6759 | 6934 | ||
| 6760 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, | 6935 | inode = btrfs_new_inode(trans, root, dir, dentry->d_name.name, |
| 6761 | dentry->d_name.len, | 6936 | dentry->d_name.len, dir->i_ino, objectid, |
| 6762 | dentry->d_parent->d_inode->i_ino, objectid, | ||
| 6763 | BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, | 6937 | BTRFS_I(dir)->block_group, S_IFLNK|S_IRWXUGO, |
| 6764 | &index); | 6938 | &index); |
| 6765 | err = PTR_ERR(inode); | 6939 | err = PTR_ERR(inode); |
| @@ -6773,7 +6947,7 @@ static int btrfs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 6773 | } | 6947 | } |
| 6774 | 6948 | ||
| 6775 | btrfs_set_trans_block_group(trans, inode); | 6949 | btrfs_set_trans_block_group(trans, inode); |
| 6776 | err = btrfs_add_nondir(trans, dentry, inode, 0, index); | 6950 | err = btrfs_add_nondir(trans, dir, dentry, inode, 0, index); |
| 6777 | if (err) | 6951 | if (err) |
| 6778 | drop_inode = 1; | 6952 | drop_inode = 1; |
| 6779 | else { | 6953 | else { |
| @@ -6844,6 +7018,7 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, | |||
| 6844 | struct btrfs_root *root = BTRFS_I(inode)->root; | 7018 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 6845 | struct btrfs_key ins; | 7019 | struct btrfs_key ins; |
| 6846 | u64 cur_offset = start; | 7020 | u64 cur_offset = start; |
| 7021 | u64 i_size; | ||
| 6847 | int ret = 0; | 7022 | int ret = 0; |
| 6848 | bool own_trans = true; | 7023 | bool own_trans = true; |
| 6849 | 7024 | ||
| @@ -6885,11 +7060,11 @@ static int __btrfs_prealloc_file_range(struct inode *inode, int mode, | |||
| 6885 | (actual_len > inode->i_size) && | 7060 | (actual_len > inode->i_size) && |
| 6886 | (cur_offset > inode->i_size)) { | 7061 | (cur_offset > inode->i_size)) { |
| 6887 | if (cur_offset > actual_len) | 7062 | if (cur_offset > actual_len) |
| 6888 | i_size_write(inode, actual_len); | 7063 | i_size = actual_len; |
| 6889 | else | 7064 | else |
| 6890 | i_size_write(inode, cur_offset); | 7065 | i_size = cur_offset; |
| 6891 | i_size_write(inode, cur_offset); | 7066 | i_size_write(inode, i_size); |
| 6892 | btrfs_ordered_update_i_size(inode, cur_offset, NULL); | 7067 | btrfs_ordered_update_i_size(inode, i_size, NULL); |
| 6893 | } | 7068 | } |
| 6894 | 7069 | ||
| 6895 | ret = btrfs_update_inode(trans, root, inode); | 7070 | ret = btrfs_update_inode(trans, root, inode); |
| @@ -6943,6 +7118,10 @@ static long btrfs_fallocate(struct inode *inode, int mode, | |||
| 6943 | btrfs_wait_ordered_range(inode, alloc_start, alloc_end - alloc_start); | 7118 | btrfs_wait_ordered_range(inode, alloc_start, alloc_end - alloc_start); |
| 6944 | 7119 | ||
| 6945 | mutex_lock(&inode->i_mutex); | 7120 | mutex_lock(&inode->i_mutex); |
| 7121 | ret = inode_newsize_ok(inode, alloc_end); | ||
| 7122 | if (ret) | ||
| 7123 | goto out; | ||
| 7124 | |||
| 6946 | if (alloc_start > inode->i_size) { | 7125 | if (alloc_start > inode->i_size) { |
| 6947 | ret = btrfs_cont_expand(inode, alloc_start); | 7126 | ret = btrfs_cont_expand(inode, alloc_start); |
| 6948 | if (ret) | 7127 | if (ret) |
| @@ -7139,6 +7318,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = { | |||
| 7139 | .readlink = generic_readlink, | 7318 | .readlink = generic_readlink, |
| 7140 | .follow_link = page_follow_link_light, | 7319 | .follow_link = page_follow_link_light, |
| 7141 | .put_link = page_put_link, | 7320 | .put_link = page_put_link, |
| 7321 | .getattr = btrfs_getattr, | ||
| 7142 | .permission = btrfs_permission, | 7322 | .permission = btrfs_permission, |
| 7143 | .setxattr = btrfs_setxattr, | 7323 | .setxattr = btrfs_setxattr, |
| 7144 | .getxattr = btrfs_getxattr, | 7324 | .getxattr = btrfs_getxattr, |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 463d91b4dd3a..f1c9bb4079ed 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -233,7 +233,8 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 233 | struct btrfs_inode_item *inode_item; | 233 | struct btrfs_inode_item *inode_item; |
| 234 | struct extent_buffer *leaf; | 234 | struct extent_buffer *leaf; |
| 235 | struct btrfs_root *new_root; | 235 | struct btrfs_root *new_root; |
| 236 | struct inode *dir = dentry->d_parent->d_inode; | 236 | struct dentry *parent = dget_parent(dentry); |
| 237 | struct inode *dir; | ||
| 237 | int ret; | 238 | int ret; |
| 238 | int err; | 239 | int err; |
| 239 | u64 objectid; | 240 | u64 objectid; |
| @@ -242,8 +243,13 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 242 | 243 | ||
| 243 | ret = btrfs_find_free_objectid(NULL, root->fs_info->tree_root, | 244 | ret = btrfs_find_free_objectid(NULL, root->fs_info->tree_root, |
| 244 | 0, &objectid); | 245 | 0, &objectid); |
| 245 | if (ret) | 246 | if (ret) { |
| 247 | dput(parent); | ||
| 246 | return ret; | 248 | return ret; |
| 249 | } | ||
| 250 | |||
| 251 | dir = parent->d_inode; | ||
| 252 | |||
| 247 | /* | 253 | /* |
| 248 | * 1 - inode item | 254 | * 1 - inode item |
| 249 | * 2 - refs | 255 | * 2 - refs |
| @@ -251,8 +257,10 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 251 | * 2 - dir items | 257 | * 2 - dir items |
| 252 | */ | 258 | */ |
| 253 | trans = btrfs_start_transaction(root, 6); | 259 | trans = btrfs_start_transaction(root, 6); |
| 254 | if (IS_ERR(trans)) | 260 | if (IS_ERR(trans)) { |
| 261 | dput(parent); | ||
| 255 | return PTR_ERR(trans); | 262 | return PTR_ERR(trans); |
| 263 | } | ||
| 256 | 264 | ||
| 257 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, | 265 | leaf = btrfs_alloc_free_block(trans, root, root->leafsize, |
| 258 | 0, objectid, NULL, 0, 0, 0); | 266 | 0, objectid, NULL, 0, 0, 0); |
| @@ -339,6 +347,7 @@ static noinline int create_subvol(struct btrfs_root *root, | |||
| 339 | 347 | ||
| 340 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); | 348 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); |
| 341 | fail: | 349 | fail: |
| 350 | dput(parent); | ||
| 342 | if (async_transid) { | 351 | if (async_transid) { |
| 343 | *async_transid = trans->transid; | 352 | *async_transid = trans->transid; |
| 344 | err = btrfs_commit_transaction_async(trans, root, 1); | 353 | err = btrfs_commit_transaction_async(trans, root, 1); |
| @@ -354,6 +363,7 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 354 | char *name, int namelen, u64 *async_transid) | 363 | char *name, int namelen, u64 *async_transid) |
| 355 | { | 364 | { |
| 356 | struct inode *inode; | 365 | struct inode *inode; |
| 366 | struct dentry *parent; | ||
| 357 | struct btrfs_pending_snapshot *pending_snapshot; | 367 | struct btrfs_pending_snapshot *pending_snapshot; |
| 358 | struct btrfs_trans_handle *trans; | 368 | struct btrfs_trans_handle *trans; |
| 359 | int ret; | 369 | int ret; |
| @@ -396,7 +406,9 @@ static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |||
| 396 | 406 | ||
| 397 | btrfs_orphan_cleanup(pending_snapshot->snap); | 407 | btrfs_orphan_cleanup(pending_snapshot->snap); |
| 398 | 408 | ||
| 399 | inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry); | 409 | parent = dget_parent(dentry); |
| 410 | inode = btrfs_lookup_dentry(parent->d_inode, dentry); | ||
| 411 | dput(parent); | ||
| 400 | if (IS_ERR(inode)) { | 412 | if (IS_ERR(inode)) { |
| 401 | ret = PTR_ERR(inode); | 413 | ret = PTR_ERR(inode); |
| 402 | goto fail; | 414 | goto fail; |
| @@ -1669,12 +1681,11 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1669 | olen = len = src->i_size - off; | 1681 | olen = len = src->i_size - off; |
| 1670 | /* if we extend to eof, continue to block boundary */ | 1682 | /* if we extend to eof, continue to block boundary */ |
| 1671 | if (off + len == src->i_size) | 1683 | if (off + len == src->i_size) |
| 1672 | len = ((src->i_size + bs-1) & ~(bs-1)) | 1684 | len = ALIGN(src->i_size, bs) - off; |
| 1673 | - off; | ||
| 1674 | 1685 | ||
| 1675 | /* verify the end result is block aligned */ | 1686 | /* verify the end result is block aligned */ |
| 1676 | if ((off & (bs-1)) || | 1687 | if (!IS_ALIGNED(off, bs) || !IS_ALIGNED(off + len, bs) || |
| 1677 | ((off + len) & (bs-1))) | 1688 | !IS_ALIGNED(destoff, bs)) |
| 1678 | goto out_unlock; | 1689 | goto out_unlock; |
| 1679 | 1690 | ||
| 1680 | /* do any pending delalloc/csum calc on src, one way or | 1691 | /* do any pending delalloc/csum calc on src, one way or |
| @@ -1874,8 +1885,8 @@ static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 1874 | * but shouldn't round up the file size | 1885 | * but shouldn't round up the file size |
| 1875 | */ | 1886 | */ |
| 1876 | endoff = new_key.offset + datal; | 1887 | endoff = new_key.offset + datal; |
| 1877 | if (endoff > off+olen) | 1888 | if (endoff > destoff+olen) |
| 1878 | endoff = off+olen; | 1889 | endoff = destoff+olen; |
| 1879 | if (endoff > inode->i_size) | 1890 | if (endoff > inode->i_size) |
| 1880 | btrfs_i_size_write(inode, endoff); | 1891 | btrfs_i_size_write(inode, endoff); |
| 1881 | 1892 | ||
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index f4621f6deca1..ae7737e352c9 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
| @@ -250,6 +250,73 @@ int btrfs_add_ordered_sum(struct inode *inode, | |||
| 250 | 250 | ||
| 251 | /* | 251 | /* |
| 252 | * this is used to account for finished IO across a given range | 252 | * this is used to account for finished IO across a given range |
| 253 | * of the file. The IO may span ordered extents. If | ||
| 254 | * a given ordered_extent is completely done, 1 is returned, otherwise | ||
| 255 | * 0. | ||
| 256 | * | ||
| 257 | * test_and_set_bit on a flag in the struct btrfs_ordered_extent is used | ||
| 258 | * to make sure this function only returns 1 once for a given ordered extent. | ||
| 259 | * | ||
| 260 | * file_offset is updated to one byte past the range that is recorded as | ||
| 261 | * complete. This allows you to walk forward in the file. | ||
| 262 | */ | ||
| 263 | int btrfs_dec_test_first_ordered_pending(struct inode *inode, | ||
| 264 | struct btrfs_ordered_extent **cached, | ||
| 265 | u64 *file_offset, u64 io_size) | ||
| 266 | { | ||
| 267 | struct btrfs_ordered_inode_tree *tree; | ||
| 268 | struct rb_node *node; | ||
| 269 | struct btrfs_ordered_extent *entry = NULL; | ||
| 270 | int ret; | ||
| 271 | u64 dec_end; | ||
| 272 | u64 dec_start; | ||
| 273 | u64 to_dec; | ||
| 274 | |||
| 275 | tree = &BTRFS_I(inode)->ordered_tree; | ||
| 276 | spin_lock(&tree->lock); | ||
| 277 | node = tree_search(tree, *file_offset); | ||
| 278 | if (!node) { | ||
| 279 | ret = 1; | ||
| 280 | goto out; | ||
| 281 | } | ||
| 282 | |||
| 283 | entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); | ||
| 284 | if (!offset_in_entry(entry, *file_offset)) { | ||
| 285 | ret = 1; | ||
| 286 | goto out; | ||
| 287 | } | ||
| 288 | |||
| 289 | dec_start = max(*file_offset, entry->file_offset); | ||
| 290 | dec_end = min(*file_offset + io_size, entry->file_offset + | ||
| 291 | entry->len); | ||
| 292 | *file_offset = dec_end; | ||
| 293 | if (dec_start > dec_end) { | ||
| 294 | printk(KERN_CRIT "bad ordering dec_start %llu end %llu\n", | ||
| 295 | (unsigned long long)dec_start, | ||
| 296 | (unsigned long long)dec_end); | ||
| 297 | } | ||
| 298 | to_dec = dec_end - dec_start; | ||
| 299 | if (to_dec > entry->bytes_left) { | ||
| 300 | printk(KERN_CRIT "bad ordered accounting left %llu size %llu\n", | ||
| 301 | (unsigned long long)entry->bytes_left, | ||
| 302 | (unsigned long long)to_dec); | ||
| 303 | } | ||
| 304 | entry->bytes_left -= to_dec; | ||
| 305 | if (entry->bytes_left == 0) | ||
| 306 | ret = test_and_set_bit(BTRFS_ORDERED_IO_DONE, &entry->flags); | ||
| 307 | else | ||
| 308 | ret = 1; | ||
| 309 | out: | ||
| 310 | if (!ret && cached && entry) { | ||
| 311 | *cached = entry; | ||
| 312 | atomic_inc(&entry->refs); | ||
| 313 | } | ||
| 314 | spin_unlock(&tree->lock); | ||
| 315 | return ret == 0; | ||
| 316 | } | ||
| 317 | |||
| 318 | /* | ||
| 319 | * this is used to account for finished IO across a given range | ||
| 253 | * of the file. The IO should not span ordered extents. If | 320 | * of the file. The IO should not span ordered extents. If |
| 254 | * a given ordered_extent is completely done, 1 is returned, otherwise | 321 | * a given ordered_extent is completely done, 1 is returned, otherwise |
| 255 | * 0. | 322 | * 0. |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 8ac365492a3f..61dca83119dd 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
| @@ -141,6 +141,9 @@ int btrfs_remove_ordered_extent(struct inode *inode, | |||
| 141 | int btrfs_dec_test_ordered_pending(struct inode *inode, | 141 | int btrfs_dec_test_ordered_pending(struct inode *inode, |
| 142 | struct btrfs_ordered_extent **cached, | 142 | struct btrfs_ordered_extent **cached, |
| 143 | u64 file_offset, u64 io_size); | 143 | u64 file_offset, u64 io_size); |
| 144 | int btrfs_dec_test_first_ordered_pending(struct inode *inode, | ||
| 145 | struct btrfs_ordered_extent **cached, | ||
| 146 | u64 *file_offset, u64 io_size); | ||
| 144 | int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | 147 | int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, |
| 145 | u64 start, u64 len, u64 disk_len, int type); | 148 | u64 start, u64 len, u64 disk_len, int type); |
| 146 | int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset, | 149 | int btrfs_add_ordered_extent_dio(struct inode *inode, u64 file_offset, |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 8299a25ffc8f..dbb51ea7a13c 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
| @@ -244,6 +244,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options) | |||
| 244 | case Opt_space_cache: | 244 | case Opt_space_cache: |
| 245 | printk(KERN_INFO "btrfs: enabling disk space caching\n"); | 245 | printk(KERN_INFO "btrfs: enabling disk space caching\n"); |
| 246 | btrfs_set_opt(info->mount_opt, SPACE_CACHE); | 246 | btrfs_set_opt(info->mount_opt, SPACE_CACHE); |
| 247 | break; | ||
| 247 | case Opt_clear_cache: | 248 | case Opt_clear_cache: |
| 248 | printk(KERN_INFO "btrfs: force clearing of disk cache\n"); | 249 | printk(KERN_INFO "btrfs: force clearing of disk cache\n"); |
| 249 | btrfs_set_opt(info->mount_opt, CLEAR_CACHE); | 250 | btrfs_set_opt(info->mount_opt, CLEAR_CACHE); |
| @@ -562,12 +563,26 @@ static int btrfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
| 562 | 563 | ||
| 563 | static int btrfs_test_super(struct super_block *s, void *data) | 564 | static int btrfs_test_super(struct super_block *s, void *data) |
| 564 | { | 565 | { |
| 565 | struct btrfs_fs_devices *test_fs_devices = data; | 566 | struct btrfs_root *test_root = data; |
| 566 | struct btrfs_root *root = btrfs_sb(s); | 567 | struct btrfs_root *root = btrfs_sb(s); |
| 567 | 568 | ||
| 568 | return root->fs_info->fs_devices == test_fs_devices; | 569 | /* |
| 570 | * If this super block is going away, return false as it | ||
| 571 | * can't match as an existing super block. | ||
| 572 | */ | ||
| 573 | if (!atomic_read(&s->s_active)) | ||
| 574 | return 0; | ||
| 575 | return root->fs_info->fs_devices == test_root->fs_info->fs_devices; | ||
| 576 | } | ||
| 577 | |||
| 578 | static int btrfs_set_super(struct super_block *s, void *data) | ||
| 579 | { | ||
| 580 | s->s_fs_info = data; | ||
| 581 | |||
| 582 | return set_anon_super(s, data); | ||
| 569 | } | 583 | } |
| 570 | 584 | ||
| 585 | |||
| 571 | /* | 586 | /* |
| 572 | * Find a superblock for the given device / mount point. | 587 | * Find a superblock for the given device / mount point. |
| 573 | * | 588 | * |
| @@ -581,6 +596,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 581 | struct super_block *s; | 596 | struct super_block *s; |
| 582 | struct dentry *root; | 597 | struct dentry *root; |
| 583 | struct btrfs_fs_devices *fs_devices = NULL; | 598 | struct btrfs_fs_devices *fs_devices = NULL; |
| 599 | struct btrfs_root *tree_root = NULL; | ||
| 600 | struct btrfs_fs_info *fs_info = NULL; | ||
| 584 | fmode_t mode = FMODE_READ; | 601 | fmode_t mode = FMODE_READ; |
| 585 | char *subvol_name = NULL; | 602 | char *subvol_name = NULL; |
| 586 | u64 subvol_objectid = 0; | 603 | u64 subvol_objectid = 0; |
| @@ -608,8 +625,24 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags, | |||
| 608 | goto error_close_devices; | 625 | goto error_close_devices; |
| 609 | } | 626 | } |
| 610 | 627 | ||
| 628 | /* | ||
| 629 | * Setup a dummy root and fs_info for test/set super. This is because | ||
| 630 | * we don't actually fill this stuff out until open_ctree, but we need | ||
| 631 | * it for searching for existing supers, so this lets us do that and | ||
| 632 | * then open_ctree will properly initialize everything later. | ||
| 633 | */ | ||
| 634 | fs_info = kzalloc(sizeof(struct btrfs_fs_info), GFP_NOFS); | ||
| 635 | tree_root = kzalloc(sizeof(struct btrfs_root), GFP_NOFS); | ||
| 636 | if (!fs_info || !tree_root) { | ||
| 637 | error = -ENOMEM; | ||
| 638 | goto error_close_devices; | ||
| 639 | } | ||
| 640 | fs_info->tree_root = tree_root; | ||
| 641 | fs_info->fs_devices = fs_devices; | ||
| 642 | tree_root->fs_info = fs_info; | ||
| 643 | |||
| 611 | bdev = fs_devices->latest_bdev; | 644 | bdev = fs_devices->latest_bdev; |
| 612 | s = sget(fs_type, btrfs_test_super, set_anon_super, fs_devices); | 645 | s = sget(fs_type, btrfs_test_super, btrfs_set_super, tree_root); |
| 613 | if (IS_ERR(s)) | 646 | if (IS_ERR(s)) |
| 614 | goto error_s; | 647 | goto error_s; |
| 615 | 648 | ||
| @@ -675,6 +708,8 @@ error_s: | |||
| 675 | error = PTR_ERR(s); | 708 | error = PTR_ERR(s); |
| 676 | error_close_devices: | 709 | error_close_devices: |
| 677 | btrfs_close_devices(fs_devices); | 710 | btrfs_close_devices(fs_devices); |
| 711 | kfree(fs_info); | ||
| 712 | kfree(tree_root); | ||
| 678 | error_free_subvol_name: | 713 | error_free_subvol_name: |
| 679 | kfree(subvol_name); | 714 | kfree(subvol_name); |
| 680 | return ERR_PTR(error); | 715 | return ERR_PTR(error); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 1fffbc017bdf..f50e931fc217 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
| @@ -902,6 +902,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 902 | struct btrfs_root *root = pending->root; | 902 | struct btrfs_root *root = pending->root; |
| 903 | struct btrfs_root *parent_root; | 903 | struct btrfs_root *parent_root; |
| 904 | struct inode *parent_inode; | 904 | struct inode *parent_inode; |
| 905 | struct dentry *parent; | ||
| 905 | struct dentry *dentry; | 906 | struct dentry *dentry; |
| 906 | struct extent_buffer *tmp; | 907 | struct extent_buffer *tmp; |
| 907 | struct extent_buffer *old; | 908 | struct extent_buffer *old; |
| @@ -941,7 +942,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 941 | trans->block_rsv = &pending->block_rsv; | 942 | trans->block_rsv = &pending->block_rsv; |
| 942 | 943 | ||
| 943 | dentry = pending->dentry; | 944 | dentry = pending->dentry; |
| 944 | parent_inode = dentry->d_parent->d_inode; | 945 | parent = dget_parent(dentry); |
| 946 | parent_inode = parent->d_inode; | ||
| 945 | parent_root = BTRFS_I(parent_inode)->root; | 947 | parent_root = BTRFS_I(parent_inode)->root; |
| 946 | record_root_in_trans(trans, parent_root); | 948 | record_root_in_trans(trans, parent_root); |
| 947 | 949 | ||
| @@ -989,6 +991,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans, | |||
| 989 | parent_inode->i_ino, index, | 991 | parent_inode->i_ino, index, |
| 990 | dentry->d_name.name, dentry->d_name.len); | 992 | dentry->d_name.name, dentry->d_name.len); |
| 991 | BUG_ON(ret); | 993 | BUG_ON(ret); |
| 994 | dput(parent); | ||
| 992 | 995 | ||
| 993 | key.offset = (u64)-1; | 996 | key.offset = (u64)-1; |
| 994 | pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key); | 997 | pending->snap = btrfs_read_fs_root_no_name(root->fs_info, &key); |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index a29f19384a27..054744ac5719 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -2869,6 +2869,7 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, | |||
| 2869 | { | 2869 | { |
| 2870 | int ret = 0; | 2870 | int ret = 0; |
| 2871 | struct btrfs_root *root; | 2871 | struct btrfs_root *root; |
| 2872 | struct dentry *old_parent = NULL; | ||
| 2872 | 2873 | ||
| 2873 | /* | 2874 | /* |
| 2874 | * for regular files, if its inode is already on disk, we don't | 2875 | * for regular files, if its inode is already on disk, we don't |
| @@ -2910,10 +2911,13 @@ static noinline int check_parent_dirs_for_sync(struct btrfs_trans_handle *trans, | |||
| 2910 | if (IS_ROOT(parent)) | 2911 | if (IS_ROOT(parent)) |
| 2911 | break; | 2912 | break; |
| 2912 | 2913 | ||
| 2913 | parent = parent->d_parent; | 2914 | parent = dget_parent(parent); |
| 2915 | dput(old_parent); | ||
| 2916 | old_parent = parent; | ||
| 2914 | inode = parent->d_inode; | 2917 | inode = parent->d_inode; |
| 2915 | 2918 | ||
| 2916 | } | 2919 | } |
| 2920 | dput(old_parent); | ||
| 2917 | out: | 2921 | out: |
| 2918 | return ret; | 2922 | return ret; |
| 2919 | } | 2923 | } |
| @@ -2945,6 +2949,7 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
| 2945 | { | 2949 | { |
| 2946 | int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL; | 2950 | int inode_only = exists_only ? LOG_INODE_EXISTS : LOG_INODE_ALL; |
| 2947 | struct super_block *sb; | 2951 | struct super_block *sb; |
| 2952 | struct dentry *old_parent = NULL; | ||
| 2948 | int ret = 0; | 2953 | int ret = 0; |
| 2949 | u64 last_committed = root->fs_info->last_trans_committed; | 2954 | u64 last_committed = root->fs_info->last_trans_committed; |
| 2950 | 2955 | ||
| @@ -3016,10 +3021,13 @@ int btrfs_log_inode_parent(struct btrfs_trans_handle *trans, | |||
| 3016 | if (IS_ROOT(parent)) | 3021 | if (IS_ROOT(parent)) |
| 3017 | break; | 3022 | break; |
| 3018 | 3023 | ||
| 3019 | parent = parent->d_parent; | 3024 | parent = dget_parent(parent); |
| 3025 | dput(old_parent); | ||
| 3026 | old_parent = parent; | ||
| 3020 | } | 3027 | } |
| 3021 | ret = 0; | 3028 | ret = 0; |
| 3022 | end_trans: | 3029 | end_trans: |
| 3030 | dput(old_parent); | ||
| 3023 | if (ret < 0) { | 3031 | if (ret < 0) { |
| 3024 | BUG_ON(ret != -ENOSPC); | 3032 | BUG_ON(ret != -ENOSPC); |
| 3025 | root->fs_info->last_trans_log_full_commit = trans->transid; | 3033 | root->fs_info->last_trans_log_full_commit = trans->transid; |
| @@ -3039,8 +3047,13 @@ end_no_trans: | |||
| 3039 | int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans, | 3047 | int btrfs_log_dentry_safe(struct btrfs_trans_handle *trans, |
| 3040 | struct btrfs_root *root, struct dentry *dentry) | 3048 | struct btrfs_root *root, struct dentry *dentry) |
| 3041 | { | 3049 | { |
| 3042 | return btrfs_log_inode_parent(trans, root, dentry->d_inode, | 3050 | struct dentry *parent = dget_parent(dentry); |
| 3043 | dentry->d_parent, 0); | 3051 | int ret; |
| 3052 | |||
| 3053 | ret = btrfs_log_inode_parent(trans, root, dentry->d_inode, parent, 0); | ||
| 3054 | dput(parent); | ||
| 3055 | |||
| 3056 | return ret; | ||
| 3044 | } | 3057 | } |
| 3045 | 3058 | ||
| 3046 | /* | 3059 | /* |
diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 0ed213970ced..ee45648b0d1a 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig | |||
| @@ -4,6 +4,7 @@ config CIFS | |||
| 4 | select NLS | 4 | select NLS |
| 5 | select CRYPTO | 5 | select CRYPTO |
| 6 | select CRYPTO_MD5 | 6 | select CRYPTO_MD5 |
| 7 | select CRYPTO_HMAC | ||
| 7 | select CRYPTO_ARC4 | 8 | select CRYPTO_ARC4 |
| 8 | help | 9 | help |
| 9 | This is the client VFS module for the Common Internet File System | 10 | This is the client VFS module for the Common Internet File System |
| @@ -143,6 +144,13 @@ config CIFS_FSCACHE | |||
| 143 | to be cached locally on disk through the general filesystem cache | 144 | to be cached locally on disk through the general filesystem cache |
| 144 | manager. If unsure, say N. | 145 | manager. If unsure, say N. |
| 145 | 146 | ||
| 147 | config CIFS_ACL | ||
| 148 | bool "Provide CIFS ACL support (EXPERIMENTAL)" | ||
| 149 | depends on EXPERIMENTAL && CIFS_XATTR | ||
| 150 | help | ||
| 151 | Allows to fetch CIFS/NTFS ACL from the server. The DACL blob | ||
| 152 | is handed over to the application/caller. | ||
| 153 | |||
| 146 | config CIFS_EXPERIMENTAL | 154 | config CIFS_EXPERIMENTAL |
| 147 | bool "CIFS Experimental Features (EXPERIMENTAL)" | 155 | bool "CIFS Experimental Features (EXPERIMENTAL)" |
| 148 | depends on CIFS && EXPERIMENTAL | 156 | depends on CIFS && EXPERIMENTAL |
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index c9b4792ae825..c6ebea088ac7 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
| @@ -560,7 +560,7 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, | |||
| 560 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 560 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
| 561 | 561 | ||
| 562 | if (IS_ERR(tlink)) | 562 | if (IS_ERR(tlink)) |
| 563 | return NULL; | 563 | return ERR_CAST(tlink); |
| 564 | 564 | ||
| 565 | xid = GetXid(); | 565 | xid = GetXid(); |
| 566 | rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); | 566 | rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), fid, &pntsd, pacllen); |
| @@ -568,7 +568,9 @@ static struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, | |||
| 568 | 568 | ||
| 569 | cifs_put_tlink(tlink); | 569 | cifs_put_tlink(tlink); |
| 570 | 570 | ||
| 571 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); | 571 | cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); |
| 572 | if (rc) | ||
| 573 | return ERR_PTR(rc); | ||
| 572 | return pntsd; | 574 | return pntsd; |
| 573 | } | 575 | } |
| 574 | 576 | ||
| @@ -583,7 +585,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
| 583 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); | 585 | struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); |
| 584 | 586 | ||
| 585 | if (IS_ERR(tlink)) | 587 | if (IS_ERR(tlink)) |
| 586 | return NULL; | 588 | return ERR_CAST(tlink); |
| 587 | 589 | ||
| 588 | tcon = tlink_tcon(tlink); | 590 | tcon = tlink_tcon(tlink); |
| 589 | xid = GetXid(); | 591 | xid = GetXid(); |
| @@ -591,23 +593,22 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, | |||
| 591 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0, | 593 | rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0, |
| 592 | &fid, &oplock, NULL, cifs_sb->local_nls, | 594 | &fid, &oplock, NULL, cifs_sb->local_nls, |
| 593 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); | 595 | cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 594 | if (rc) { | 596 | if (!rc) { |
| 595 | cERROR(1, "Unable to open file to get ACL"); | 597 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); |
| 596 | goto out; | 598 | CIFSSMBClose(xid, tcon, fid); |
| 597 | } | 599 | } |
| 598 | 600 | ||
| 599 | rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); | ||
| 600 | cFYI(1, "GetCIFSACL rc = %d ACL len %d", rc, *pacllen); | ||
| 601 | |||
| 602 | CIFSSMBClose(xid, tcon, fid); | ||
| 603 | out: | ||
| 604 | cifs_put_tlink(tlink); | 601 | cifs_put_tlink(tlink); |
| 605 | FreeXid(xid); | 602 | FreeXid(xid); |
| 603 | |||
| 604 | cFYI(1, "%s: rc = %d ACL len %d", __func__, rc, *pacllen); | ||
| 605 | if (rc) | ||
| 606 | return ERR_PTR(rc); | ||
| 606 | return pntsd; | 607 | return pntsd; |
| 607 | } | 608 | } |
| 608 | 609 | ||
| 609 | /* Retrieve an ACL from the server */ | 610 | /* Retrieve an ACL from the server */ |
| 610 | static struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, | 611 | struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, |
| 611 | struct inode *inode, const char *path, | 612 | struct inode *inode, const char *path, |
| 612 | u32 *pacllen) | 613 | u32 *pacllen) |
| 613 | { | 614 | { |
| @@ -695,7 +696,7 @@ static int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, | |||
| 695 | } | 696 | } |
| 696 | 697 | ||
| 697 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ | 698 | /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ |
| 698 | void | 699 | int |
| 699 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | 700 | cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, |
| 700 | struct inode *inode, const char *path, const __u16 *pfid) | 701 | struct inode *inode, const char *path, const __u16 *pfid) |
| 701 | { | 702 | { |
| @@ -711,17 +712,21 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, | |||
| 711 | pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); | 712 | pntsd = get_cifs_acl(cifs_sb, inode, path, &acllen); |
| 712 | 713 | ||
| 713 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ | 714 | /* if we can retrieve the ACL, now parse Access Control Entries, ACEs */ |
| 714 | if (pntsd) | 715 | if (IS_ERR(pntsd)) { |
| 716 | rc = PTR_ERR(pntsd); | ||
| 717 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); | ||
| 718 | } else { | ||
| 715 | rc = parse_sec_desc(pntsd, acllen, fattr); | 719 | rc = parse_sec_desc(pntsd, acllen, fattr); |
| 716 | if (rc) | 720 | kfree(pntsd); |
| 717 | cFYI(1, "parse sec desc failed rc = %d", rc); | 721 | if (rc) |
| 722 | cERROR(1, "parse sec desc failed rc = %d", rc); | ||
| 723 | } | ||
| 718 | 724 | ||
| 719 | kfree(pntsd); | 725 | return rc; |
| 720 | return; | ||
| 721 | } | 726 | } |
| 722 | 727 | ||
| 723 | /* Convert mode bits to an ACL so we can update the ACL on the server */ | 728 | /* Convert mode bits to an ACL so we can update the ACL on the server */ |
| 724 | int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) | 729 | int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode) |
| 725 | { | 730 | { |
| 726 | int rc = 0; | 731 | int rc = 0; |
| 727 | __u32 secdesclen = 0; | 732 | __u32 secdesclen = 0; |
| @@ -736,7 +741,10 @@ int mode_to_acl(struct inode *inode, const char *path, __u64 nmode) | |||
| 736 | /* Add three ACEs for owner, group, everyone getting rid of | 741 | /* Add three ACEs for owner, group, everyone getting rid of |
| 737 | other ACEs as chmod disables ACEs and set the security descriptor */ | 742 | other ACEs as chmod disables ACEs and set the security descriptor */ |
| 738 | 743 | ||
| 739 | if (pntsd) { | 744 | if (IS_ERR(pntsd)) { |
| 745 | rc = PTR_ERR(pntsd); | ||
| 746 | cERROR(1, "%s: error %d getting sec desc", __func__, rc); | ||
| 747 | } else { | ||
| 740 | /* allocate memory for the smb header, | 748 | /* allocate memory for the smb header, |
| 741 | set security descriptor request security descriptor | 749 | set security descriptor request security descriptor |
| 742 | parameters, and secuirty descriptor itself */ | 750 | parameters, and secuirty descriptor itself */ |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 9c3789762ab7..76c8a906a63e 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
| @@ -458,6 +458,8 @@ cifs_show_options(struct seq_file *s, struct vfsmount *m) | |||
| 458 | seq_printf(s, ",acl"); | 458 | seq_printf(s, ",acl"); |
| 459 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) | 459 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) |
| 460 | seq_printf(s, ",mfsymlinks"); | 460 | seq_printf(s, ",mfsymlinks"); |
| 461 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) | ||
| 462 | seq_printf(s, ",fsc"); | ||
| 461 | 463 | ||
| 462 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); | 464 | seq_printf(s, ",rsize=%d", cifs_sb->rsize); |
| 463 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); | 465 | seq_printf(s, ",wsize=%d", cifs_sb->wsize); |
diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 7ed69b6b5fe6..db961dc4fd3d 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h | |||
| @@ -130,10 +130,12 @@ extern int cifs_get_file_info_unix(struct file *filp); | |||
| 130 | extern int cifs_get_inode_info_unix(struct inode **pinode, | 130 | extern int cifs_get_inode_info_unix(struct inode **pinode, |
| 131 | const unsigned char *search_path, | 131 | const unsigned char *search_path, |
| 132 | struct super_block *sb, int xid); | 132 | struct super_block *sb, int xid); |
| 133 | extern void cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, | 133 | extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, |
| 134 | struct cifs_fattr *fattr, struct inode *inode, | 134 | struct cifs_fattr *fattr, struct inode *inode, |
| 135 | const char *path, const __u16 *pfid); | 135 | const char *path, const __u16 *pfid); |
| 136 | extern int mode_to_acl(struct inode *inode, const char *path, __u64); | 136 | extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); |
| 137 | extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, | ||
| 138 | const char *, u32 *); | ||
| 137 | 139 | ||
| 138 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, | 140 | extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *, |
| 139 | const char *); | 141 | const char *); |
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index 251a17c03545..32fa4d9b5dbc 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c | |||
| @@ -1352,6 +1352,11 @@ cifs_parse_mount_options(char *options, const char *devname, | |||
| 1352 | "supported. Instead set " | 1352 | "supported. Instead set " |
| 1353 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); | 1353 | "/proc/fs/cifs/LookupCacheEnabled to 0\n"); |
| 1354 | } else if (strnicmp(data, "fsc", 3) == 0) { | 1354 | } else if (strnicmp(data, "fsc", 3) == 0) { |
| 1355 | #ifndef CONFIG_CIFS_FSCACHE | ||
| 1356 | cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE" | ||
| 1357 | "kernel config option set"); | ||
| 1358 | return 1; | ||
| 1359 | #endif | ||
| 1355 | vol->fsc = true; | 1360 | vol->fsc = true; |
| 1356 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { | 1361 | } else if (strnicmp(data, "mfsymlinks", 10) == 0) { |
| 1357 | vol->mfsymlinks = true; | 1362 | vol->mfsymlinks = true; |
diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 0eb87026cad3..548f06230a6d 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c | |||
| @@ -66,7 +66,7 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) | |||
| 66 | /* Search for server name delimiter */ | 66 | /* Search for server name delimiter */ |
| 67 | sep = memchr(hostname, '\\', len); | 67 | sep = memchr(hostname, '\\', len); |
| 68 | if (sep) | 68 | if (sep) |
| 69 | len = sep - unc; | 69 | len = sep - hostname; |
| 70 | else | 70 | else |
| 71 | cFYI(1, "%s: probably server name is whole unc: %s", | 71 | cFYI(1, "%s: probably server name is whole unc: %s", |
| 72 | __func__, unc); | 72 | __func__, unc); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 06c3e83fa387..b857ce5db775 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -2271,8 +2271,10 @@ void cifs_oplock_break_get(struct cifsFileInfo *cfile) | |||
| 2271 | 2271 | ||
| 2272 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) | 2272 | void cifs_oplock_break_put(struct cifsFileInfo *cfile) |
| 2273 | { | 2273 | { |
| 2274 | struct super_block *sb = cfile->dentry->d_sb; | ||
| 2275 | |||
| 2274 | cifsFileInfo_put(cfile); | 2276 | cifsFileInfo_put(cfile); |
| 2275 | cifs_sb_deactive(cfile->dentry->d_sb); | 2277 | cifs_sb_deactive(sb); |
| 2276 | } | 2278 | } |
| 2277 | 2279 | ||
| 2278 | const struct address_space_operations cifs_addr_ops = { | 2280 | const struct address_space_operations cifs_addr_ops = { |
diff --git a/fs/cifs/fscache.c b/fs/cifs/fscache.c index a2ad94efcfe6..297a43d0ff7f 100644 --- a/fs/cifs/fscache.c +++ b/fs/cifs/fscache.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * fs/cifs/fscache.c - CIFS filesystem cache interface | 2 | * fs/cifs/fscache.c - CIFS filesystem cache interface |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2010 Novell, Inc. | 4 | * Copyright (c) 2010 Novell, Inc. |
| 5 | * Author(s): Suresh Jayaraman (sjayaraman@suse.de> | 5 | * Author(s): Suresh Jayaraman <sjayaraman@suse.de> |
| 6 | * | 6 | * |
| 7 | * This library is free software; you can redistribute it and/or modify | 7 | * This library is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU Lesser General Public License as published | 8 | * it under the terms of the GNU Lesser General Public License as published |
| @@ -67,10 +67,12 @@ static void cifs_fscache_enable_inode_cookie(struct inode *inode) | |||
| 67 | if (cifsi->fscache) | 67 | if (cifsi->fscache) |
| 68 | return; | 68 | return; |
| 69 | 69 | ||
| 70 | cifsi->fscache = fscache_acquire_cookie(tcon->fscache, | 70 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) { |
| 71 | cifsi->fscache = fscache_acquire_cookie(tcon->fscache, | ||
| 71 | &cifs_fscache_inode_object_def, cifsi); | 72 | &cifs_fscache_inode_object_def, cifsi); |
| 72 | cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, | 73 | cFYI(1, "CIFS: got FH cookie (0x%p/0x%p)", tcon->fscache, |
| 73 | cifsi->fscache); | 74 | cifsi->fscache); |
| 75 | } | ||
| 74 | } | 76 | } |
| 75 | 77 | ||
| 76 | void cifs_fscache_release_inode_cookie(struct inode *inode) | 78 | void cifs_fscache_release_inode_cookie(struct inode *inode) |
| @@ -101,10 +103,8 @@ void cifs_fscache_set_inode_cookie(struct inode *inode, struct file *filp) | |||
| 101 | { | 103 | { |
| 102 | if ((filp->f_flags & O_ACCMODE) != O_RDONLY) | 104 | if ((filp->f_flags & O_ACCMODE) != O_RDONLY) |
| 103 | cifs_fscache_disable_inode_cookie(inode); | 105 | cifs_fscache_disable_inode_cookie(inode); |
| 104 | else { | 106 | else |
| 105 | cifs_fscache_enable_inode_cookie(inode); | 107 | cifs_fscache_enable_inode_cookie(inode); |
| 106 | cFYI(1, "CIFS: fscache inode cookie set"); | ||
| 107 | } | ||
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | void cifs_fscache_reset_inode_cookie(struct inode *inode) | 110 | void cifs_fscache_reset_inode_cookie(struct inode *inode) |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index ef3a55bf86b6..28cb6e735943 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
| @@ -689,8 +689,13 @@ int cifs_get_inode_info(struct inode **pinode, | |||
| 689 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 689 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 690 | /* fill in 0777 bits from ACL */ | 690 | /* fill in 0777 bits from ACL */ |
| 691 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | 691 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
| 692 | cFYI(1, "Getting mode bits from ACL"); | 692 | rc = cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, |
| 693 | cifs_acl_to_fattr(cifs_sb, &fattr, *pinode, full_path, pfid); | 693 | pfid); |
| 694 | if (rc) { | ||
| 695 | cFYI(1, "%s: Getting ACL failed with error: %d", | ||
| 696 | __func__, rc); | ||
| 697 | goto cgii_exit; | ||
| 698 | } | ||
| 694 | } | 699 | } |
| 695 | #endif | 700 | #endif |
| 696 | 701 | ||
| @@ -881,8 +886,10 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
| 881 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, | 886 | rc = cifs_get_inode_info(&inode, full_path, NULL, sb, |
| 882 | xid, NULL); | 887 | xid, NULL); |
| 883 | 888 | ||
| 884 | if (!inode) | 889 | if (!inode) { |
| 885 | return ERR_PTR(rc); | 890 | inode = ERR_PTR(rc); |
| 891 | goto out; | ||
| 892 | } | ||
| 886 | 893 | ||
| 887 | #ifdef CONFIG_CIFS_FSCACHE | 894 | #ifdef CONFIG_CIFS_FSCACHE |
| 888 | /* populate tcon->resource_id */ | 895 | /* populate tcon->resource_id */ |
| @@ -898,13 +905,11 @@ struct inode *cifs_root_iget(struct super_block *sb, unsigned long ino) | |||
| 898 | inode->i_uid = cifs_sb->mnt_uid; | 905 | inode->i_uid = cifs_sb->mnt_uid; |
| 899 | inode->i_gid = cifs_sb->mnt_gid; | 906 | inode->i_gid = cifs_sb->mnt_gid; |
| 900 | } else if (rc) { | 907 | } else if (rc) { |
| 901 | kfree(full_path); | ||
| 902 | _FreeXid(xid); | ||
| 903 | iget_failed(inode); | 908 | iget_failed(inode); |
| 904 | return ERR_PTR(rc); | 909 | inode = ERR_PTR(rc); |
| 905 | } | 910 | } |
| 906 | 911 | ||
| 907 | 912 | out: | |
| 908 | kfree(full_path); | 913 | kfree(full_path); |
| 909 | /* can not call macro FreeXid here since in a void func | 914 | /* can not call macro FreeXid here since in a void func |
| 910 | * TODO: This is no longer true | 915 | * TODO: This is no longer true |
| @@ -1670,7 +1675,9 @@ cifs_inode_needs_reval(struct inode *inode) | |||
| 1670 | return false; | 1675 | return false; |
| 1671 | } | 1676 | } |
| 1672 | 1677 | ||
| 1673 | /* check invalid_mapping flag and zap the cache if it's set */ | 1678 | /* |
| 1679 | * Zap the cache. Called when invalid_mapping flag is set. | ||
| 1680 | */ | ||
| 1674 | static void | 1681 | static void |
| 1675 | cifs_invalidate_mapping(struct inode *inode) | 1682 | cifs_invalidate_mapping(struct inode *inode) |
| 1676 | { | 1683 | { |
| @@ -2115,9 +2122,14 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) | |||
| 2115 | if (attrs->ia_valid & ATTR_MODE) { | 2122 | if (attrs->ia_valid & ATTR_MODE) { |
| 2116 | rc = 0; | 2123 | rc = 0; |
| 2117 | #ifdef CONFIG_CIFS_EXPERIMENTAL | 2124 | #ifdef CONFIG_CIFS_EXPERIMENTAL |
| 2118 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) | 2125 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { |
| 2119 | rc = mode_to_acl(inode, full_path, mode); | 2126 | rc = mode_to_cifs_acl(inode, full_path, mode); |
| 2120 | else | 2127 | if (rc) { |
| 2128 | cFYI(1, "%s: Setting ACL failed with error: %d", | ||
| 2129 | __func__, rc); | ||
| 2130 | goto cifs_setattr_exit; | ||
| 2131 | } | ||
| 2132 | } else | ||
| 2121 | #endif | 2133 | #endif |
| 2122 | if (((mode & S_IWUGO) == 0) && | 2134 | if (((mode & S_IWUGO) == 0) && |
| 2123 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { | 2135 | (cifsInode->cifsAttrs & ATTR_READONLY) == 0) { |
diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index ef7bb7b50f58..32d300e8f20e 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c | |||
| @@ -226,26 +226,29 @@ static int initiate_cifs_search(const int xid, struct file *file) | |||
| 226 | char *full_path = NULL; | 226 | char *full_path = NULL; |
| 227 | struct cifsFileInfo *cifsFile; | 227 | struct cifsFileInfo *cifsFile; |
| 228 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | 228 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); |
| 229 | struct tcon_link *tlink; | 229 | struct tcon_link *tlink = NULL; |
| 230 | struct cifsTconInfo *pTcon; | 230 | struct cifsTconInfo *pTcon; |
| 231 | 231 | ||
| 232 | tlink = cifs_sb_tlink(cifs_sb); | ||
| 233 | if (IS_ERR(tlink)) | ||
| 234 | return PTR_ERR(tlink); | ||
| 235 | pTcon = tlink_tcon(tlink); | ||
| 236 | |||
| 237 | if (file->private_data == NULL) | ||
| 238 | file->private_data = | ||
| 239 | kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | ||
| 240 | if (file->private_data == NULL) { | 232 | if (file->private_data == NULL) { |
| 241 | rc = -ENOMEM; | 233 | tlink = cifs_sb_tlink(cifs_sb); |
| 242 | goto error_exit; | 234 | if (IS_ERR(tlink)) |
| 235 | return PTR_ERR(tlink); | ||
| 236 | |||
| 237 | cifsFile = kzalloc(sizeof(struct cifsFileInfo), GFP_KERNEL); | ||
| 238 | if (cifsFile == NULL) { | ||
| 239 | rc = -ENOMEM; | ||
| 240 | goto error_exit; | ||
| 241 | } | ||
| 242 | file->private_data = cifsFile; | ||
| 243 | cifsFile->tlink = cifs_get_tlink(tlink); | ||
| 244 | pTcon = tlink_tcon(tlink); | ||
| 245 | } else { | ||
| 246 | cifsFile = file->private_data; | ||
| 247 | pTcon = tlink_tcon(cifsFile->tlink); | ||
| 243 | } | 248 | } |
| 244 | 249 | ||
| 245 | cifsFile = file->private_data; | ||
| 246 | cifsFile->invalidHandle = true; | 250 | cifsFile->invalidHandle = true; |
| 247 | cifsFile->srch_inf.endOfSearch = false; | 251 | cifsFile->srch_inf.endOfSearch = false; |
| 248 | cifsFile->tlink = cifs_get_tlink(tlink); | ||
| 249 | 252 | ||
| 250 | full_path = build_path_from_dentry(file->f_path.dentry); | 253 | full_path = build_path_from_dentry(file->f_path.dentry); |
| 251 | if (full_path == NULL) { | 254 | if (full_path == NULL) { |
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index a264b744bb41..eae2a1491608 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c | |||
| @@ -30,10 +30,11 @@ | |||
| 30 | 30 | ||
| 31 | #define MAX_EA_VALUE_SIZE 65535 | 31 | #define MAX_EA_VALUE_SIZE 65535 |
| 32 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" | 32 | #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" |
| 33 | #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" | ||
| 33 | #define CIFS_XATTR_USER_PREFIX "user." | 34 | #define CIFS_XATTR_USER_PREFIX "user." |
| 34 | #define CIFS_XATTR_SYSTEM_PREFIX "system." | 35 | #define CIFS_XATTR_SYSTEM_PREFIX "system." |
| 35 | #define CIFS_XATTR_OS2_PREFIX "os2." | 36 | #define CIFS_XATTR_OS2_PREFIX "os2." |
| 36 | #define CIFS_XATTR_SECURITY_PREFIX ".security" | 37 | #define CIFS_XATTR_SECURITY_PREFIX "security." |
| 37 | #define CIFS_XATTR_TRUSTED_PREFIX "trusted." | 38 | #define CIFS_XATTR_TRUSTED_PREFIX "trusted." |
| 38 | #define XATTR_TRUSTED_PREFIX_LEN 8 | 39 | #define XATTR_TRUSTED_PREFIX_LEN 8 |
| 39 | #define XATTR_SECURITY_PREFIX_LEN 9 | 40 | #define XATTR_SECURITY_PREFIX_LEN 9 |
| @@ -277,29 +278,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
| 277 | cifs_sb->local_nls, | 278 | cifs_sb->local_nls, |
| 278 | cifs_sb->mnt_cifs_flags & | 279 | cifs_sb->mnt_cifs_flags & |
| 279 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 280 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 280 | #ifdef CONFIG_CIFS_EXPERIMENTAL | ||
| 281 | else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { | ||
| 282 | __u16 fid; | ||
| 283 | int oplock = 0; | ||
| 284 | struct cifs_ntsd *pacl = NULL; | ||
| 285 | __u32 buflen = 0; | ||
| 286 | if (experimEnabled) | ||
| 287 | rc = CIFSSMBOpen(xid, pTcon, full_path, | ||
| 288 | FILE_OPEN, GENERIC_READ, 0, &fid, | ||
| 289 | &oplock, NULL, cifs_sb->local_nls, | ||
| 290 | cifs_sb->mnt_cifs_flags & | ||
| 291 | CIFS_MOUNT_MAP_SPECIAL_CHR); | ||
| 292 | /* else rc is EOPNOTSUPP from above */ | ||
| 293 | |||
| 294 | if (rc == 0) { | ||
| 295 | rc = CIFSSMBGetCIFSACL(xid, pTcon, fid, &pacl, | ||
| 296 | &buflen); | ||
| 297 | CIFSSMBClose(xid, pTcon, fid); | ||
| 298 | } | ||
| 299 | } | ||
| 300 | #endif /* EXPERIMENTAL */ | ||
| 301 | #else | 281 | #else |
| 302 | cFYI(1, "query POSIX ACL not supported yet"); | 282 | cFYI(1, "Query POSIX ACL not supported yet"); |
| 303 | #endif /* CONFIG_CIFS_POSIX */ | 283 | #endif /* CONFIG_CIFS_POSIX */ |
| 304 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, | 284 | } else if (strncmp(ea_name, POSIX_ACL_XATTR_DEFAULT, |
| 305 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { | 285 | strlen(POSIX_ACL_XATTR_DEFAULT)) == 0) { |
| @@ -311,8 +291,33 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, | |||
| 311 | cifs_sb->mnt_cifs_flags & | 291 | cifs_sb->mnt_cifs_flags & |
| 312 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 292 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 313 | #else | 293 | #else |
| 314 | cFYI(1, "query POSIX default ACL not supported yet"); | 294 | cFYI(1, "Query POSIX default ACL not supported yet"); |
| 315 | #endif | 295 | #endif /* CONFIG_CIFS_POSIX */ |
| 296 | } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, | ||
| 297 | strlen(CIFS_XATTR_CIFS_ACL)) == 0) { | ||
| 298 | #ifdef CONFIG_CIFS_ACL | ||
| 299 | u32 acllen; | ||
| 300 | struct cifs_ntsd *pacl; | ||
| 301 | |||
| 302 | pacl = get_cifs_acl(cifs_sb, direntry->d_inode, | ||
| 303 | full_path, &acllen); | ||
| 304 | if (IS_ERR(pacl)) { | ||
| 305 | rc = PTR_ERR(pacl); | ||
| 306 | cERROR(1, "%s: error %zd getting sec desc", | ||
| 307 | __func__, rc); | ||
| 308 | } else { | ||
| 309 | if (ea_value) { | ||
| 310 | if (acllen > buf_size) | ||
| 311 | acllen = -ERANGE; | ||
| 312 | else | ||
| 313 | memcpy(ea_value, pacl, acllen); | ||
| 314 | } | ||
| 315 | rc = acllen; | ||
| 316 | kfree(pacl); | ||
| 317 | } | ||
| 318 | #else | ||
| 319 | cFYI(1, "Query CIFS ACL not supported yet"); | ||
| 320 | #endif /* CONFIG_CIFS_ACL */ | ||
| 316 | } else if (strncmp(ea_name, | 321 | } else if (strncmp(ea_name, |
| 317 | CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { | 322 | CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { |
| 318 | cFYI(1, "Trusted xattr namespace not supported yet"); | 323 | cFYI(1, "Trusted xattr namespace not supported yet"); |
diff --git a/fs/compat.c b/fs/compat.c index c580c322fa6b..eb1740ac8c0a 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
| @@ -1350,6 +1350,10 @@ static int compat_count(compat_uptr_t __user *argv, int max) | |||
| 1350 | argv++; | 1350 | argv++; |
| 1351 | if (i++ >= max) | 1351 | if (i++ >= max) |
| 1352 | return -E2BIG; | 1352 | return -E2BIG; |
| 1353 | |||
| 1354 | if (fatal_signal_pending(current)) | ||
| 1355 | return -ERESTARTNOHAND; | ||
| 1356 | cond_resched(); | ||
| 1353 | } | 1357 | } |
| 1354 | } | 1358 | } |
| 1355 | return i; | 1359 | return i; |
| @@ -1391,6 +1395,12 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, | |||
| 1391 | while (len > 0) { | 1395 | while (len > 0) { |
| 1392 | int offset, bytes_to_copy; | 1396 | int offset, bytes_to_copy; |
| 1393 | 1397 | ||
| 1398 | if (fatal_signal_pending(current)) { | ||
| 1399 | ret = -ERESTARTNOHAND; | ||
| 1400 | goto out; | ||
| 1401 | } | ||
| 1402 | cond_resched(); | ||
| 1403 | |||
| 1394 | offset = pos % PAGE_SIZE; | 1404 | offset = pos % PAGE_SIZE; |
| 1395 | if (offset == 0) | 1405 | if (offset == 0) |
| 1396 | offset = PAGE_SIZE; | 1406 | offset = PAGE_SIZE; |
| @@ -1407,18 +1417,8 @@ static int compat_copy_strings(int argc, compat_uptr_t __user *argv, | |||
| 1407 | if (!kmapped_page || kpos != (pos & PAGE_MASK)) { | 1417 | if (!kmapped_page || kpos != (pos & PAGE_MASK)) { |
| 1408 | struct page *page; | 1418 | struct page *page; |
| 1409 | 1419 | ||
| 1410 | #ifdef CONFIG_STACK_GROWSUP | 1420 | page = get_arg_page(bprm, pos, 1); |
| 1411 | ret = expand_stack_downwards(bprm->vma, pos); | 1421 | if (!page) { |
| 1412 | if (ret < 0) { | ||
| 1413 | /* We've exceed the stack rlimit. */ | ||
| 1414 | ret = -E2BIG; | ||
| 1415 | goto out; | ||
| 1416 | } | ||
| 1417 | #endif | ||
| 1418 | ret = get_user_pages(current, bprm->mm, pos, | ||
| 1419 | 1, 1, 1, &page, NULL); | ||
| 1420 | if (ret <= 0) { | ||
| 1421 | /* We've exceed the stack rlimit. */ | ||
| 1422 | ret = -E2BIG; | 1422 | ret = -E2BIG; |
| 1423 | goto out; | 1423 | goto out; |
| 1424 | } | 1424 | } |
| @@ -1539,8 +1539,10 @@ int compat_do_execve(char * filename, | |||
| 1539 | return retval; | 1539 | return retval; |
| 1540 | 1540 | ||
| 1541 | out: | 1541 | out: |
| 1542 | if (bprm->mm) | 1542 | if (bprm->mm) { |
| 1543 | acct_arg_size(bprm, 0); | ||
| 1543 | mmput(bprm->mm); | 1544 | mmput(bprm->mm); |
| 1545 | } | ||
| 1544 | 1546 | ||
| 1545 | out_file: | 1547 | out_file: |
| 1546 | if (bprm->file) { | 1548 | if (bprm->file) { |
| @@ -164,7 +164,26 @@ out: | |||
| 164 | 164 | ||
| 165 | #ifdef CONFIG_MMU | 165 | #ifdef CONFIG_MMU |
| 166 | 166 | ||
| 167 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 167 | void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) |
| 168 | { | ||
| 169 | struct mm_struct *mm = current->mm; | ||
| 170 | long diff = (long)(pages - bprm->vma_pages); | ||
| 171 | |||
| 172 | if (!mm || !diff) | ||
| 173 | return; | ||
| 174 | |||
| 175 | bprm->vma_pages = pages; | ||
| 176 | |||
| 177 | #ifdef SPLIT_RSS_COUNTING | ||
| 178 | add_mm_counter(mm, MM_ANONPAGES, diff); | ||
| 179 | #else | ||
| 180 | spin_lock(&mm->page_table_lock); | ||
| 181 | add_mm_counter(mm, MM_ANONPAGES, diff); | ||
| 182 | spin_unlock(&mm->page_table_lock); | ||
| 183 | #endif | ||
| 184 | } | ||
| 185 | |||
| 186 | struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | ||
| 168 | int write) | 187 | int write) |
| 169 | { | 188 | { |
| 170 | struct page *page; | 189 | struct page *page; |
| @@ -186,6 +205,8 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | |||
| 186 | unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; | 205 | unsigned long size = bprm->vma->vm_end - bprm->vma->vm_start; |
| 187 | struct rlimit *rlim; | 206 | struct rlimit *rlim; |
| 188 | 207 | ||
| 208 | acct_arg_size(bprm, size / PAGE_SIZE); | ||
| 209 | |||
| 189 | /* | 210 | /* |
| 190 | * We've historically supported up to 32 pages (ARG_MAX) | 211 | * We've historically supported up to 32 pages (ARG_MAX) |
| 191 | * of argument strings even with small stacks | 212 | * of argument strings even with small stacks |
| @@ -276,7 +297,11 @@ static bool valid_arg_len(struct linux_binprm *bprm, long len) | |||
| 276 | 297 | ||
| 277 | #else | 298 | #else |
| 278 | 299 | ||
| 279 | static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | 300 | void acct_arg_size(struct linux_binprm *bprm, unsigned long pages) |
| 301 | { | ||
| 302 | } | ||
| 303 | |||
| 304 | struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos, | ||
| 280 | int write) | 305 | int write) |
| 281 | { | 306 | { |
| 282 | struct page *page; | 307 | struct page *page; |
| @@ -1003,6 +1028,7 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
| 1003 | /* | 1028 | /* |
| 1004 | * Release all of the old mmap stuff | 1029 | * Release all of the old mmap stuff |
| 1005 | */ | 1030 | */ |
| 1031 | acct_arg_size(bprm, 0); | ||
| 1006 | retval = exec_mmap(bprm->mm); | 1032 | retval = exec_mmap(bprm->mm); |
| 1007 | if (retval) | 1033 | if (retval) |
| 1008 | goto out; | 1034 | goto out; |
| @@ -1426,8 +1452,10 @@ int do_execve(const char * filename, | |||
| 1426 | return retval; | 1452 | return retval; |
| 1427 | 1453 | ||
| 1428 | out: | 1454 | out: |
| 1429 | if (bprm->mm) | 1455 | if (bprm->mm) { |
| 1430 | mmput (bprm->mm); | 1456 | acct_arg_size(bprm, 0); |
| 1457 | mmput(bprm->mm); | ||
| 1458 | } | ||
| 1431 | 1459 | ||
| 1432 | out_file: | 1460 | out_file: |
| 1433 | if (bprm->file) { | 1461 | if (bprm->file) { |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index c8224587123f..9242d294fe90 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
| @@ -134,6 +134,7 @@ EXPORT_SYMBOL_GPL(fuse_do_open); | |||
| 134 | void fuse_finish_open(struct inode *inode, struct file *file) | 134 | void fuse_finish_open(struct inode *inode, struct file *file) |
| 135 | { | 135 | { |
| 136 | struct fuse_file *ff = file->private_data; | 136 | struct fuse_file *ff = file->private_data; |
| 137 | struct fuse_conn *fc = get_fuse_conn(inode); | ||
| 137 | 138 | ||
| 138 | if (ff->open_flags & FOPEN_DIRECT_IO) | 139 | if (ff->open_flags & FOPEN_DIRECT_IO) |
| 139 | file->f_op = &fuse_direct_io_file_operations; | 140 | file->f_op = &fuse_direct_io_file_operations; |
| @@ -141,6 +142,15 @@ void fuse_finish_open(struct inode *inode, struct file *file) | |||
| 141 | invalidate_inode_pages2(inode->i_mapping); | 142 | invalidate_inode_pages2(inode->i_mapping); |
| 142 | if (ff->open_flags & FOPEN_NONSEEKABLE) | 143 | if (ff->open_flags & FOPEN_NONSEEKABLE) |
| 143 | nonseekable_open(inode, file); | 144 | nonseekable_open(inode, file); |
| 145 | if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) { | ||
| 146 | struct fuse_inode *fi = get_fuse_inode(inode); | ||
| 147 | |||
| 148 | spin_lock(&fc->lock); | ||
| 149 | fi->attr_version = ++fc->attr_version; | ||
| 150 | i_size_write(inode, 0); | ||
| 151 | spin_unlock(&fc->lock); | ||
| 152 | fuse_invalidate_attr(inode); | ||
| 153 | } | ||
| 144 | } | 154 | } |
| 145 | 155 | ||
| 146 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir) | 156 | int fuse_open_common(struct inode *inode, struct file *file, bool isdir) |
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c index 58a9b9998b42..f606baf9ba72 100644 --- a/fs/gfs2/quota.c +++ b/fs/gfs2/quota.c | |||
| @@ -631,6 +631,7 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
| 631 | struct fs_disk_quota *fdq) | 631 | struct fs_disk_quota *fdq) |
| 632 | { | 632 | { |
| 633 | struct inode *inode = &ip->i_inode; | 633 | struct inode *inode = &ip->i_inode; |
| 634 | struct gfs2_sbd *sdp = GFS2_SB(inode); | ||
| 634 | struct address_space *mapping = inode->i_mapping; | 635 | struct address_space *mapping = inode->i_mapping; |
| 635 | unsigned long index = loc >> PAGE_CACHE_SHIFT; | 636 | unsigned long index = loc >> PAGE_CACHE_SHIFT; |
| 636 | unsigned offset = loc & (PAGE_CACHE_SIZE - 1); | 637 | unsigned offset = loc & (PAGE_CACHE_SIZE - 1); |
| @@ -658,11 +659,11 @@ static int gfs2_adjust_quota(struct gfs2_inode *ip, loff_t loc, | |||
| 658 | qd->qd_qb.qb_value = qp->qu_value; | 659 | qd->qd_qb.qb_value = qp->qu_value; |
| 659 | if (fdq) { | 660 | if (fdq) { |
| 660 | if (fdq->d_fieldmask & FS_DQ_BSOFT) { | 661 | if (fdq->d_fieldmask & FS_DQ_BSOFT) { |
| 661 | qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit); | 662 | qp->qu_warn = cpu_to_be64(fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift); |
| 662 | qd->qd_qb.qb_warn = qp->qu_warn; | 663 | qd->qd_qb.qb_warn = qp->qu_warn; |
| 663 | } | 664 | } |
| 664 | if (fdq->d_fieldmask & FS_DQ_BHARD) { | 665 | if (fdq->d_fieldmask & FS_DQ_BHARD) { |
| 665 | qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit); | 666 | qp->qu_limit = cpu_to_be64(fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift); |
| 666 | qd->qd_qb.qb_limit = qp->qu_limit; | 667 | qd->qd_qb.qb_limit = qp->qu_limit; |
| 667 | } | 668 | } |
| 668 | } | 669 | } |
| @@ -1497,9 +1498,9 @@ static int gfs2_get_dqblk(struct super_block *sb, int type, qid_t id, | |||
| 1497 | fdq->d_version = FS_DQUOT_VERSION; | 1498 | fdq->d_version = FS_DQUOT_VERSION; |
| 1498 | fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA; | 1499 | fdq->d_flags = (type == QUOTA_USER) ? FS_USER_QUOTA : FS_GROUP_QUOTA; |
| 1499 | fdq->d_id = id; | 1500 | fdq->d_id = id; |
| 1500 | fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit); | 1501 | fdq->d_blk_hardlimit = be64_to_cpu(qlvb->qb_limit) << sdp->sd_fsb2bb_shift; |
| 1501 | fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn); | 1502 | fdq->d_blk_softlimit = be64_to_cpu(qlvb->qb_warn) << sdp->sd_fsb2bb_shift; |
| 1502 | fdq->d_bcount = be64_to_cpu(qlvb->qb_value); | 1503 | fdq->d_bcount = be64_to_cpu(qlvb->qb_value) << sdp->sd_fsb2bb_shift; |
| 1503 | 1504 | ||
| 1504 | gfs2_glock_dq_uninit(&q_gh); | 1505 | gfs2_glock_dq_uninit(&q_gh); |
| 1505 | out: | 1506 | out: |
| @@ -1566,10 +1567,10 @@ static int gfs2_set_dqblk(struct super_block *sb, int type, qid_t id, | |||
| 1566 | 1567 | ||
| 1567 | /* If nothing has changed, this is a no-op */ | 1568 | /* If nothing has changed, this is a no-op */ |
| 1568 | if ((fdq->d_fieldmask & FS_DQ_BSOFT) && | 1569 | if ((fdq->d_fieldmask & FS_DQ_BSOFT) && |
| 1569 | (fdq->d_blk_softlimit == be64_to_cpu(qd->qd_qb.qb_warn))) | 1570 | ((fdq->d_blk_softlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_warn))) |
| 1570 | fdq->d_fieldmask ^= FS_DQ_BSOFT; | 1571 | fdq->d_fieldmask ^= FS_DQ_BSOFT; |
| 1571 | if ((fdq->d_fieldmask & FS_DQ_BHARD) && | 1572 | if ((fdq->d_fieldmask & FS_DQ_BHARD) && |
| 1572 | (fdq->d_blk_hardlimit == be64_to_cpu(qd->qd_qb.qb_limit))) | 1573 | ((fdq->d_blk_hardlimit >> sdp->sd_fsb2bb_shift) == be64_to_cpu(qd->qd_qb.qb_limit))) |
| 1573 | fdq->d_fieldmask ^= FS_DQ_BHARD; | 1574 | fdq->d_fieldmask ^= FS_DQ_BHARD; |
| 1574 | if (fdq->d_fieldmask == 0) | 1575 | if (fdq->d_fieldmask == 0) |
| 1575 | goto out_i; | 1576 | goto out_i; |
diff --git a/fs/ioprio.c b/fs/ioprio.c index 2f7d05c89922..7da2a06508e5 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c | |||
| @@ -103,22 +103,15 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | ret = -ESRCH; | 105 | ret = -ESRCH; |
| 106 | /* | 106 | rcu_read_lock(); |
| 107 | * We want IOPRIO_WHO_PGRP/IOPRIO_WHO_USER to be "atomic", | ||
| 108 | * so we can't use rcu_read_lock(). See re-copy of ->ioprio | ||
| 109 | * in copy_process(). | ||
| 110 | */ | ||
| 111 | read_lock(&tasklist_lock); | ||
| 112 | switch (which) { | 107 | switch (which) { |
| 113 | case IOPRIO_WHO_PROCESS: | 108 | case IOPRIO_WHO_PROCESS: |
| 114 | rcu_read_lock(); | ||
| 115 | if (!who) | 109 | if (!who) |
| 116 | p = current; | 110 | p = current; |
| 117 | else | 111 | else |
| 118 | p = find_task_by_vpid(who); | 112 | p = find_task_by_vpid(who); |
| 119 | if (p) | 113 | if (p) |
| 120 | ret = set_task_ioprio(p, ioprio); | 114 | ret = set_task_ioprio(p, ioprio); |
| 121 | rcu_read_unlock(); | ||
| 122 | break; | 115 | break; |
| 123 | case IOPRIO_WHO_PGRP: | 116 | case IOPRIO_WHO_PGRP: |
| 124 | if (!who) | 117 | if (!who) |
| @@ -141,12 +134,7 @@ SYSCALL_DEFINE3(ioprio_set, int, which, int, who, int, ioprio) | |||
| 141 | break; | 134 | break; |
| 142 | 135 | ||
| 143 | do_each_thread(g, p) { | 136 | do_each_thread(g, p) { |
| 144 | int match; | 137 | if (__task_cred(p)->uid != who) |
| 145 | |||
| 146 | rcu_read_lock(); | ||
| 147 | match = __task_cred(p)->uid == who; | ||
| 148 | rcu_read_unlock(); | ||
| 149 | if (!match) | ||
| 150 | continue; | 138 | continue; |
| 151 | ret = set_task_ioprio(p, ioprio); | 139 | ret = set_task_ioprio(p, ioprio); |
| 152 | if (ret) | 140 | if (ret) |
| @@ -160,7 +148,7 @@ free_uid: | |||
| 160 | ret = -EINVAL; | 148 | ret = -EINVAL; |
| 161 | } | 149 | } |
| 162 | 150 | ||
| 163 | read_unlock(&tasklist_lock); | 151 | rcu_read_unlock(); |
| 164 | return ret; | 152 | return ret; |
| 165 | } | 153 | } |
| 166 | 154 | ||
| @@ -204,17 +192,15 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) | |||
| 204 | int ret = -ESRCH; | 192 | int ret = -ESRCH; |
| 205 | int tmpio; | 193 | int tmpio; |
| 206 | 194 | ||
| 207 | read_lock(&tasklist_lock); | 195 | rcu_read_lock(); |
| 208 | switch (which) { | 196 | switch (which) { |
| 209 | case IOPRIO_WHO_PROCESS: | 197 | case IOPRIO_WHO_PROCESS: |
| 210 | rcu_read_lock(); | ||
| 211 | if (!who) | 198 | if (!who) |
| 212 | p = current; | 199 | p = current; |
| 213 | else | 200 | else |
| 214 | p = find_task_by_vpid(who); | 201 | p = find_task_by_vpid(who); |
| 215 | if (p) | 202 | if (p) |
| 216 | ret = get_task_ioprio(p); | 203 | ret = get_task_ioprio(p); |
| 217 | rcu_read_unlock(); | ||
| 218 | break; | 204 | break; |
| 219 | case IOPRIO_WHO_PGRP: | 205 | case IOPRIO_WHO_PGRP: |
| 220 | if (!who) | 206 | if (!who) |
| @@ -241,12 +227,7 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) | |||
| 241 | break; | 227 | break; |
| 242 | 228 | ||
| 243 | do_each_thread(g, p) { | 229 | do_each_thread(g, p) { |
| 244 | int match; | 230 | if (__task_cred(p)->uid != user->uid) |
| 245 | |||
| 246 | rcu_read_lock(); | ||
| 247 | match = __task_cred(p)->uid == user->uid; | ||
| 248 | rcu_read_unlock(); | ||
| 249 | if (!match) | ||
| 250 | continue; | 231 | continue; |
| 251 | tmpio = get_task_ioprio(p); | 232 | tmpio = get_task_ioprio(p); |
| 252 | if (tmpio < 0) | 233 | if (tmpio < 0) |
| @@ -264,6 +245,6 @@ SYSCALL_DEFINE2(ioprio_get, int, which, int, who) | |||
| 264 | ret = -EINVAL; | 245 | ret = -EINVAL; |
| 265 | } | 246 | } |
| 266 | 247 | ||
| 267 | read_unlock(&tasklist_lock); | 248 | rcu_read_unlock(); |
| 268 | return ret; | 249 | return ret; |
| 269 | } | 250 | } |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 662df2a5fad5..f0a384e2ae63 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -162,6 +162,7 @@ struct nfs_cache_array_entry { | |||
| 162 | u64 cookie; | 162 | u64 cookie; |
| 163 | u64 ino; | 163 | u64 ino; |
| 164 | struct qstr string; | 164 | struct qstr string; |
| 165 | unsigned char d_type; | ||
| 165 | }; | 166 | }; |
| 166 | 167 | ||
| 167 | struct nfs_cache_array { | 168 | struct nfs_cache_array { |
| @@ -171,8 +172,6 @@ struct nfs_cache_array { | |||
| 171 | struct nfs_cache_array_entry array[0]; | 172 | struct nfs_cache_array_entry array[0]; |
| 172 | }; | 173 | }; |
| 173 | 174 | ||
| 174 | #define MAX_READDIR_ARRAY ((PAGE_SIZE - sizeof(struct nfs_cache_array)) / sizeof(struct nfs_cache_array_entry)) | ||
| 175 | |||
| 176 | typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); | 175 | typedef __be32 * (*decode_dirent_t)(struct xdr_stream *, struct nfs_entry *, struct nfs_server *, int); |
| 177 | typedef struct { | 176 | typedef struct { |
| 178 | struct file *file; | 177 | struct file *file; |
| @@ -257,13 +256,17 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) | |||
| 257 | 256 | ||
| 258 | if (IS_ERR(array)) | 257 | if (IS_ERR(array)) |
| 259 | return PTR_ERR(array); | 258 | return PTR_ERR(array); |
| 259 | |||
| 260 | cache_entry = &array->array[array->size]; | ||
| 261 | |||
| 262 | /* Check that this entry lies within the page bounds */ | ||
| 260 | ret = -ENOSPC; | 263 | ret = -ENOSPC; |
| 261 | if (array->size >= MAX_READDIR_ARRAY) | 264 | if ((char *)&cache_entry[1] - (char *)page_address(page) > PAGE_SIZE) |
| 262 | goto out; | 265 | goto out; |
| 263 | 266 | ||
| 264 | cache_entry = &array->array[array->size]; | ||
| 265 | cache_entry->cookie = entry->prev_cookie; | 267 | cache_entry->cookie = entry->prev_cookie; |
| 266 | cache_entry->ino = entry->ino; | 268 | cache_entry->ino = entry->ino; |
| 269 | cache_entry->d_type = entry->d_type; | ||
| 267 | ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); | 270 | ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len); |
| 268 | if (ret) | 271 | if (ret) |
| 269 | goto out; | 272 | goto out; |
| @@ -392,13 +395,9 @@ int xdr_decode(nfs_readdir_descriptor_t *desc, struct nfs_entry *entry, struct x | |||
| 392 | static | 395 | static |
| 393 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) | 396 | int nfs_same_file(struct dentry *dentry, struct nfs_entry *entry) |
| 394 | { | 397 | { |
| 395 | struct nfs_inode *node; | ||
| 396 | if (dentry->d_inode == NULL) | 398 | if (dentry->d_inode == NULL) |
| 397 | goto different; | 399 | goto different; |
| 398 | node = NFS_I(dentry->d_inode); | 400 | if (nfs_compare_fh(entry->fh, NFS_FH(dentry->d_inode)) != 0) |
| 399 | if (node->fh.size != entry->fh->size) | ||
| 400 | goto different; | ||
| 401 | if (strncmp(node->fh.data, entry->fh->data, node->fh.size) != 0) | ||
| 402 | goto different; | 401 | goto different; |
| 403 | return 1; | 402 | return 1; |
| 404 | different: | 403 | different: |
| @@ -466,8 +465,9 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en | |||
| 466 | struct xdr_stream stream; | 465 | struct xdr_stream stream; |
| 467 | struct xdr_buf buf; | 466 | struct xdr_buf buf; |
| 468 | __be32 *ptr = xdr_page; | 467 | __be32 *ptr = xdr_page; |
| 469 | int status; | ||
| 470 | struct nfs_cache_array *array; | 468 | struct nfs_cache_array *array; |
| 469 | unsigned int count = 0; | ||
| 470 | int status; | ||
| 471 | 471 | ||
| 472 | buf.head->iov_base = xdr_page; | 472 | buf.head->iov_base = xdr_page; |
| 473 | buf.head->iov_len = buflen; | 473 | buf.head->iov_len = buflen; |
| @@ -488,6 +488,8 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en | |||
| 488 | break; | 488 | break; |
| 489 | } | 489 | } |
| 490 | 490 | ||
| 491 | count++; | ||
| 492 | |||
| 491 | if (desc->plus == 1) | 493 | if (desc->plus == 1) |
| 492 | nfs_prime_dcache(desc->file->f_path.dentry, entry); | 494 | nfs_prime_dcache(desc->file->f_path.dentry, entry); |
| 493 | 495 | ||
| @@ -496,13 +498,14 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en | |||
| 496 | break; | 498 | break; |
| 497 | } while (!entry->eof); | 499 | } while (!entry->eof); |
| 498 | 500 | ||
| 499 | if (status == -EBADCOOKIE && entry->eof) { | 501 | if (count == 0 || (status == -EBADCOOKIE && entry->eof == 1)) { |
| 500 | array = nfs_readdir_get_array(page); | 502 | array = nfs_readdir_get_array(page); |
| 501 | if (!IS_ERR(array)) { | 503 | if (!IS_ERR(array)) { |
| 502 | array->eof_index = array->size; | 504 | array->eof_index = array->size; |
| 503 | status = 0; | 505 | status = 0; |
| 504 | nfs_readdir_release_array(page); | 506 | nfs_readdir_release_array(page); |
| 505 | } | 507 | } else |
| 508 | status = PTR_ERR(array); | ||
| 506 | } | 509 | } |
| 507 | return status; | 510 | return status; |
| 508 | } | 511 | } |
| @@ -696,21 +699,23 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
| 696 | int i = 0; | 699 | int i = 0; |
| 697 | int res = 0; | 700 | int res = 0; |
| 698 | struct nfs_cache_array *array = NULL; | 701 | struct nfs_cache_array *array = NULL; |
| 699 | unsigned int d_type = DT_UNKNOWN; | ||
| 700 | struct dentry *dentry = NULL; | ||
| 701 | 702 | ||
| 702 | array = nfs_readdir_get_array(desc->page); | 703 | array = nfs_readdir_get_array(desc->page); |
| 703 | if (IS_ERR(array)) | 704 | if (IS_ERR(array)) { |
| 704 | return PTR_ERR(array); | 705 | res = PTR_ERR(array); |
| 706 | goto out; | ||
| 707 | } | ||
| 705 | 708 | ||
| 706 | for (i = desc->cache_entry_index; i < array->size; i++) { | 709 | for (i = desc->cache_entry_index; i < array->size; i++) { |
| 707 | d_type = DT_UNKNOWN; | 710 | struct nfs_cache_array_entry *ent; |
| 708 | 711 | ||
| 709 | res = filldir(dirent, array->array[i].string.name, | 712 | ent = &array->array[i]; |
| 710 | array->array[i].string.len, file->f_pos, | 713 | if (filldir(dirent, ent->string.name, ent->string.len, |
| 711 | nfs_compat_user_ino64(array->array[i].ino), d_type); | 714 | file->f_pos, nfs_compat_user_ino64(ent->ino), |
| 712 | if (res < 0) | 715 | ent->d_type) < 0) { |
| 716 | desc->eof = 1; | ||
| 713 | break; | 717 | break; |
| 718 | } | ||
| 714 | file->f_pos++; | 719 | file->f_pos++; |
| 715 | desc->cache_entry_index = i; | 720 | desc->cache_entry_index = i; |
| 716 | if (i < (array->size-1)) | 721 | if (i < (array->size-1)) |
| @@ -722,9 +727,8 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
| 722 | desc->eof = 1; | 727 | desc->eof = 1; |
| 723 | 728 | ||
| 724 | nfs_readdir_release_array(desc->page); | 729 | nfs_readdir_release_array(desc->page); |
| 730 | out: | ||
| 725 | cache_page_release(desc); | 731 | cache_page_release(desc); |
| 726 | if (dentry != NULL) | ||
| 727 | dput(dentry); | ||
| 728 | dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", | 732 | dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n", |
| 729 | (unsigned long long)*desc->dir_cookie, res); | 733 | (unsigned long long)*desc->dir_cookie, res); |
| 730 | return res; | 734 | return res; |
| @@ -759,13 +763,13 @@ int uncached_readdir(nfs_readdir_descriptor_t *desc, void *dirent, | |||
| 759 | goto out; | 763 | goto out; |
| 760 | } | 764 | } |
| 761 | 765 | ||
| 762 | if (nfs_readdir_xdr_to_array(desc, page, inode) == -1) { | ||
| 763 | status = -EIO; | ||
| 764 | goto out_release; | ||
| 765 | } | ||
| 766 | |||
| 767 | desc->page_index = 0; | 766 | desc->page_index = 0; |
| 768 | desc->page = page; | 767 | desc->page = page; |
| 768 | |||
| 769 | status = nfs_readdir_xdr_to_array(desc, page, inode); | ||
| 770 | if (status < 0) | ||
| 771 | goto out_release; | ||
| 772 | |||
| 769 | status = nfs_do_filldir(desc, dirent, filldir); | 773 | status = nfs_do_filldir(desc, dirent, filldir); |
| 770 | 774 | ||
| 771 | out: | 775 | out: |
| @@ -816,14 +820,14 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 816 | res = readdir_search_pagecache(desc); | 820 | res = readdir_search_pagecache(desc); |
| 817 | 821 | ||
| 818 | if (res == -EBADCOOKIE) { | 822 | if (res == -EBADCOOKIE) { |
| 823 | res = 0; | ||
| 819 | /* This means either end of directory */ | 824 | /* This means either end of directory */ |
| 820 | if (*desc->dir_cookie && desc->eof == 0) { | 825 | if (*desc->dir_cookie && desc->eof == 0) { |
| 821 | /* Or that the server has 'lost' a cookie */ | 826 | /* Or that the server has 'lost' a cookie */ |
| 822 | res = uncached_readdir(desc, dirent, filldir); | 827 | res = uncached_readdir(desc, dirent, filldir); |
| 823 | if (res >= 0) | 828 | if (res == 0) |
| 824 | continue; | 829 | continue; |
| 825 | } | 830 | } |
| 826 | res = 0; | ||
| 827 | break; | 831 | break; |
| 828 | } | 832 | } |
| 829 | if (res == -ETOOSMALL && desc->plus) { | 833 | if (res == -ETOOSMALL && desc->plus) { |
| @@ -838,10 +842,8 @@ static int nfs_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 838 | break; | 842 | break; |
| 839 | 843 | ||
| 840 | res = nfs_do_filldir(desc, dirent, filldir); | 844 | res = nfs_do_filldir(desc, dirent, filldir); |
| 841 | if (res < 0) { | 845 | if (res < 0) |
| 842 | res = 0; | ||
| 843 | break; | 846 | break; |
| 844 | } | ||
| 845 | } | 847 | } |
| 846 | out: | 848 | out: |
| 847 | nfs_unblock_sillyrename(dentry); | 849 | nfs_unblock_sillyrename(dentry); |
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 84d3c8b90206..e6ace0d93c71 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c | |||
| @@ -867,7 +867,7 @@ static ssize_t nfs_direct_write(struct kiocb *iocb, const struct iovec *iov, | |||
| 867 | goto out; | 867 | goto out; |
| 868 | nfs_alloc_commit_data(dreq); | 868 | nfs_alloc_commit_data(dreq); |
| 869 | 869 | ||
| 870 | if (dreq->commit_data == NULL || count < wsize) | 870 | if (dreq->commit_data == NULL || count <= wsize) |
| 871 | sync = NFS_FILE_SYNC; | 871 | sync = NFS_FILE_SYNC; |
| 872 | 872 | ||
| 873 | dreq->inode = inode; | 873 | dreq->inode = inode; |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index db08ff3ff454..e6356b750b77 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -362,6 +362,15 @@ unsigned int nfs_page_length(struct page *page) | |||
| 362 | } | 362 | } |
| 363 | 363 | ||
| 364 | /* | 364 | /* |
| 365 | * Convert a umode to a dirent->d_type | ||
| 366 | */ | ||
| 367 | static inline | ||
| 368 | unsigned char nfs_umode_to_dtype(umode_t mode) | ||
| 369 | { | ||
| 370 | return (mode >> 12) & 15; | ||
| 371 | } | ||
| 372 | |||
| 373 | /* | ||
| 365 | * Determine the number of pages in an array of length 'len' and | 374 | * Determine the number of pages in an array of length 'len' and |
| 366 | * with a base offset of 'base' | 375 | * with a base offset of 'base' |
| 367 | */ | 376 | */ |
diff --git a/fs/nfs/nfs2xdr.c b/fs/nfs/nfs2xdr.c index 2563f765c9b4..5914a1911c95 100644 --- a/fs/nfs/nfs2xdr.c +++ b/fs/nfs/nfs2xdr.c | |||
| @@ -485,6 +485,8 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se | |||
| 485 | entry->prev_cookie = entry->cookie; | 485 | entry->prev_cookie = entry->cookie; |
| 486 | entry->cookie = ntohl(*p++); | 486 | entry->cookie = ntohl(*p++); |
| 487 | 487 | ||
| 488 | entry->d_type = DT_UNKNOWN; | ||
| 489 | |||
| 488 | p = xdr_inline_peek(xdr, 8); | 490 | p = xdr_inline_peek(xdr, 8); |
| 489 | if (p != NULL) | 491 | if (p != NULL) |
| 490 | entry->eof = !p[0] && p[1]; | 492 | entry->eof = !p[0] && p[1]; |
| @@ -495,7 +497,7 @@ nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_se | |||
| 495 | 497 | ||
| 496 | out_overflow: | 498 | out_overflow: |
| 497 | print_overflow_msg(__func__, xdr); | 499 | print_overflow_msg(__func__, xdr); |
| 498 | return ERR_PTR(-EIO); | 500 | return ERR_PTR(-EAGAIN); |
| 499 | } | 501 | } |
| 500 | 502 | ||
| 501 | /* | 503 | /* |
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index 748dc91a4a14..f6cc60f06dac 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
| @@ -622,11 +622,13 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s | |||
| 622 | entry->prev_cookie = entry->cookie; | 622 | entry->prev_cookie = entry->cookie; |
| 623 | p = xdr_decode_hyper(p, &entry->cookie); | 623 | p = xdr_decode_hyper(p, &entry->cookie); |
| 624 | 624 | ||
| 625 | entry->d_type = DT_UNKNOWN; | ||
| 625 | if (plus) { | 626 | if (plus) { |
| 626 | entry->fattr->valid = 0; | 627 | entry->fattr->valid = 0; |
| 627 | p = xdr_decode_post_op_attr_stream(xdr, entry->fattr); | 628 | p = xdr_decode_post_op_attr_stream(xdr, entry->fattr); |
| 628 | if (IS_ERR(p)) | 629 | if (IS_ERR(p)) |
| 629 | goto out_overflow_exit; | 630 | goto out_overflow_exit; |
| 631 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); | ||
| 630 | /* In fact, a post_op_fh3: */ | 632 | /* In fact, a post_op_fh3: */ |
| 631 | p = xdr_inline_decode(xdr, 4); | 633 | p = xdr_inline_decode(xdr, 4); |
| 632 | if (unlikely(!p)) | 634 | if (unlikely(!p)) |
| @@ -656,7 +658,7 @@ nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_s | |||
| 656 | out_overflow: | 658 | out_overflow: |
| 657 | print_overflow_msg(__func__, xdr); | 659 | print_overflow_msg(__func__, xdr); |
| 658 | out_overflow_exit: | 660 | out_overflow_exit: |
| 659 | return ERR_PTR(-EIO); | 661 | return ERR_PTR(-EAGAIN); |
| 660 | } | 662 | } |
| 661 | 663 | ||
| 662 | /* | 664 | /* |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index b7a204ff6fe1..9f1826b012e6 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
| @@ -6208,6 +6208,10 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
| 6208 | if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) | 6208 | if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID) |
| 6209 | entry->ino = entry->fattr->fileid; | 6209 | entry->ino = entry->fattr->fileid; |
| 6210 | 6210 | ||
| 6211 | entry->d_type = DT_UNKNOWN; | ||
| 6212 | if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE) | ||
| 6213 | entry->d_type = nfs_umode_to_dtype(entry->fattr->mode); | ||
| 6214 | |||
| 6211 | if (verify_attr_len(xdr, p, len) < 0) | 6215 | if (verify_attr_len(xdr, p, len) < 0) |
| 6212 | goto out_overflow; | 6216 | goto out_overflow; |
| 6213 | 6217 | ||
| @@ -6221,7 +6225,7 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
| 6221 | 6225 | ||
| 6222 | out_overflow: | 6226 | out_overflow: |
| 6223 | print_overflow_msg(__func__, xdr); | 6227 | print_overflow_msg(__func__, xdr); |
| 6224 | return ERR_PTR(-EIO); | 6228 | return ERR_PTR(-EAGAIN); |
| 6225 | } | 6229 | } |
| 6226 | 6230 | ||
| 6227 | /* | 6231 | /* |
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c index 49c844dab33a..59e5fe742f7b 100644 --- a/fs/nilfs2/dat.c +++ b/fs/nilfs2/dat.c | |||
| @@ -335,7 +335,7 @@ int nilfs_dat_move(struct inode *dat, __u64 vblocknr, sector_t blocknr) | |||
| 335 | * the device at this point. | 335 | * the device at this point. |
| 336 | * | 336 | * |
| 337 | * To prevent nilfs_dat_translate() from returning the | 337 | * To prevent nilfs_dat_translate() from returning the |
| 338 | * uncommited block number, this makes a copy of the entry | 338 | * uncommitted block number, this makes a copy of the entry |
| 339 | * buffer and redirects nilfs_dat_translate() to the copy. | 339 | * buffer and redirects nilfs_dat_translate() to the copy. |
| 340 | */ | 340 | */ |
| 341 | if (!buffer_nilfs_redirected(entry_bh)) { | 341 | if (!buffer_nilfs_redirected(entry_bh)) { |
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c index 3e90f86d5bfe..e00d9457c256 100644 --- a/fs/nilfs2/ioctl.c +++ b/fs/nilfs2/ioctl.c | |||
| @@ -349,8 +349,8 @@ static int nilfs_ioctl_move_blocks(struct super_block *sb, | |||
| 349 | ino = vdesc->vd_ino; | 349 | ino = vdesc->vd_ino; |
| 350 | cno = vdesc->vd_cno; | 350 | cno = vdesc->vd_cno; |
| 351 | inode = nilfs_iget_for_gc(sb, ino, cno); | 351 | inode = nilfs_iget_for_gc(sb, ino, cno); |
| 352 | if (unlikely(inode == NULL)) { | 352 | if (IS_ERR(inode)) { |
| 353 | ret = -ENOMEM; | 353 | ret = PTR_ERR(inode); |
| 354 | goto failed; | 354 | goto failed; |
| 355 | } | 355 | } |
| 356 | do { | 356 | do { |
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c index 52c7557f3e25..9f26ac9be2a4 100644 --- a/fs/ocfs2/cluster/heartbeat.c +++ b/fs/ocfs2/cluster/heartbeat.c | |||
| @@ -1964,8 +1964,10 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g | |||
| 1964 | if (reg == NULL) | 1964 | if (reg == NULL) |
| 1965 | return ERR_PTR(-ENOMEM); | 1965 | return ERR_PTR(-ENOMEM); |
| 1966 | 1966 | ||
| 1967 | if (strlen(name) > O2HB_MAX_REGION_NAME_LEN) | 1967 | if (strlen(name) > O2HB_MAX_REGION_NAME_LEN) { |
| 1968 | return ERR_PTR(-ENAMETOOLONG); | 1968 | ret = -ENAMETOOLONG; |
| 1969 | goto free; | ||
| 1970 | } | ||
| 1969 | 1971 | ||
| 1970 | spin_lock(&o2hb_live_lock); | 1972 | spin_lock(&o2hb_live_lock); |
| 1971 | reg->hr_region_num = 0; | 1973 | reg->hr_region_num = 0; |
| @@ -1974,7 +1976,8 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g | |||
| 1974 | O2NM_MAX_REGIONS); | 1976 | O2NM_MAX_REGIONS); |
| 1975 | if (reg->hr_region_num >= O2NM_MAX_REGIONS) { | 1977 | if (reg->hr_region_num >= O2NM_MAX_REGIONS) { |
| 1976 | spin_unlock(&o2hb_live_lock); | 1978 | spin_unlock(&o2hb_live_lock); |
| 1977 | return ERR_PTR(-EFBIG); | 1979 | ret = -EFBIG; |
| 1980 | goto free; | ||
| 1978 | } | 1981 | } |
| 1979 | set_bit(reg->hr_region_num, o2hb_region_bitmap); | 1982 | set_bit(reg->hr_region_num, o2hb_region_bitmap); |
| 1980 | } | 1983 | } |
| @@ -1986,10 +1989,13 @@ static struct config_item *o2hb_heartbeat_group_make_item(struct config_group *g | |||
| 1986 | ret = o2hb_debug_region_init(reg, o2hb_debug_dir); | 1989 | ret = o2hb_debug_region_init(reg, o2hb_debug_dir); |
| 1987 | if (ret) { | 1990 | if (ret) { |
| 1988 | config_item_put(®->hr_item); | 1991 | config_item_put(®->hr_item); |
| 1989 | return ERR_PTR(ret); | 1992 | goto free; |
| 1990 | } | 1993 | } |
| 1991 | 1994 | ||
| 1992 | return ®->hr_item; | 1995 | return ®->hr_item; |
| 1996 | free: | ||
| 1997 | kfree(reg); | ||
| 1998 | return ERR_PTR(ret); | ||
| 1993 | } | 1999 | } |
| 1994 | 2000 | ||
| 1995 | static void o2hb_heartbeat_group_drop_item(struct config_group *group, | 2001 | static void o2hb_heartbeat_group_drop_item(struct config_group *group, |
diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index edaded48e7e9..895532ac4d98 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c | |||
| @@ -476,7 +476,6 @@ static void ocfs2_dentry_iput(struct dentry *dentry, struct inode *inode) | |||
| 476 | 476 | ||
| 477 | out: | 477 | out: |
| 478 | iput(inode); | 478 | iput(inode); |
| 479 | ocfs2_dentry_attach_gen(dentry); | ||
| 480 | } | 479 | } |
| 481 | 480 | ||
| 482 | /* | 481 | /* |
diff --git a/fs/ocfs2/dlm/dlmdomain.c b/fs/ocfs2/dlm/dlmdomain.c index 58a93b953735..cc2aaa96cfe5 100644 --- a/fs/ocfs2/dlm/dlmdomain.c +++ b/fs/ocfs2/dlm/dlmdomain.c | |||
| @@ -959,7 +959,7 @@ static int dlm_match_regions(struct dlm_ctxt *dlm, | |||
| 959 | r += O2HB_MAX_REGION_NAME_LEN; | 959 | r += O2HB_MAX_REGION_NAME_LEN; |
| 960 | } | 960 | } |
| 961 | 961 | ||
| 962 | local = kmalloc(sizeof(qr->qr_regions), GFP_KERNEL); | 962 | local = kmalloc(sizeof(qr->qr_regions), GFP_ATOMIC); |
| 963 | if (!local) { | 963 | if (!local) { |
| 964 | status = -ENOMEM; | 964 | status = -ENOMEM; |
| 965 | goto bail; | 965 | goto bail; |
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 1efea3615589..70dd3b1798f1 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h | |||
| @@ -159,9 +159,9 @@ struct ocfs2_lock_res { | |||
| 159 | char l_name[OCFS2_LOCK_ID_MAX_LEN]; | 159 | char l_name[OCFS2_LOCK_ID_MAX_LEN]; |
| 160 | unsigned int l_ro_holders; | 160 | unsigned int l_ro_holders; |
| 161 | unsigned int l_ex_holders; | 161 | unsigned int l_ex_holders; |
| 162 | char l_level; | 162 | signed char l_level; |
| 163 | char l_requested; | 163 | signed char l_requested; |
| 164 | char l_blocking; | 164 | signed char l_blocking; |
| 165 | 165 | ||
| 166 | /* Data packed - type enum ocfs2_lock_type */ | 166 | /* Data packed - type enum ocfs2_lock_type */ |
| 167 | unsigned char l_type; | 167 | unsigned char l_type; |
diff --git a/fs/ocfs2/stack_user.c b/fs/ocfs2/stack_user.c index 252e7c82f929..a5ebe421195f 100644 --- a/fs/ocfs2/stack_user.c +++ b/fs/ocfs2/stack_user.c | |||
| @@ -190,7 +190,7 @@ static struct ocfs2_live_connection *ocfs2_connection_find(const char *name) | |||
| 190 | return c; | 190 | return c; |
| 191 | } | 191 | } |
| 192 | 192 | ||
| 193 | return c; | 193 | return NULL; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | /* | 196 | /* |
| @@ -1199,12 +1199,24 @@ int pipe_proc_fn(struct ctl_table *table, int write, void __user *buf, | |||
| 1199 | return ret; | 1199 | return ret; |
| 1200 | } | 1200 | } |
| 1201 | 1201 | ||
| 1202 | /* | ||
| 1203 | * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same | ||
| 1204 | * location, so checking ->i_pipe is not enough to verify that this is a | ||
| 1205 | * pipe. | ||
| 1206 | */ | ||
| 1207 | struct pipe_inode_info *get_pipe_info(struct file *file) | ||
| 1208 | { | ||
| 1209 | struct inode *i = file->f_path.dentry->d_inode; | ||
| 1210 | |||
| 1211 | return S_ISFIFO(i->i_mode) ? i->i_pipe : NULL; | ||
| 1212 | } | ||
| 1213 | |||
| 1202 | long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) | 1214 | long pipe_fcntl(struct file *file, unsigned int cmd, unsigned long arg) |
| 1203 | { | 1215 | { |
| 1204 | struct pipe_inode_info *pipe; | 1216 | struct pipe_inode_info *pipe; |
| 1205 | long ret; | 1217 | long ret; |
| 1206 | 1218 | ||
| 1207 | pipe = file->f_path.dentry->d_inode->i_pipe; | 1219 | pipe = get_pipe_info(file); |
| 1208 | if (!pipe) | 1220 | if (!pipe) |
| 1209 | return -EBADF; | 1221 | return -EBADF; |
| 1210 | 1222 | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index f3d02ca461ec..182845147fe4 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -1574,7 +1574,7 @@ static int do_proc_readlink(struct path *path, char __user *buffer, int buflen) | |||
| 1574 | if (!tmp) | 1574 | if (!tmp) |
| 1575 | return -ENOMEM; | 1575 | return -ENOMEM; |
| 1576 | 1576 | ||
| 1577 | pathname = d_path_with_unreachable(path, tmp, PAGE_SIZE); | 1577 | pathname = d_path(path, tmp, PAGE_SIZE); |
| 1578 | len = PTR_ERR(pathname); | 1578 | len = PTR_ERR(pathname); |
| 1579 | if (IS_ERR(pathname)) | 1579 | if (IS_ERR(pathname)) |
| 1580 | goto out; | 1580 | goto out; |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index da6b01d70f01..c126c83b9a45 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
| @@ -706,6 +706,7 @@ static int pagemap_hugetlb_range(pte_t *pte, unsigned long hmask, | |||
| 706 | * skip over unmapped regions. | 706 | * skip over unmapped regions. |
| 707 | */ | 707 | */ |
| 708 | #define PAGEMAP_WALK_SIZE (PMD_SIZE) | 708 | #define PAGEMAP_WALK_SIZE (PMD_SIZE) |
| 709 | #define PAGEMAP_WALK_MASK (PMD_MASK) | ||
| 709 | static ssize_t pagemap_read(struct file *file, char __user *buf, | 710 | static ssize_t pagemap_read(struct file *file, char __user *buf, |
| 710 | size_t count, loff_t *ppos) | 711 | size_t count, loff_t *ppos) |
| 711 | { | 712 | { |
| @@ -776,7 +777,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf, | |||
| 776 | unsigned long end; | 777 | unsigned long end; |
| 777 | 778 | ||
| 778 | pm.pos = 0; | 779 | pm.pos = 0; |
| 779 | end = start_vaddr + PAGEMAP_WALK_SIZE; | 780 | end = (start_vaddr + PAGEMAP_WALK_SIZE) & PAGEMAP_WALK_MASK; |
| 780 | /* overflow ? */ | 781 | /* overflow ? */ |
| 781 | if (end < start_vaddr || end > end_vaddr) | 782 | if (end < start_vaddr || end > end_vaddr) |
| 782 | end = end_vaddr; | 783 | end = end_vaddr; |
diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index bd9763e76bae..79265fdc317a 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c | |||
| @@ -183,12 +183,11 @@ int reiserfs_unpack(struct inode *inode, struct file *filp) | |||
| 183 | return 0; | 183 | return 0; |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | /* we need to make sure nobody is changing the file size beneath | ||
| 187 | ** us | ||
| 188 | */ | ||
| 189 | reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); | ||
| 190 | depth = reiserfs_write_lock_once(inode->i_sb); | 186 | depth = reiserfs_write_lock_once(inode->i_sb); |
| 191 | 187 | ||
| 188 | /* we need to make sure nobody is changing the file size beneath us */ | ||
| 189 | reiserfs_mutex_lock_safe(&inode->i_mutex, inode->i_sb); | ||
| 190 | |||
| 192 | write_from = inode->i_size & (blocksize - 1); | 191 | write_from = inode->i_size & (blocksize - 1); |
| 193 | /* if we are on a block boundary, we are already unpacked. */ | 192 | /* if we are on a block boundary, we are already unpacked. */ |
| 194 | if (write_from == 0) { | 193 | if (write_from == 0) { |
diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index 536d697a8a28..90d2fcb67a31 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c | |||
| @@ -472,7 +472,9 @@ int reiserfs_acl_chmod(struct inode *inode) | |||
| 472 | struct reiserfs_transaction_handle th; | 472 | struct reiserfs_transaction_handle th; |
| 473 | size_t size = reiserfs_xattr_nblocks(inode, | 473 | size_t size = reiserfs_xattr_nblocks(inode, |
| 474 | reiserfs_acl_size(clone->a_count)); | 474 | reiserfs_acl_size(clone->a_count)); |
| 475 | reiserfs_write_lock(inode->i_sb); | 475 | int depth; |
| 476 | |||
| 477 | depth = reiserfs_write_lock_once(inode->i_sb); | ||
| 476 | error = journal_begin(&th, inode->i_sb, size * 2); | 478 | error = journal_begin(&th, inode->i_sb, size * 2); |
| 477 | if (!error) { | 479 | if (!error) { |
| 478 | int error2; | 480 | int error2; |
| @@ -482,7 +484,7 @@ int reiserfs_acl_chmod(struct inode *inode) | |||
| 482 | if (error2) | 484 | if (error2) |
| 483 | error = error2; | 485 | error = error2; |
| 484 | } | 486 | } |
| 485 | reiserfs_write_unlock(inode->i_sb); | 487 | reiserfs_write_unlock_once(inode->i_sb, depth); |
| 486 | } | 488 | } |
| 487 | posix_acl_release(clone); | 489 | posix_acl_release(clone); |
| 488 | return error; | 490 | return error; |
diff --git a/fs/splice.c b/fs/splice.c index 8f1dfaecc8f0..ce2f02579e35 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -1311,18 +1311,6 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, | |||
| 1311 | static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, | 1311 | static int splice_pipe_to_pipe(struct pipe_inode_info *ipipe, |
| 1312 | struct pipe_inode_info *opipe, | 1312 | struct pipe_inode_info *opipe, |
| 1313 | size_t len, unsigned int flags); | 1313 | size_t len, unsigned int flags); |
| 1314 | /* | ||
| 1315 | * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same | ||
| 1316 | * location, so checking ->i_pipe is not enough to verify that this is a | ||
| 1317 | * pipe. | ||
| 1318 | */ | ||
| 1319 | static inline struct pipe_inode_info *pipe_info(struct inode *inode) | ||
| 1320 | { | ||
| 1321 | if (S_ISFIFO(inode->i_mode)) | ||
| 1322 | return inode->i_pipe; | ||
| 1323 | |||
| 1324 | return NULL; | ||
| 1325 | } | ||
| 1326 | 1314 | ||
| 1327 | /* | 1315 | /* |
| 1328 | * Determine where to splice to/from. | 1316 | * Determine where to splice to/from. |
| @@ -1336,8 +1324,8 @@ static long do_splice(struct file *in, loff_t __user *off_in, | |||
| 1336 | loff_t offset, *off; | 1324 | loff_t offset, *off; |
| 1337 | long ret; | 1325 | long ret; |
| 1338 | 1326 | ||
| 1339 | ipipe = pipe_info(in->f_path.dentry->d_inode); | 1327 | ipipe = get_pipe_info(in); |
| 1340 | opipe = pipe_info(out->f_path.dentry->d_inode); | 1328 | opipe = get_pipe_info(out); |
| 1341 | 1329 | ||
| 1342 | if (ipipe && opipe) { | 1330 | if (ipipe && opipe) { |
| 1343 | if (off_in || off_out) | 1331 | if (off_in || off_out) |
| @@ -1555,7 +1543,7 @@ static long vmsplice_to_user(struct file *file, const struct iovec __user *iov, | |||
| 1555 | int error; | 1543 | int error; |
| 1556 | long ret; | 1544 | long ret; |
| 1557 | 1545 | ||
| 1558 | pipe = pipe_info(file->f_path.dentry->d_inode); | 1546 | pipe = get_pipe_info(file); |
| 1559 | if (!pipe) | 1547 | if (!pipe) |
| 1560 | return -EBADF; | 1548 | return -EBADF; |
| 1561 | 1549 | ||
| @@ -1642,7 +1630,7 @@ static long vmsplice_to_pipe(struct file *file, const struct iovec __user *iov, | |||
| 1642 | }; | 1630 | }; |
| 1643 | long ret; | 1631 | long ret; |
| 1644 | 1632 | ||
| 1645 | pipe = pipe_info(file->f_path.dentry->d_inode); | 1633 | pipe = get_pipe_info(file); |
| 1646 | if (!pipe) | 1634 | if (!pipe) |
| 1647 | return -EBADF; | 1635 | return -EBADF; |
| 1648 | 1636 | ||
| @@ -2022,8 +2010,8 @@ static int link_pipe(struct pipe_inode_info *ipipe, | |||
| 2022 | static long do_tee(struct file *in, struct file *out, size_t len, | 2010 | static long do_tee(struct file *in, struct file *out, size_t len, |
| 2023 | unsigned int flags) | 2011 | unsigned int flags) |
| 2024 | { | 2012 | { |
| 2025 | struct pipe_inode_info *ipipe = pipe_info(in->f_path.dentry->d_inode); | 2013 | struct pipe_inode_info *ipipe = get_pipe_info(in); |
| 2026 | struct pipe_inode_info *opipe = pipe_info(out->f_path.dentry->d_inode); | 2014 | struct pipe_inode_info *opipe = get_pipe_info(out); |
| 2027 | int ret = -EINVAL; | 2015 | int ret = -EINVAL; |
| 2028 | 2016 | ||
| 2029 | /* | 2017 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 7d287afccde5..691f61223ed6 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
| @@ -934,7 +934,6 @@ xfs_aops_discard_page( | |||
| 934 | struct xfs_inode *ip = XFS_I(inode); | 934 | struct xfs_inode *ip = XFS_I(inode); |
| 935 | struct buffer_head *bh, *head; | 935 | struct buffer_head *bh, *head; |
| 936 | loff_t offset = page_offset(page); | 936 | loff_t offset = page_offset(page); |
| 937 | ssize_t len = 1 << inode->i_blkbits; | ||
| 938 | 937 | ||
| 939 | if (!xfs_is_delayed_page(page, IO_DELAY)) | 938 | if (!xfs_is_delayed_page(page, IO_DELAY)) |
| 940 | goto out_invalidate; | 939 | goto out_invalidate; |
| @@ -949,58 +948,14 @@ xfs_aops_discard_page( | |||
| 949 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 948 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
| 950 | bh = head = page_buffers(page); | 949 | bh = head = page_buffers(page); |
| 951 | do { | 950 | do { |
| 952 | int done; | ||
| 953 | xfs_fileoff_t offset_fsb; | ||
| 954 | xfs_bmbt_irec_t imap; | ||
| 955 | int nimaps = 1; | ||
| 956 | int error; | 951 | int error; |
| 957 | xfs_fsblock_t firstblock; | 952 | xfs_fileoff_t start_fsb; |
| 958 | xfs_bmap_free_t flist; | ||
| 959 | 953 | ||
| 960 | if (!buffer_delay(bh)) | 954 | if (!buffer_delay(bh)) |
| 961 | goto next_buffer; | 955 | goto next_buffer; |
| 962 | 956 | ||
| 963 | offset_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); | 957 | start_fsb = XFS_B_TO_FSBT(ip->i_mount, offset); |
| 964 | 958 | error = xfs_bmap_punch_delalloc_range(ip, start_fsb, 1); | |
| 965 | /* | ||
| 966 | * Map the range first and check that it is a delalloc extent | ||
| 967 | * before trying to unmap the range. Otherwise we will be | ||
| 968 | * trying to remove a real extent (which requires a | ||
| 969 | * transaction) or a hole, which is probably a bad idea... | ||
| 970 | */ | ||
| 971 | error = xfs_bmapi(NULL, ip, offset_fsb, 1, | ||
| 972 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | ||
| 973 | &nimaps, NULL); | ||
| 974 | |||
| 975 | if (error) { | ||
| 976 | /* something screwed, just bail */ | ||
| 977 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
| 978 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | ||
| 979 | "page discard failed delalloc mapping lookup."); | ||
| 980 | } | ||
| 981 | break; | ||
| 982 | } | ||
| 983 | if (!nimaps) { | ||
| 984 | /* nothing there */ | ||
| 985 | goto next_buffer; | ||
| 986 | } | ||
| 987 | if (imap.br_startblock != DELAYSTARTBLOCK) { | ||
| 988 | /* been converted, ignore */ | ||
| 989 | goto next_buffer; | ||
| 990 | } | ||
| 991 | WARN_ON(imap.br_blockcount == 0); | ||
| 992 | |||
| 993 | /* | ||
| 994 | * Note: while we initialise the firstblock/flist pair, they | ||
| 995 | * should never be used because blocks should never be | ||
| 996 | * allocated or freed for a delalloc extent and hence we need | ||
| 997 | * don't cancel or finish them after the xfs_bunmapi() call. | ||
| 998 | */ | ||
| 999 | xfs_bmap_init(&flist, &firstblock); | ||
| 1000 | error = xfs_bunmapi(NULL, ip, offset_fsb, 1, 0, 1, &firstblock, | ||
| 1001 | &flist, &done); | ||
| 1002 | |||
| 1003 | ASSERT(!flist.xbf_count && !flist.xbf_first); | ||
| 1004 | if (error) { | 959 | if (error) { |
| 1005 | /* something screwed, just bail */ | 960 | /* something screwed, just bail */ |
| 1006 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | 961 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
| @@ -1010,7 +965,7 @@ xfs_aops_discard_page( | |||
| 1010 | break; | 965 | break; |
| 1011 | } | 966 | } |
| 1012 | next_buffer: | 967 | next_buffer: |
| 1013 | offset += len; | 968 | offset += 1 << inode->i_blkbits; |
| 1014 | 969 | ||
| 1015 | } while ((bh = bh->b_this_page) != head); | 970 | } while ((bh = bh->b_this_page) != head); |
| 1016 | 971 | ||
| @@ -1505,11 +1460,42 @@ xfs_vm_write_failed( | |||
| 1505 | struct inode *inode = mapping->host; | 1460 | struct inode *inode = mapping->host; |
| 1506 | 1461 | ||
| 1507 | if (to > inode->i_size) { | 1462 | if (to > inode->i_size) { |
| 1508 | struct iattr ia = { | 1463 | /* |
| 1509 | .ia_valid = ATTR_SIZE | ATTR_FORCE, | 1464 | * punch out the delalloc blocks we have already allocated. We |
| 1510 | .ia_size = inode->i_size, | 1465 | * don't call xfs_setattr() to do this as we may be in the |
| 1511 | }; | 1466 | * middle of a multi-iovec write and so the vfs inode->i_size |
| 1512 | xfs_setattr(XFS_I(inode), &ia, XFS_ATTR_NOLOCK); | 1467 | * will not match the xfs ip->i_size and so it will zero too |
| 1468 | * much. Hence we jus truncate the page cache to zero what is | ||
| 1469 | * necessary and punch the delalloc blocks directly. | ||
| 1470 | */ | ||
| 1471 | struct xfs_inode *ip = XFS_I(inode); | ||
| 1472 | xfs_fileoff_t start_fsb; | ||
| 1473 | xfs_fileoff_t end_fsb; | ||
| 1474 | int error; | ||
| 1475 | |||
| 1476 | truncate_pagecache(inode, to, inode->i_size); | ||
| 1477 | |||
| 1478 | /* | ||
| 1479 | * Check if there are any blocks that are outside of i_size | ||
| 1480 | * that need to be trimmed back. | ||
| 1481 | */ | ||
| 1482 | start_fsb = XFS_B_TO_FSB(ip->i_mount, inode->i_size) + 1; | ||
| 1483 | end_fsb = XFS_B_TO_FSB(ip->i_mount, to); | ||
| 1484 | if (end_fsb <= start_fsb) | ||
| 1485 | return; | ||
| 1486 | |||
| 1487 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
| 1488 | error = xfs_bmap_punch_delalloc_range(ip, start_fsb, | ||
| 1489 | end_fsb - start_fsb); | ||
| 1490 | if (error) { | ||
| 1491 | /* something screwed, just bail */ | ||
| 1492 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
| 1493 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | ||
| 1494 | "xfs_vm_write_failed: unable to clean up ino %lld", | ||
| 1495 | ip->i_ino); | ||
| 1496 | } | ||
| 1497 | } | ||
| 1498 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
| 1513 | } | 1499 | } |
| 1514 | } | 1500 | } |
| 1515 | 1501 | ||
diff --git a/fs/xfs/linux-2.6/xfs_buf.c b/fs/xfs/linux-2.6/xfs_buf.c index aa1d353def29..4c5deb6e9e31 100644 --- a/fs/xfs/linux-2.6/xfs_buf.c +++ b/fs/xfs/linux-2.6/xfs_buf.c | |||
| @@ -488,29 +488,16 @@ found: | |||
| 488 | spin_unlock(&pag->pag_buf_lock); | 488 | spin_unlock(&pag->pag_buf_lock); |
| 489 | xfs_perag_put(pag); | 489 | xfs_perag_put(pag); |
| 490 | 490 | ||
| 491 | /* Attempt to get the semaphore without sleeping, | 491 | if (xfs_buf_cond_lock(bp)) { |
| 492 | * if this does not work then we need to drop the | 492 | /* failed, so wait for the lock if requested. */ |
| 493 | * spinlock and do a hard attempt on the semaphore. | ||
| 494 | */ | ||
| 495 | if (down_trylock(&bp->b_sema)) { | ||
| 496 | if (!(flags & XBF_TRYLOCK)) { | 493 | if (!(flags & XBF_TRYLOCK)) { |
| 497 | /* wait for buffer ownership */ | ||
| 498 | xfs_buf_lock(bp); | 494 | xfs_buf_lock(bp); |
| 499 | XFS_STATS_INC(xb_get_locked_waited); | 495 | XFS_STATS_INC(xb_get_locked_waited); |
| 500 | } else { | 496 | } else { |
| 501 | /* We asked for a trylock and failed, no need | ||
| 502 | * to look at file offset and length here, we | ||
| 503 | * know that this buffer at least overlaps our | ||
| 504 | * buffer and is locked, therefore our buffer | ||
| 505 | * either does not exist, or is this buffer. | ||
| 506 | */ | ||
| 507 | xfs_buf_rele(bp); | 497 | xfs_buf_rele(bp); |
| 508 | XFS_STATS_INC(xb_busy_locked); | 498 | XFS_STATS_INC(xb_busy_locked); |
| 509 | return NULL; | 499 | return NULL; |
| 510 | } | 500 | } |
| 511 | } else { | ||
| 512 | /* trylock worked */ | ||
| 513 | XB_SET_OWNER(bp); | ||
| 514 | } | 501 | } |
| 515 | 502 | ||
| 516 | if (bp->b_flags & XBF_STALE) { | 503 | if (bp->b_flags & XBF_STALE) { |
| @@ -876,10 +863,18 @@ xfs_buf_rele( | |||
| 876 | */ | 863 | */ |
| 877 | 864 | ||
| 878 | /* | 865 | /* |
| 879 | * Locks a buffer object, if it is not already locked. | 866 | * Locks a buffer object, if it is not already locked. Note that this in |
| 880 | * Note that this in no way locks the underlying pages, so it is only | 867 | * no way locks the underlying pages, so it is only useful for |
| 881 | * useful for synchronizing concurrent use of buffer objects, not for | 868 | * synchronizing concurrent use of buffer objects, not for synchronizing |
| 882 | * synchronizing independent access to the underlying pages. | 869 | * independent access to the underlying pages. |
| 870 | * | ||
| 871 | * If we come across a stale, pinned, locked buffer, we know that we are | ||
| 872 | * being asked to lock a buffer that has been reallocated. Because it is | ||
| 873 | * pinned, we know that the log has not been pushed to disk and hence it | ||
| 874 | * will still be locked. Rather than continuing to have trylock attempts | ||
| 875 | * fail until someone else pushes the log, push it ourselves before | ||
| 876 | * returning. This means that the xfsaild will not get stuck trying | ||
| 877 | * to push on stale inode buffers. | ||
| 883 | */ | 878 | */ |
| 884 | int | 879 | int |
| 885 | xfs_buf_cond_lock( | 880 | xfs_buf_cond_lock( |
| @@ -890,6 +885,8 @@ xfs_buf_cond_lock( | |||
| 890 | locked = down_trylock(&bp->b_sema) == 0; | 885 | locked = down_trylock(&bp->b_sema) == 0; |
| 891 | if (locked) | 886 | if (locked) |
| 892 | XB_SET_OWNER(bp); | 887 | XB_SET_OWNER(bp); |
| 888 | else if (atomic_read(&bp->b_pin_count) && (bp->b_flags & XBF_STALE)) | ||
| 889 | xfs_log_force(bp->b_target->bt_mount, 0); | ||
| 893 | 890 | ||
| 894 | trace_xfs_buf_cond_lock(bp, _RET_IP_); | 891 | trace_xfs_buf_cond_lock(bp, _RET_IP_); |
| 895 | return locked ? 0 : -EBUSY; | 892 | return locked ? 0 : -EBUSY; |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 8abd12e32e13..4111cd3966c7 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
| @@ -5471,8 +5471,13 @@ xfs_getbmap( | |||
| 5471 | if (error) | 5471 | if (error) |
| 5472 | goto out_unlock_iolock; | 5472 | goto out_unlock_iolock; |
| 5473 | } | 5473 | } |
| 5474 | 5474 | /* | |
| 5475 | ASSERT(ip->i_delayed_blks == 0); | 5475 | * even after flushing the inode, there can still be delalloc |
| 5476 | * blocks on the inode beyond EOF due to speculative | ||
| 5477 | * preallocation. These are not removed until the release | ||
| 5478 | * function is called or the inode is inactivated. Hence we | ||
| 5479 | * cannot assert here that ip->i_delayed_blks == 0. | ||
| 5480 | */ | ||
| 5476 | } | 5481 | } |
| 5477 | 5482 | ||
| 5478 | lock = xfs_ilock_map_shared(ip); | 5483 | lock = xfs_ilock_map_shared(ip); |
| @@ -6070,3 +6075,79 @@ xfs_bmap_disk_count_leaves( | |||
| 6070 | *count += xfs_bmbt_disk_get_blockcount(frp); | 6075 | *count += xfs_bmbt_disk_get_blockcount(frp); |
| 6071 | } | 6076 | } |
| 6072 | } | 6077 | } |
| 6078 | |||
| 6079 | /* | ||
| 6080 | * dead simple method of punching delalyed allocation blocks from a range in | ||
| 6081 | * the inode. Walks a block at a time so will be slow, but is only executed in | ||
| 6082 | * rare error cases so the overhead is not critical. This will alays punch out | ||
| 6083 | * both the start and end blocks, even if the ranges only partially overlap | ||
| 6084 | * them, so it is up to the caller to ensure that partial blocks are not | ||
| 6085 | * passed in. | ||
| 6086 | */ | ||
| 6087 | int | ||
| 6088 | xfs_bmap_punch_delalloc_range( | ||
| 6089 | struct xfs_inode *ip, | ||
| 6090 | xfs_fileoff_t start_fsb, | ||
| 6091 | xfs_fileoff_t length) | ||
| 6092 | { | ||
| 6093 | xfs_fileoff_t remaining = length; | ||
| 6094 | int error = 0; | ||
| 6095 | |||
| 6096 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
| 6097 | |||
| 6098 | do { | ||
| 6099 | int done; | ||
| 6100 | xfs_bmbt_irec_t imap; | ||
| 6101 | int nimaps = 1; | ||
| 6102 | xfs_fsblock_t firstblock; | ||
| 6103 | xfs_bmap_free_t flist; | ||
| 6104 | |||
| 6105 | /* | ||
| 6106 | * Map the range first and check that it is a delalloc extent | ||
| 6107 | * before trying to unmap the range. Otherwise we will be | ||
| 6108 | * trying to remove a real extent (which requires a | ||
| 6109 | * transaction) or a hole, which is probably a bad idea... | ||
| 6110 | */ | ||
| 6111 | error = xfs_bmapi(NULL, ip, start_fsb, 1, | ||
| 6112 | XFS_BMAPI_ENTIRE, NULL, 0, &imap, | ||
| 6113 | &nimaps, NULL); | ||
| 6114 | |||
| 6115 | if (error) { | ||
| 6116 | /* something screwed, just bail */ | ||
| 6117 | if (!XFS_FORCED_SHUTDOWN(ip->i_mount)) { | ||
| 6118 | xfs_fs_cmn_err(CE_ALERT, ip->i_mount, | ||
| 6119 | "Failed delalloc mapping lookup ino %lld fsb %lld.", | ||
| 6120 | ip->i_ino, start_fsb); | ||
| 6121 | } | ||
| 6122 | break; | ||
| 6123 | } | ||
| 6124 | if (!nimaps) { | ||
| 6125 | /* nothing there */ | ||
| 6126 | goto next_block; | ||
| 6127 | } | ||
| 6128 | if (imap.br_startblock != DELAYSTARTBLOCK) { | ||
| 6129 | /* been converted, ignore */ | ||
| 6130 | goto next_block; | ||
| 6131 | } | ||
| 6132 | WARN_ON(imap.br_blockcount == 0); | ||
| 6133 | |||
| 6134 | /* | ||
| 6135 | * Note: while we initialise the firstblock/flist pair, they | ||
| 6136 | * should never be used because blocks should never be | ||
| 6137 | * allocated or freed for a delalloc extent and hence we need | ||
| 6138 | * don't cancel or finish them after the xfs_bunmapi() call. | ||
| 6139 | */ | ||
| 6140 | xfs_bmap_init(&flist, &firstblock); | ||
| 6141 | error = xfs_bunmapi(NULL, ip, start_fsb, 1, 0, 1, &firstblock, | ||
| 6142 | &flist, &done); | ||
| 6143 | if (error) | ||
| 6144 | break; | ||
| 6145 | |||
| 6146 | ASSERT(!flist.xbf_count && !flist.xbf_first); | ||
| 6147 | next_block: | ||
| 6148 | start_fsb++; | ||
| 6149 | remaining--; | ||
| 6150 | } while(remaining > 0); | ||
| 6151 | |||
| 6152 | return error; | ||
| 6153 | } | ||
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 71ec9b6ecdfc..3651191daea1 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
| @@ -394,6 +394,11 @@ xfs_bmap_count_blocks( | |||
| 394 | int whichfork, | 394 | int whichfork, |
| 395 | int *count); | 395 | int *count); |
| 396 | 396 | ||
| 397 | int | ||
| 398 | xfs_bmap_punch_delalloc_range( | ||
| 399 | struct xfs_inode *ip, | ||
| 400 | xfs_fileoff_t start_fsb, | ||
| 401 | xfs_fileoff_t length); | ||
| 397 | #endif /* __KERNEL__ */ | 402 | #endif /* __KERNEL__ */ |
| 398 | 403 | ||
| 399 | #endif /* __XFS_BMAP_H__ */ | 404 | #endif /* __XFS_BMAP_H__ */ |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 3b9582c60a22..e60490bc00a6 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
| @@ -377,6 +377,19 @@ xfs_swap_extents( | |||
| 377 | ip->i_d.di_format = tip->i_d.di_format; | 377 | ip->i_d.di_format = tip->i_d.di_format; |
| 378 | tip->i_d.di_format = tmp; | 378 | tip->i_d.di_format = tmp; |
| 379 | 379 | ||
| 380 | /* | ||
| 381 | * The extents in the source inode could still contain speculative | ||
| 382 | * preallocation beyond EOF (e.g. the file is open but not modified | ||
| 383 | * while defrag is in progress). In that case, we need to copy over the | ||
| 384 | * number of delalloc blocks the data fork in the source inode is | ||
| 385 | * tracking beyond EOF so that when the fork is truncated away when the | ||
| 386 | * temporary inode is unlinked we don't underrun the i_delayed_blks | ||
| 387 | * counter on that inode. | ||
| 388 | */ | ||
| 389 | ASSERT(tip->i_delayed_blks == 0); | ||
| 390 | tip->i_delayed_blks = ip->i_delayed_blks; | ||
| 391 | ip->i_delayed_blks = 0; | ||
| 392 | |||
| 380 | ilf_fields = XFS_ILOG_CORE; | 393 | ilf_fields = XFS_ILOG_CORE; |
| 381 | 394 | ||
| 382 | switch(ip->i_d.di_format) { | 395 | switch(ip->i_d.di_format) { |
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index ed9990267661..c78cc6a3d87c 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c | |||
| @@ -58,6 +58,7 @@ xfs_error_trap(int e) | |||
| 58 | int xfs_etest[XFS_NUM_INJECT_ERROR]; | 58 | int xfs_etest[XFS_NUM_INJECT_ERROR]; |
| 59 | int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; | 59 | int64_t xfs_etest_fsid[XFS_NUM_INJECT_ERROR]; |
| 60 | char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; | 60 | char * xfs_etest_fsname[XFS_NUM_INJECT_ERROR]; |
| 61 | int xfs_error_test_active; | ||
| 61 | 62 | ||
| 62 | int | 63 | int |
| 63 | xfs_error_test(int error_tag, int *fsidp, char *expression, | 64 | xfs_error_test(int error_tag, int *fsidp, char *expression, |
| @@ -108,6 +109,7 @@ xfs_errortag_add(int error_tag, xfs_mount_t *mp) | |||
| 108 | len = strlen(mp->m_fsname); | 109 | len = strlen(mp->m_fsname); |
| 109 | xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP); | 110 | xfs_etest_fsname[i] = kmem_alloc(len + 1, KM_SLEEP); |
| 110 | strcpy(xfs_etest_fsname[i], mp->m_fsname); | 111 | strcpy(xfs_etest_fsname[i], mp->m_fsname); |
| 112 | xfs_error_test_active++; | ||
| 111 | return 0; | 113 | return 0; |
| 112 | } | 114 | } |
| 113 | } | 115 | } |
| @@ -137,6 +139,7 @@ xfs_errortag_clearall(xfs_mount_t *mp, int loud) | |||
| 137 | xfs_etest_fsid[i] = 0LL; | 139 | xfs_etest_fsid[i] = 0LL; |
| 138 | kmem_free(xfs_etest_fsname[i]); | 140 | kmem_free(xfs_etest_fsname[i]); |
| 139 | xfs_etest_fsname[i] = NULL; | 141 | xfs_etest_fsname[i] = NULL; |
| 142 | xfs_error_test_active--; | ||
| 140 | } | 143 | } |
| 141 | } | 144 | } |
| 142 | 145 | ||
diff --git a/fs/xfs/xfs_error.h b/fs/xfs/xfs_error.h index c2c1a072bb82..f338847f80b8 100644 --- a/fs/xfs/xfs_error.h +++ b/fs/xfs/xfs_error.h | |||
| @@ -127,13 +127,14 @@ extern void xfs_corruption_error(const char *tag, int level, | |||
| 127 | #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT | 127 | #define XFS_RANDOM_BMAPIFORMAT XFS_RANDOM_DEFAULT |
| 128 | 128 | ||
| 129 | #ifdef DEBUG | 129 | #ifdef DEBUG |
| 130 | extern int xfs_error_test_active; | ||
| 130 | extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); | 131 | extern int xfs_error_test(int, int *, char *, int, char *, unsigned long); |
| 131 | 132 | ||
| 132 | #define XFS_NUM_INJECT_ERROR 10 | 133 | #define XFS_NUM_INJECT_ERROR 10 |
| 133 | #define XFS_TEST_ERROR(expr, mp, tag, rf) \ | 134 | #define XFS_TEST_ERROR(expr, mp, tag, rf) \ |
| 134 | ((expr) || \ | 135 | ((expr) || (xfs_error_test_active && \ |
| 135 | xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \ | 136 | xfs_error_test((tag), (mp)->m_fixedfsid, "expr", __LINE__, __FILE__, \ |
| 136 | (rf))) | 137 | (rf)))) |
| 137 | 138 | ||
| 138 | extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); | 139 | extern int xfs_errortag_add(int error_tag, xfs_mount_t *mp); |
| 139 | extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); | 140 | extern int xfs_errortag_clearall(xfs_mount_t *mp, int loud); |
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index c7ac020705df..7c8d30c453c3 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
| @@ -657,18 +657,37 @@ xfs_inode_item_unlock( | |||
| 657 | } | 657 | } |
| 658 | 658 | ||
| 659 | /* | 659 | /* |
| 660 | * This is called to find out where the oldest active copy of the | 660 | * This is called to find out where the oldest active copy of the inode log |
| 661 | * inode log item in the on disk log resides now that the last log | 661 | * item in the on disk log resides now that the last log write of it completed |
| 662 | * write of it completed at the given lsn. Since we always re-log | 662 | * at the given lsn. Since we always re-log all dirty data in an inode, the |
| 663 | * all dirty data in an inode, the latest copy in the on disk log | 663 | * latest copy in the on disk log is the only one that matters. Therefore, |
| 664 | * is the only one that matters. Therefore, simply return the | 664 | * simply return the given lsn. |
| 665 | * given lsn. | 665 | * |
| 666 | * If the inode has been marked stale because the cluster is being freed, we | ||
| 667 | * don't want to (re-)insert this inode into the AIL. There is a race condition | ||
| 668 | * where the cluster buffer may be unpinned before the inode is inserted into | ||
| 669 | * the AIL during transaction committed processing. If the buffer is unpinned | ||
| 670 | * before the inode item has been committed and inserted, then it is possible | ||
| 671 | * for the buffer to be written and IO completions before the inode is inserted | ||
| 672 | * into the AIL. In that case, we'd be inserting a clean, stale inode into the | ||
| 673 | * AIL which will never get removed. It will, however, get reclaimed which | ||
| 674 | * triggers an assert in xfs_inode_free() complaining about freein an inode | ||
| 675 | * still in the AIL. | ||
| 676 | * | ||
| 677 | * To avoid this, return a lower LSN than the one passed in so that the | ||
| 678 | * transaction committed code will not move the inode forward in the AIL but | ||
| 679 | * will still unpin it properly. | ||
| 666 | */ | 680 | */ |
| 667 | STATIC xfs_lsn_t | 681 | STATIC xfs_lsn_t |
| 668 | xfs_inode_item_committed( | 682 | xfs_inode_item_committed( |
| 669 | struct xfs_log_item *lip, | 683 | struct xfs_log_item *lip, |
| 670 | xfs_lsn_t lsn) | 684 | xfs_lsn_t lsn) |
| 671 | { | 685 | { |
| 686 | struct xfs_inode_log_item *iip = INODE_ITEM(lip); | ||
| 687 | struct xfs_inode *ip = iip->ili_inode; | ||
| 688 | |||
| 689 | if (xfs_iflags_test(ip, XFS_ISTALE)) | ||
| 690 | return lsn - 1; | ||
| 672 | return lsn; | 691 | return lsn; |
| 673 | } | 692 | } |
| 674 | 693 | ||
