fs/dlm/dir.c

Source file repositories/reference/linux-study-clean/fs/dlm/dir.c

File Facts

System
Linux kernel
Corpus path
fs/dlm/dir.c
Extension
.c
Size
9665 bytes
Lines
401
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

struct dlm_dir_dump {
	/* init values to match if whole
	 * dump fits to one seq. Sanity check only.
	 */
	uint64_t seq_init;
	uint64_t nodeid_init;
	/* compare local pointer with last lookup,
	 * just a sanity check.
	 */
	struct list_head *last;

	unsigned int sent_res; /* for log info */
	unsigned int sent_msg; /* for log info */

	struct list_head list;
};

static void drop_dir_ctx(struct dlm_ls *ls, int nodeid)
{
	struct dlm_dir_dump *dd, *safe;

	write_lock_bh(&ls->ls_dir_dump_lock);
	list_for_each_entry_safe(dd, safe, &ls->ls_dir_dump_list, list) {
		if (dd->nodeid_init == nodeid) {
			log_error(ls, "drop dump seq %llu",
				 (unsigned long long)dd->seq_init);
			list_del(&dd->list);
			kfree(dd);
		}
	}
	write_unlock_bh(&ls->ls_dir_dump_lock);
}

static struct dlm_dir_dump *lookup_dir_dump(struct dlm_ls *ls, int nodeid)
{
	struct dlm_dir_dump *iter, *dd = NULL;

	read_lock_bh(&ls->ls_dir_dump_lock);
	list_for_each_entry(iter, &ls->ls_dir_dump_list, list) {
		if (iter->nodeid_init == nodeid) {
			dd = iter;
			break;
		}
	}
	read_unlock_bh(&ls->ls_dir_dump_lock);

	return dd;
}

static struct dlm_dir_dump *init_dir_dump(struct dlm_ls *ls, int nodeid)
{
	struct dlm_dir_dump *dd;

	dd = lookup_dir_dump(ls, nodeid);
	if (dd) {
		log_error(ls, "found ongoing dir dump for node %d, will drop it",
			  nodeid);
		drop_dir_ctx(ls, nodeid);
	}

	dd = kzalloc_obj(*dd, GFP_ATOMIC);
	if (!dd)
		return NULL;

	dd->seq_init = ls->ls_recover_seq;
	dd->nodeid_init = nodeid;

	write_lock_bh(&ls->ls_dir_dump_lock);
	list_add(&dd->list, &ls->ls_dir_dump_list);
	write_unlock_bh(&ls->ls_dir_dump_lock);

	return dd;
}

/* Find the rsb where we left off (or start again), then send rsb names
   for rsb's we're master of and whose directory node matches the requesting
   node.  inbuf is the rsb name last sent, inlen is the name's length */

void dlm_copy_master_names(struct dlm_ls *ls, const char *inbuf, int inlen,
 			   char *outbuf, int outlen, int nodeid)
{
	struct list_head *list;
	struct dlm_rsb *r;
	int offset = 0, dir_nodeid;
	struct dlm_dir_dump *dd;
	__be16 be_namelen;

	read_lock_bh(&ls->ls_masters_lock);

	if (inlen > 1) {

Annotation

Implementation Notes