Misc cleanups / fixes
Subsystems (16)
cover Misc cleanups / fixes
This is a collection of fixes and cleanups from the slab defrag, virtual compound and the large block patchset that are useful independent of these patchsets and that were rediffed against 2.6.23-rc8-mm1.
1+2 Page cache zeroing simplifications
3-8 vmalloc fixes
9-11 slub cleanups / fixes
12 General capability to take a refcount on a compound page
13 Dentry code consolidation
14 Revert buffer_head patch to get the constructor back.
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 1/14 Pagecache zeroing: zero_user_segment, zero_user_segments and zero_user
Simplify page cache zeroing of segments of pages through 3 functions
zero_user_segments(page, start1, end1, start2, end2)
Zeros two segments of the page. It takes the position where to start and end the zeroing which avoids length calculations and makes code clearer.
zero_user_segment(page, start, end)
Same for a single segment.
zero_user(page, start, length)
Length variant for the case where we know the length.
We remove the zero_user_page macro. Issues:
1. Its a macro. Inline functions are preferable.
2. The KM_USER0 macro is only defined for HIGHMEM.
Having to treat this special case everywhere makes the code needlessly complex. The parameter for zeroing is always KM_USER0 except in one single case that we open code.
Avoiding KM_USER0 makes a lot of code not having to be dealing with the special casing for HIGHMEM anymore. Dealing with kmap is only necessary for HIGHMEM configurations. In those configurations we use KM_USER0 like we do for a series of other functions defined in highmem.h.
Since KM_USER0 is depends on HIGHMEM the existing zero_user_page function could not be a macro. zero_user_* functions introduced here can be be inline because that constant is not used when these functions are called.
Also extract the flushing of the caches to be outside of the kmap.
--- fs/buffer.c | 47 +++++++++++++------------------------------ fs/cifs/inode.c | 2 - fs/direct-io.c | 4 +-- fs/ecryptfs/mmap.c | 7 ++---- fs/ext3/inode.c | 4 +-- fs/ext4/inode.c | 4 +-- fs/gfs2/bmap.c | 2 - fs/gfs2/ops_address.c | 2 - fs/libfs.c | 11 +++------- fs/mpage.c | 7 +----- fs/nfs/read.c | 10 ++++----- fs/nfs/write.c | 2 - fs/ntfs/aops.c | 18 +++++++++------- fs/ntfs/file.c | 32 +++++++++++++---------------- fs/ocfs2/aops.c | 6 ++--- fs/reiserfs/inode.c | 4 +-- fs/xfs/linux-2.6/xfs_lrw.c | 2 - include/linux/highmem.h | 49 ++++++++++++++++++++++++++++----------------- mm/filemap_xip.c | 2 - mm/truncate.c | 2 - 20 files changed, 103 insertions(+), 114 deletions(-)
fs/buffer.c +15 -32
@@ -1805,7 +1805,7 @@ void page_zero_new_buffers(struct page * start =max (from, block_start); size =min (to, block_end) - start; -zero_user_page (page, start, size,KM_USER0 ); +zero_user (page, start, size);set_buffer_uptodate (bh); }
@@ -1868,19 +1868,10 @@ static int __block_prepare_write(structmark_buffer_dirty (bh);continue ; } -if (block_end > to || block_start < from) { -void *kaddr; - - kaddr =kmap_atomic (page,KM_USER0 ); -if (block_end > to) -memset (kaddr+to,0 , - block_end-to); -if (block_start < from) -memset (kaddr+block_start, -0 , from-block_start); -flush_dcache_page (page); -kunmap_atomic (kaddr,KM_USER0 ); - } +if (block_end > to || block_start < from) +zero_user_segments (page, + to, block_end, + block_start, from);continue ; } }
@@ -2111,8 +2102,7 @@ int block_read_full_page(struct page *paSetPageError (page); }if (!buffer_mapped (bh)) { -zero_user_page (page, i * blocksize, blocksize, -KM_USER0 ); +zero_user (page, i * blocksize, blocksize);if (!err)set_buffer_uptodate (bh);continue ;
@@ -2225,7 +2215,7 @@ int cont_expand_zero(struct file *file, &page, &fsdata);if (err) goto out; -zero_user_page (page, zerofrom, len,KM_USER0 ); +zero_user (page, zerofrom, len); err =pagecache_write_end (file, mapping, curpos, len, len, page, fsdata);if (err <0 )
@@ -2252,7 +2242,7 @@ int cont_expand_zero(struct file *file, &page, &fsdata);if (err) goto out; -zero_user_page (page, zerofrom, len,KM_USER0 ); +zero_user (page, zerofrom, len); err =pagecache_write_end (file, mapping, curpos, len, len, page, fsdata);if (err <0 )
@@ -2400,7 +2390,6 @@ int nobh_prepare_write(struct page *pageunsigned block_in_page;unsigned block_start, block_end;sector_t block_in_file; -char *kaddr;int nr_reads =0 ;int ret =0 ;int is_mapped_to_disk =1 ;
@@ -2454,13 +2443,8 @@ int nobh_prepare_write(struct page *pagecontinue ; }if (buffer_new (bh) || !buffer_mapped (bh)) { - kaddr =kmap_atomic (page,KM_USER0 ); -if (block_start < from) -memset (kaddr+block_start,0 , from-block_start); -if (block_end > to) -memset (kaddr + to,0 , block_end - to); -flush_dcache_page (page); -kunmap_atomic (kaddr,KM_USER0 ); +zero_user_segments (page, block_start, from, + to, block_end);continue ; }if (buffer_uptodate (bh))
@@ -2525,7 +2509,7 @@ failed:if (buffer_new (bh)) {clear_buffer_new (bh);if (!buffer_uptodate (bh)) { -zero_user_page (page, block_start, bh->b_size,KM_USER0 ); +zero_user (page, block_start, bh->b_size);set_buffer_uptodate (bh); }mark_buffer_dirty (bh);
@@ -2608,7 +2592,7 @@ int nobh_writepage(struct page *page, ge* the page size, the remaining memory is zeroed when mapped, and * writes to that region are not written out to the file." */ -zero_user_page (page, offset,PAGE_CACHE_SIZE - offset,KM_USER0 ); +zero_user_segment (page, offset,PAGE_CACHE_SIZE ); out: ret =mpage_writepage (page, get_block, wbc);if (ret == -EAGAIN )
@@ -2642,8 +2626,7 @@ int nobh_truncate_page(struct address_sp to = (offset + blocksize) & ~(blocksize -1 ); ret = a_ops->prepare_write (NULL , page, offset, to);if (ret ==0 ) { -zero_user_page (page, offset,PAGE_CACHE_SIZE - offset, -KM_USER0 ); +zero_user_segment (page, offset,PAGE_CACHE_SIZE );/* * It would be more correct to call aops->commit_write() * here, but this is more efficient.
@@ -2722,7 +2705,7 @@ int block_truncate_page(struct address_s goto unlock; } -zero_user_page (page, offset, length,KM_USER0 ); +zero_user (page, offset, length);mark_buffer_dirty (bh); err =0 ;
@@ -2768,7 +2751,7 @@ int block_write_full_page(struct page *p* the page size, the remaining memory is zeroed when mapped, and * writes to that region are not written out to the file." */ -zero_user_page (page, offset,PAGE_CACHE_SIZE - offset,KM_USER0 ); +zero_user_segment (page, offset,PAGE_CACHE_SIZE );return __block_write_full_page (inode, page, get_block, wbc); }
fs/cifs/inode.c +1 -1
@@ -1361,7 +1361,7 @@ static int cifs_truncate_page(struct addif (!page)return -ENOMEM ; -zero_user_page (page, offset,PAGE_CACHE_SIZE - offset,KM_USER0 ); +zero_user_segment (page, offset,PAGE_CACHE_SIZE );unlock_page (page);page_cache_release (page);return rc;
fs/direct-io.c +2 -2
@@ -887,8 +887,8 @@ do_holes:page_cache_release (page); goto out; } -zero_user_page (page, block_in_page << blkbits, -1 << blkbits,KM_USER0 ); +zero_user (page, block_in_page << blkbits, +1 << blkbits); dio->block_in_file++; block_in_page++; goto next_block;
fs/ecryptfs/mmap.c +2 -3
@@ -251,8 +251,7 @@ static int fill_zeros_to_end_of_page(str end_byte_in_page =i_size_read (inode) %PAGE_CACHE_SIZE ;if (to > end_byte_in_page) end_byte_in_page = to; -zero_user_page (page, end_byte_in_page, -PAGE_CACHE_SIZE - end_byte_in_page,KM_USER0 ); +zero_user_segment (page, end_byte_in_page,PAGE_CACHE_SIZE ); out:return 0 ; }
@@ -284,7 +283,7 @@ static int ecryptfs_prepare_write(struct } }if (end_of_prev_pg_pos +1 >i_size_read (page->mapping->host)) -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE ); } out:return rc;
fs/ext3/inode.c +2 -2
@@ -1845,7 +1845,7 @@ static int ext3_block_truncate_page(hand*/ if (!page_has_buffers (page) &&test_opt (inode->i_sb,NOBH ) &&ext3_should_writeback_data (inode) &&PageUptodate (page)) { -zero_user_page (page, offset, length,KM_USER0 ); +zero_user (page, offset, length);set_page_dirty (page); goto unlock; }
@@ -1898,7 +1898,7 @@ static int ext3_block_truncate_page(hand goto unlock; } -zero_user_page (page, offset, length,KM_USER0 ); +zero_user (page, offset, length);BUFFER_TRACE (bh,"zeroed end of block" ); err =0 ;
fs/ext4/inode.c +2 -2
@@ -1873,7 +1873,7 @@ int ext4_block_truncate_page(handle_t *h*/ if (!page_has_buffers (page) &&test_opt (inode->i_sb,NOBH ) &&ext4_should_writeback_data (inode) &&PageUptodate (page)) { -zero_user_page (page, offset, length,KM_USER0 ); +zero_user (page, offset, length);set_page_dirty (page); goto unlock; }
@@ -1926,7 +1926,7 @@ int ext4_block_truncate_page(handle_t *h goto unlock; } -zero_user_page (page, offset, length,KM_USER0 ); +zero_user (page, offset, length);BUFFER_TRACE (bh,"zeroed end of block" );
fs/gfs2/bmap.c +1 -1
@@ -934,7 +934,7 @@ static int gfs2_block_truncate_page(struif (sdp->sd_args.ar_data ==GFS2_DATA_ORDERED ||gfs2_is_jdata (ip))gfs2_trans_add_bh (ip->i_gl, bh,0 ); -zero_user_page (page, offset, length,KM_USER0 ); +zero_user (page, offset, length); unlock:unlock_page (page);
fs/gfs2/ops_address.c +1 -1
@@ -209,7 +209,7 @@ static int stuffed_readpage(struct gfs2_* so we need to supply one here. It doesn't happen often. */ if (unlikely (page->index)) { -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE );return 0 ; }
fs/libfs.c +4 -7
@@ -341,13 +341,10 @@ int simple_prepare_write(struct file *fi unsigned from, unsigned to) {if (!PageUptodate (page)) { -if (to - from !=PAGE_CACHE_SIZE ) { -void *kaddr =kmap_atomic (page,KM_USER0 ); -memset (kaddr,0 , from); -memset (kaddr + to,0 ,PAGE_CACHE_SIZE - to); -flush_dcache_page (page); -kunmap_atomic (kaddr,KM_USER0 ); - } +if (to - from !=PAGE_CACHE_SIZE ) +zero_user_segments (page, +0 , from, + to,PAGE_CACHE_SIZE ); }return 0 ; }
fs/mpage.c +2 -5
@@ -284,9 +284,7 @@ do_mpage_readpage(struct bio *bio, struc }if (first_hole != blocks_per_page) { -zero_user_page (page, first_hole << blkbits, -PAGE_CACHE_SIZE - (first_hole << blkbits), -KM_USER0 ); +zero_user_segment (page, first_hole << blkbits,PAGE_CACHE_SIZE );if (first_hole ==0 ) {SetPageUptodate (page);unlock_page (page);
@@ -579,8 +577,7 @@ page_is_mapped:if (page->index > end_index || !offset) goto confused; -zero_user_page (page, offset,PAGE_CACHE_SIZE - offset, -KM_USER0 ); +zero_user_segment (page, offset,PAGE_CACHE_SIZE ); }/*
fs/nfs/read.c +5 -5
@@ -79,7 +79,7 @@ void nfs_readdata_release(void *data)static int nfs_return_empty_page (struct page *page) { -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE );SetPageUptodate (page);unlock_page (page);return 0 ;
@@ -103,10 +103,10 @@ static void nfs_readpage_truncate_uninit pglen =PAGE_CACHE_SIZE - base;for (;;) {if (remainder <= pglen) { -zero_user_page (*pages, base, remainder,KM_USER0 ); +zero_user (*pages, base, remainder);break ; } -zero_user_page (*pages, base, pglen,KM_USER0 ); +zero_user (*pages, base, pglen); pages++; remainder -= pglen; pglen =PAGE_CACHE_SIZE ;
@@ -130,7 +130,7 @@ static int nfs_readpage_async(struct nfsreturn PTR_ERR (new); }if (len <PAGE_CACHE_SIZE ) -zero_user_page (page, len,PAGE_CACHE_SIZE - len,KM_USER0 ); +zero_user_segment (page, len,PAGE_CACHE_SIZE );nfs_list_add_request (new, &one_request);if (NFS_SERVER (inode)->rsize <PAGE_CACHE_SIZE )
@@ -537,7 +537,7 @@ readpage_async_filler(void *data, struct goto out_error;if (len <PAGE_CACHE_SIZE ) -zero_user_page (page, len,PAGE_CACHE_SIZE - len,KM_USER0 ); +zero_user_segment (page, len,PAGE_CACHE_SIZE );nfs_pageio_add_request (desc->pgio, new);return 0 ; out_error:
fs/nfs/write.c +1 -1
@@ -175,7 +175,7 @@ static void nfs_mark_uptodate(struct pagif (count !=nfs_page_length (page))return ;if (count !=PAGE_CACHE_SIZE ) -zero_user_page (page, count,PAGE_CACHE_SIZE - count,KM_USER0 ); +zero_user_segment (page, count,PAGE_CACHE_SIZE );SetPageUptodate (page); }
fs/ntfs/aops.c +10 -8
@@ -87,13 +87,17 @@ static void ntfs_end_buffer_async_read(s/* Check for the current buffer head overflowing. */ if (unlikely (file_ofs + bh->b_size > init_size)) {int ofs; +void *kaddr; ofs =0 ;if (file_ofs < init_size) ofs = init_size - file_ofs;local_irq_save (flags); -zero_user_page (page,bh_offset (bh) + ofs, - bh->b_size - ofs,KM_BIO_SRC_IRQ ); + kaddr =kmap_atomic (page,KM_BIO_SRC_IRQ ); +memset (kaddr +bh_offset (bh) + ofs,0 , + bh->b_size - ofs); +flush_dcache_page (page); +kunmap_atomic (kaddr,KM_BIO_SRC_IRQ );local_irq_restore (flags); } }else {
@@ -334,7 +338,7 @@ handle_hole: bh->b_blocknr =-1UL ;clear_buffer_mapped (bh); handle_zblock: -zero_user_page (page, i * blocksize, blocksize,KM_USER0 ); +zero_user (page, i * blocksize, blocksize);if (likely (!err))set_buffer_uptodate (bh); }while (i++, iblock++, (bh = bh->b_this_page) != head);
@@ -451,7 +455,7 @@ retry_readpage:* ok to ignore the compressed flag here. */ if (unlikely (page->index >0 )) { -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE ); goto done; }if (!NInoAttr (ni))
@@ -780,8 +784,7 @@ lock_retry_remap:if (err == -ENOENT || lcn ==LCN_ENOENT ) { bh->b_blocknr =-1 ;clear_buffer_dirty (bh); -zero_user_page (page,bh_offset (bh), blocksize, -KM_USER0 ); +zero_user (page,bh_offset (bh), blocksize);set_buffer_uptodate (bh); err =0 ;continue ;
@@ -1406,8 +1409,7 @@ retry_writepage:if (page->index >= (i_size >>PAGE_CACHE_SHIFT )) {/* The page straddles i_size. */ unsigned int ofs = i_size & ~PAGE_CACHE_MASK ; -zero_user_page (page, ofs,PAGE_CACHE_SIZE - ofs, -KM_USER0 ); +zero_user_segment (page, ofs,PAGE_CACHE_SIZE ); }/* Handle mst protected attributes. */ if (NInoMstProtected (ni))
fs/ntfs/file.c +15 -17
@@ -606,8 +606,8 @@ do_next_page:ntfs_submit_bh_for_read (bh); *wait_bh++ = bh; }else { -zero_user_page (page,bh_offset (bh), - blocksize,KM_USER0 ); +zero_user (page,bh_offset (bh), + blocksize);set_buffer_uptodate (bh); } }
@@ -682,9 +682,8 @@ map_buffer_cached:ntfs_submit_bh_for_read (bh); *wait_bh++ = bh; }else { -zero_user_page (page, -bh_offset (bh), - blocksize,KM_USER0 ); +zero_user (page,bh_offset (bh), + blocksize);set_buffer_uptodate (bh); } }
@@ -702,8 +701,8 @@ map_buffer_cached:*/ if (bh_end <= pos || bh_pos >= end) {if (!buffer_uptodate (bh)) { -zero_user_page (page,bh_offset (bh), - blocksize,KM_USER0 ); +zero_user (page,bh_offset (bh), + blocksize);set_buffer_uptodate (bh); }mark_buffer_dirty (bh);
@@ -742,8 +741,7 @@ map_buffer_cached:if (!buffer_uptodate (bh))set_buffer_uptodate (bh); }else if (!buffer_uptodate (bh)) { -zero_user_page (page,bh_offset (bh), blocksize, -KM_USER0 ); +zero_user (page,bh_offset (bh), blocksize);set_buffer_uptodate (bh); }continue ;
@@ -867,8 +865,8 @@ rl_not_mapped_enoent:if (!buffer_uptodate (bh))set_buffer_uptodate (bh); }else if (!buffer_uptodate (bh)) { -zero_user_page (page,bh_offset (bh), - blocksize,KM_USER0 ); +zero_user (page,bh_offset (bh), + blocksize);set_buffer_uptodate (bh); }continue ;
@@ -1127,8 +1125,8 @@ rl_not_mapped_enoent:if (likely (bh_pos < initialized_size)) ofs = initialized_size - bh_pos; -zero_user_page (page,bh_offset (bh) + ofs, - blocksize - ofs,KM_USER0 ); +zero_user_segment (page,bh_offset (bh) + ofs, + blocksize); } }else /* if (unlikely(!buffer_uptodate(bh))) */ err = -EIO ;
@@ -1268,8 +1266,8 @@ rl_not_mapped_enoent:if (PageUptodate (page))set_buffer_uptodate (bh);else { -zero_user_page (page,bh_offset (bh), - blocksize,KM_USER0 ); +zero_user (page,bh_offset (bh), + blocksize);set_buffer_uptodate (bh); } }
@@ -1329,7 +1327,7 @@ err_out: len =PAGE_CACHE_SIZE ;if (len > bytes) len = bytes; -zero_user_page (*pages,0 , len,KM_USER0 ); +zero_user (*pages,0 , len); } goto out; }
@@ -1450,7 +1448,7 @@ err_out: len =PAGE_CACHE_SIZE ;if (len > bytes) len = bytes; -zero_user_page (*pages,0 , len,KM_USER0 ); +zero_user (*pages,0 , len); } goto out; }
fs/ocfs2/aops.c +3 -3
@@ -299,7 +299,7 @@ static int ocfs2_readpage(struct file *f* XXX sys_readahead() seems to get that wrong? */ if (start >=i_size_read (inode)) { -zero_user_page (page,0 ,PAGE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_SIZE );SetPageUptodate (page); ret =0 ; goto out_alloc;
@@ -814,7 +814,7 @@ int ocfs2_map_page_blocks(struct page *pif (block_start >= to)break ; -zero_user_page (page, block_start, bh->b_size,KM_USER0 ); +zero_user (page, block_start, bh->b_size);set_buffer_uptodate (bh);mark_buffer_dirty (bh);
@@ -979,7 +979,7 @@ static void ocfs2_zero_new_buffers(struc start =max (from, block_start); end =min (to, block_end); -zero_user_page (page, start, end - start,KM_USER0 ); +zero_user_segment (page, start, end);set_buffer_uptodate (bh); }
fs/reiserfs/inode.c +2 -2
@@ -2143,7 +2143,7 @@ int reiserfs_truncate_file(struct inode/* if we are not on a block boundary */ if (length) { length = blocksize - length; -zero_user_page (page, offset, length,KM_USER0 ); +zero_user (page, offset, length);if (buffer_mapped (bh) && bh->b_blocknr !=0 ) {mark_buffer_dirty (bh); }
@@ -2367,7 +2367,7 @@ static int reiserfs_write_full_page(struunlock_page (page);return 0 ; } -zero_user_page (page, last_offset,PAGE_CACHE_SIZE - last_offset,KM_USER0 ); +zero_user_segment (page, last_offset,PAGE_CACHE_SIZE ); } bh = head; block = page->index << (PAGE_CACHE_SHIFT - s->s_blocksize_bits);
fs/xfs/linux-2.6/xfs_lrw.c +1 -1
@@ -156,7 +156,7 @@ xfs_iozero(if (status)break ; -zero_user_page (page, offset, bytes,KM_USER0 ); +zero_user (page, offset, bytes); status =pagecache_write_end (NULL , mapping, pos, bytes, bytes, page, fsdata);
include/linux/highmem.h +31 -18
59 lines not on this page · raw message
mm/filemap_xip.c +1 -1
@@ -430,7 +430,7 @@ xip_truncate_page(struct address_space *else return PTR_ERR (page); } -zero_user_page (page, offset, length,KM_USER0 ); +zero_user (page, offset, length);return 0 ; }EXPORT_SYMBOL_GPL (xip_truncate_page);
mm/truncate.c +1 -1
@@ -48,7 +48,7 @@ void do_invalidatepage(struct page *pagestatic inline void truncate_partial_page (struct page *page,unsigned partial) { -zero_user_page (page, partial,PAGE_CACHE_SIZE - partial,KM_USER0 ); +zero_user_segment (page, partial,PAGE_CACHE_SIZE );if (PagePrivate (page))do_invalidatepage (page, partial); }
fs/ocfs2/alloc.c +1 -1
@@ -5646,7 +5646,7 @@ static void ocfs2_map_and_dirty_page(strmlog_errno (ret);if (zero) -zero_user_page (page, from, to - from,KM_USER0 ); +zero_user_segment (page, from, to);/* * Need to set the buffers we zero'd into uptodate
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 2/14 Reiser4 portion of zero_user cleanup patch
In reply to Christoph LameterReiser4 only exists in mm. So split this off.
--- fs/buffer.c | 2 +- fs/reiser4/plugin/file/cryptcompress.c | 8 +++----- fs/reiser4/plugin/file/file.c | 4 ++-- fs/reiser4/plugin/item/ctail.c | 8 ++++---- fs/reiser4/plugin/item/extent_file_ops.c | 4 ++-- fs/reiser4/plugin/item/tail.c | 3 +-- 6 files changed, 13 insertions(+), 16 deletions(-)
fs/reiser4/plugin/file/cryptcompress.c +3 -5
@@ -2056,7 +2056,7 @@ static int write_hole(struct inode *inod to_pg =min ((typeof (pg_off ))PAGE_CACHE_SIZE - pg_off, cl_count);lock_page (page); -zero_user_page (page, pg_off, to_pg,KM_USER0 ); +zero_user (page, pg_off, to_pg);SetPageUptodate (page);reiser4_set_page_dirty_internal (page);mark_page_accessed (page);
@@ -2294,8 +2294,7 @@ static int read_some_cluster_pages(struc off =off_to_pgoff (win->off+win->count+win->delta);if (off) {lock_page (pg); -zero_user_page (pg, off,PAGE_CACHE_SIZE - off, -KM_USER0 ); +zero_user_segment (pg, off,PAGE_CACHE_SIZE );unlock_page (pg); } }
@@ -2342,8 +2341,7 @@ static int read_some_cluster_pages(struc offset =off_to_pgoff (win->off + win->count + win->delta); -zero_user_page (pg, offset,PAGE_CACHE_SIZE - offset, -KM_USER0 ); +zero_user_segment (pg, offset,PAGE_CACHE_SIZE );unlock_page (pg);/* still not uptodate */ break ;
fs/reiser4/plugin/file/file.c +2 -2
@@ -532,7 +532,7 @@ static int shorten_file(struct inode *inlock_page (page);assert ("vs-1066" ,PageLocked (page)); -zero_user_page (page, padd_from,PAGE_CACHE_SIZE - padd_from,KM_USER0 ); +zero_user_segment (page, padd_from,PAGE_CACHE_SIZE );unlock_page (page);page_cache_release (page);/* the below does up(sbinfo->delete_mutex). Do not get confused */
@@ -1437,7 +1437,7 @@ int readpage_unix_file(struct file *fileif (page->mapping->host->i_size <=page_offset (page)) {/* page is out of file */ -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE );SetPageUptodate (page);unlock_page (page);return 0 ;
fs/reiser4/plugin/item/ctail.c +4 -4
@@ -638,7 +638,7 @@ int do_readpage_ctail(struct inode * ino goto exit; to_page =pbytes (page_index (page), inode);if (to_page ==0 ) { -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE );SetPageUptodate (page); goto exit; }
@@ -655,7 +655,7 @@ int do_readpage_ctail(struct inode * ino/* refresh bytes */ to_page =pbytes (page_index (page), inode);if (to_page ==0 ) { -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE );SetPageUptodate (page); goto exit; }
@@ -678,7 +678,7 @@ int do_readpage_ctail(struct inode * ino*/ case FAKE_DISK_CLUSTER :/* fill the page by zeroes */ -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE );SetPageUptodate (page);break ;case PREP_DISK_CLUSTER :
@@ -788,7 +788,7 @@ static int ctail_readpages_filler(void *return 0 ; }if (pbytes (page_index (page), inode) ==0 ) { -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE );SetPageUptodate (page);unlock_page (page);return 0 ;
fs/reiser4/plugin/item/extent_file_ops.c +2 -2
@@ -1136,7 +1136,7 @@ int reiser4_do_readpage_extent(reiser4_e*/ j =jfind (mapping, index);if (j ==NULL ) { -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE );SetPageUptodate (page);unlock_page (page);return 0 ;
@@ -1151,7 +1151,7 @@ int reiser4_do_readpage_extent(reiser4_e block = *jnode_get_io_block (j);spin_unlock_jnode (j);if (block ==0 ) { -zero_user_page (page,0 ,PAGE_CACHE_SIZE ,KM_USER0 ); +zero_user (page,0 ,PAGE_CACHE_SIZE );SetPageUptodate (page);unlock_page (page);jput (j);
fs/reiser4/plugin/item/tail.c +1 -2
@@ -392,8 +392,7 @@ static int do_readpage_tail(uf_coord_t * done:if (mapped !=PAGE_CACHE_SIZE ) -zero_user_page (page, mapped,PAGE_CACHE_SIZE - mapped, -KM_USER0 ); +zero_user_segment (page, mapped,PAGE_CACHE_SIZE );SetPageUptodate (page); out_unlock_page:unlock_page (page);
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 3/14 Move vmalloc_to_page() to mm/vmalloc.
In reply to Christoph LameterWe already have page table manipulation for vmalloc in vmalloc.c. Move the vmalloc_to_page() function there as well.
Move the definitions for vmalloc related functions in mm.h to a newly created section. A better place would be vmalloc.h but mm.h is basic and may depend on these functions. An alternative would be to include vmalloc.h in mm.h (like done for vmstat.h).
--- include/linux/mm.h | 5 +++-- mm/memory.c | 40 ---------------------------------------- mm/vmalloc.c | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 42 deletions(-)
mm/memory.c +0 -40
@@ -2651,46 +2651,6 @@ int make_pages_present(unsigned long addreturn ret == len ?0 :-1 ; } -/* -* Map a vmalloc()-space virtual address to the physical page. -*/ -struct page *vmalloc_to_page (void * vmalloc_addr) -{ -unsigned long addr = (unsigned long ) vmalloc_addr; -struct page *page =NULL ; -pgd_t *pgd =pgd_offset_k (addr); -pud_t *pud; -pmd_t *pmd; -pte_t *ptep, pte; - -if (!pgd_none (*pgd)) { - pud =pud_offset (pgd, addr); -if (!pud_none (*pud)) { - pmd =pmd_offset (pud, addr); -if (!pmd_none (*pmd)) { - ptep =pte_offset_map (pmd, addr); - pte = *ptep; -if (pte_present (pte)) - page =pte_page (pte); -pte_unmap (ptep); - } - } - } -return page; -} - -EXPORT_SYMBOL (vmalloc_to_page); - -/* -* Map a vmalloc()-space virtual address to the physical page frame number. -*/ -unsigned long vmalloc_to_pfn (void * vmalloc_addr) -{ -return page_to_pfn (vmalloc_to_page (vmalloc_addr)); -} - -EXPORT_SYMBOL (vmalloc_to_pfn); -#if !defined(__HAVE_ARCH_GATE_AREA)#if defined(AT_SYSINFO_EHDR )
mm/vmalloc.c +38 -0
@@ -166,6 +166,44 @@ int map_vm_area(struct vm_struct *area, }EXPORT_SYMBOL_GPL (map_vm_area); +/* +* Map a vmalloc()-space virtual address to the physical page. +*/ +struct page *vmalloc_to_page (void *vmalloc_addr) +{ +unsigned long addr = (unsigned long ) vmalloc_addr; +struct page *page =NULL ; +pgd_t *pgd =pgd_offset_k (addr); +pud_t *pud; +pmd_t *pmd; +pte_t *ptep, pte; + +if (!pgd_none (*pgd)) { + pud =pud_offset (pgd, addr); +if (!pud_none (*pud)) { + pmd =pmd_offset (pud, addr); +if (!pmd_none (*pmd)) { + ptep =pte_offset_map (pmd, addr); + pte = *ptep; +if (pte_present (pte)) + page =pte_page (pte); +pte_unmap (ptep); + } + } + } +return page; +} +EXPORT_SYMBOL (vmalloc_to_page); + +/* +* Map a vmalloc()-space virtual address to the physical page frame number. +*/ +unsigned long vmalloc_to_pfn (void *vmalloc_addr) +{ +return page_to_pfn (vmalloc_to_page (vmalloc_addr)); +} +EXPORT_SYMBOL (vmalloc_to_pfn); +static struct vm_struct *__get_vm_area_node (unsigned long size,unsigned long flags,unsigned long start,unsigned long end,int node,gfp_t gfp_mask)
include/linux/mm.h +4 -2
@@ -231,6 +231,10 @@ static inline int get_page_unless_zero(sreturn atomic_inc_not_zero (&page->_count); } +/* Support for virtually mapped pages */ +struct page *vmalloc_to_page (void *addr); +unsigned long vmalloc_to_pfn (void *addr); +static inline struct page *compound_head (struct page *page) {if (unlikely (PageTail (page)))
@@ -1086,8 +1090,6 @@ static inline unsigned long vma_pages(stpgprot_t vm_get_page_prot (unsigned long vm_flags);struct vm_area_struct *find_extend_vma (struct mm_struct *,unsigned long addr); -struct page *vmalloc_to_page (void *addr); -unsigned long vmalloc_to_pfn (void *addr);int remap_pfn_range (struct vm_area_struct *,unsigned long addr,unsigned long pfn,unsigned long size,pgprot_t );int vm_insert_page (struct vm_area_struct *,unsigned long addr,struct page *);
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 4/14 vmalloc: add const to void ..tmp_kallsyms1.o.cmd ..tmp_kallsyms2.o.cmd ..tmp_vmlinux1.cmd ..tmp_vmlinux2.cmd .cf .cf1 .cf2 .cf3 .cfnet .config .config.old .gitignore .mailmap .missing-syscalls.d .pc .tmp_System.map .tmp_kallsyms1.S .tmp_kallsyms1.o .tmp_kallsyms2.S .tmp_kallsyms2.o .tmp_versions .tmp_vmlinux1 .tmp_vmlinux2 .version .vmlinux.cmd .vmlinux.o.cmd COPYING CREDITS Documentation Kbuild MAINTAINERS Makefile Module.symvers README REPORTING-BUGS System.map arch b block crypto drivers fs include init ipc kernel lib linux-2.6.23-rc8-mm1.tar.gz mips mm net patches scripts security sound tar-install test test_out usr vmlinux vmlinux.gz vmlinux.o vmlinux.sym xx parameters.
In reply to Christoph LameterMake vmalloc functions work the same way as kfree() and friends that take a const void * argument.
--- include/linux/mm.h | 4 ++-- include/linux/vmalloc.h | 6 +++--- mm/vmalloc.c | 16 ++++++++-------- 3 files changed, 13 insertions(+), 13 deletions(-)
mm/vmalloc.c +8 -8
@@ -169,7 +169,7 @@ EXPORT_SYMBOL_GPL(map_vm_area);/* * Map a vmalloc()-space virtual address to the physical page. */ -struct page *vmalloc_to_page (void *vmalloc_addr) +struct page *vmalloc_to_page (const void *vmalloc_addr) {unsigned long addr = (unsigned long ) vmalloc_addr;struct page *page =NULL ;
@@ -198,7 +198,7 @@ EXPORT_SYMBOL(vmalloc_to_page);/* * Map a vmalloc()-space virtual address to the physical page frame number. */ -unsigned long vmalloc_to_pfn (void *vmalloc_addr) +unsigned long vmalloc_to_pfn (const void *vmalloc_addr) {return page_to_pfn (vmalloc_to_page (vmalloc_addr)); }
@@ -306,7 +306,7 @@ struct vm_struct *get_vm_area_node(unsig }/* Caller must hold vmlist_lock */ -static struct vm_struct *__find_vm_area (void *addr) +static struct vm_struct *__find_vm_area (const void *addr) {struct vm_struct *tmp;
@@ -319,7 +319,7 @@ static struct vm_struct *__find_vm_area( }/* Caller must hold vmlist_lock */ -static struct vm_struct *__remove_vm_area (void *addr) +static struct vm_struct *__remove_vm_area (const void *addr) {struct vm_struct **p, *tmp;
@@ -348,7 +348,7 @@ found:* This function returns the found VM area, but using it is NOT safe * on SMP machines, except for its size or flags. */ -struct vm_struct *remove_vm_area (void *addr) +struct vm_struct *remove_vm_area (const void *addr) {struct vm_struct *v;write_lock (&vmlist_lock);
@@ -357,7 +357,7 @@ struct vm_struct *remove_vm_area(void *areturn v; } -static void __vunmap (void *addr,int deallocate_pages) +static void __vunmap (const void *addr,int deallocate_pages) {struct vm_struct *area;
@@ -408,7 +408,7 @@ static void __vunmap(void *addr, int dea* * Must not be called in interrupt context. */ -void vfree (void *addr) +void vfree (const void *addr) {BUG_ON (in_interrupt ());__vunmap (addr,1 );
@@ -424,7 +424,7 @@ EXPORT_SYMBOL(vfree);* * Must not be called in interrupt context. */ -void vunmap (void *addr) +void vunmap (const void *addr) {BUG_ON (in_interrupt ());__vunmap (addr,0 );
include/linux/vmalloc.h +3 -3
@@ -45,11 +45,11 @@ extern void *vmalloc_32_user(unsigned loextern void *__vmalloc (unsigned long size,gfp_t gfp_mask,pgprot_t prot);extern void *__vmalloc_area (struct vm_struct *area,gfp_t gfp_mask,pgprot_t prot); -extern void vfree (void *addr); +extern void vfree (const void *addr);extern void *vmap (struct page **pages,unsigned int count,unsigned long flags,pgprot_t prot); -extern void vunmap (void *addr); +extern void vunmap (const void *addr);extern int remap_vmalloc_range (struct vm_area_struct *vma,void *addr,unsigned long pgoff);
@@ -71,7 +71,7 @@ extern struct vm_struct *__get_vm_area(uextern struct vm_struct *get_vm_area_node (unsigned long size,unsigned long flags,int node,gfp_t gfp_mask); -extern struct vm_struct *remove_vm_area (void *addr); +extern struct vm_struct *remove_vm_area (const void *addr);extern int map_vm_area (struct vm_struct *area,pgprot_t prot,struct page ***pages);
include/linux/mm.h +2 -2
@@ -232,8 +232,8 @@ static inline int get_page_unless_zero(s }/* Support for virtually mapped pages */ -struct page *vmalloc_to_page (void *addr); -unsigned long vmalloc_to_pfn (void *addr); +struct page *vmalloc_to_page (const void *addr); +unsigned long vmalloc_to_pfn (const void *addr);static inline struct page *compound_head (struct page *page) {
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 5/14 i386: Resolve dependency of asm-i386/pgtable.h on highmem.h
In reply to Christoph Lameterpgtable.h does not include highmem.h but uses various constants from highmem.h. We cannot include highmem.h because highmem.h will in turn include many other include files that also depend on pgtable.h
So move the definitions from highmem.h into pgtable.h.
--- include/asm-i386/highmem.h | 6 ------ include/asm-i386/pgtable.h | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-)
include/asm-i386/highmem.h +0 -6
@@ -38,11 +38,6 @@ extern pte_t *pkmap_page_table;* easily, subsequent pte tables have to be allocated in one physical * chunk of RAM. */ -#ifdef CONFIG_X86_PAE -#define LAST_PKMAP 512 -#else -#define LAST_PKMAP 1024 -#endif /* * Ordering is: *
@@ -58,7 +53,6 @@ extern pte_t *pkmap_page_table;* VMALLOC_START * high_memory */ -#define PKMAP_BASE ( (FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK )#define LAST_PKMAP_MASK (LAST_PKMAP-1)#define PKMAP_NR (virt) ((virt-PKMAP_BASE) >> PAGE_SHIFT)#define PKMAP_ADDR (nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
include/asm-i386/pgtable.h +8 -0
@@ -78,6 +78,14 @@ void paging_init(void);#define VMALLOC_OFFSET (8*1024*1024)#define VMALLOC_START (((unsigned long) high_memory + \ 2*VMALLOC_OFFSET-1) & ~(VMALLOC_OFFSET-1)) +#ifdef CONFIG_X86_PAE +#define LAST_PKMAP 512 +#else +#define LAST_PKMAP 1024 +#endif + +#define PKMAP_BASE ( (FIXADDR_BOOT_START - PAGE_SIZE*(LAST_PKMAP + 1)) & PMD_MASK ) +#ifdef CONFIG_HIGHMEM # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)#else
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 6/14 is_vmalloc_addr(): Check if an address is within the vmalloc boundaries
In reply to Christoph LameterChecking if an address is a vmalloc address is done in a couple of places. Define a common version in mm.h and replace the other checks.
Again the include structures suck. The definition of VMALLOC_START and VMALLOC_END is not available in vmalloc.h since highmem.c cannot be included there.
--- drivers/net/cxgb3/cxgb3_offload.c | 4 +--- fs/ntfs/malloc.h | 3 +-- fs/proc/kcore.c | 2 +- fs/xfs/linux-2.6/kmem.c | 3 +-- fs/xfs/linux-2.6/xfs_buf.c | 3 +-- include/linux/mm.h | 8 ++++++++ mm/sparse.c | 10 +--------- 7 files changed, 14 insertions(+), 19 deletions(-)
include/linux/mm.h +8 -0
@@ -235,6 +235,14 @@ static inline int get_page_unless_zero(sstruct page *vmalloc_to_page (const void *addr);unsigned long vmalloc_to_pfn (const void *addr); +/* Determine if an address is within the vmalloc range */ +static inline int is_vmalloc_addr (const void *x) +{ +unsigned long addr = (unsigned long )x; + +return addr >=VMALLOC_START && addr <VMALLOC_END ; +} +static inline struct page *compound_head (struct page *page) {if (unlikely (PageTail (page)))
mm/sparse.c +1 -9
@@ -362,17 +362,9 @@ static inline struct page *kmalloc_sectireturn __kmalloc_section_memmap (nr_pages); } -static int vaddr_in_vmalloc_area (void *addr) -{ -if (addr >= (void *)VMALLOC_START && - addr < (void *)VMALLOC_END ) -return 1 ; -return 0 ; -} -static void __kfree_section_memmap (struct page *memmap,unsigned long nr_pages) { -if (vaddr_in_vmalloc_area (memmap)) +if (is_vmalloc_addr (memmap))vfree (memmap);else free_pages((unsigned long)memmap,
drivers/net/cxgb3/cxgb3_offload.c +1 -3
@@ -1060,9 +1060,7 @@ void *cxgb_alloc_mem(unsigned long size)*/ void cxgb_free_mem (void *addr) { -unsigned long p = (unsigned long )addr; - -if (p >=VMALLOC_START && p <VMALLOC_END ) +if (is_vmalloc_addr (addr))vfree (addr);else kfree (addr);
fs/ntfs/malloc.h +1 -2
@@ -85,8 +85,7 @@ static inline void *ntfs_malloc_nofs_nofstatic inline void ntfs_free (void *addr) { -if (likely (((unsigned long )addr <VMALLOC_START ) || - ((unsigned long )addr >=VMALLOC_END ))) { +if (!is_vmalloc_addr (addr)) {kfree (addr);/* free_page((unsigned long)addr); */ return ;
fs/proc/kcore.c +1 -1
@@ -325,7 +325,7 @@ read_kcore(struct file *file, char __useif (m ==NULL ) {if (clear_user (buffer, tsz))return -EFAULT ; - }else if ((start >=VMALLOC_START ) && (start <VMALLOC_END )) { + }else if (is_vmalloc_addr ((void *)start)) {char * elf_buf;struct vm_struct *m;unsigned long curstart = start;
fs/xfs/linux-2.6/kmem.c +1 -2
@@ -92,8 +92,7 @@ kmem_zalloc_greedy(size_t *size, size_tvoid kmem_free (void *ptr,size_t size) { -if (((unsigned long )ptr <VMALLOC_START ) || - ((unsigned long )ptr >=VMALLOC_END )) { +if (!is_vmalloc_addr (ptr)) {kfree (ptr); }else {vfree (ptr);
fs/xfs/linux-2.6/xfs_buf.c +1 -2
@@ -696,8 +696,7 @@ static inline struct page *mem_to_page ( void *addr) { -if (((unsigned long )addr <VMALLOC_START ) || - ((unsigned long )addr >=VMALLOC_END )) { +if ((!is_vmalloc_addr (addr))) {return virt_to_page (addr); }else {return vmalloc_to_page (addr);
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 7/14 vmalloc: Clean up page array indexing
In reply to Christoph LameterThe page array is repeatedly indexed both in vunmap and vmalloc_area_node(). Add a temporary variable to make it easier to read (and easier to patch later).
--- mm/vmalloc.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
mm/vmalloc.c +11 -5
@@ -384,8 +384,10 @@ static void __vunmap(const void *addr, iint i;for (i =0 ; i < area->nr_pages; i++) { -BUG_ON (!area->pages[i]); -__free_page (area->pages[i]); +struct page *page = area->pages[i]; + +BUG_ON (!page); +__free_page (page); }if (area->flags &VM_VPAGES )
@@ -489,15 +491,19 @@ void *__vmalloc_area_node(struct vm_stru }for (i =0 ; i < area->nr_pages; i++) { +struct page *page; +if (node <0 ) - area->pages[i] =alloc_page (gfp_mask); + page =alloc_page (gfp_mask);else - area->pages[i] =alloc_pages_node (node, gfp_mask,0 ); -if (unlikely (!area->pages[i])) { + page =alloc_pages_node (node, gfp_mask,0 ); + +if (unlikely (!page)) {/* Successfully allocated i pages, free them in __vunmap() */ area->nr_pages = i; goto fail; } + area->pages[i] = page; }if (map_vm_area (area, prot, &pages))
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 8/14 vunmap: return page array passed on vmap()
In reply to Christoph LameterMake vunmap return the page array that was used at vmap. This is useful if one has no structures to track the page array but simply stores the virtual address somewhere. The disposition of the page array can be decided upon after vunmap. vfree() may now also be used instead of vunmap which will release the page array after vunmap'ping it.
As noted by Kamezawa: The same subsystem that provides the page array to vmap must must use its own method to dispose of the page array.
If vfree() is called to free the page array passed to vmap() [We currently do not do that] then the page array must either be
1. Allocated via the slab allocator
2. Allocated via vmalloc but then VM_VPAGES must have been passed at vunmap to specify that a vfree is needed.
RFC->v1:
- Add comment explaining how to use vfree() to dispose of the page array passed on vmap().
--- include/linux/vmalloc.h | 2 +- mm/vmalloc.c | 33 +++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 11 deletions(-)
include/linux/vmalloc.h +1 -1
@@ -49,7 +49,7 @@ extern void vfree(const void *addr);extern void *vmap (struct page **pages,unsigned int count,unsigned long flags,pgprot_t prot); -extern void vunmap (const void *addr); +extern struct page **vunmap (const void *addr);extern int remap_vmalloc_range (struct vm_area_struct *vma,void *addr,unsigned long pgoff);
mm/vmalloc.c +23 -10
@@ -357,17 +357,18 @@ struct vm_struct *remove_vm_area(const vreturn v; } -static void __vunmap (const void *addr,int deallocate_pages) +static struct page **__vunmap (const void *addr,int deallocate_pages) {struct vm_struct *area; +struct page **pages;if (!addr) -return ; +return NULL ;if ((PAGE_SIZE -1 ) & (unsigned long )addr) {printk (KERN_ERR "Trying to vfree() bad address (%p)\n" , addr);WARN_ON (1 ); -return ; +return NULL ; } area =remove_vm_area (addr);
@@ -375,29 +376,30 @@ static void __vunmap(const void *addr, iprintk (KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n" , addr);WARN_ON (1 ); -return ; +return NULL ; } + pages = area->pages;debug_check_no_locks_freed (addr, area->size);if (deallocate_pages) {int i;for (i =0 ; i < area->nr_pages; i++) { -struct page *page = area->pages[i]; +struct page *page = pages[i];BUG_ON (!page);__free_page (page); }if (area->flags &VM_VPAGES ) -vfree (area->pages); +vfree (pages);else -kfree (area->pages); +kfree (pages); }kfree (area); -return ; +return pages; }/**
@@ -425,11 +427,13 @@ EXPORT_SYMBOL(vfree);* which was created from the page array passed to vmap(). * * Must not be called in interrupt context. +* +* Returns a pointer to the array of pointers to page structs */ -void vunmap (const void *addr) +struct page **vunmap (const void *addr) {BUG_ON (in_interrupt ()); -__vunmap (addr,0 ); +return __vunmap (addr,0 ); }EXPORT_SYMBOL (vunmap);
@@ -442,6 +446,13 @@ EXPORT_SYMBOL(vunmap);* * Maps @count pages from @pages into contiguous kernel virtual * space. +* +* The page array may be freed via vfree() with the virtual address +* returned from vmap. In that case the page array must be allocated via +* the slab allocator. If the page array was allocated via +* vmalloc then VM_VPAGES must be specified in the flags. There is +* no support for vfree() freeing pages allocated via the +* page allocator. */ void *vmap (struct page **pages,unsigned int count,unsigned long flags,pgprot_t prot)
@@ -454,6 +465,8 @@ void *vmap(struct page **pages, unsigned area =get_vm_area ((count <<PAGE_SHIFT ), flags);if (!area)return NULL ; + area->pages = pages; + area->nr_pages = count;if (map_vm_area (area, prot, &pages)) {vunmap (area->addr);return NULL ;
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 9/14 SLUB: Move count_partial()
In reply to Christoph LameterMove the counting function for objects in partial slabs so that it is placed before kmem_cache_shrink.
--- mm/slub.c | 26 +++++++++++++------------- 1 files changed, 13 insertions(+), 13 deletions(-)
mm/slub.c +13 -13
@@ -2626,6 +2626,19 @@ void kfree(const void *x) }EXPORT_SYMBOL (kfree); +static unsigned long count_partial (struct kmem_cache_node *n) +{ +unsigned long flags; +unsigned long x =0 ; +struct page *page; + +spin_lock_irqsave (&n->list_lock, flags); +list_for_each_entry (page, &n->partial, lru) + x += page->inuse; +spin_unlock_irqrestore (&n->list_lock, flags); +return x; +} +/* * kmem_cache_shrink removes empty slabs from the partial lists and sorts * the remaining slabs by the number of items in use. The slabs with the
@@ -3372,19 +3385,6 @@ static int list_locations(struct kmem_careturn n; } -static unsigned long count_partial (struct kmem_cache_node *n) -{ -unsigned long flags; -unsigned long x =0 ; -struct page *page; - -spin_lock_irqsave (&n->list_lock, flags); -list_for_each_entry (page, &n->partial, lru) - x += page->inuse; -spin_unlock_irqrestore (&n->list_lock, flags); -return x; -} -enum slab_stat_type {SL_FULL ,SL_PARTIAL ,
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 10/14 SLUB: Rename NUMA defrag_ratio to remote_node_defrag_ratio
In reply to Christoph LameterThe NUMA defrag works by allocating objects from partial slabs on remote nodes. Rename it to
remote_node_defrag_ratio
to be clear about this.
--- include/linux/slub_def.h | 5 ++++- mm/slub.c | 17 +++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-)
include/linux/slub_def.h +4 -1
@@ -59,7 +59,10 @@ struct kmem_cache {#endif #ifdef CONFIG_NUMA -int defrag_ratio; +/* +* Defragmentation by allocating from a remote node. +*/ +int remote_node_defrag_ratio;struct kmem_cache_node *node[MAX_NUMNODES ];#endif #ifdef CONFIG_SMP
mm/slub.c +9 -8
@@ -1300,7 +1300,8 @@ static struct page *get_any_partial(stru* expensive if we do it every time we are trying to find a slab * with available objects. */ -if (!s->defrag_ratio ||get_cycles () %1024 > s->defrag_ratio) +if (!s->remote_node_defrag_ratio || +get_cycles () %1024 > s->remote_node_defrag_ratio)return NULL ; zonelist = &NODE_DATA (slab_node (current->mempolicy))
@@ -2231,7 +2232,7 @@ static int kmem_cache_open(struct kmem_c s->refcount =1 ;#ifdef CONFIG_NUMA - s->defrag_ratio =100 ; + s->remote_node_defrag_ratio =100 ;#endif if (!init_kmem_cache_nodes (s, gfpflags & ~SLUB_DMA )) goto error;
@@ -3762,21 +3763,21 @@ static ssize_t free_calls_show(struct kmSLAB_ATTR_RO (free_calls);#ifdef CONFIG_NUMA -static ssize_t defrag_ratio_show (struct kmem_cache *s,char *buf) +static ssize_t remote_node_defrag_ratio_show (struct kmem_cache *s,char *buf) { -return sprintf (buf,"%d\n" , s->defrag_ratio /10 ); +return sprintf (buf,"%d\n" , s->remote_node_defrag_ratio /10 ); } -static ssize_t defrag_ratio_store (struct kmem_cache *s, +static ssize_t remote_node_defrag_ratio_store (struct kmem_cache *s,const char *buf,size_t length) {int n =simple_strtoul (buf,NULL ,10 );if (n <100 ) - s->defrag_ratio = n *10 ; + s->remote_node_defrag_ratio = n *10 ;return length; } -SLAB_ATTR (defrag_ratio); +SLAB_ATTR (remote_node_defrag_ratio);#endif static struct attribute * slab_attrs[] = {
@@ -3807,7 +3808,7 @@ static struct attribute * slab_attrs[] = &cache_dma_attr.attr,#endif #ifdef CONFIG_NUMA - &defrag_ratio_attr.attr, + &remote_node_defrag_ratio_attr.attr, #endifNULL };
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 11/14 SLUB: Consolidate add_partial() and add_partial_tail() to one function
In reply to Christoph LameterAdd a parameter to add_partial instead of having separate functions. The parameter allows a more detailed control of where the slab pages is placed in the partial queues.
If we put slabs back to the front then they are likely immediately used for allocations. If they are put at the end then we can maximize the time that the partial slabs spent without being subject to allocations.
When deactivating slab we can put the slabs that had remote objects freed (we can see that because objects were put on the freelist that requires locks) to them at the end of the list so that the cachelines of remote processors can cool down. Slabs that had objects from the local cpu freed to them (objects exist in the lockless freelist) are put in the front of the list to be reused ASAP in order to exploit the cache hot state of the local cpu.
--- mm/slub.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-)
mm/slub.c +15 -16
@@ -1203,19 +1203,15 @@ static __always_inline int slab_trylock(/* * Management of partially allocated slabs */ -static void add_partial_tail (struct kmem_cache_node *n,struct page *page) +static void add_partial (struct kmem_cache_node *n, +struct page *page,int tail) {spin_lock (&n->list_lock); n->nr_partial++; -list_add_tail (&page->lru, &n->partial); -spin_unlock (&n->list_lock); -} - -static void add_partial (struct kmem_cache_node *n,struct page *page) -{ -spin_lock (&n->list_lock); - n->nr_partial++; -list_add (&page->lru, &n->partial); +if (tail) +list_add_tail (&page->lru, &n->partial); +else +list_add (&page->lru, &n->partial);spin_unlock (&n->list_lock); }
@@ -1344,7 +1340,7 @@ static struct page *get_partial(struct k* * On exit the slab lock will have been dropped. */ -static void unfreeze_slab (struct kmem_cache *s,struct page *page) +static void unfreeze_slab (struct kmem_cache *s,struct page *page,int tail) {struct kmem_cache_node *n =get_node (s,page_to_nid (page));
@@ -1352,7 +1348,7 @@ static void unfreeze_slab(struct kmem_caif (page->inuse) {if (page->freelist) -add_partial (n, page); +add_partial (n, page, tail);else if (SlabDebug (page) && (s->flags &SLAB_STORE_USER ))add_full (n, page);slab_unlock (page);
@@ -1367,7 +1363,7 @@ static void unfreeze_slab(struct kmem_ca* partial list stays small. kmem_cache_shrink can * reclaim empty slabs from the partial list. */ -add_partial_tail (n, page); +add_partial (n, page,1 );slab_unlock (page); }else {slab_unlock (page);
@@ -1382,6 +1378,7 @@ static void unfreeze_slab(struct kmem_castatic void deactivate_slab (struct kmem_cache *s,struct kmem_cache_cpu *c) {struct page *page = c->page; +int tail =1 ;/* * Merge cpu freelist into freelist. Typically we get here * because both freelists are empty. So this is unlikely
@@ -1390,6 +1387,8 @@ static void deactivate_slab(struct kmem_while (unlikely (c->freelist)) {void **object; + tail =0 ;/* Hot objects. Put the slab first */ +/* Retrieve object from cpu_freelist */ object = c->freelist; c->freelist = c->freelist[c->offset];
@@ -1400,7 +1399,7 @@ static void deactivate_slab(struct kmem_ page->inuse--; } c->page =NULL ; -unfreeze_slab (s, page); +unfreeze_slab (s, page, tail); }static inline void flush_slab (struct kmem_cache *s,struct kmem_cache_cpu *c)
@@ -1640,7 +1639,7 @@ checks_ok:* then add it. */ if (unlikely (!prior)) -add_partial (get_node (s,page_to_nid (page)), page); +add_partial (get_node (s,page_to_nid (page)), page,0 ); out_unlock:slab_unlock (page);
@@ -2047,7 +2046,7 @@ static struct kmem_cache_node *early_kme#endif init_kmem_cache_node (n);atomic_long_inc (&n->nr_slabs); -add_partial (n, page); +add_partial (n, page,0 );return n; }
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 12/14 VM: Allow get_page_unless_zero on compound pages
In reply to Christoph LameterBoth slab defrag and the large blocksize patches need to ability to take refcounts on compound pages. May be useful in other places as well.
--- include/linux/mm.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/mm.h +1 -1
@@ -227,7 +227,7 @@ static inline int put_page_testzero(stru*/ static inline int get_page_unless_zero (struct page *page) { -VM_BUG_ON (PageCompound (page)); +VM_BUG_ON (PageTail (page));return atomic_inc_not_zero (&page->_count); }
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 13/14 dentries: Extract common code to remove dentry from lru
In reply to Christoph LameterExtract the common code to remove a dentry from the lru into a new function dentry_lru_remove().
Two call sites used list_del() instead of list_del_init(). AFAIK the performance of both is the same. dentry_lru_remove() does a list_del_init().
As a result dentry->d_lru is now always empty when a dentry is freed.
--- fs/dcache.c | 42 ++++++++++++++---------------------------- 1 files changed, 14 insertions(+), 28 deletions(-)
fs/dcache.c +14 -28
@@ -95,6 +95,14 @@ static void d_free(struct dentry *dentrycall_rcu (&dentry->d_u.d_rcu, d_callback); } +static void dentry_lru_remove (struct dentry *dentry) +{ +if (!list_empty (&dentry->d_lru)) { +list_del_init (&dentry->d_lru); + dentry_stat.nr_unused--; + } +} +/* * Release the dentry's inode, using the filesystem * d_iput() operation if defined.
@@ -212,13 +220,7 @@ repeat: unhash_it:__d_drop (dentry); kill_it: -/* If dentry was on d_lru list -* delete it from there -*/ -if (!list_empty (&dentry->d_lru)) { -list_del (&dentry->d_lru); - dentry_stat.nr_unused--; - } +dentry_lru_remove (dentry); dentry =d_kill (dentry);if (dentry) goto repeat;
@@ -286,10 +288,7 @@ int d_invalidate(struct dentry * dentry)static inline struct dentry *__dget_locked (struct dentry *dentry) {atomic_inc (&dentry->d_count); -if (!list_empty (&dentry->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&dentry->d_lru); - } +dentry_lru_remove (dentry);return dentry; }
@@ -405,10 +404,7 @@ static void prune_one_dentry(struct dentif (dentry->d_op && dentry->d_op->d_delete) dentry->d_op->d_delete (dentry); -if (!list_empty (&dentry->d_lru)) { -list_del (&dentry->d_lru); - dentry_stat.nr_unused--; - } +dentry_lru_remove (dentry);__d_drop (dentry); dentry =d_kill (dentry);spin_lock (&dcache_lock);
@@ -597,10 +593,7 @@ static void shrink_dcache_for_umount_sub/* detach this root from the system */ spin_lock (&dcache_lock); -if (!list_empty (&dentry->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&dentry->d_lru); - } +dentry_lru_remove (dentry);__d_drop (dentry);spin_unlock (&dcache_lock);
@@ -614,11 +607,7 @@ static void shrink_dcache_for_umount_subspin_lock (&dcache_lock);list_for_each_entry (loop, &dentry->d_subdirs, d_u.d_child) { -if (!list_empty (&loop->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&loop->d_lru); - } - +dentry_lru_remove (dentry);__d_drop (loop);cond_resched_lock (&dcache_lock); }
@@ -800,10 +789,7 @@ resume: struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); next = tmp->next; -if (!list_empty (&dentry->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&dentry->d_lru); - } +dentry_lru_remove (dentry);/* * move only zero ref count dentries to the end * of the unused list for prune_dcache
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerRe: [patch 13/14] dentries: Extract common code to remove dentry from lru
Quoted 5 lines · On Tue, 25 Sep 2007 16:25:56 -0700 Christoph Lameter <[email protected]> wrote:
Extract the common code to remove a dentry from the lru into a new function
dentry_lru_remove().Two call sites used
list_del()instead oflist_del_init(). AFAIK the performance of both is the same.dentry_lru_remove()does alist_del_init().
list_del() will dirty two cachelines, but list_del_init() needs to dirty a third, by writing to the to-be-removed list_head().
Quoted 12 lines
As a result
dentry->d_lruis now always empty when a dentry is freed.Signed-off-by Christoph Lameter <[email protected]>--- fs/dcache.c | 42 ++++++++++++++---------------------------- 1 files changed, 14 insertions(+), 28 deletions(-)Index:
linux-2.6.23-rc8-mm1/fs/dcache.c
===================================================================
fs/dcache.c static void d_free(struct dentry *dentry · line 104
Quoted 10 lines
fs/dcache.c +7
-0@@ -95,6 +95,14 @@ static void d_free(struct dentry *dentrycall_rcu (&dentry->d_u.d_rcu, d_callback); } +static void dentry_lru_remove (struct dentry *dentry) +{ +if (!list_empty (&dentry->d_lru)) { +list_del_init (&dentry->d_lru); + dentry_stat.nr_unused--; + } +}
So can we switch this to list_del()?
Quoted 19 lines
fs/dcache.c +1
-7/* * Release the dentry's inode, using the filesystem * d_iput() operation if defined. @@ -212,13 +220,7 @@ repeat: unhash_it:__d_drop (dentry); kill_it: -/* If dentry was on d_lru list -* delete it from there -*/ -if (!list_empty (&dentry->d_lru)) { -list_del (&dentry->d_lru); - dentry_stat.nr_unused--; - } +dentry_lru_remove (dentry); dentry =d_kill (dentry);if (dentry) goto repeat;
fs/dcache.c int d_invalidate(struct dentry * dentry) · line 292
Quoted 7 lines
fs/dcache.c +0
-4@@ -286,10 +288,7 @@ int d_invalidate(struct dentry * dentry)static inline struct dentry *__dget_locked (struct dentry *dentry) {atomic_inc (&dentry->d_count); -if (!list_empty (&dentry->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&dentry->d_lru); - }
No, we can't.
Quoted 42 lines
fs/dcache.c +4
-13+dentry_lru_remove (dentry);return dentry; }@@ -405,10 +404,7 @@ static void prune_one_dentry(struct dentif (dentry->d_op && dentry->d_op->d_delete) dentry->d_op->d_delete (dentry); -if (!list_empty (&dentry->d_lru)) { -list_del (&dentry->d_lru); - dentry_stat.nr_unused--; - } +dentry_lru_remove (dentry);__d_drop (dentry); dentry =d_kill (dentry);spin_lock (&dcache_lock);@@ -597,10 +593,7 @@ static void shrink_dcache_for_umount_sub/* detach this root from the system */ spin_lock (&dcache_lock); -if (!list_empty (&dentry->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&dentry->d_lru); - } +dentry_lru_remove (dentry);__d_drop (dentry);spin_unlock (&dcache_lock);@@ -614,11 +607,7 @@ static void shrink_dcache_for_umount_subspin_lock (&dcache_lock);list_for_each_entry (loop, &dentry->d_subdirs, d_u.d_child) { -if (!list_empty (&loop->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&loop->d_lru); - } - +dentry_lru_remove (dentry);__d_drop (loop);cond_resched_lock (&dcache_lock); }
fs/dcache.c resume: · line 792
Quoted 8 lines
fs/dcache.c +1
-4@@ -800,10 +789,7 @@ resume: struct dentry *dentry = list_entry(tmp, struct dentry, d_u.d_child); next = tmp->next; -if (!list_empty (&dentry->d_lru)) { - dentry_stat.nr_unused--; -list_del_init (&dentry->d_lru); - } +dentry_lru_remove (dentry);
Doesn't seem like a terribly good change to me - it's one of those cant-measure-a-difference changes which add up to a slower kernel after we've merged three years worth of them.
Perhaps not all of those list_del_init() callers actually need to be using the _init version?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 13/14] dentries: Extract common code to remove dentry from lru
Quoted 6 lines · Andrew Morton
Doesn't seem like a terribly good change to me - it's one of those cant-measure-a-difference changes which add up to a slower kernel after we've merged three years worth of them.
Perhaps not all of those
list_del_init()callers actually need to be using the_initversion?
Sometimes we check the list head using list_empty() so we cannot avoid list_del_init. Always using list_del_init results in a consistent state of affairs before the object is freed (which the slab defrag patchset depends on)
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerRe: [patch 13/14] dentries: Extract common code to remove dentry from lru
Quoted 6 lines · On Wed, 24 Oct 2007 19:23:36 -0700 (PDT) Christoph Lameter <[email protected]>…
Quoted 4 lines · Andrew Morton
Doesn't seem like a terribly good change to me - it's one of those cant-measure-a-difference changes which add up to a slower kernel after we've merged three years worth of them.
Quoted 7 lines
Quoted 2 lines
Perhaps not all of those
list_del_init()callers actually need to be using the_initversion?Sometimes we check the list head using
list_empty()so we cannot avoidlist_del_init. Always usinglist_del_initresults in a consistent state of affairs before the object is freed (which the slab defrag patchset depends on)
OK, but it's slower.
So I think it should be changlogged as such, with an explanation that there will (hopefully) be a net benefit because it enables slab defrag, and it should be moved into the slab-defrag patchset.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 13/14] dentries: Extract common code to remove dentry from lru
Quoted 10 lines · Andrew Morton
Quoted 4 lines
Sometimes we check the list head using
list_empty()so we cannot avoidlist_del_init. Always usinglist_del_initresults in a consistent state of affairs before the object is freed (which the slab defrag patchset depends on)OK, but it's slower.
So I think it should be changlogged as such, with an explanation that there will (hopefully) be a net benefit because it enables slab defrag, and it should be moved into the slab-defrag patchset.
really?
list_del_init does:
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}So it touches the cachelines of the entry and prev/next to fix up the links.
list_del does:
#ifndef CONFIG_DEBUG_LIST
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}#else
extern void list_del(struct list_head *entry);
#endif
In the !DEBUG case it touches the same cachelines. The only change is that we poison entry.
So its not slower.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerRe: [patch 13/14] dentries: Extract common code to remove dentry from lru
Quoted 35 lines · On Wed, 24 Oct 2007 19:50:19 -0700 (PDT) Christoph Lameter <[email protected]>…
Quoted 10 lines · Andrew Morton
Quoted 4 lines
Sometimes we check the list head using
list_empty()so we cannot avoidlist_del_init. Always usinglist_del_initresults in a consistent state of affairs before the object is freed (which the slab defrag patchset depends on)OK, but it's slower.
So I think it should be changlogged as such, with an explanation that there will (hopefully) be a net benefit because it enables slab defrag, and it should be moved into the slab-defrag patchset.
really?
list_del_initdoes:static inline void
list_del_init(struct list_head *entry){ __list_del(entry->prev, entry->next); INIT_LIST_HEAD(entry); }So it touches the cachelines of the entry and prev/next to fix up the links.
list_deldoes:#ifndef
CONFIG_DEBUG_LIST
static inline voidlist_del(struct list_head *entry){ __list_del(entry->prev, entry->next); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }
Quoted 6 lines
#else
extern voidlist_del(struct list_head *entry);
#endifIn the !DEBUG case it touches the same cachelines. The only change is that we poison entry.
bugger, I'd forgotten that we do the poisoning even if !CONFIG_DEBUG_LIST.
We really shouldn't do that, especially now that we have the list debugging config option.
Fixing this might break net/rxrpc/af_rxrpc.c and detach_timer(), but they deserve to be broken.
Quoted 1 line
So its not slower.
It should be.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
PATCH 14/14 bufferhead: Revert constructor removal
In reply to Christoph LameterThe constructor for buffer_head slabs was removed recently. We need the constructor back in slab defrag in order to insure that slab objects always have a definite state even before we allocated them.
--- fs/buffer.c | 19 +++++++++++++++---- 1 files changed, 15 insertions(+), 4 deletions(-)
fs/buffer.c +15 -3
@@ -3093,7 +3093,7 @@ static void recalc_bh_state(void)struct buffer_head *alloc_buffer_head (gfp_t gfp_flags) { -struct buffer_head *ret =kmem_cache_zalloc (bh_cachep, +struct buffer_head *ret =kmem_cache_alloc (bh_cachep,set_migrateflags (gfp_flags, __GFP_RECLAIMABLE));if (ret) {INIT_LIST_HEAD (&ret->b_assoc_buffers);
@@ -3137,12 +3137,24 @@ static int buffer_cpu_notify(struct notireturn NOTIFY_OK ; } +static void +init_buffer_head (struct kmem_cache *cachep,void *data) +{ +struct buffer_head * bh = (struct buffer_head *)data; + +memset (bh,0 ,sizeof (*bh)); +INIT_LIST_HEAD (&bh->b_assoc_buffers); +} +void __init buffer_init (void ) {int nrpages; - bh_cachep =KMEM_CACHE (buffer_head, -SLAB_RECLAIM_ACCOUNT |SLAB_PANIC |SLAB_MEM_SPREAD ); + bh_cachep =kmem_cache_create ("buffer_head" , +sizeof (struct buffer_head ),0 , + (SLAB_RECLAIM_ACCOUNT |SLAB_PANIC | +SLAB_MEM_SPREAD ), + init_buffer_head);/* * Limit the bh occupancy to 10% of ZONE_NORMAL
Signature · 5 lines
-- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerRe: [patch 14/14] bufferhead: Revert constructor removal
Quoted 4 lines · On Tue, 25 Sep 2007 16:25:57 -0700 Christoph Lameter <[email protected]> wrote:
The constructor for
buffer_headslabs was removed recently. We need the constructor back in slab defrag in order to insure that slab objects always have a definite state even before we allocated them.
I don't understand. Slab defrag isn't merged.
Quoted 33 lines
--- fs/buffer.c | 19 +++++++++++++++---- 1 files changed, 15 insertions(+), 4 deletions(-)Index:
linux-2.6.23-rc8-mm1/fs/buffer.c
===================================================================fs/buffer.c +10
-1@@ -3093,7 +3093,7 @@ static void recalc_bh_state(void)struct buffer_head *alloc_buffer_head (gfp_t gfp_flags) { -struct buffer_head *ret =kmem_cache_zalloc (bh_cachep, +struct buffer_head *ret =kmem_cache_alloc (bh_cachep,set_migrateflags (gfp_flags, __GFP_RECLAIMABLE));if (ret) {INIT_LIST_HEAD (&ret->b_assoc_buffers);@@ -3137,12 +3137,24 @@ static int buffer_cpu_notify(struct notireturn NOTIFY_OK ; } +static void +init_buffer_head (struct kmem_cache *cachep,void *data) +{ +struct buffer_head * bh = (struct buffer_head *)data; + +memset (bh,0 ,sizeof (*bh)); +INIT_LIST_HEAD (&bh->b_assoc_buffers); +} +void __init buffer_init (void ) {
fs/buffer.c static int buffer_cpu_notify(struct noti · line 3158
Quoted 10 lines
fs/buffer.c +5
-2int nrpages; - bh_cachep =KMEM_CACHE (buffer_head, -SLAB_RECLAIM_ACCOUNT |SLAB_PANIC |SLAB_MEM_SPREAD ); + bh_cachep =kmem_cache_create ("buffer_head" , +sizeof (struct buffer_head ),0 , + (SLAB_RECLAIM_ACCOUNT |SLAB_PANIC | +SLAB_MEM_SPREAD ), + init_buffer_head);
So I see no need for this patch? Shouldn't it be part of a slab-defrag patch series?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Re: [patch 14/14] bufferhead: Revert constructor removal
Quoted 2 lines · Andrew Morton
So I see no need for this patch? Shouldn't it be part of a slab-defrag patch series?
It could be part of it. However, I think we mistakenly merged the removal of the constuctor into a cleanup patch. You had a test that showed that the removal of the constructor led to a small regression. The prior state makes things easier for slab defrag.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Andrew Morton
maintainerQuoted 4 lines · On Tue, 25 Sep 2007 16:25:43 -0700 Christoph Lameter <[email protected]> wrote:
This is a collection of fixes and cleanups from the slab defrag, virtual compound and the large block patchset that are useful independent of these patchsets and that were rediffed against 2.6.23-rc8-mm1.
Christoph, I think I'll duck these for now - I'm a bit worried about the even-worse-than-usual stability levels in the 2.6.24 lineup, so I'd prefer not to churn things in a way which will distract from fixing all that up.
I'll keep the patches, see if I can get them to apply and work around the -rc1 timeframe.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>