- 论坛徽章:
- 0
|
以前追踪过O_TRUNC
O_TRUNC跟踪:
从fs/open.c->filp_open()开始:O_TRUNC就在flags中
struct file *filp_open(const char * filename, int flags, int mode) ->
open_namei(filename, namei_flags, mode, &nd) ->
may_open(nd, acc_mode, flag) ->在这个函数看到,对于O_TRUNC,会比其他情况下,多调用一个do_truncate()
do_truncate(dentry, 0) ->第二个参数就是0了
notify_change(dentry, &newattrs) -> 长度为0,存储在newattrs中
inode_setattr(inode, attr) ->设置inode的相关属性了
vmtruncate(inode, attr->ia_size) ->进行vm的截断操作了。
vmtruncate()是这次的重点了,贴出注视和最关键的三句:
/*
* Handle all mappings that got truncated by a "truncate()"
* system call.
*
* NOTE! We have to be ready to update the memory sharing
* between the file and the memory map for a potential last
* incomplete page. Ugly, but necessary.
*/
int vmtruncate(struct inode * inode, loff_t offset)//这里offset为0,从0开始截断,就全截了,相当清空一次inode的所有页缓存,
{
struct address_space *mapping = inode->i_mapping;//获取的就是inode的页缓存结构,后两个函数有很好的注释
unmap_mapping_range(mapping, offset + PAGE_SIZE - 1, 0, 1);
truncate_inode_pages(mapping, offset);
}
unmap_mapping_range()的注视:
/**
* unmap_mapping_range - unmap the portion of all mmaps
* in the specified address_space corresponding to the specified
* page range in the underlying file.
* @address_space: the address space containing mmaps to be unmapped.
* @holebegin: byte in first page to unmap, relative to the start of
* the underlying file. This will be rounded down to a PAGE_SIZE
* boundary. Note that this is different from vmtruncate(), which
* must keep the partial page. In contrast, we must get rid of
* partial pages.
* @holelen: size of prospective hole in bytes. This will be rounded
* up to a PAGE_SIZE boundary. A holelen of zero truncates to the
* end of the file.
* @even_cows: 1 when truncating a file, unmap even private COWed pages;
* but 0 when invalidating pagecache, don't throw away private data.
*/
void unmap_mapping_range(struct address_space *mapping,
loff_t const holebegin, loff_t const holelen, int even_cows)
{
}
truncate_inode_pages()的注视:
/**
* truncate_inode_pages - truncate *all* the pages from an offset
* @mapping: mapping to truncate
* @lstart: offset from which to truncate
*
* Truncate the page cache at a set offset, removing the pages that are beyond
* that offset (and zeroing out partial pages).
*
* Truncate takes two passes - the first pass is nonblocking. It will not
* block on page locks and it will not block on writeback. The second pass
* will wait. This is to prevent as much IO as possible in the affected region.
* The first pass will remove most pages, so the search cost of the second pass
* is low.
*
* When looking at page->index outside the page lock we need to be careful to
* copy it into a local to avoid races (it could change at any time).
*
* We pass down the cache-hot hint to the page freeing code. Even if the
* mapping is large, it is probably the case that the final pages are the most
* recently touched, and freeing happens in ascending file offset order.
*
* Called under (and serialised by) inode->i_sem.
*/
void truncate_inode_pages(struct address_space *mapping, loff_t lstart)
{
} |
|