fs/kernfs/inode.c

Source file repositories/reference/linux-study-clean/fs/kernfs/inode.c

File Facts

System
Linux kernel
Corpus path
fs/kernfs/inode.c
Extension
.c
Size
10527 bytes
Lines
407
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

// SPDX-License-Identifier: GPL-2.0-only
/*
 * fs/kernfs/inode.c - kernfs inode implementation
 *
 * Copyright (c) 2001-3 Patrick Mochel
 * Copyright (c) 2007 SUSE Linux Products GmbH
 * Copyright (c) 2007, 2013 Tejun Heo <tj@kernel.org>
 */

#include <linux/pagemap.h>
#include <linux/backing-dev.h>
#include <linux/capability.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/xattr.h>
#include <linux/security.h>

#include "kernfs-internal.h"

static const struct inode_operations kernfs_iops = {
	.permission	= kernfs_iop_permission,
	.setattr	= kernfs_iop_setattr,
	.getattr	= kernfs_iop_getattr,
	.listxattr	= kernfs_iop_listxattr,
};

static struct kernfs_iattrs *__kernfs_iattrs(struct kernfs_node *kn, bool alloc)
{
	struct kernfs_iattrs *ret __free(kfree) = NULL;
	struct kernfs_iattrs *attr;

	attr = READ_ONCE(kn->iattr);
	if (attr || !alloc)
		return attr;

	ret = kmem_cache_zalloc(kernfs_iattrs_cache, GFP_KERNEL);
	if (!ret)
		return NULL;

	INIT_LIST_HEAD_RCU(&ret->xattrs);
	/* assign default attributes */
	ret->ia_uid = GLOBAL_ROOT_UID;
	ret->ia_gid = GLOBAL_ROOT_GID;

	ktime_get_real_ts64(&ret->ia_atime);
	ret->ia_mtime = ret->ia_atime;
	ret->ia_ctime = ret->ia_atime;

	simple_xattr_limits_init(&ret->xattr_limits);

	/* If someone raced us, recognize it. */
	if (!try_cmpxchg(&kn->iattr, &attr, ret))
		return READ_ONCE(kn->iattr);

	return no_free_ptr(ret);
}

static struct kernfs_iattrs *kernfs_iattrs(struct kernfs_node *kn)
{
	return __kernfs_iattrs(kn, true);
}

static struct kernfs_iattrs *kernfs_iattrs_noalloc(struct kernfs_node *kn)
{
	return __kernfs_iattrs(kn, false);
}

int __kernfs_setattr(struct kernfs_node *kn, const struct iattr *iattr)
{
	struct kernfs_iattrs *attrs;
	unsigned int ia_valid = iattr->ia_valid;

	attrs = kernfs_iattrs(kn);
	if (!attrs)
		return -ENOMEM;

	if (ia_valid & ATTR_UID)
		attrs->ia_uid = iattr->ia_uid;
	if (ia_valid & ATTR_GID)
		attrs->ia_gid = iattr->ia_gid;
	if (ia_valid & ATTR_ATIME)
		attrs->ia_atime = iattr->ia_atime;
	if (ia_valid & ATTR_MTIME)
		attrs->ia_mtime = iattr->ia_mtime;
	if (ia_valid & ATTR_CTIME)
		attrs->ia_ctime = iattr->ia_ctime;
	if (ia_valid & ATTR_MODE)
		kn->mode = iattr->ia_mode;
	return 0;
}

Annotation

Implementation Notes