fs/jbd2/commit.c

Source file repositories/reference/linux-study-clean/fs/jbd2/commit.c

File Facts

System
Linux kernel
Corpus path
fs/jbd2/commit.c
Extension
.c
Size
36243 bytes
Lines
1187
Domain
Core OS
Bucket
VFS And Filesystem Core
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 (journal->j_submit_inode_data_buffers) {
			err = journal->j_submit_inode_data_buffers(jinode);
			if (!ret)
				ret = err;
		}
		spin_lock(&journal->j_list_lock);
		J_ASSERT(jinode->i_transaction == commit_transaction);
		WRITE_ONCE(jinode->i_flags,
			   jinode->i_flags & ~JI_COMMIT_RUNNING);
		smp_mb();
		wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING);
	}
	spin_unlock(&journal->j_list_lock);
	return ret;
}

int jbd2_journal_finish_inode_data_buffers(struct jbd2_inode *jinode)
{
	struct address_space *mapping = jinode->i_vfs_inode->i_mapping;
	loff_t start_byte, end_byte;

	if (!jbd2_jinode_get_dirty_range(jinode, &start_byte, &end_byte))
		return 0;

	return filemap_fdatawait_range_keep_errors(mapping,
						   start_byte, end_byte);
}

/*
 * Wait for data submitted for writeout, refile inodes to proper
 * transaction if needed.
 *
 */
static int journal_finish_inode_data_buffers(journal_t *journal,
		transaction_t *commit_transaction)
{
	struct jbd2_inode *jinode, *next_i;
	int err, ret = 0;

	/* For locking, see the comment in journal_submit_data_buffers() */
	spin_lock(&journal->j_list_lock);
	list_for_each_entry(jinode, &commit_transaction->t_inode_list, i_list) {
		if (!(jinode->i_flags & JI_WAIT_DATA))
			continue;
		WRITE_ONCE(jinode->i_flags, jinode->i_flags | JI_COMMIT_RUNNING);
		spin_unlock(&journal->j_list_lock);
		/* wait for the inode data buffers writeout. */
		if (journal->j_finish_inode_data_buffers) {
			err = journal->j_finish_inode_data_buffers(jinode);
			if (!ret)
				ret = err;
		}
		cond_resched();
		spin_lock(&journal->j_list_lock);
		WRITE_ONCE(jinode->i_flags, jinode->i_flags & ~JI_COMMIT_RUNNING);
		smp_mb();
		wake_up_bit(&jinode->i_flags, __JI_COMMIT_RUNNING);
	}

	/* Now refile inode to proper lists */
	list_for_each_entry_safe(jinode, next_i,
				 &commit_transaction->t_inode_list, i_list) {
		list_del(&jinode->i_list);
		if (jinode->i_next_transaction) {
			jinode->i_transaction = jinode->i_next_transaction;
			jinode->i_next_transaction = NULL;
			list_add(&jinode->i_list,
				&jinode->i_transaction->t_inode_list);
		} else {
			jinode->i_transaction = NULL;
			WRITE_ONCE(jinode->i_dirty_start_page, 0);
			WRITE_ONCE(jinode->i_dirty_end_page, 0);
		}
	}
	spin_unlock(&journal->j_list_lock);

	return ret;
}

static __u32 jbd2_checksum_data(__u32 crc32_sum, struct buffer_head *bh)
{
	char *addr;
	__u32 checksum;

	addr = kmap_local_folio(bh->b_folio, bh_offset(bh));
	checksum = crc32_be(crc32_sum, addr, bh->b_size);
	kunmap_local(addr);

	return checksum;
}

Annotation

Implementation Notes