Ejemplo n.º 1
0
/*
 * 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.
 */
void vmtruncate(struct inode * inode, loff_t offset)
{
	unsigned long partial, pgoff;
	struct address_space *mapping = inode->i_mapping;
	unsigned long limit;

	if (inode->i_size < offset)
		goto do_expand;
	inode->i_size = offset;
	truncate_inode_pages(mapping, offset);
	spin_lock(&mapping->i_shared_lock);
	if (!mapping->i_mmap && !mapping->i_mmap_shared)
		goto out_unlock;

	pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
	partial = (unsigned long)offset & (PAGE_CACHE_SIZE - 1);

	if (mapping->i_mmap != NULL)
		vmtruncate_list(mapping->i_mmap, pgoff, partial);
	if (mapping->i_mmap_shared != NULL)
		vmtruncate_list(mapping->i_mmap_shared, pgoff, partial);

out_unlock:
	spin_unlock(&mapping->i_shared_lock);
	/* this should go into ->truncate */
	inode->i_size = offset;
	if (inode->i_op && inode->i_op->truncate)
		inode->i_op->truncate(inode);
	return;

do_expand:
	limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
	if (limit != RLIM_INFINITY) {
		if (inode->i_size >= limit) {
			send_sig(SIGXFSZ, current, 0);
			goto out;
		}
		if (offset > limit) {
			send_sig(SIGXFSZ, current, 0);
			offset = limit;
		}
	}
	inode->i_size = offset;
	if (inode->i_op && inode->i_op->truncate)
		inode->i_op->truncate(inode);
out:
	return;
}
Ejemplo n.º 2
0
/*
 * 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)
{
	unsigned long pgoff;
	struct address_space *mapping = inode->i_mapping;
	unsigned long limit;

	if (inode->i_size < offset)
		goto do_expand;
	inode->i_size = offset;
	spin_lock(&mapping->i_shared_lock);
	if (!mapping->i_mmap && !mapping->i_mmap_shared)
		goto out_unlock;

	pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
	if (mapping->i_mmap != NULL)
		vmtruncate_list(mapping->i_mmap, pgoff);
	if (mapping->i_mmap_shared != NULL)
		vmtruncate_list(mapping->i_mmap_shared, pgoff);

out_unlock:
	spin_unlock(&mapping->i_shared_lock);
	truncate_inode_pages(mapping, offset);
	goto out_truncate;

do_expand:
	limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
	if (limit != RLIM_INFINITY) {
		if (inode->i_size >= limit) {
			send_sig(SIGXFSZ, current, 0);
			goto out;
		}
		if (offset > limit) {
			send_sig(SIGXFSZ, current, 0);
			offset = limit;
		}
	}
	inode->i_size = offset;

out_truncate:
	if (inode->i_op && inode->i_op->truncate) {
		lock_kernel();
		inode->i_op->truncate(inode);
		unlock_kernel();
	}
out:
	return 0;
}