diff options
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/file.c | 2 | ||||
| -rw-r--r-- | fs/nfs/dir.c | 5 | ||||
| -rw-r--r-- | fs/ocfs2/alloc.c | 2 | ||||
| -rw-r--r-- | fs/ocfs2/file.c | 52 | ||||
| -rw-r--r-- | fs/ocfs2/namei.c | 17 | ||||
| -rw-r--r-- | fs/proc/vmcore.c | 26 |
6 files changed, 81 insertions, 23 deletions
| @@ -34,7 +34,7 @@ static void *alloc_fdmem(size_t size) | |||
| 34 | * vmalloc() if the allocation size will be considered "large" by the VM. | 34 | * vmalloc() if the allocation size will be considered "large" by the VM. |
| 35 | */ | 35 | */ |
| 36 | if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { | 36 | if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) { |
| 37 | void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN); | 37 | void *data = kmalloc(size, GFP_KERNEL|__GFP_NOWARN|__GFP_NORETRY); |
| 38 | if (data != NULL) | 38 | if (data != NULL) |
| 39 | return data; | 39 | return data; |
| 40 | } | 40 | } |
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index be38b573495a..4a48fe4b84b6 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
| @@ -1846,6 +1846,11 @@ int nfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) | |||
| 1846 | GFP_KERNEL)) { | 1846 | GFP_KERNEL)) { |
| 1847 | SetPageUptodate(page); | 1847 | SetPageUptodate(page); |
| 1848 | unlock_page(page); | 1848 | unlock_page(page); |
| 1849 | /* | ||
| 1850 | * add_to_page_cache_lru() grabs an extra page refcount. | ||
| 1851 | * Drop it here to avoid leaking this page later. | ||
| 1852 | */ | ||
| 1853 | page_cache_release(page); | ||
| 1849 | } else | 1854 | } else |
| 1850 | __free_page(page); | 1855 | __free_page(page); |
| 1851 | 1856 | ||
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index aada5801567a..e2edff38be52 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c | |||
| @@ -7158,7 +7158,7 @@ int ocfs2_truncate_inline(struct inode *inode, struct buffer_head *di_bh, | |||
| 7158 | if (end > i_size_read(inode)) | 7158 | if (end > i_size_read(inode)) |
| 7159 | end = i_size_read(inode); | 7159 | end = i_size_read(inode); |
| 7160 | 7160 | ||
| 7161 | BUG_ON(start >= end); | 7161 | BUG_ON(start > end); |
| 7162 | 7162 | ||
| 7163 | if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) || | 7163 | if (!(OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) || |
| 7164 | !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) || | 7164 | !(le16_to_cpu(di->i_dyn_features) & OCFS2_INLINE_DATA_FL) || |
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index d77d71ead8d1..8450262bcf2a 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c | |||
| @@ -185,6 +185,9 @@ static int ocfs2_sync_file(struct file *file, loff_t start, loff_t end, | |||
| 185 | file->f_path.dentry->d_name.name, | 185 | file->f_path.dentry->d_name.name, |
| 186 | (unsigned long long)datasync); | 186 | (unsigned long long)datasync); |
| 187 | 187 | ||
| 188 | if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb)) | ||
| 189 | return -EROFS; | ||
| 190 | |||
| 188 | err = filemap_write_and_wait_range(inode->i_mapping, start, end); | 191 | err = filemap_write_and_wait_range(inode->i_mapping, start, end); |
| 189 | if (err) | 192 | if (err) |
| 190 | return err; | 193 | return err; |
| @@ -474,11 +477,6 @@ static int ocfs2_truncate_file(struct inode *inode, | |||
| 474 | goto bail; | 477 | goto bail; |
| 475 | } | 478 | } |
| 476 | 479 | ||
| 477 | /* lets handle the simple truncate cases before doing any more | ||
| 478 | * cluster locking. */ | ||
| 479 | if (new_i_size == le64_to_cpu(fe->i_size)) | ||
| 480 | goto bail; | ||
| 481 | |||
| 482 | down_write(&OCFS2_I(inode)->ip_alloc_sem); | 480 | down_write(&OCFS2_I(inode)->ip_alloc_sem); |
| 483 | 481 | ||
| 484 | ocfs2_resv_discard(&osb->osb_la_resmap, | 482 | ocfs2_resv_discard(&osb->osb_la_resmap, |
| @@ -718,7 +716,8 @@ leave: | |||
| 718 | * While a write will already be ordering the data, a truncate will not. | 716 | * While a write will already be ordering the data, a truncate will not. |
| 719 | * Thus, we need to explicitly order the zeroed pages. | 717 | * Thus, we need to explicitly order the zeroed pages. |
| 720 | */ | 718 | */ |
| 721 | static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode) | 719 | static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode, |
| 720 | struct buffer_head *di_bh) | ||
| 722 | { | 721 | { |
| 723 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); | 722 | struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); |
| 724 | handle_t *handle = NULL; | 723 | handle_t *handle = NULL; |
| @@ -735,7 +734,14 @@ static handle_t *ocfs2_zero_start_ordered_transaction(struct inode *inode) | |||
| 735 | } | 734 | } |
| 736 | 735 | ||
| 737 | ret = ocfs2_jbd2_file_inode(handle, inode); | 736 | ret = ocfs2_jbd2_file_inode(handle, inode); |
| 738 | if (ret < 0) | 737 | if (ret < 0) { |
| 738 | mlog_errno(ret); | ||
| 739 | goto out; | ||
| 740 | } | ||
| 741 | |||
| 742 | ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh, | ||
| 743 | OCFS2_JOURNAL_ACCESS_WRITE); | ||
| 744 | if (ret) | ||
| 739 | mlog_errno(ret); | 745 | mlog_errno(ret); |
| 740 | 746 | ||
| 741 | out: | 747 | out: |
| @@ -751,7 +757,7 @@ out: | |||
| 751 | * to be too fragile to do exactly what we need without us having to | 757 | * to be too fragile to do exactly what we need without us having to |
| 752 | * worry about recursive locking in ->write_begin() and ->write_end(). */ | 758 | * worry about recursive locking in ->write_begin() and ->write_end(). */ |
| 753 | static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, | 759 | static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, |
| 754 | u64 abs_to) | 760 | u64 abs_to, struct buffer_head *di_bh) |
| 755 | { | 761 | { |
| 756 | struct address_space *mapping = inode->i_mapping; | 762 | struct address_space *mapping = inode->i_mapping; |
| 757 | struct page *page; | 763 | struct page *page; |
| @@ -759,6 +765,7 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, | |||
| 759 | handle_t *handle = NULL; | 765 | handle_t *handle = NULL; |
| 760 | int ret = 0; | 766 | int ret = 0; |
| 761 | unsigned zero_from, zero_to, block_start, block_end; | 767 | unsigned zero_from, zero_to, block_start, block_end; |
| 768 | struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data; | ||
| 762 | 769 | ||
| 763 | BUG_ON(abs_from >= abs_to); | 770 | BUG_ON(abs_from >= abs_to); |
| 764 | BUG_ON(abs_to > (((u64)index + 1) << PAGE_CACHE_SHIFT)); | 771 | BUG_ON(abs_to > (((u64)index + 1) << PAGE_CACHE_SHIFT)); |
| @@ -801,7 +808,8 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, | |||
| 801 | } | 808 | } |
| 802 | 809 | ||
| 803 | if (!handle) { | 810 | if (!handle) { |
| 804 | handle = ocfs2_zero_start_ordered_transaction(inode); | 811 | handle = ocfs2_zero_start_ordered_transaction(inode, |
| 812 | di_bh); | ||
| 805 | if (IS_ERR(handle)) { | 813 | if (IS_ERR(handle)) { |
| 806 | ret = PTR_ERR(handle); | 814 | ret = PTR_ERR(handle); |
| 807 | handle = NULL; | 815 | handle = NULL; |
| @@ -818,8 +826,22 @@ static int ocfs2_write_zero_page(struct inode *inode, u64 abs_from, | |||
| 818 | ret = 0; | 826 | ret = 0; |
| 819 | } | 827 | } |
| 820 | 828 | ||
| 821 | if (handle) | 829 | if (handle) { |
| 830 | /* | ||
| 831 | * fs-writeback will release the dirty pages without page lock | ||
| 832 | * whose offset are over inode size, the release happens at | ||
| 833 | * block_write_full_page_endio(). | ||
| 834 | */ | ||
| 835 | i_size_write(inode, abs_to); | ||
| 836 | inode->i_blocks = ocfs2_inode_sector_count(inode); | ||
| 837 | di->i_size = cpu_to_le64((u64)i_size_read(inode)); | ||
| 838 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
| 839 | di->i_mtime = di->i_ctime = cpu_to_le64(inode->i_mtime.tv_sec); | ||
| 840 | di->i_ctime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); | ||
| 841 | di->i_mtime_nsec = di->i_ctime_nsec; | ||
| 842 | ocfs2_journal_dirty(handle, di_bh); | ||
| 822 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); | 843 | ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle); |
| 844 | } | ||
| 823 | 845 | ||
| 824 | out_unlock: | 846 | out_unlock: |
| 825 | unlock_page(page); | 847 | unlock_page(page); |
| @@ -915,7 +937,7 @@ out: | |||
| 915 | * has made sure that the entire range needs zeroing. | 937 | * has made sure that the entire range needs zeroing. |
| 916 | */ | 938 | */ |
| 917 | static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, | 939 | static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, |
| 918 | u64 range_end) | 940 | u64 range_end, struct buffer_head *di_bh) |
| 919 | { | 941 | { |
| 920 | int rc = 0; | 942 | int rc = 0; |
| 921 | u64 next_pos; | 943 | u64 next_pos; |
| @@ -931,7 +953,7 @@ static int ocfs2_zero_extend_range(struct inode *inode, u64 range_start, | |||
| 931 | next_pos = (zero_pos & PAGE_CACHE_MASK) + PAGE_CACHE_SIZE; | 953 | next_pos = (zero_pos & PAGE_CACHE_MASK) + PAGE_CACHE_SIZE; |
| 932 | if (next_pos > range_end) | 954 | if (next_pos > range_end) |
| 933 | next_pos = range_end; | 955 | next_pos = range_end; |
| 934 | rc = ocfs2_write_zero_page(inode, zero_pos, next_pos); | 956 | rc = ocfs2_write_zero_page(inode, zero_pos, next_pos, di_bh); |
| 935 | if (rc < 0) { | 957 | if (rc < 0) { |
| 936 | mlog_errno(rc); | 958 | mlog_errno(rc); |
| 937 | break; | 959 | break; |
| @@ -977,7 +999,7 @@ int ocfs2_zero_extend(struct inode *inode, struct buffer_head *di_bh, | |||
| 977 | range_end = zero_to_size; | 999 | range_end = zero_to_size; |
| 978 | 1000 | ||
| 979 | ret = ocfs2_zero_extend_range(inode, range_start, | 1001 | ret = ocfs2_zero_extend_range(inode, range_start, |
| 980 | range_end); | 1002 | range_end, di_bh); |
| 981 | if (ret) { | 1003 | if (ret) { |
| 982 | mlog_errno(ret); | 1004 | mlog_errno(ret); |
| 983 | break; | 1005 | break; |
| @@ -1145,14 +1167,14 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 1145 | goto bail_unlock_rw; | 1167 | goto bail_unlock_rw; |
| 1146 | } | 1168 | } |
| 1147 | 1169 | ||
| 1148 | if (size_change && attr->ia_size != i_size_read(inode)) { | 1170 | if (size_change) { |
| 1149 | status = inode_newsize_ok(inode, attr->ia_size); | 1171 | status = inode_newsize_ok(inode, attr->ia_size); |
| 1150 | if (status) | 1172 | if (status) |
| 1151 | goto bail_unlock; | 1173 | goto bail_unlock; |
| 1152 | 1174 | ||
| 1153 | inode_dio_wait(inode); | 1175 | inode_dio_wait(inode); |
| 1154 | 1176 | ||
| 1155 | if (i_size_read(inode) > attr->ia_size) { | 1177 | if (i_size_read(inode) >= attr->ia_size) { |
| 1156 | if (ocfs2_should_order_data(inode)) { | 1178 | if (ocfs2_should_order_data(inode)) { |
| 1157 | status = ocfs2_begin_ordered_truncate(inode, | 1179 | status = ocfs2_begin_ordered_truncate(inode, |
| 1158 | attr->ia_size); | 1180 | attr->ia_size); |
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index f4d609be9400..3683643f3f0e 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c | |||
| @@ -664,6 +664,7 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
| 664 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); | 664 | struct ocfs2_super *osb = OCFS2_SB(dir->i_sb); |
| 665 | struct ocfs2_dir_lookup_result lookup = { NULL, }; | 665 | struct ocfs2_dir_lookup_result lookup = { NULL, }; |
| 666 | sigset_t oldset; | 666 | sigset_t oldset; |
| 667 | u64 old_de_ino; | ||
| 667 | 668 | ||
| 668 | trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno, | 669 | trace_ocfs2_link((unsigned long long)OCFS2_I(inode)->ip_blkno, |
| 669 | old_dentry->d_name.len, old_dentry->d_name.name, | 670 | old_dentry->d_name.len, old_dentry->d_name.name, |
| @@ -686,6 +687,22 @@ static int ocfs2_link(struct dentry *old_dentry, | |||
| 686 | goto out; | 687 | goto out; |
| 687 | } | 688 | } |
| 688 | 689 | ||
| 690 | err = ocfs2_lookup_ino_from_name(dir, old_dentry->d_name.name, | ||
| 691 | old_dentry->d_name.len, &old_de_ino); | ||
| 692 | if (err) { | ||
| 693 | err = -ENOENT; | ||
| 694 | goto out; | ||
| 695 | } | ||
| 696 | |||
| 697 | /* | ||
| 698 | * Check whether another node removed the source inode while we | ||
| 699 | * were in the vfs. | ||
| 700 | */ | ||
| 701 | if (old_de_ino != OCFS2_I(inode)->ip_blkno) { | ||
| 702 | err = -ENOENT; | ||
| 703 | goto out; | ||
| 704 | } | ||
| 705 | |||
| 689 | err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, | 706 | err = ocfs2_check_dir_for_entry(dir, dentry->d_name.name, |
| 690 | dentry->d_name.len); | 707 | dentry->d_name.len); |
| 691 | if (err) | 708 | if (err) |
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c index 2ca7ba047f04..88d4585b30f1 100644 --- a/fs/proc/vmcore.c +++ b/fs/proc/vmcore.c | |||
| @@ -468,17 +468,24 @@ static int __init update_note_header_size_elf64(const Elf64_Ehdr *ehdr_ptr) | |||
| 468 | return rc; | 468 | return rc; |
| 469 | } | 469 | } |
| 470 | nhdr_ptr = notes_section; | 470 | nhdr_ptr = notes_section; |
| 471 | while (real_sz < max_sz) { | 471 | while (nhdr_ptr->n_namesz != 0) { |
| 472 | if (nhdr_ptr->n_namesz == 0) | ||
| 473 | break; | ||
| 474 | sz = sizeof(Elf64_Nhdr) + | 472 | sz = sizeof(Elf64_Nhdr) + |
| 475 | ((nhdr_ptr->n_namesz + 3) & ~3) + | 473 | ((nhdr_ptr->n_namesz + 3) & ~3) + |
| 476 | ((nhdr_ptr->n_descsz + 3) & ~3); | 474 | ((nhdr_ptr->n_descsz + 3) & ~3); |
| 475 | if ((real_sz + sz) > max_sz) { | ||
| 476 | pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", | ||
| 477 | nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); | ||
| 478 | break; | ||
| 479 | } | ||
| 477 | real_sz += sz; | 480 | real_sz += sz; |
| 478 | nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz); | 481 | nhdr_ptr = (Elf64_Nhdr*)((char*)nhdr_ptr + sz); |
| 479 | } | 482 | } |
| 480 | kfree(notes_section); | 483 | kfree(notes_section); |
| 481 | phdr_ptr->p_memsz = real_sz; | 484 | phdr_ptr->p_memsz = real_sz; |
| 485 | if (real_sz == 0) { | ||
| 486 | pr_warn("Warning: Zero PT_NOTE entries found\n"); | ||
| 487 | return -EINVAL; | ||
| 488 | } | ||
| 482 | } | 489 | } |
| 483 | 490 | ||
| 484 | return 0; | 491 | return 0; |
| @@ -648,17 +655,24 @@ static int __init update_note_header_size_elf32(const Elf32_Ehdr *ehdr_ptr) | |||
| 648 | return rc; | 655 | return rc; |
| 649 | } | 656 | } |
| 650 | nhdr_ptr = notes_section; | 657 | nhdr_ptr = notes_section; |
| 651 | while (real_sz < max_sz) { | 658 | while (nhdr_ptr->n_namesz != 0) { |
| 652 | if (nhdr_ptr->n_namesz == 0) | ||
| 653 | break; | ||
| 654 | sz = sizeof(Elf32_Nhdr) + | 659 | sz = sizeof(Elf32_Nhdr) + |
| 655 | ((nhdr_ptr->n_namesz + 3) & ~3) + | 660 | ((nhdr_ptr->n_namesz + 3) & ~3) + |
| 656 | ((nhdr_ptr->n_descsz + 3) & ~3); | 661 | ((nhdr_ptr->n_descsz + 3) & ~3); |
| 662 | if ((real_sz + sz) > max_sz) { | ||
| 663 | pr_warn("Warning: Exceeded p_memsz, dropping PT_NOTE entry n_namesz=0x%x, n_descsz=0x%x\n", | ||
| 664 | nhdr_ptr->n_namesz, nhdr_ptr->n_descsz); | ||
| 665 | break; | ||
| 666 | } | ||
| 657 | real_sz += sz; | 667 | real_sz += sz; |
| 658 | nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz); | 668 | nhdr_ptr = (Elf32_Nhdr*)((char*)nhdr_ptr + sz); |
| 659 | } | 669 | } |
| 660 | kfree(notes_section); | 670 | kfree(notes_section); |
| 661 | phdr_ptr->p_memsz = real_sz; | 671 | phdr_ptr->p_memsz = real_sz; |
| 672 | if (real_sz == 0) { | ||
| 673 | pr_warn("Warning: Zero PT_NOTE entries found\n"); | ||
| 674 | return -EINVAL; | ||
| 675 | } | ||
| 662 | } | 676 | } |
| 663 | 677 | ||
| 664 | return 0; | 678 | return 0; |
