fs/nilfs2/page.c

Source file repositories/reference/linux-study-clean/fs/nilfs2/page.c

File Facts

System
Linux kernel
Corpus path
fs/nilfs2/page.c
Extension
.c
Size
14203 bytes
Lines
568
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source 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 (IS_ERR(dfolio)) {
			/* No empty page is added to the page cache */
			folio_unlock(folio);
			err = PTR_ERR(dfolio);
			break;
		}
		if (unlikely(!folio_buffers(folio)))
			NILFS_FOLIO_BUG(folio,
				       "found empty page in dat page cache");

		nilfs_copy_folio(dfolio, folio, true);
		filemap_dirty_folio(folio_mapping(dfolio), dfolio);

		folio_unlock(dfolio);
		folio_put(dfolio);
		folio_unlock(folio);
	}
	folio_batch_release(&fbatch);
	cond_resched();

	if (likely(!err))
		goto repeat;
	return err;
}

/**
 * nilfs_copy_back_pages -- copy back pages to original cache from shadow cache
 * @dmap: destination page cache
 * @smap: source page cache
 *
 * No pages must be added to the cache during this process.
 * This must be ensured by the caller.
 */
void nilfs_copy_back_pages(struct address_space *dmap,
			   struct address_space *smap)
{
	struct folio_batch fbatch;
	unsigned int i, n;
	pgoff_t start = 0;

	folio_batch_init(&fbatch);
repeat:
	n = filemap_get_folios(smap, &start, ~0UL, &fbatch);
	if (!n)
		return;

	for (i = 0; i < folio_batch_count(&fbatch); i++) {
		struct folio *folio = fbatch.folios[i], *dfolio;
		pgoff_t index = folio->index;

		folio_lock(folio);
		dfolio = filemap_lock_folio(dmap, index);
		if (!IS_ERR(dfolio)) {
			/* overwrite existing folio in the destination cache */
			WARN_ON(folio_test_dirty(dfolio));
			nilfs_copy_folio(dfolio, folio, false);
			folio_unlock(dfolio);
			folio_put(dfolio);
			/* Do we not need to remove folio from smap here? */
		} else {
			struct folio *f;

			/* move the folio to the destination cache */
			xa_lock_irq(&smap->i_pages);
			f = __xa_erase(&smap->i_pages, index);
			WARN_ON(folio != f);
			smap->nrpages--;
			xa_unlock_irq(&smap->i_pages);

			xa_lock_irq(&dmap->i_pages);
			f = __xa_store(&dmap->i_pages, index, folio, GFP_NOFS);
			if (unlikely(f)) {
				/* Probably -ENOMEM */
				folio->mapping = NULL;
				folio_put(folio);
			} else {
				folio->mapping = dmap;
				dmap->nrpages++;
				if (folio_test_dirty(folio))
					__xa_set_mark(&dmap->i_pages, index,
							PAGECACHE_TAG_DIRTY);
			}
			xa_unlock_irq(&dmap->i_pages);
		}
		folio_unlock(folio);
	}
	folio_batch_release(&fbatch);
	cond_resched();

	goto repeat;

Annotation

Implementation Notes