fs/fuse/readdir.c

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

File Facts

System
Linux kernel
Corpus path
fs/fuse/readdir.c
Extension
.c
Size
15813 bytes
Lines
657
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

fuse_stale_inode(inode, o->generation, &o->attr)) {
			if (inode)
				fuse_make_bad(inode);
			d_invalidate(dentry);
			dput(dentry);
			goto retry;
		}
		if (fuse_is_bad(inode)) {
			dput(dentry);
			return -EIO;
		}

		fi = get_fuse_inode(inode);
		spin_lock(&fi->lock);
		fi->nlookup++;
		spin_unlock(&fi->lock);

		forget_all_cached_acls(inode);
		fuse_change_attributes(inode, &o->attr, NULL,
				       ATTR_TIMEOUT(o),
				       attr_version);
		/*
		 * The other branch comes via fuse_iget()
		 * which bumps nlookup inside
		 */
	} else {
		inode = fuse_iget(dir->i_sb, o->nodeid, o->generation,
				  &o->attr, ATTR_TIMEOUT(o),
				  attr_version, evict_ctr);
		if (!inode)
			inode = ERR_PTR(-ENOMEM);

		alias = d_splice_alias(inode, dentry);
		d_lookup_done(dentry);
		if (alias) {
			dput(dentry);
			dentry = alias;
		}
		if (IS_ERR(dentry)) {
			if (!IS_ERR(inode)) {
				struct fuse_inode *fi = get_fuse_inode(inode);

				spin_lock(&fi->lock);
				fi->nlookup--;
				spin_unlock(&fi->lock);
			}
			return PTR_ERR(dentry);
		}
	}
	if (fc->readdirplus_auto)
		set_bit(FUSE_I_INIT_RDPLUS, &get_fuse_inode(inode)->state);
	dentry->d_time = epoch;
	fuse_change_entry_timeout(dentry, o);

	dput(dentry);
	return 0;
}

static void fuse_force_forget(struct file *file, u64 nodeid)
{
	struct inode *inode = file_inode(file);
	struct fuse_mount *fm = get_fuse_mount(inode);
	struct fuse_forget_in inarg;
	FUSE_ARGS(args);

	memset(&inarg, 0, sizeof(inarg));
	inarg.nlookup = 1;
	args.opcode = FUSE_FORGET;
	args.nodeid = nodeid;
	args.in_numargs = 1;
	args.in_args[0].size = sizeof(inarg);
	args.in_args[0].value = &inarg;
	args.force = true;
	args.noreply = true;

	fuse_simple_request(fm, &args);
	/* ignore errors */
}

static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
			     struct dir_context *ctx, u64 attr_version,
			     u64 evict_ctr)
{
	struct fuse_direntplus *direntplus;
	struct fuse_dirent *dirent;
	size_t reclen;
	int over = 0;
	int ret;

	while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) {

Annotation

Implementation Notes