mm/truncate.c

Source file repositories/reference/linux-study-clean/mm/truncate.c

File Facts

System
Linux kernel
Corpus path
mm/truncate.c
Extension
.c
Size
28103 bytes
Lines
928
Domain
Core OS
Bucket
Memory Management
Inferred role
Core OS: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (xa_is_value(fbatch->folios[i])) {
				/*
				 * File systems should already have called
				 * dax_break_layout_entry() to remove all DAX
				 * entries while holding a lock to prevent
				 * establishing new entries. Therefore we
				 * shouldn't find any here.
				 */
				WARN_ON_ONCE(1);

				/*
				 * Delete the mapping so truncate_pagecache()
				 * doesn't loop forever.
				 */
				dax_delete_mapping_entry(mapping, indices[i]);
			}
		}
		goto out;
	}

	xas_set(&xas, indices[j]);
	xas_set_update(&xas, workingset_update_node);

	spin_lock(&mapping->host->i_lock);
	xas_lock_irq(&xas);

	xas_for_each(&xas, folio, indices[nr-1]) {
		if (xa_is_value(folio))
			xas_store(&xas, NULL);
	}

	xas_unlock_irq(&xas);
	if (mapping_shrinkable(mapping))
		inode_lru_list_add(mapping->host);
	spin_unlock(&mapping->host->i_lock);
out:
	folio_batch_remove_exceptionals(fbatch);
}

/**
 * folio_invalidate - Invalidate part or all of a folio.
 * @folio: The folio which is affected.
 * @offset: start of the range to invalidate
 * @length: length of the range to invalidate
 *
 * folio_invalidate() is called when all or part of the folio has become
 * invalidated by a truncate operation.
 *
 * folio_invalidate() does not have to release all buffers, but it must
 * ensure that no dirty buffer is left outside @offset and that no I/O
 * is underway against any of the blocks which are outside the truncation
 * point.  Because the caller is about to free (and possibly reuse) those
 * blocks on-disk.
 */
void folio_invalidate(struct folio *folio, size_t offset, size_t length)
{
	const struct address_space_operations *aops = folio->mapping->a_ops;

	if (aops->invalidate_folio)
		aops->invalidate_folio(folio, offset, length);
}
EXPORT_SYMBOL_GPL(folio_invalidate);

/*
 * If truncate cannot remove the fs-private metadata from the page, the page
 * becomes orphaned.  It will be left on the LRU and may even be mapped into
 * user pagetables if we're racing with filemap_fault().
 *
 * We need to bail out if page->mapping is no longer equal to the original
 * mapping.  This happens a) when the VM reclaimed the page while we waited on
 * its lock, b) when a concurrent invalidate_mapping_pages got there first and
 * c) when tmpfs swizzles a page between a tmpfs inode and swapper_space.
 */
static void truncate_cleanup_folio(struct folio *folio)
{
	if (folio_mapped(folio))
		unmap_mapping_folio(folio);

	if (folio_needs_release(folio))
		folio_invalidate(folio, 0, folio_size(folio));

	/*
	 * Some filesystems seem to re-dirty the page even after
	 * the VM has canceled the dirty bit (eg ext3 journaling).
	 * Hence dirty accounting check is placed after invalidation.
	 */
	folio_cancel_dirty(folio);
}

int truncate_inode_folio(struct address_space *mapping, struct folio *folio)

Annotation

Implementation Notes