fs/cachefiles/namei.c

Source file repositories/reference/linux-study-clean/fs/cachefiles/namei.c

File Facts

System
Linux kernel
Corpus path
fs/cachefiles/namei.c
Extension
.c
Size
21179 bytes
Lines
835
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 (ret == 0) {
			subdir = vfs_mkdir(&nop_mnt_idmap, d_inode(dir), subdir, 0700, NULL);
			if (IS_ERR(subdir))
				ret = PTR_ERR(subdir);
		} else {
			end_creating(subdir);
			subdir = ERR_PTR(ret);
		}
		if (IS_ERR(subdir)) {
			trace_cachefiles_vfs_error(NULL, d_inode(dir), ret,
						   cachefiles_trace_mkdir_error);
			goto mkdir_error;
		}
		trace_cachefiles_mkdir(dir, subdir);

		if (unlikely(d_unhashed(subdir) || d_is_negative(subdir))) {
			end_creating(subdir);
			goto retry;
		}
		ASSERT(d_backing_inode(subdir));

		_debug("mkdir -> %pd{ino=%llu}",
		       subdir, d_backing_inode(subdir)->i_ino);
		if (_is_new)
			*_is_new = true;
	}

	/* Tell rmdir() it's not allowed to delete the subdir */
	inode_lock(d_inode(subdir));
	end_creating_keep(subdir);

	if (!__cachefiles_mark_inode_in_use(NULL, d_inode(subdir))) {
		pr_notice("cachefiles: Inode already in use: %pd (B=%llx)\n",
			  subdir, d_inode(subdir)->i_ino);
		goto mark_error;
	}

	inode_unlock(d_inode(subdir));

	/* we need to make sure the subdir is a directory */
	ASSERT(d_backing_inode(subdir));

	if (!d_can_lookup(subdir)) {
		pr_err("%s is not a directory\n", dirname);
		ret = -EIO;
		goto check_error;
	}

	ret = -EPERM;
	if (!(d_backing_inode(subdir)->i_opflags & IOP_XATTR) ||
	    !d_backing_inode(subdir)->i_op->lookup ||
	    !d_backing_inode(subdir)->i_op->mkdir ||
	    !d_backing_inode(subdir)->i_op->rename ||
	    !d_backing_inode(subdir)->i_op->rmdir ||
	    !d_backing_inode(subdir)->i_op->unlink)
		goto check_error;

	_leave(" = [%llu]", d_backing_inode(subdir)->i_ino);
	return subdir;

check_error:
	cachefiles_put_directory(subdir);
	_leave(" = %d [check]", ret);
	return ERR_PTR(ret);

mark_error:
	inode_unlock(d_inode(subdir));
	dput(subdir);
	return ERR_PTR(-EBUSY);

mkdir_error:
	end_creating(subdir);
	pr_err("mkdir %s failed with error %d\n", dirname, ret);
	return ERR_PTR(ret);

lookup_error:
	ret = PTR_ERR(subdir);
	pr_err("Lookup %s failed with error %d\n", dirname, ret);
	return ERR_PTR(ret);

nomem_d_alloc:
	inode_unlock(d_inode(dir));
	_leave(" = -ENOMEM");
	return ERR_PTR(-ENOMEM);
}

/*
 * Put a subdirectory.
 */
void cachefiles_put_directory(struct dentry *dir)

Annotation

Implementation Notes