diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/Kconfig | 2 | ||||
-rw-r--r-- | fs/block_dev.c | 2 | ||||
-rw-r--r-- | fs/dcache.c | 19 | ||||
-rw-r--r-- | fs/ext4/resize.c | 23 | ||||
-rw-r--r-- | fs/hugetlbfs/inode.c | 25 | ||||
-rw-r--r-- | fs/jbd/transaction.c | 15 | ||||
-rw-r--r-- | fs/jbd2/transaction.c | 15 | ||||
-rw-r--r-- | fs/splice.c | 9 |
8 files changed, 74 insertions, 36 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index fee318e6f4bb..133dcc8a4150 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1777,6 +1777,7 @@ config RPCSEC_GSS_KRB5 select CRYPTO select CRYPTO_MD5 select CRYPTO_DES + select CRYPTO_CBC help Provides for secure RPC calls by means of a gss-api mechanism based on Kerberos V5. This is required for @@ -1795,6 +1796,7 @@ config RPCSEC_GSS_SPKM3 select CRYPTO_MD5 select CRYPTO_DES select CRYPTO_CAST5 + select CRYPTO_CBC help Provides for secure RPC calls by means of a gss-api mechanism based on the SPKM3 public-key mechanism. diff --git a/fs/block_dev.c b/fs/block_dev.c index bc8f27cc4483..702b88cbd91d 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -1131,6 +1131,8 @@ static int blkdev_open(struct inode * inode, struct file * filp) filp->f_flags |= O_LARGEFILE; bdev = bd_acquire(inode); + if (bdev == NULL) + return -ENOMEM; res = do_open(bdev, filp, BD_MUTEX_NORMAL); if (res) diff --git a/fs/dcache.c b/fs/dcache.c index a1ff91eef108..fd4a428998ef 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -478,11 +478,12 @@ static void prune_dcache(int count, struct super_block *sb) up_read(s_umount); } spin_unlock(&dentry->d_lock); - /* Cannot remove the first dentry, and it isn't appropriate - * to move it to the head of the list, so give up, and try - * later + /* + * Insert dentry at the head of the list as inserting at the + * tail leads to a cycle. */ - break; + list_add(&dentry->d_lru, &dentry_unused); + dentry_stat.nr_unused++; } spin_unlock(&dcache_lock); } @@ -556,6 +557,7 @@ repeat: static void shrink_dcache_for_umount_subtree(struct dentry *dentry) { struct dentry *parent; + unsigned detached = 0; BUG_ON(!IS_ROOT(dentry)); @@ -620,7 +622,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) atomic_dec(&parent->d_count); list_del(&dentry->d_u.d_child); - dentry_stat.nr_dentry--; /* For d_free, below */ + detached++; inode = dentry->d_inode; if (inode) { @@ -638,7 +640,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) * otherwise we ascend to the parent and move to the * next sibling if there is one */ if (!parent) - return; + goto out; dentry = parent; @@ -647,6 +649,11 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry) dentry = list_entry(dentry->d_subdirs.next, struct dentry, d_u.d_child); } +out: + /* several dentries were freed, need to correct nr_dentry */ + spin_lock(&dcache_lock); + dentry_stat.nr_dentry -= detached; + spin_unlock(&dcache_lock); } /* diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c index 1e9578052cd3..4fe49c3661b2 100644 --- a/fs/ext4/resize.c +++ b/fs/ext4/resize.c @@ -69,44 +69,49 @@ static int verify_group_input(struct super_block *sb, else if (outside(input->block_bitmap, start, end)) ext4_warning(sb, __FUNCTION__, "Block bitmap not in group (block %llu)", - input->block_bitmap); + (unsigned long long)input->block_bitmap); else if (outside(input->inode_bitmap, start, end)) ext4_warning(sb, __FUNCTION__, "Inode bitmap not in group (block %llu)", - input->inode_bitmap); + (unsigned long long)input->inode_bitmap); else if (outside(input->inode_table, start, end) || outside(itend - 1, start, end)) ext4_warning(sb, __FUNCTION__, "Inode table not in group (blocks %llu-%llu)", - input->inode_table, itend - 1); + (unsigned long long)input->inode_table, itend - 1); else if (input->inode_bitmap == input->block_bitmap) ext4_warning(sb, __FUNCTION__, "Block bitmap same as inode bitmap (%llu)", - input->block_bitmap); + (unsigned long long)input->block_bitmap); else if (inside(input->block_bitmap, input->inode_table, itend)) ext4_warning(sb, __FUNCTION__, "Block bitmap (%llu) in inode table (%llu-%llu)", - input->block_bitmap, input->inode_table, itend-1); + (unsigned long long)input->block_bitmap, + (unsigned long long)input->inode_table, itend - 1); else if (inside(input->inode_bitmap, input->inode_table, itend)) ext4_warning(sb, __FUNCTION__, "Inode bitmap (%llu) in inode table (%llu-%llu)", - input->inode_bitmap, input->inode_table, itend-1); + (unsigned long long)input->inode_bitmap, + (unsigned long long)input->inode_table, itend - 1); else if (inside(input->block_bitmap, start, metaend)) ext4_warning(sb, __FUNCTION__, "Block bitmap (%llu) in GDT table" " (%llu-%llu)", - input->block_bitmap, start, metaend - 1); + (unsigned long long)input->block_bitmap, + start, metaend - 1); else if (inside(input->inode_bitmap, start, metaend)) ext4_warning(sb, __FUNCTION__, "Inode bitmap (%llu) in GDT table" " (%llu-%llu)", - input->inode_bitmap, start, metaend - 1); + (unsigned long long)input->inode_bitmap, + start, metaend - 1); else if (inside(input->inode_table, start, metaend) || inside(itend - 1, start, metaend)) ext4_warning(sb, __FUNCTION__, "Inode table (%llu-%llu) overlaps" "GDT table (%llu-%llu)", - input->inode_table, itend - 1, start, metaend - 1); + (unsigned long long)input->inode_table, + itend - 1, start, metaend - 1); else err = 0; brelse(bh); diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 4ee3f006b861..0bea6a619e10 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -271,26 +271,24 @@ static void hugetlbfs_drop_inode(struct inode *inode) hugetlbfs_forget_inode(inode); } -/* - * h_pgoff is in HPAGE_SIZE units. - * vma->vm_pgoff is in PAGE_SIZE units. - */ static inline void -hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff) +hugetlb_vmtruncate_list(struct prio_tree_root *root, pgoff_t pgoff) { struct vm_area_struct *vma; struct prio_tree_iter iter; - vma_prio_tree_foreach(vma, &iter, root, h_pgoff, ULONG_MAX) { - unsigned long h_vm_pgoff; + vma_prio_tree_foreach(vma, &iter, root, pgoff, ULONG_MAX) { unsigned long v_offset; - h_vm_pgoff = vma->vm_pgoff >> (HPAGE_SHIFT - PAGE_SHIFT); - v_offset = (h_pgoff - h_vm_pgoff) << HPAGE_SHIFT; /* - * Is this VMA fully outside the truncation point? + * Can the expression below overflow on 32-bit arches? + * No, because the prio_tree returns us only those vmas + * which overlap the truncated area starting at pgoff, + * and no vma on a 32-bit arch can span beyond the 4GB. */ - if (h_vm_pgoff >= h_pgoff) + if (vma->vm_pgoff < pgoff) + v_offset = (pgoff - vma->vm_pgoff) << PAGE_SHIFT; + else v_offset = 0; __unmap_hugepage_range(vma, @@ -303,14 +301,14 @@ hugetlb_vmtruncate_list(struct prio_tree_root *root, unsigned long h_pgoff) */ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset) { - unsigned long pgoff; + pgoff_t pgoff; struct address_space *mapping = inode->i_mapping; if (offset > inode->i_size) return -EINVAL; BUG_ON(offset & ~HPAGE_MASK); - pgoff = offset >> HPAGE_SHIFT; + pgoff = offset >> PAGE_SHIFT; inode->i_size = offset; spin_lock(&mapping->i_mmap_lock); @@ -624,7 +622,6 @@ hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) do_div(size, 100); rest++; } - size &= HPAGE_MASK; pconfig->nr_blocks = (size >> HPAGE_SHIFT); value = rest; } else if (!strcmp(opt,"nr_inodes")) { diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index d5c63047a8b3..4f82bcd63e48 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -967,6 +967,13 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh) */ jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); + + /* Now that we have bh_state locked, are we really still mapped? */ + if (!buffer_mapped(bh)) { + JBUFFER_TRACE(jh, "unmapped buffer, bailing out"); + goto no_journal; + } + if (jh->b_transaction) { JBUFFER_TRACE(jh, "has transaction"); if (jh->b_transaction != handle->h_transaction) { @@ -1028,6 +1035,11 @@ int journal_dirty_data(handle_t *handle, struct buffer_head *bh) sync_dirty_buffer(bh); jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); + /* Since we dropped the lock... */ + if (!buffer_mapped(bh)) { + JBUFFER_TRACE(jh, "buffer got unmapped"); + goto no_journal; + } /* The buffer may become locked again at any time if it is redirtied */ } @@ -1824,6 +1836,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } } } else if (transaction == journal->j_committing_transaction) { + JBUFFER_TRACE(jh, "on committing transaction"); if (jh->b_jlist == BJ_Locked) { /* * The buffer is on the committing transaction's locked @@ -1838,7 +1851,6 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * can remove it's next_transaction pointer from the * running transaction if that is set, but nothing * else. */ - JBUFFER_TRACE(jh, "on committing transaction"); set_buffer_freed(bh); if (jh->b_next_transaction) { J_ASSERT(jh->b_next_transaction == @@ -1858,6 +1870,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * i_size already for this truncate so recovery will not * expose the disk blocks we are discarding here.) */ J_ASSERT_JH(jh, transaction == journal->j_running_transaction); + JBUFFER_TRACE(jh, "on running transaction"); may_free = __dispose_buffer(jh, transaction); } diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index b6cf2be845a1..c051a94c8a97 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -967,6 +967,13 @@ int jbd2_journal_dirty_data(handle_t *handle, struct buffer_head *bh) */ jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); + + /* Now that we have bh_state locked, are we really still mapped? */ + if (!buffer_mapped(bh)) { + JBUFFER_TRACE(jh, "unmapped buffer, bailing out"); + goto no_journal; + } + if (jh->b_transaction) { JBUFFER_TRACE(jh, "has transaction"); if (jh->b_transaction != handle->h_transaction) { @@ -1028,6 +1035,11 @@ int jbd2_journal_dirty_data(handle_t *handle, struct buffer_head *bh) sync_dirty_buffer(bh); jbd_lock_bh_state(bh); spin_lock(&journal->j_list_lock); + /* Since we dropped the lock... */ + if (!buffer_mapped(bh)) { + JBUFFER_TRACE(jh, "buffer got unmapped"); + goto no_journal; + } /* The buffer may become locked again at any time if it is redirtied */ } @@ -1824,6 +1836,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) } } } else if (transaction == journal->j_committing_transaction) { + JBUFFER_TRACE(jh, "on committing transaction"); if (jh->b_jlist == BJ_Locked) { /* * The buffer is on the committing transaction's locked @@ -1838,7 +1851,6 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * can remove it's next_transaction pointer from the * running transaction if that is set, but nothing * else. */ - JBUFFER_TRACE(jh, "on committing transaction"); set_buffer_freed(bh); if (jh->b_next_transaction) { J_ASSERT(jh->b_next_transaction == @@ -1858,6 +1870,7 @@ static int journal_unmap_buffer(journal_t *journal, struct buffer_head *bh) * i_size already for this truncate so recovery will not * expose the disk blocks we are discarding here.) */ J_ASSERT_JH(jh, transaction == journal->j_running_transaction); + JBUFFER_TRACE(jh, "on running transaction"); may_free = __dispose_buffer(jh, transaction); } diff --git a/fs/splice.c b/fs/splice.c index 49fb9f129938..8d705954d294 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -74,7 +74,7 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe, wait_on_page_writeback(page); if (PagePrivate(page)) - try_to_release_page(page, mapping_gfp_mask(mapping)); + try_to_release_page(page, GFP_KERNEL); /* * If we succeeded in removing the mapping, set LRU flag @@ -333,7 +333,7 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, break; error = add_to_page_cache_lru(page, mapping, index, - mapping_gfp_mask(mapping)); + GFP_KERNEL); if (unlikely(error)) { page_cache_release(page); if (error == -EEXIST) @@ -557,7 +557,6 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, { struct file *file = sd->file; struct address_space *mapping = file->f_mapping; - gfp_t gfp_mask = mapping_gfp_mask(mapping); unsigned int offset, this_len; struct page *page; pgoff_t index; @@ -591,7 +590,7 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, goto find_page; page = buf->page; - if (add_to_page_cache(page, mapping, index, gfp_mask)) { + if (add_to_page_cache(page, mapping, index, GFP_KERNEL)) { unlock_page(page); goto find_page; } @@ -613,7 +612,7 @@ find_page: * This will also lock the page */ ret = add_to_page_cache_lru(page, mapping, index, - gfp_mask); + GFP_KERNEL); if (unlikely(ret)) goto out; } |