fs/overlayfs/readdir.c

Source file repositories/reference/linux-study-clean/fs/overlayfs/readdir.c

File Facts

System
Linux kernel
Corpus path
fs/overlayfs/readdir.c
Extension
.c
Size
30619 bytes
Lines
1327
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: operation-table or driver-model contract
Status
pattern 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

const struct file_operations ovl_dir_operations = {
	.read		= generic_read_dir,
	.open		= ovl_dir_open,
	.iterate_shared	= shared_ovl_iterate,
	.llseek		= ovl_dir_llseek,
	.fsync		= ovl_dir_fsync,
	.release	= ovl_dir_release,
	.setlease	= generic_setlease,
};

int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
{
	int err;
	struct ovl_cache_entry *p, *n;
	struct rb_root root = RB_ROOT;

	with_ovl_creds(dentry->d_sb)
		err = ovl_dir_read_merged(dentry, list, &root);
	if (err)
		return err;

	err = 0;

	list_for_each_entry_safe(p, n, list, l_node) {
		/*
		 * Select whiteouts in upperdir, they should
		 * be cleared when deleting this directory.
		 */
		if (p->is_whiteout) {
			if (p->is_upper)
				continue;
			goto del_entry;
		}

		if (name_is_dot_dotdot(p->name, p->len))
			goto del_entry;
		err = -ENOTEMPTY;
		break;

del_entry:
		list_del(&p->l_node);
		ovl_cache_entry_free(p);
	}

	return err;
}

void ovl_cleanup_whiteouts(struct ovl_fs *ofs, struct dentry *upper,
			   struct list_head *list)
{
	struct ovl_cache_entry *p;

	list_for_each_entry(p, list, l_node) {
		struct dentry *dentry;

		if (WARN_ON(!p->is_whiteout || !p->is_upper))
			continue;

		dentry = ovl_lookup_upper_unlocked(ofs, p->name, upper, p->len);
		if (IS_ERR(dentry)) {
			pr_err("lookup '%s/%.*s' failed (%i)\n",
			       upper->d_name.name, p->len, p->name,
			       (int) PTR_ERR(dentry));
			continue;
		}
		if (dentry->d_inode)
			ovl_cleanup(ofs, upper, dentry);
		dput(dentry);
	}
}

static bool ovl_check_d_type(struct dir_context *ctx, const char *name,
			  int namelen, loff_t offset, u64 ino,
			  unsigned int d_type)
{
	struct ovl_readdir_data *rdd =
		container_of(ctx, struct ovl_readdir_data, ctx);

	/* Even if d_type is not supported, DT_DIR is returned for . and .. */
	if (name_is_dot_dotdot(name, namelen))
		return true;

	if (d_type != DT_UNKNOWN)
		rdd->d_type_supported = true;

	return true;
}

/*
 * Returns 1 if d_type is supported, 0 not supported/unknown. Negative values

Annotation

Implementation Notes