162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *	fs/libfs.c
462306a36Sopenharmony_ci *	Library for filesystems writers.
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <linux/blkdev.h>
862306a36Sopenharmony_ci#include <linux/export.h>
962306a36Sopenharmony_ci#include <linux/pagemap.h>
1062306a36Sopenharmony_ci#include <linux/slab.h>
1162306a36Sopenharmony_ci#include <linux/cred.h>
1262306a36Sopenharmony_ci#include <linux/mount.h>
1362306a36Sopenharmony_ci#include <linux/vfs.h>
1462306a36Sopenharmony_ci#include <linux/quotaops.h>
1562306a36Sopenharmony_ci#include <linux/mutex.h>
1662306a36Sopenharmony_ci#include <linux/namei.h>
1762306a36Sopenharmony_ci#include <linux/exportfs.h>
1862306a36Sopenharmony_ci#include <linux/iversion.h>
1962306a36Sopenharmony_ci#include <linux/writeback.h>
2062306a36Sopenharmony_ci#include <linux/buffer_head.h> /* sync_mapping_buffers */
2162306a36Sopenharmony_ci#include <linux/fs_context.h>
2262306a36Sopenharmony_ci#include <linux/pseudo_fs.h>
2362306a36Sopenharmony_ci#include <linux/fsnotify.h>
2462306a36Sopenharmony_ci#include <linux/unicode.h>
2562306a36Sopenharmony_ci#include <linux/fscrypt.h>
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci#include <linux/uaccess.h>
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include "internal.h"
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ciint simple_getattr(struct mnt_idmap *idmap, const struct path *path,
3262306a36Sopenharmony_ci		   struct kstat *stat, u32 request_mask,
3362306a36Sopenharmony_ci		   unsigned int query_flags)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	struct inode *inode = d_inode(path->dentry);
3662306a36Sopenharmony_ci	generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
3762306a36Sopenharmony_ci	stat->blocks = inode->i_mapping->nrpages << (PAGE_SHIFT - 9);
3862306a36Sopenharmony_ci	return 0;
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ciEXPORT_SYMBOL(simple_getattr);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ciint simple_statfs(struct dentry *dentry, struct kstatfs *buf)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	buf->f_type = dentry->d_sb->s_magic;
4562306a36Sopenharmony_ci	buf->f_bsize = PAGE_SIZE;
4662306a36Sopenharmony_ci	buf->f_namelen = NAME_MAX;
4762306a36Sopenharmony_ci	return 0;
4862306a36Sopenharmony_ci}
4962306a36Sopenharmony_ciEXPORT_SYMBOL(simple_statfs);
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/*
5262306a36Sopenharmony_ci * Retaining negative dentries for an in-memory filesystem just wastes
5362306a36Sopenharmony_ci * memory and lookup time: arrange for them to be deleted immediately.
5462306a36Sopenharmony_ci */
5562306a36Sopenharmony_ciint always_delete_dentry(const struct dentry *dentry)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	return 1;
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ciEXPORT_SYMBOL(always_delete_dentry);
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ciconst struct dentry_operations simple_dentry_operations = {
6262306a36Sopenharmony_ci	.d_delete = always_delete_dentry,
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ciEXPORT_SYMBOL(simple_dentry_operations);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/*
6762306a36Sopenharmony_ci * Lookup the data. This is trivial - if the dentry didn't already
6862306a36Sopenharmony_ci * exist, we know it is negative.  Set d_op to delete negative dentries.
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_cistruct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	if (dentry->d_name.len > NAME_MAX)
7362306a36Sopenharmony_ci		return ERR_PTR(-ENAMETOOLONG);
7462306a36Sopenharmony_ci	if (!dentry->d_sb->s_d_op)
7562306a36Sopenharmony_ci		d_set_d_op(dentry, &simple_dentry_operations);
7662306a36Sopenharmony_ci	d_add(dentry, NULL);
7762306a36Sopenharmony_ci	return NULL;
7862306a36Sopenharmony_ci}
7962306a36Sopenharmony_ciEXPORT_SYMBOL(simple_lookup);
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciint dcache_dir_open(struct inode *inode, struct file *file)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	file->private_data = d_alloc_cursor(file->f_path.dentry);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	return file->private_data ? 0 : -ENOMEM;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ciEXPORT_SYMBOL(dcache_dir_open);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ciint dcache_dir_close(struct inode *inode, struct file *file)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	dput(file->private_data);
9262306a36Sopenharmony_ci	return 0;
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ciEXPORT_SYMBOL(dcache_dir_close);
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci/* parent is locked at least shared */
9762306a36Sopenharmony_ci/*
9862306a36Sopenharmony_ci * Returns an element of siblings' list.
9962306a36Sopenharmony_ci * We are looking for <count>th positive after <p>; if
10062306a36Sopenharmony_ci * found, dentry is grabbed and returned to caller.
10162306a36Sopenharmony_ci * If no such element exists, NULL is returned.
10262306a36Sopenharmony_ci */
10362306a36Sopenharmony_cistatic struct dentry *scan_positives(struct dentry *cursor,
10462306a36Sopenharmony_ci					struct list_head *p,
10562306a36Sopenharmony_ci					loff_t count,
10662306a36Sopenharmony_ci					struct dentry *last)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	struct dentry *dentry = cursor->d_parent, *found = NULL;
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	spin_lock(&dentry->d_lock);
11162306a36Sopenharmony_ci	while ((p = p->next) != &dentry->d_subdirs) {
11262306a36Sopenharmony_ci		struct dentry *d = list_entry(p, struct dentry, d_child);
11362306a36Sopenharmony_ci		// we must at least skip cursors, to avoid livelocks
11462306a36Sopenharmony_ci		if (d->d_flags & DCACHE_DENTRY_CURSOR)
11562306a36Sopenharmony_ci			continue;
11662306a36Sopenharmony_ci		if (simple_positive(d) && !--count) {
11762306a36Sopenharmony_ci			spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
11862306a36Sopenharmony_ci			if (simple_positive(d))
11962306a36Sopenharmony_ci				found = dget_dlock(d);
12062306a36Sopenharmony_ci			spin_unlock(&d->d_lock);
12162306a36Sopenharmony_ci			if (likely(found))
12262306a36Sopenharmony_ci				break;
12362306a36Sopenharmony_ci			count = 1;
12462306a36Sopenharmony_ci		}
12562306a36Sopenharmony_ci		if (need_resched()) {
12662306a36Sopenharmony_ci			list_move(&cursor->d_child, p);
12762306a36Sopenharmony_ci			p = &cursor->d_child;
12862306a36Sopenharmony_ci			spin_unlock(&dentry->d_lock);
12962306a36Sopenharmony_ci			cond_resched();
13062306a36Sopenharmony_ci			spin_lock(&dentry->d_lock);
13162306a36Sopenharmony_ci		}
13262306a36Sopenharmony_ci	}
13362306a36Sopenharmony_ci	spin_unlock(&dentry->d_lock);
13462306a36Sopenharmony_ci	dput(last);
13562306a36Sopenharmony_ci	return found;
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ciloff_t dcache_dir_lseek(struct file *file, loff_t offset, int whence)
13962306a36Sopenharmony_ci{
14062306a36Sopenharmony_ci	struct dentry *dentry = file->f_path.dentry;
14162306a36Sopenharmony_ci	switch (whence) {
14262306a36Sopenharmony_ci		case 1:
14362306a36Sopenharmony_ci			offset += file->f_pos;
14462306a36Sopenharmony_ci			fallthrough;
14562306a36Sopenharmony_ci		case 0:
14662306a36Sopenharmony_ci			if (offset >= 0)
14762306a36Sopenharmony_ci				break;
14862306a36Sopenharmony_ci			fallthrough;
14962306a36Sopenharmony_ci		default:
15062306a36Sopenharmony_ci			return -EINVAL;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci	if (offset != file->f_pos) {
15362306a36Sopenharmony_ci		struct dentry *cursor = file->private_data;
15462306a36Sopenharmony_ci		struct dentry *to = NULL;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci		inode_lock_shared(dentry->d_inode);
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci		if (offset > 2)
15962306a36Sopenharmony_ci			to = scan_positives(cursor, &dentry->d_subdirs,
16062306a36Sopenharmony_ci					    offset - 2, NULL);
16162306a36Sopenharmony_ci		spin_lock(&dentry->d_lock);
16262306a36Sopenharmony_ci		if (to)
16362306a36Sopenharmony_ci			list_move(&cursor->d_child, &to->d_child);
16462306a36Sopenharmony_ci		else
16562306a36Sopenharmony_ci			list_del_init(&cursor->d_child);
16662306a36Sopenharmony_ci		spin_unlock(&dentry->d_lock);
16762306a36Sopenharmony_ci		dput(to);
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci		file->f_pos = offset;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci		inode_unlock_shared(dentry->d_inode);
17262306a36Sopenharmony_ci	}
17362306a36Sopenharmony_ci	return offset;
17462306a36Sopenharmony_ci}
17562306a36Sopenharmony_ciEXPORT_SYMBOL(dcache_dir_lseek);
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci/*
17862306a36Sopenharmony_ci * Directory is locked and all positive dentries in it are safe, since
17962306a36Sopenharmony_ci * for ramfs-type trees they can't go away without unlink() or rmdir(),
18062306a36Sopenharmony_ci * both impossible due to the lock on directory.
18162306a36Sopenharmony_ci */
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ciint dcache_readdir(struct file *file, struct dir_context *ctx)
18462306a36Sopenharmony_ci{
18562306a36Sopenharmony_ci	struct dentry *dentry = file->f_path.dentry;
18662306a36Sopenharmony_ci	struct dentry *cursor = file->private_data;
18762306a36Sopenharmony_ci	struct list_head *anchor = &dentry->d_subdirs;
18862306a36Sopenharmony_ci	struct dentry *next = NULL;
18962306a36Sopenharmony_ci	struct list_head *p;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	if (!dir_emit_dots(file, ctx))
19262306a36Sopenharmony_ci		return 0;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	if (ctx->pos == 2)
19562306a36Sopenharmony_ci		p = anchor;
19662306a36Sopenharmony_ci	else if (!list_empty(&cursor->d_child))
19762306a36Sopenharmony_ci		p = &cursor->d_child;
19862306a36Sopenharmony_ci	else
19962306a36Sopenharmony_ci		return 0;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	while ((next = scan_positives(cursor, p, 1, next)) != NULL) {
20262306a36Sopenharmony_ci		if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
20362306a36Sopenharmony_ci			      d_inode(next)->i_ino,
20462306a36Sopenharmony_ci			      fs_umode_to_dtype(d_inode(next)->i_mode)))
20562306a36Sopenharmony_ci			break;
20662306a36Sopenharmony_ci		ctx->pos++;
20762306a36Sopenharmony_ci		p = &next->d_child;
20862306a36Sopenharmony_ci	}
20962306a36Sopenharmony_ci	spin_lock(&dentry->d_lock);
21062306a36Sopenharmony_ci	if (next)
21162306a36Sopenharmony_ci		list_move_tail(&cursor->d_child, &next->d_child);
21262306a36Sopenharmony_ci	else
21362306a36Sopenharmony_ci		list_del_init(&cursor->d_child);
21462306a36Sopenharmony_ci	spin_unlock(&dentry->d_lock);
21562306a36Sopenharmony_ci	dput(next);
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	return 0;
21862306a36Sopenharmony_ci}
21962306a36Sopenharmony_ciEXPORT_SYMBOL(dcache_readdir);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cissize_t generic_read_dir(struct file *filp, char __user *buf, size_t siz, loff_t *ppos)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	return -EISDIR;
22462306a36Sopenharmony_ci}
22562306a36Sopenharmony_ciEXPORT_SYMBOL(generic_read_dir);
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ciconst struct file_operations simple_dir_operations = {
22862306a36Sopenharmony_ci	.open		= dcache_dir_open,
22962306a36Sopenharmony_ci	.release	= dcache_dir_close,
23062306a36Sopenharmony_ci	.llseek		= dcache_dir_lseek,
23162306a36Sopenharmony_ci	.read		= generic_read_dir,
23262306a36Sopenharmony_ci	.iterate_shared	= dcache_readdir,
23362306a36Sopenharmony_ci	.fsync		= noop_fsync,
23462306a36Sopenharmony_ci};
23562306a36Sopenharmony_ciEXPORT_SYMBOL(simple_dir_operations);
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ciconst struct inode_operations simple_dir_inode_operations = {
23862306a36Sopenharmony_ci	.lookup		= simple_lookup,
23962306a36Sopenharmony_ci};
24062306a36Sopenharmony_ciEXPORT_SYMBOL(simple_dir_inode_operations);
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_cistatic void offset_set(struct dentry *dentry, u32 offset)
24362306a36Sopenharmony_ci{
24462306a36Sopenharmony_ci	dentry->d_fsdata = (void *)((uintptr_t)(offset));
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic u32 dentry2offset(struct dentry *dentry)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	return (u32)((uintptr_t)(dentry->d_fsdata));
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_cistatic struct lock_class_key simple_offset_xa_lock;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci/**
25562306a36Sopenharmony_ci * simple_offset_init - initialize an offset_ctx
25662306a36Sopenharmony_ci * @octx: directory offset map to be initialized
25762306a36Sopenharmony_ci *
25862306a36Sopenharmony_ci */
25962306a36Sopenharmony_civoid simple_offset_init(struct offset_ctx *octx)
26062306a36Sopenharmony_ci{
26162306a36Sopenharmony_ci	xa_init_flags(&octx->xa, XA_FLAGS_ALLOC1);
26262306a36Sopenharmony_ci	lockdep_set_class(&octx->xa.xa_lock, &simple_offset_xa_lock);
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	/* 0 is '.', 1 is '..', so always start with offset 2 */
26562306a36Sopenharmony_ci	octx->next_offset = 2;
26662306a36Sopenharmony_ci}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci/**
26962306a36Sopenharmony_ci * simple_offset_add - Add an entry to a directory's offset map
27062306a36Sopenharmony_ci * @octx: directory offset ctx to be updated
27162306a36Sopenharmony_ci * @dentry: new dentry being added
27262306a36Sopenharmony_ci *
27362306a36Sopenharmony_ci * Returns zero on success. @so_ctx and the dentry offset are updated.
27462306a36Sopenharmony_ci * Otherwise, a negative errno value is returned.
27562306a36Sopenharmony_ci */
27662306a36Sopenharmony_ciint simple_offset_add(struct offset_ctx *octx, struct dentry *dentry)
27762306a36Sopenharmony_ci{
27862306a36Sopenharmony_ci	static const struct xa_limit limit = XA_LIMIT(2, U32_MAX);
27962306a36Sopenharmony_ci	u32 offset;
28062306a36Sopenharmony_ci	int ret;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	if (dentry2offset(dentry) != 0)
28362306a36Sopenharmony_ci		return -EBUSY;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	ret = xa_alloc_cyclic(&octx->xa, &offset, dentry, limit,
28662306a36Sopenharmony_ci			      &octx->next_offset, GFP_KERNEL);
28762306a36Sopenharmony_ci	if (ret < 0)
28862306a36Sopenharmony_ci		return ret;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	offset_set(dentry, offset);
29162306a36Sopenharmony_ci	return 0;
29262306a36Sopenharmony_ci}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci/**
29562306a36Sopenharmony_ci * simple_offset_remove - Remove an entry to a directory's offset map
29662306a36Sopenharmony_ci * @octx: directory offset ctx to be updated
29762306a36Sopenharmony_ci * @dentry: dentry being removed
29862306a36Sopenharmony_ci *
29962306a36Sopenharmony_ci */
30062306a36Sopenharmony_civoid simple_offset_remove(struct offset_ctx *octx, struct dentry *dentry)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	u32 offset;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	offset = dentry2offset(dentry);
30562306a36Sopenharmony_ci	if (offset == 0)
30662306a36Sopenharmony_ci		return;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	xa_erase(&octx->xa, offset);
30962306a36Sopenharmony_ci	offset_set(dentry, 0);
31062306a36Sopenharmony_ci}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci/**
31362306a36Sopenharmony_ci * simple_offset_rename_exchange - exchange rename with directory offsets
31462306a36Sopenharmony_ci * @old_dir: parent of dentry being moved
31562306a36Sopenharmony_ci * @old_dentry: dentry being moved
31662306a36Sopenharmony_ci * @new_dir: destination parent
31762306a36Sopenharmony_ci * @new_dentry: destination dentry
31862306a36Sopenharmony_ci *
31962306a36Sopenharmony_ci * Returns zero on success. Otherwise a negative errno is returned and the
32062306a36Sopenharmony_ci * rename is rolled back.
32162306a36Sopenharmony_ci */
32262306a36Sopenharmony_ciint simple_offset_rename_exchange(struct inode *old_dir,
32362306a36Sopenharmony_ci				  struct dentry *old_dentry,
32462306a36Sopenharmony_ci				  struct inode *new_dir,
32562306a36Sopenharmony_ci				  struct dentry *new_dentry)
32662306a36Sopenharmony_ci{
32762306a36Sopenharmony_ci	struct offset_ctx *old_ctx = old_dir->i_op->get_offset_ctx(old_dir);
32862306a36Sopenharmony_ci	struct offset_ctx *new_ctx = new_dir->i_op->get_offset_ctx(new_dir);
32962306a36Sopenharmony_ci	u32 old_index = dentry2offset(old_dentry);
33062306a36Sopenharmony_ci	u32 new_index = dentry2offset(new_dentry);
33162306a36Sopenharmony_ci	int ret;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	simple_offset_remove(old_ctx, old_dentry);
33462306a36Sopenharmony_ci	simple_offset_remove(new_ctx, new_dentry);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	ret = simple_offset_add(new_ctx, old_dentry);
33762306a36Sopenharmony_ci	if (ret)
33862306a36Sopenharmony_ci		goto out_restore;
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	ret = simple_offset_add(old_ctx, new_dentry);
34162306a36Sopenharmony_ci	if (ret) {
34262306a36Sopenharmony_ci		simple_offset_remove(new_ctx, old_dentry);
34362306a36Sopenharmony_ci		goto out_restore;
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	ret = simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry);
34762306a36Sopenharmony_ci	if (ret) {
34862306a36Sopenharmony_ci		simple_offset_remove(new_ctx, old_dentry);
34962306a36Sopenharmony_ci		simple_offset_remove(old_ctx, new_dentry);
35062306a36Sopenharmony_ci		goto out_restore;
35162306a36Sopenharmony_ci	}
35262306a36Sopenharmony_ci	return 0;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ciout_restore:
35562306a36Sopenharmony_ci	offset_set(old_dentry, old_index);
35662306a36Sopenharmony_ci	xa_store(&old_ctx->xa, old_index, old_dentry, GFP_KERNEL);
35762306a36Sopenharmony_ci	offset_set(new_dentry, new_index);
35862306a36Sopenharmony_ci	xa_store(&new_ctx->xa, new_index, new_dentry, GFP_KERNEL);
35962306a36Sopenharmony_ci	return ret;
36062306a36Sopenharmony_ci}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci/**
36362306a36Sopenharmony_ci * simple_offset_destroy - Release offset map
36462306a36Sopenharmony_ci * @octx: directory offset ctx that is about to be destroyed
36562306a36Sopenharmony_ci *
36662306a36Sopenharmony_ci * During fs teardown (eg. umount), a directory's offset map might still
36762306a36Sopenharmony_ci * contain entries. xa_destroy() cleans out anything that remains.
36862306a36Sopenharmony_ci */
36962306a36Sopenharmony_civoid simple_offset_destroy(struct offset_ctx *octx)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	xa_destroy(&octx->xa);
37262306a36Sopenharmony_ci}
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci/**
37562306a36Sopenharmony_ci * offset_dir_llseek - Advance the read position of a directory descriptor
37662306a36Sopenharmony_ci * @file: an open directory whose position is to be updated
37762306a36Sopenharmony_ci * @offset: a byte offset
37862306a36Sopenharmony_ci * @whence: enumerator describing the starting position for this update
37962306a36Sopenharmony_ci *
38062306a36Sopenharmony_ci * SEEK_END, SEEK_DATA, and SEEK_HOLE are not supported for directories.
38162306a36Sopenharmony_ci *
38262306a36Sopenharmony_ci * Returns the updated read position if successful; otherwise a
38362306a36Sopenharmony_ci * negative errno is returned and the read position remains unchanged.
38462306a36Sopenharmony_ci */
38562306a36Sopenharmony_cistatic loff_t offset_dir_llseek(struct file *file, loff_t offset, int whence)
38662306a36Sopenharmony_ci{
38762306a36Sopenharmony_ci	switch (whence) {
38862306a36Sopenharmony_ci	case SEEK_CUR:
38962306a36Sopenharmony_ci		offset += file->f_pos;
39062306a36Sopenharmony_ci		fallthrough;
39162306a36Sopenharmony_ci	case SEEK_SET:
39262306a36Sopenharmony_ci		if (offset >= 0)
39362306a36Sopenharmony_ci			break;
39462306a36Sopenharmony_ci		fallthrough;
39562306a36Sopenharmony_ci	default:
39662306a36Sopenharmony_ci		return -EINVAL;
39762306a36Sopenharmony_ci	}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	/* In this case, ->private_data is protected by f_pos_lock */
40062306a36Sopenharmony_ci	file->private_data = NULL;
40162306a36Sopenharmony_ci	return vfs_setpos(file, offset, U32_MAX);
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_cistatic struct dentry *offset_find_next(struct xa_state *xas)
40562306a36Sopenharmony_ci{
40662306a36Sopenharmony_ci	struct dentry *child, *found = NULL;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	rcu_read_lock();
40962306a36Sopenharmony_ci	child = xas_next_entry(xas, U32_MAX);
41062306a36Sopenharmony_ci	if (!child)
41162306a36Sopenharmony_ci		goto out;
41262306a36Sopenharmony_ci	spin_lock(&child->d_lock);
41362306a36Sopenharmony_ci	if (simple_positive(child))
41462306a36Sopenharmony_ci		found = dget_dlock(child);
41562306a36Sopenharmony_ci	spin_unlock(&child->d_lock);
41662306a36Sopenharmony_ciout:
41762306a36Sopenharmony_ci	rcu_read_unlock();
41862306a36Sopenharmony_ci	return found;
41962306a36Sopenharmony_ci}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_cistatic bool offset_dir_emit(struct dir_context *ctx, struct dentry *dentry)
42262306a36Sopenharmony_ci{
42362306a36Sopenharmony_ci	u32 offset = dentry2offset(dentry);
42462306a36Sopenharmony_ci	struct inode *inode = d_inode(dentry);
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	return ctx->actor(ctx, dentry->d_name.name, dentry->d_name.len, offset,
42762306a36Sopenharmony_ci			  inode->i_ino, fs_umode_to_dtype(inode->i_mode));
42862306a36Sopenharmony_ci}
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_cistatic void *offset_iterate_dir(struct inode *inode, struct dir_context *ctx)
43162306a36Sopenharmony_ci{
43262306a36Sopenharmony_ci	struct offset_ctx *so_ctx = inode->i_op->get_offset_ctx(inode);
43362306a36Sopenharmony_ci	XA_STATE(xas, &so_ctx->xa, ctx->pos);
43462306a36Sopenharmony_ci	struct dentry *dentry;
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	while (true) {
43762306a36Sopenharmony_ci		dentry = offset_find_next(&xas);
43862306a36Sopenharmony_ci		if (!dentry)
43962306a36Sopenharmony_ci			return ERR_PTR(-ENOENT);
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci		if (!offset_dir_emit(ctx, dentry)) {
44262306a36Sopenharmony_ci			dput(dentry);
44362306a36Sopenharmony_ci			break;
44462306a36Sopenharmony_ci		}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci		dput(dentry);
44762306a36Sopenharmony_ci		ctx->pos = xas.xa_index + 1;
44862306a36Sopenharmony_ci	}
44962306a36Sopenharmony_ci	return NULL;
45062306a36Sopenharmony_ci}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci/**
45362306a36Sopenharmony_ci * offset_readdir - Emit entries starting at offset @ctx->pos
45462306a36Sopenharmony_ci * @file: an open directory to iterate over
45562306a36Sopenharmony_ci * @ctx: directory iteration context
45662306a36Sopenharmony_ci *
45762306a36Sopenharmony_ci * Caller must hold @file's i_rwsem to prevent insertion or removal of
45862306a36Sopenharmony_ci * entries during this call.
45962306a36Sopenharmony_ci *
46062306a36Sopenharmony_ci * On entry, @ctx->pos contains an offset that represents the first entry
46162306a36Sopenharmony_ci * to be read from the directory.
46262306a36Sopenharmony_ci *
46362306a36Sopenharmony_ci * The operation continues until there are no more entries to read, or
46462306a36Sopenharmony_ci * until the ctx->actor indicates there is no more space in the caller's
46562306a36Sopenharmony_ci * output buffer.
46662306a36Sopenharmony_ci *
46762306a36Sopenharmony_ci * On return, @ctx->pos contains an offset that will read the next entry
46862306a36Sopenharmony_ci * in this directory when offset_readdir() is called again with @ctx.
46962306a36Sopenharmony_ci *
47062306a36Sopenharmony_ci * Return values:
47162306a36Sopenharmony_ci *   %0 - Complete
47262306a36Sopenharmony_ci */
47362306a36Sopenharmony_cistatic int offset_readdir(struct file *file, struct dir_context *ctx)
47462306a36Sopenharmony_ci{
47562306a36Sopenharmony_ci	struct dentry *dir = file->f_path.dentry;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci	lockdep_assert_held(&d_inode(dir)->i_rwsem);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci	if (!dir_emit_dots(file, ctx))
48062306a36Sopenharmony_ci		return 0;
48162306a36Sopenharmony_ci
48262306a36Sopenharmony_ci	/* In this case, ->private_data is protected by f_pos_lock */
48362306a36Sopenharmony_ci	if (ctx->pos == 2)
48462306a36Sopenharmony_ci		file->private_data = NULL;
48562306a36Sopenharmony_ci	else if (file->private_data == ERR_PTR(-ENOENT))
48662306a36Sopenharmony_ci		return 0;
48762306a36Sopenharmony_ci	file->private_data = offset_iterate_dir(d_inode(dir), ctx);
48862306a36Sopenharmony_ci	return 0;
48962306a36Sopenharmony_ci}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ciconst struct file_operations simple_offset_dir_operations = {
49262306a36Sopenharmony_ci	.llseek		= offset_dir_llseek,
49362306a36Sopenharmony_ci	.iterate_shared	= offset_readdir,
49462306a36Sopenharmony_ci	.read		= generic_read_dir,
49562306a36Sopenharmony_ci	.fsync		= noop_fsync,
49662306a36Sopenharmony_ci};
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_cistatic struct dentry *find_next_child(struct dentry *parent, struct dentry *prev)
49962306a36Sopenharmony_ci{
50062306a36Sopenharmony_ci	struct dentry *child = NULL;
50162306a36Sopenharmony_ci	struct list_head *p = prev ? &prev->d_child : &parent->d_subdirs;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	spin_lock(&parent->d_lock);
50462306a36Sopenharmony_ci	while ((p = p->next) != &parent->d_subdirs) {
50562306a36Sopenharmony_ci		struct dentry *d = container_of(p, struct dentry, d_child);
50662306a36Sopenharmony_ci		if (simple_positive(d)) {
50762306a36Sopenharmony_ci			spin_lock_nested(&d->d_lock, DENTRY_D_LOCK_NESTED);
50862306a36Sopenharmony_ci			if (simple_positive(d))
50962306a36Sopenharmony_ci				child = dget_dlock(d);
51062306a36Sopenharmony_ci			spin_unlock(&d->d_lock);
51162306a36Sopenharmony_ci			if (likely(child))
51262306a36Sopenharmony_ci				break;
51362306a36Sopenharmony_ci		}
51462306a36Sopenharmony_ci	}
51562306a36Sopenharmony_ci	spin_unlock(&parent->d_lock);
51662306a36Sopenharmony_ci	dput(prev);
51762306a36Sopenharmony_ci	return child;
51862306a36Sopenharmony_ci}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_civoid simple_recursive_removal(struct dentry *dentry,
52162306a36Sopenharmony_ci                              void (*callback)(struct dentry *))
52262306a36Sopenharmony_ci{
52362306a36Sopenharmony_ci	struct dentry *this = dget(dentry);
52462306a36Sopenharmony_ci	while (true) {
52562306a36Sopenharmony_ci		struct dentry *victim = NULL, *child;
52662306a36Sopenharmony_ci		struct inode *inode = this->d_inode;
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci		inode_lock(inode);
52962306a36Sopenharmony_ci		if (d_is_dir(this))
53062306a36Sopenharmony_ci			inode->i_flags |= S_DEAD;
53162306a36Sopenharmony_ci		while ((child = find_next_child(this, victim)) == NULL) {
53262306a36Sopenharmony_ci			// kill and ascend
53362306a36Sopenharmony_ci			// update metadata while it's still locked
53462306a36Sopenharmony_ci			inode_set_ctime_current(inode);
53562306a36Sopenharmony_ci			clear_nlink(inode);
53662306a36Sopenharmony_ci			inode_unlock(inode);
53762306a36Sopenharmony_ci			victim = this;
53862306a36Sopenharmony_ci			this = this->d_parent;
53962306a36Sopenharmony_ci			inode = this->d_inode;
54062306a36Sopenharmony_ci			inode_lock(inode);
54162306a36Sopenharmony_ci			if (simple_positive(victim)) {
54262306a36Sopenharmony_ci				d_invalidate(victim);	// avoid lost mounts
54362306a36Sopenharmony_ci				if (d_is_dir(victim))
54462306a36Sopenharmony_ci					fsnotify_rmdir(inode, victim);
54562306a36Sopenharmony_ci				else
54662306a36Sopenharmony_ci					fsnotify_unlink(inode, victim);
54762306a36Sopenharmony_ci				if (callback)
54862306a36Sopenharmony_ci					callback(victim);
54962306a36Sopenharmony_ci				dput(victim);		// unpin it
55062306a36Sopenharmony_ci			}
55162306a36Sopenharmony_ci			if (victim == dentry) {
55262306a36Sopenharmony_ci				inode_set_mtime_to_ts(inode,
55362306a36Sopenharmony_ci						      inode_set_ctime_current(inode));
55462306a36Sopenharmony_ci				if (d_is_dir(dentry))
55562306a36Sopenharmony_ci					drop_nlink(inode);
55662306a36Sopenharmony_ci				inode_unlock(inode);
55762306a36Sopenharmony_ci				dput(dentry);
55862306a36Sopenharmony_ci				return;
55962306a36Sopenharmony_ci			}
56062306a36Sopenharmony_ci		}
56162306a36Sopenharmony_ci		inode_unlock(inode);
56262306a36Sopenharmony_ci		this = child;
56362306a36Sopenharmony_ci	}
56462306a36Sopenharmony_ci}
56562306a36Sopenharmony_ciEXPORT_SYMBOL(simple_recursive_removal);
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_cistatic const struct super_operations simple_super_operations = {
56862306a36Sopenharmony_ci	.statfs		= simple_statfs,
56962306a36Sopenharmony_ci};
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_cistatic int pseudo_fs_fill_super(struct super_block *s, struct fs_context *fc)
57262306a36Sopenharmony_ci{
57362306a36Sopenharmony_ci	struct pseudo_fs_context *ctx = fc->fs_private;
57462306a36Sopenharmony_ci	struct inode *root;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	s->s_maxbytes = MAX_LFS_FILESIZE;
57762306a36Sopenharmony_ci	s->s_blocksize = PAGE_SIZE;
57862306a36Sopenharmony_ci	s->s_blocksize_bits = PAGE_SHIFT;
57962306a36Sopenharmony_ci	s->s_magic = ctx->magic;
58062306a36Sopenharmony_ci	s->s_op = ctx->ops ?: &simple_super_operations;
58162306a36Sopenharmony_ci	s->s_xattr = ctx->xattr;
58262306a36Sopenharmony_ci	s->s_time_gran = 1;
58362306a36Sopenharmony_ci	root = new_inode(s);
58462306a36Sopenharmony_ci	if (!root)
58562306a36Sopenharmony_ci		return -ENOMEM;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	/*
58862306a36Sopenharmony_ci	 * since this is the first inode, make it number 1. New inodes created
58962306a36Sopenharmony_ci	 * after this must take care not to collide with it (by passing
59062306a36Sopenharmony_ci	 * max_reserved of 1 to iunique).
59162306a36Sopenharmony_ci	 */
59262306a36Sopenharmony_ci	root->i_ino = 1;
59362306a36Sopenharmony_ci	root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR;
59462306a36Sopenharmony_ci	simple_inode_init_ts(root);
59562306a36Sopenharmony_ci	s->s_root = d_make_root(root);
59662306a36Sopenharmony_ci	if (!s->s_root)
59762306a36Sopenharmony_ci		return -ENOMEM;
59862306a36Sopenharmony_ci	s->s_d_op = ctx->dops;
59962306a36Sopenharmony_ci	return 0;
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_cistatic int pseudo_fs_get_tree(struct fs_context *fc)
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	return get_tree_nodev(fc, pseudo_fs_fill_super);
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_cistatic void pseudo_fs_free(struct fs_context *fc)
60862306a36Sopenharmony_ci{
60962306a36Sopenharmony_ci	kfree(fc->fs_private);
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cistatic const struct fs_context_operations pseudo_fs_context_ops = {
61362306a36Sopenharmony_ci	.free		= pseudo_fs_free,
61462306a36Sopenharmony_ci	.get_tree	= pseudo_fs_get_tree,
61562306a36Sopenharmony_ci};
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci/*
61862306a36Sopenharmony_ci * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that
61962306a36Sopenharmony_ci * will never be mountable)
62062306a36Sopenharmony_ci */
62162306a36Sopenharmony_cistruct pseudo_fs_context *init_pseudo(struct fs_context *fc,
62262306a36Sopenharmony_ci					unsigned long magic)
62362306a36Sopenharmony_ci{
62462306a36Sopenharmony_ci	struct pseudo_fs_context *ctx;
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	ctx = kzalloc(sizeof(struct pseudo_fs_context), GFP_KERNEL);
62762306a36Sopenharmony_ci	if (likely(ctx)) {
62862306a36Sopenharmony_ci		ctx->magic = magic;
62962306a36Sopenharmony_ci		fc->fs_private = ctx;
63062306a36Sopenharmony_ci		fc->ops = &pseudo_fs_context_ops;
63162306a36Sopenharmony_ci		fc->sb_flags |= SB_NOUSER;
63262306a36Sopenharmony_ci		fc->global = true;
63362306a36Sopenharmony_ci	}
63462306a36Sopenharmony_ci	return ctx;
63562306a36Sopenharmony_ci}
63662306a36Sopenharmony_ciEXPORT_SYMBOL(init_pseudo);
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_ciint simple_open(struct inode *inode, struct file *file)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci	if (inode->i_private)
64162306a36Sopenharmony_ci		file->private_data = inode->i_private;
64262306a36Sopenharmony_ci	return 0;
64362306a36Sopenharmony_ci}
64462306a36Sopenharmony_ciEXPORT_SYMBOL(simple_open);
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ciint simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
64762306a36Sopenharmony_ci{
64862306a36Sopenharmony_ci	struct inode *inode = d_inode(old_dentry);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	inode_set_mtime_to_ts(dir,
65162306a36Sopenharmony_ci			      inode_set_ctime_to_ts(dir, inode_set_ctime_current(inode)));
65262306a36Sopenharmony_ci	inc_nlink(inode);
65362306a36Sopenharmony_ci	ihold(inode);
65462306a36Sopenharmony_ci	dget(dentry);
65562306a36Sopenharmony_ci	d_instantiate(dentry, inode);
65662306a36Sopenharmony_ci	return 0;
65762306a36Sopenharmony_ci}
65862306a36Sopenharmony_ciEXPORT_SYMBOL(simple_link);
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ciint simple_empty(struct dentry *dentry)
66162306a36Sopenharmony_ci{
66262306a36Sopenharmony_ci	struct dentry *child;
66362306a36Sopenharmony_ci	int ret = 0;
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	spin_lock(&dentry->d_lock);
66662306a36Sopenharmony_ci	list_for_each_entry(child, &dentry->d_subdirs, d_child) {
66762306a36Sopenharmony_ci		spin_lock_nested(&child->d_lock, DENTRY_D_LOCK_NESTED);
66862306a36Sopenharmony_ci		if (simple_positive(child)) {
66962306a36Sopenharmony_ci			spin_unlock(&child->d_lock);
67062306a36Sopenharmony_ci			goto out;
67162306a36Sopenharmony_ci		}
67262306a36Sopenharmony_ci		spin_unlock(&child->d_lock);
67362306a36Sopenharmony_ci	}
67462306a36Sopenharmony_ci	ret = 1;
67562306a36Sopenharmony_ciout:
67662306a36Sopenharmony_ci	spin_unlock(&dentry->d_lock);
67762306a36Sopenharmony_ci	return ret;
67862306a36Sopenharmony_ci}
67962306a36Sopenharmony_ciEXPORT_SYMBOL(simple_empty);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ciint simple_unlink(struct inode *dir, struct dentry *dentry)
68262306a36Sopenharmony_ci{
68362306a36Sopenharmony_ci	struct inode *inode = d_inode(dentry);
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	inode_set_mtime_to_ts(dir,
68662306a36Sopenharmony_ci			      inode_set_ctime_to_ts(dir, inode_set_ctime_current(inode)));
68762306a36Sopenharmony_ci	drop_nlink(inode);
68862306a36Sopenharmony_ci	dput(dentry);
68962306a36Sopenharmony_ci	return 0;
69062306a36Sopenharmony_ci}
69162306a36Sopenharmony_ciEXPORT_SYMBOL(simple_unlink);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ciint simple_rmdir(struct inode *dir, struct dentry *dentry)
69462306a36Sopenharmony_ci{
69562306a36Sopenharmony_ci	if (!simple_empty(dentry))
69662306a36Sopenharmony_ci		return -ENOTEMPTY;
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	drop_nlink(d_inode(dentry));
69962306a36Sopenharmony_ci	simple_unlink(dir, dentry);
70062306a36Sopenharmony_ci	drop_nlink(dir);
70162306a36Sopenharmony_ci	return 0;
70262306a36Sopenharmony_ci}
70362306a36Sopenharmony_ciEXPORT_SYMBOL(simple_rmdir);
70462306a36Sopenharmony_ci
70562306a36Sopenharmony_ci/**
70662306a36Sopenharmony_ci * simple_rename_timestamp - update the various inode timestamps for rename
70762306a36Sopenharmony_ci * @old_dir: old parent directory
70862306a36Sopenharmony_ci * @old_dentry: dentry that is being renamed
70962306a36Sopenharmony_ci * @new_dir: new parent directory
71062306a36Sopenharmony_ci * @new_dentry: target for rename
71162306a36Sopenharmony_ci *
71262306a36Sopenharmony_ci * POSIX mandates that the old and new parent directories have their ctime and
71362306a36Sopenharmony_ci * mtime updated, and that inodes of @old_dentry and @new_dentry (if any), have
71462306a36Sopenharmony_ci * their ctime updated.
71562306a36Sopenharmony_ci */
71662306a36Sopenharmony_civoid simple_rename_timestamp(struct inode *old_dir, struct dentry *old_dentry,
71762306a36Sopenharmony_ci			     struct inode *new_dir, struct dentry *new_dentry)
71862306a36Sopenharmony_ci{
71962306a36Sopenharmony_ci	struct inode *newino = d_inode(new_dentry);
72062306a36Sopenharmony_ci
72162306a36Sopenharmony_ci	inode_set_mtime_to_ts(old_dir, inode_set_ctime_current(old_dir));
72262306a36Sopenharmony_ci	if (new_dir != old_dir)
72362306a36Sopenharmony_ci		inode_set_mtime_to_ts(new_dir,
72462306a36Sopenharmony_ci				      inode_set_ctime_current(new_dir));
72562306a36Sopenharmony_ci	inode_set_ctime_current(d_inode(old_dentry));
72662306a36Sopenharmony_ci	if (newino)
72762306a36Sopenharmony_ci		inode_set_ctime_current(newino);
72862306a36Sopenharmony_ci}
72962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(simple_rename_timestamp);
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_ciint simple_rename_exchange(struct inode *old_dir, struct dentry *old_dentry,
73262306a36Sopenharmony_ci			   struct inode *new_dir, struct dentry *new_dentry)
73362306a36Sopenharmony_ci{
73462306a36Sopenharmony_ci	bool old_is_dir = d_is_dir(old_dentry);
73562306a36Sopenharmony_ci	bool new_is_dir = d_is_dir(new_dentry);
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	if (old_dir != new_dir && old_is_dir != new_is_dir) {
73862306a36Sopenharmony_ci		if (old_is_dir) {
73962306a36Sopenharmony_ci			drop_nlink(old_dir);
74062306a36Sopenharmony_ci			inc_nlink(new_dir);
74162306a36Sopenharmony_ci		} else {
74262306a36Sopenharmony_ci			drop_nlink(new_dir);
74362306a36Sopenharmony_ci			inc_nlink(old_dir);
74462306a36Sopenharmony_ci		}
74562306a36Sopenharmony_ci	}
74662306a36Sopenharmony_ci	simple_rename_timestamp(old_dir, old_dentry, new_dir, new_dentry);
74762306a36Sopenharmony_ci	return 0;
74862306a36Sopenharmony_ci}
74962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(simple_rename_exchange);
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ciint simple_rename(struct mnt_idmap *idmap, struct inode *old_dir,
75262306a36Sopenharmony_ci		  struct dentry *old_dentry, struct inode *new_dir,
75362306a36Sopenharmony_ci		  struct dentry *new_dentry, unsigned int flags)
75462306a36Sopenharmony_ci{
75562306a36Sopenharmony_ci	int they_are_dirs = d_is_dir(old_dentry);
75662306a36Sopenharmony_ci
75762306a36Sopenharmony_ci	if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
75862306a36Sopenharmony_ci		return -EINVAL;
75962306a36Sopenharmony_ci
76062306a36Sopenharmony_ci	if (flags & RENAME_EXCHANGE)
76162306a36Sopenharmony_ci		return simple_rename_exchange(old_dir, old_dentry, new_dir, new_dentry);
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	if (!simple_empty(new_dentry))
76462306a36Sopenharmony_ci		return -ENOTEMPTY;
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci	if (d_really_is_positive(new_dentry)) {
76762306a36Sopenharmony_ci		simple_unlink(new_dir, new_dentry);
76862306a36Sopenharmony_ci		if (they_are_dirs) {
76962306a36Sopenharmony_ci			drop_nlink(d_inode(new_dentry));
77062306a36Sopenharmony_ci			drop_nlink(old_dir);
77162306a36Sopenharmony_ci		}
77262306a36Sopenharmony_ci	} else if (they_are_dirs) {
77362306a36Sopenharmony_ci		drop_nlink(old_dir);
77462306a36Sopenharmony_ci		inc_nlink(new_dir);
77562306a36Sopenharmony_ci	}
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	simple_rename_timestamp(old_dir, old_dentry, new_dir, new_dentry);
77862306a36Sopenharmony_ci	return 0;
77962306a36Sopenharmony_ci}
78062306a36Sopenharmony_ciEXPORT_SYMBOL(simple_rename);
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci/**
78362306a36Sopenharmony_ci * simple_setattr - setattr for simple filesystem
78462306a36Sopenharmony_ci * @idmap: idmap of the target mount
78562306a36Sopenharmony_ci * @dentry: dentry
78662306a36Sopenharmony_ci * @iattr: iattr structure
78762306a36Sopenharmony_ci *
78862306a36Sopenharmony_ci * Returns 0 on success, -error on failure.
78962306a36Sopenharmony_ci *
79062306a36Sopenharmony_ci * simple_setattr is a simple ->setattr implementation without a proper
79162306a36Sopenharmony_ci * implementation of size changes.
79262306a36Sopenharmony_ci *
79362306a36Sopenharmony_ci * It can either be used for in-memory filesystems or special files
79462306a36Sopenharmony_ci * on simple regular filesystems.  Anything that needs to change on-disk
79562306a36Sopenharmony_ci * or wire state on size changes needs its own setattr method.
79662306a36Sopenharmony_ci */
79762306a36Sopenharmony_ciint simple_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
79862306a36Sopenharmony_ci		   struct iattr *iattr)
79962306a36Sopenharmony_ci{
80062306a36Sopenharmony_ci	struct inode *inode = d_inode(dentry);
80162306a36Sopenharmony_ci	int error;
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_ci	error = setattr_prepare(idmap, dentry, iattr);
80462306a36Sopenharmony_ci	if (error)
80562306a36Sopenharmony_ci		return error;
80662306a36Sopenharmony_ci
80762306a36Sopenharmony_ci	if (iattr->ia_valid & ATTR_SIZE)
80862306a36Sopenharmony_ci		truncate_setsize(inode, iattr->ia_size);
80962306a36Sopenharmony_ci	setattr_copy(idmap, inode, iattr);
81062306a36Sopenharmony_ci	mark_inode_dirty(inode);
81162306a36Sopenharmony_ci	return 0;
81262306a36Sopenharmony_ci}
81362306a36Sopenharmony_ciEXPORT_SYMBOL(simple_setattr);
81462306a36Sopenharmony_ci
81562306a36Sopenharmony_cistatic int simple_read_folio(struct file *file, struct folio *folio)
81662306a36Sopenharmony_ci{
81762306a36Sopenharmony_ci	folio_zero_range(folio, 0, folio_size(folio));
81862306a36Sopenharmony_ci	flush_dcache_folio(folio);
81962306a36Sopenharmony_ci	folio_mark_uptodate(folio);
82062306a36Sopenharmony_ci	folio_unlock(folio);
82162306a36Sopenharmony_ci	return 0;
82262306a36Sopenharmony_ci}
82362306a36Sopenharmony_ci
82462306a36Sopenharmony_ciint simple_write_begin(struct file *file, struct address_space *mapping,
82562306a36Sopenharmony_ci			loff_t pos, unsigned len,
82662306a36Sopenharmony_ci			struct page **pagep, void **fsdata)
82762306a36Sopenharmony_ci{
82862306a36Sopenharmony_ci	struct folio *folio;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	folio = __filemap_get_folio(mapping, pos / PAGE_SIZE, FGP_WRITEBEGIN,
83162306a36Sopenharmony_ci			mapping_gfp_mask(mapping));
83262306a36Sopenharmony_ci	if (IS_ERR(folio))
83362306a36Sopenharmony_ci		return PTR_ERR(folio);
83462306a36Sopenharmony_ci
83562306a36Sopenharmony_ci	*pagep = &folio->page;
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	if (!folio_test_uptodate(folio) && (len != folio_size(folio))) {
83862306a36Sopenharmony_ci		size_t from = offset_in_folio(folio, pos);
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci		folio_zero_segments(folio, 0, from,
84162306a36Sopenharmony_ci				from + len, folio_size(folio));
84262306a36Sopenharmony_ci	}
84362306a36Sopenharmony_ci	return 0;
84462306a36Sopenharmony_ci}
84562306a36Sopenharmony_ciEXPORT_SYMBOL(simple_write_begin);
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci/**
84862306a36Sopenharmony_ci * simple_write_end - .write_end helper for non-block-device FSes
84962306a36Sopenharmony_ci * @file: See .write_end of address_space_operations
85062306a36Sopenharmony_ci * @mapping: 		"
85162306a36Sopenharmony_ci * @pos: 		"
85262306a36Sopenharmony_ci * @len: 		"
85362306a36Sopenharmony_ci * @copied: 		"
85462306a36Sopenharmony_ci * @page: 		"
85562306a36Sopenharmony_ci * @fsdata: 		"
85662306a36Sopenharmony_ci *
85762306a36Sopenharmony_ci * simple_write_end does the minimum needed for updating a page after writing is
85862306a36Sopenharmony_ci * done. It has the same API signature as the .write_end of
85962306a36Sopenharmony_ci * address_space_operations vector. So it can just be set onto .write_end for
86062306a36Sopenharmony_ci * FSes that don't need any other processing. i_mutex is assumed to be held.
86162306a36Sopenharmony_ci * Block based filesystems should use generic_write_end().
86262306a36Sopenharmony_ci * NOTE: Even though i_size might get updated by this function, mark_inode_dirty
86362306a36Sopenharmony_ci * is not called, so a filesystem that actually does store data in .write_inode
86462306a36Sopenharmony_ci * should extend on what's done here with a call to mark_inode_dirty() in the
86562306a36Sopenharmony_ci * case that i_size has changed.
86662306a36Sopenharmony_ci *
86762306a36Sopenharmony_ci * Use *ONLY* with simple_read_folio()
86862306a36Sopenharmony_ci */
86962306a36Sopenharmony_cistatic int simple_write_end(struct file *file, struct address_space *mapping,
87062306a36Sopenharmony_ci			loff_t pos, unsigned len, unsigned copied,
87162306a36Sopenharmony_ci			struct page *page, void *fsdata)
87262306a36Sopenharmony_ci{
87362306a36Sopenharmony_ci	struct folio *folio = page_folio(page);
87462306a36Sopenharmony_ci	struct inode *inode = folio->mapping->host;
87562306a36Sopenharmony_ci	loff_t last_pos = pos + copied;
87662306a36Sopenharmony_ci
87762306a36Sopenharmony_ci	/* zero the stale part of the folio if we did a short copy */
87862306a36Sopenharmony_ci	if (!folio_test_uptodate(folio)) {
87962306a36Sopenharmony_ci		if (copied < len) {
88062306a36Sopenharmony_ci			size_t from = offset_in_folio(folio, pos);
88162306a36Sopenharmony_ci
88262306a36Sopenharmony_ci			folio_zero_range(folio, from + copied, len - copied);
88362306a36Sopenharmony_ci		}
88462306a36Sopenharmony_ci		folio_mark_uptodate(folio);
88562306a36Sopenharmony_ci	}
88662306a36Sopenharmony_ci	/*
88762306a36Sopenharmony_ci	 * No need to use i_size_read() here, the i_size
88862306a36Sopenharmony_ci	 * cannot change under us because we hold the i_mutex.
88962306a36Sopenharmony_ci	 */
89062306a36Sopenharmony_ci	if (last_pos > inode->i_size)
89162306a36Sopenharmony_ci		i_size_write(inode, last_pos);
89262306a36Sopenharmony_ci
89362306a36Sopenharmony_ci	folio_mark_dirty(folio);
89462306a36Sopenharmony_ci	folio_unlock(folio);
89562306a36Sopenharmony_ci	folio_put(folio);
89662306a36Sopenharmony_ci
89762306a36Sopenharmony_ci	return copied;
89862306a36Sopenharmony_ci}
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci/*
90162306a36Sopenharmony_ci * Provides ramfs-style behavior: data in the pagecache, but no writeback.
90262306a36Sopenharmony_ci */
90362306a36Sopenharmony_ciconst struct address_space_operations ram_aops = {
90462306a36Sopenharmony_ci	.read_folio	= simple_read_folio,
90562306a36Sopenharmony_ci	.write_begin	= simple_write_begin,
90662306a36Sopenharmony_ci	.write_end	= simple_write_end,
90762306a36Sopenharmony_ci	.dirty_folio	= noop_dirty_folio,
90862306a36Sopenharmony_ci};
90962306a36Sopenharmony_ciEXPORT_SYMBOL(ram_aops);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci/*
91262306a36Sopenharmony_ci * the inodes created here are not hashed. If you use iunique to generate
91362306a36Sopenharmony_ci * unique inode values later for this filesystem, then you must take care
91462306a36Sopenharmony_ci * to pass it an appropriate max_reserved value to avoid collisions.
91562306a36Sopenharmony_ci */
91662306a36Sopenharmony_ciint simple_fill_super(struct super_block *s, unsigned long magic,
91762306a36Sopenharmony_ci		      const struct tree_descr *files)
91862306a36Sopenharmony_ci{
91962306a36Sopenharmony_ci	struct inode *inode;
92062306a36Sopenharmony_ci	struct dentry *root;
92162306a36Sopenharmony_ci	struct dentry *dentry;
92262306a36Sopenharmony_ci	int i;
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	s->s_blocksize = PAGE_SIZE;
92562306a36Sopenharmony_ci	s->s_blocksize_bits = PAGE_SHIFT;
92662306a36Sopenharmony_ci	s->s_magic = magic;
92762306a36Sopenharmony_ci	s->s_op = &simple_super_operations;
92862306a36Sopenharmony_ci	s->s_time_gran = 1;
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	inode = new_inode(s);
93162306a36Sopenharmony_ci	if (!inode)
93262306a36Sopenharmony_ci		return -ENOMEM;
93362306a36Sopenharmony_ci	/*
93462306a36Sopenharmony_ci	 * because the root inode is 1, the files array must not contain an
93562306a36Sopenharmony_ci	 * entry at index 1
93662306a36Sopenharmony_ci	 */
93762306a36Sopenharmony_ci	inode->i_ino = 1;
93862306a36Sopenharmony_ci	inode->i_mode = S_IFDIR | 0755;
93962306a36Sopenharmony_ci	simple_inode_init_ts(inode);
94062306a36Sopenharmony_ci	inode->i_op = &simple_dir_inode_operations;
94162306a36Sopenharmony_ci	inode->i_fop = &simple_dir_operations;
94262306a36Sopenharmony_ci	set_nlink(inode, 2);
94362306a36Sopenharmony_ci	root = d_make_root(inode);
94462306a36Sopenharmony_ci	if (!root)
94562306a36Sopenharmony_ci		return -ENOMEM;
94662306a36Sopenharmony_ci	for (i = 0; !files->name || files->name[0]; i++, files++) {
94762306a36Sopenharmony_ci		if (!files->name)
94862306a36Sopenharmony_ci			continue;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci		/* warn if it tries to conflict with the root inode */
95162306a36Sopenharmony_ci		if (unlikely(i == 1))
95262306a36Sopenharmony_ci			printk(KERN_WARNING "%s: %s passed in a files array"
95362306a36Sopenharmony_ci				"with an index of 1!\n", __func__,
95462306a36Sopenharmony_ci				s->s_type->name);
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci		dentry = d_alloc_name(root, files->name);
95762306a36Sopenharmony_ci		if (!dentry)
95862306a36Sopenharmony_ci			goto out;
95962306a36Sopenharmony_ci		inode = new_inode(s);
96062306a36Sopenharmony_ci		if (!inode) {
96162306a36Sopenharmony_ci			dput(dentry);
96262306a36Sopenharmony_ci			goto out;
96362306a36Sopenharmony_ci		}
96462306a36Sopenharmony_ci		inode->i_mode = S_IFREG | files->mode;
96562306a36Sopenharmony_ci		simple_inode_init_ts(inode);
96662306a36Sopenharmony_ci		inode->i_fop = files->ops;
96762306a36Sopenharmony_ci		inode->i_ino = i;
96862306a36Sopenharmony_ci		d_add(dentry, inode);
96962306a36Sopenharmony_ci	}
97062306a36Sopenharmony_ci	s->s_root = root;
97162306a36Sopenharmony_ci	return 0;
97262306a36Sopenharmony_ciout:
97362306a36Sopenharmony_ci	d_genocide(root);
97462306a36Sopenharmony_ci	shrink_dcache_parent(root);
97562306a36Sopenharmony_ci	dput(root);
97662306a36Sopenharmony_ci	return -ENOMEM;
97762306a36Sopenharmony_ci}
97862306a36Sopenharmony_ciEXPORT_SYMBOL(simple_fill_super);
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_cistatic DEFINE_SPINLOCK(pin_fs_lock);
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ciint simple_pin_fs(struct file_system_type *type, struct vfsmount **mount, int *count)
98362306a36Sopenharmony_ci{
98462306a36Sopenharmony_ci	struct vfsmount *mnt = NULL;
98562306a36Sopenharmony_ci	spin_lock(&pin_fs_lock);
98662306a36Sopenharmony_ci	if (unlikely(!*mount)) {
98762306a36Sopenharmony_ci		spin_unlock(&pin_fs_lock);
98862306a36Sopenharmony_ci		mnt = vfs_kern_mount(type, SB_KERNMOUNT, type->name, NULL);
98962306a36Sopenharmony_ci		if (IS_ERR(mnt))
99062306a36Sopenharmony_ci			return PTR_ERR(mnt);
99162306a36Sopenharmony_ci		spin_lock(&pin_fs_lock);
99262306a36Sopenharmony_ci		if (!*mount)
99362306a36Sopenharmony_ci			*mount = mnt;
99462306a36Sopenharmony_ci	}
99562306a36Sopenharmony_ci	mntget(*mount);
99662306a36Sopenharmony_ci	++*count;
99762306a36Sopenharmony_ci	spin_unlock(&pin_fs_lock);
99862306a36Sopenharmony_ci	mntput(mnt);
99962306a36Sopenharmony_ci	return 0;
100062306a36Sopenharmony_ci}
100162306a36Sopenharmony_ciEXPORT_SYMBOL(simple_pin_fs);
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_civoid simple_release_fs(struct vfsmount **mount, int *count)
100462306a36Sopenharmony_ci{
100562306a36Sopenharmony_ci	struct vfsmount *mnt;
100662306a36Sopenharmony_ci	spin_lock(&pin_fs_lock);
100762306a36Sopenharmony_ci	mnt = *mount;
100862306a36Sopenharmony_ci	if (!--*count)
100962306a36Sopenharmony_ci		*mount = NULL;
101062306a36Sopenharmony_ci	spin_unlock(&pin_fs_lock);
101162306a36Sopenharmony_ci	mntput(mnt);
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ciEXPORT_SYMBOL(simple_release_fs);
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci/**
101662306a36Sopenharmony_ci * simple_read_from_buffer - copy data from the buffer to user space
101762306a36Sopenharmony_ci * @to: the user space buffer to read to
101862306a36Sopenharmony_ci * @count: the maximum number of bytes to read
101962306a36Sopenharmony_ci * @ppos: the current position in the buffer
102062306a36Sopenharmony_ci * @from: the buffer to read from
102162306a36Sopenharmony_ci * @available: the size of the buffer
102262306a36Sopenharmony_ci *
102362306a36Sopenharmony_ci * The simple_read_from_buffer() function reads up to @count bytes from the
102462306a36Sopenharmony_ci * buffer @from at offset @ppos into the user space address starting at @to.
102562306a36Sopenharmony_ci *
102662306a36Sopenharmony_ci * On success, the number of bytes read is returned and the offset @ppos is
102762306a36Sopenharmony_ci * advanced by this number, or negative value is returned on error.
102862306a36Sopenharmony_ci **/
102962306a36Sopenharmony_cissize_t simple_read_from_buffer(void __user *to, size_t count, loff_t *ppos,
103062306a36Sopenharmony_ci				const void *from, size_t available)
103162306a36Sopenharmony_ci{
103262306a36Sopenharmony_ci	loff_t pos = *ppos;
103362306a36Sopenharmony_ci	size_t ret;
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	if (pos < 0)
103662306a36Sopenharmony_ci		return -EINVAL;
103762306a36Sopenharmony_ci	if (pos >= available || !count)
103862306a36Sopenharmony_ci		return 0;
103962306a36Sopenharmony_ci	if (count > available - pos)
104062306a36Sopenharmony_ci		count = available - pos;
104162306a36Sopenharmony_ci	ret = copy_to_user(to, from + pos, count);
104262306a36Sopenharmony_ci	if (ret == count)
104362306a36Sopenharmony_ci		return -EFAULT;
104462306a36Sopenharmony_ci	count -= ret;
104562306a36Sopenharmony_ci	*ppos = pos + count;
104662306a36Sopenharmony_ci	return count;
104762306a36Sopenharmony_ci}
104862306a36Sopenharmony_ciEXPORT_SYMBOL(simple_read_from_buffer);
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci/**
105162306a36Sopenharmony_ci * simple_write_to_buffer - copy data from user space to the buffer
105262306a36Sopenharmony_ci * @to: the buffer to write to
105362306a36Sopenharmony_ci * @available: the size of the buffer
105462306a36Sopenharmony_ci * @ppos: the current position in the buffer
105562306a36Sopenharmony_ci * @from: the user space buffer to read from
105662306a36Sopenharmony_ci * @count: the maximum number of bytes to read
105762306a36Sopenharmony_ci *
105862306a36Sopenharmony_ci * The simple_write_to_buffer() function reads up to @count bytes from the user
105962306a36Sopenharmony_ci * space address starting at @from into the buffer @to at offset @ppos.
106062306a36Sopenharmony_ci *
106162306a36Sopenharmony_ci * On success, the number of bytes written is returned and the offset @ppos is
106262306a36Sopenharmony_ci * advanced by this number, or negative value is returned on error.
106362306a36Sopenharmony_ci **/
106462306a36Sopenharmony_cissize_t simple_write_to_buffer(void *to, size_t available, loff_t *ppos,
106562306a36Sopenharmony_ci		const void __user *from, size_t count)
106662306a36Sopenharmony_ci{
106762306a36Sopenharmony_ci	loff_t pos = *ppos;
106862306a36Sopenharmony_ci	size_t res;
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	if (pos < 0)
107162306a36Sopenharmony_ci		return -EINVAL;
107262306a36Sopenharmony_ci	if (pos >= available || !count)
107362306a36Sopenharmony_ci		return 0;
107462306a36Sopenharmony_ci	if (count > available - pos)
107562306a36Sopenharmony_ci		count = available - pos;
107662306a36Sopenharmony_ci	res = copy_from_user(to + pos, from, count);
107762306a36Sopenharmony_ci	if (res == count)
107862306a36Sopenharmony_ci		return -EFAULT;
107962306a36Sopenharmony_ci	count -= res;
108062306a36Sopenharmony_ci	*ppos = pos + count;
108162306a36Sopenharmony_ci	return count;
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ciEXPORT_SYMBOL(simple_write_to_buffer);
108462306a36Sopenharmony_ci
108562306a36Sopenharmony_ci/**
108662306a36Sopenharmony_ci * memory_read_from_buffer - copy data from the buffer
108762306a36Sopenharmony_ci * @to: the kernel space buffer to read to
108862306a36Sopenharmony_ci * @count: the maximum number of bytes to read
108962306a36Sopenharmony_ci * @ppos: the current position in the buffer
109062306a36Sopenharmony_ci * @from: the buffer to read from
109162306a36Sopenharmony_ci * @available: the size of the buffer
109262306a36Sopenharmony_ci *
109362306a36Sopenharmony_ci * The memory_read_from_buffer() function reads up to @count bytes from the
109462306a36Sopenharmony_ci * buffer @from at offset @ppos into the kernel space address starting at @to.
109562306a36Sopenharmony_ci *
109662306a36Sopenharmony_ci * On success, the number of bytes read is returned and the offset @ppos is
109762306a36Sopenharmony_ci * advanced by this number, or negative value is returned on error.
109862306a36Sopenharmony_ci **/
109962306a36Sopenharmony_cissize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
110062306a36Sopenharmony_ci				const void *from, size_t available)
110162306a36Sopenharmony_ci{
110262306a36Sopenharmony_ci	loff_t pos = *ppos;
110362306a36Sopenharmony_ci
110462306a36Sopenharmony_ci	if (pos < 0)
110562306a36Sopenharmony_ci		return -EINVAL;
110662306a36Sopenharmony_ci	if (pos >= available)
110762306a36Sopenharmony_ci		return 0;
110862306a36Sopenharmony_ci	if (count > available - pos)
110962306a36Sopenharmony_ci		count = available - pos;
111062306a36Sopenharmony_ci	memcpy(to, from + pos, count);
111162306a36Sopenharmony_ci	*ppos = pos + count;
111262306a36Sopenharmony_ci
111362306a36Sopenharmony_ci	return count;
111462306a36Sopenharmony_ci}
111562306a36Sopenharmony_ciEXPORT_SYMBOL(memory_read_from_buffer);
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci/*
111862306a36Sopenharmony_ci * Transaction based IO.
111962306a36Sopenharmony_ci * The file expects a single write which triggers the transaction, and then
112062306a36Sopenharmony_ci * possibly a read which collects the result - which is stored in a
112162306a36Sopenharmony_ci * file-local buffer.
112262306a36Sopenharmony_ci */
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_civoid simple_transaction_set(struct file *file, size_t n)
112562306a36Sopenharmony_ci{
112662306a36Sopenharmony_ci	struct simple_transaction_argresp *ar = file->private_data;
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	BUG_ON(n > SIMPLE_TRANSACTION_LIMIT);
112962306a36Sopenharmony_ci
113062306a36Sopenharmony_ci	/*
113162306a36Sopenharmony_ci	 * The barrier ensures that ar->size will really remain zero until
113262306a36Sopenharmony_ci	 * ar->data is ready for reading.
113362306a36Sopenharmony_ci	 */
113462306a36Sopenharmony_ci	smp_mb();
113562306a36Sopenharmony_ci	ar->size = n;
113662306a36Sopenharmony_ci}
113762306a36Sopenharmony_ciEXPORT_SYMBOL(simple_transaction_set);
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_cichar *simple_transaction_get(struct file *file, const char __user *buf, size_t size)
114062306a36Sopenharmony_ci{
114162306a36Sopenharmony_ci	struct simple_transaction_argresp *ar;
114262306a36Sopenharmony_ci	static DEFINE_SPINLOCK(simple_transaction_lock);
114362306a36Sopenharmony_ci
114462306a36Sopenharmony_ci	if (size > SIMPLE_TRANSACTION_LIMIT - 1)
114562306a36Sopenharmony_ci		return ERR_PTR(-EFBIG);
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	ar = (struct simple_transaction_argresp *)get_zeroed_page(GFP_KERNEL);
114862306a36Sopenharmony_ci	if (!ar)
114962306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	spin_lock(&simple_transaction_lock);
115262306a36Sopenharmony_ci
115362306a36Sopenharmony_ci	/* only one write allowed per open */
115462306a36Sopenharmony_ci	if (file->private_data) {
115562306a36Sopenharmony_ci		spin_unlock(&simple_transaction_lock);
115662306a36Sopenharmony_ci		free_page((unsigned long)ar);
115762306a36Sopenharmony_ci		return ERR_PTR(-EBUSY);
115862306a36Sopenharmony_ci	}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_ci	file->private_data = ar;
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_ci	spin_unlock(&simple_transaction_lock);
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	if (copy_from_user(ar->data, buf, size))
116562306a36Sopenharmony_ci		return ERR_PTR(-EFAULT);
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	return ar->data;
116862306a36Sopenharmony_ci}
116962306a36Sopenharmony_ciEXPORT_SYMBOL(simple_transaction_get);
117062306a36Sopenharmony_ci
117162306a36Sopenharmony_cissize_t simple_transaction_read(struct file *file, char __user *buf, size_t size, loff_t *pos)
117262306a36Sopenharmony_ci{
117362306a36Sopenharmony_ci	struct simple_transaction_argresp *ar = file->private_data;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	if (!ar)
117662306a36Sopenharmony_ci		return 0;
117762306a36Sopenharmony_ci	return simple_read_from_buffer(buf, size, pos, ar->data, ar->size);
117862306a36Sopenharmony_ci}
117962306a36Sopenharmony_ciEXPORT_SYMBOL(simple_transaction_read);
118062306a36Sopenharmony_ci
118162306a36Sopenharmony_ciint simple_transaction_release(struct inode *inode, struct file *file)
118262306a36Sopenharmony_ci{
118362306a36Sopenharmony_ci	free_page((unsigned long)file->private_data);
118462306a36Sopenharmony_ci	return 0;
118562306a36Sopenharmony_ci}
118662306a36Sopenharmony_ciEXPORT_SYMBOL(simple_transaction_release);
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci/* Simple attribute files */
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_cistruct simple_attr {
119162306a36Sopenharmony_ci	int (*get)(void *, u64 *);
119262306a36Sopenharmony_ci	int (*set)(void *, u64);
119362306a36Sopenharmony_ci	char get_buf[24];	/* enough to store a u64 and "\n\0" */
119462306a36Sopenharmony_ci	char set_buf[24];
119562306a36Sopenharmony_ci	void *data;
119662306a36Sopenharmony_ci	const char *fmt;	/* format for read operation */
119762306a36Sopenharmony_ci	struct mutex mutex;	/* protects access to these buffers */
119862306a36Sopenharmony_ci};
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci/* simple_attr_open is called by an actual attribute open file operation
120162306a36Sopenharmony_ci * to set the attribute specific access operations. */
120262306a36Sopenharmony_ciint simple_attr_open(struct inode *inode, struct file *file,
120362306a36Sopenharmony_ci		     int (*get)(void *, u64 *), int (*set)(void *, u64),
120462306a36Sopenharmony_ci		     const char *fmt)
120562306a36Sopenharmony_ci{
120662306a36Sopenharmony_ci	struct simple_attr *attr;
120762306a36Sopenharmony_ci
120862306a36Sopenharmony_ci	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
120962306a36Sopenharmony_ci	if (!attr)
121062306a36Sopenharmony_ci		return -ENOMEM;
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	attr->get = get;
121362306a36Sopenharmony_ci	attr->set = set;
121462306a36Sopenharmony_ci	attr->data = inode->i_private;
121562306a36Sopenharmony_ci	attr->fmt = fmt;
121662306a36Sopenharmony_ci	mutex_init(&attr->mutex);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	file->private_data = attr;
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_ci	return nonseekable_open(inode, file);
122162306a36Sopenharmony_ci}
122262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(simple_attr_open);
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ciint simple_attr_release(struct inode *inode, struct file *file)
122562306a36Sopenharmony_ci{
122662306a36Sopenharmony_ci	kfree(file->private_data);
122762306a36Sopenharmony_ci	return 0;
122862306a36Sopenharmony_ci}
122962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(simple_attr_release);	/* GPL-only?  This?  Really? */
123062306a36Sopenharmony_ci
123162306a36Sopenharmony_ci/* read from the buffer that is filled with the get function */
123262306a36Sopenharmony_cissize_t simple_attr_read(struct file *file, char __user *buf,
123362306a36Sopenharmony_ci			 size_t len, loff_t *ppos)
123462306a36Sopenharmony_ci{
123562306a36Sopenharmony_ci	struct simple_attr *attr;
123662306a36Sopenharmony_ci	size_t size;
123762306a36Sopenharmony_ci	ssize_t ret;
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	attr = file->private_data;
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci	if (!attr->get)
124262306a36Sopenharmony_ci		return -EACCES;
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	ret = mutex_lock_interruptible(&attr->mutex);
124562306a36Sopenharmony_ci	if (ret)
124662306a36Sopenharmony_ci		return ret;
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci	if (*ppos && attr->get_buf[0]) {
124962306a36Sopenharmony_ci		/* continued read */
125062306a36Sopenharmony_ci		size = strlen(attr->get_buf);
125162306a36Sopenharmony_ci	} else {
125262306a36Sopenharmony_ci		/* first read */
125362306a36Sopenharmony_ci		u64 val;
125462306a36Sopenharmony_ci		ret = attr->get(attr->data, &val);
125562306a36Sopenharmony_ci		if (ret)
125662306a36Sopenharmony_ci			goto out;
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci		size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
125962306a36Sopenharmony_ci				 attr->fmt, (unsigned long long)val);
126062306a36Sopenharmony_ci	}
126162306a36Sopenharmony_ci
126262306a36Sopenharmony_ci	ret = simple_read_from_buffer(buf, len, ppos, attr->get_buf, size);
126362306a36Sopenharmony_ciout:
126462306a36Sopenharmony_ci	mutex_unlock(&attr->mutex);
126562306a36Sopenharmony_ci	return ret;
126662306a36Sopenharmony_ci}
126762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(simple_attr_read);
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci/* interpret the buffer as a number to call the set function with */
127062306a36Sopenharmony_cistatic ssize_t simple_attr_write_xsigned(struct file *file, const char __user *buf,
127162306a36Sopenharmony_ci			  size_t len, loff_t *ppos, bool is_signed)
127262306a36Sopenharmony_ci{
127362306a36Sopenharmony_ci	struct simple_attr *attr;
127462306a36Sopenharmony_ci	unsigned long long val;
127562306a36Sopenharmony_ci	size_t size;
127662306a36Sopenharmony_ci	ssize_t ret;
127762306a36Sopenharmony_ci
127862306a36Sopenharmony_ci	attr = file->private_data;
127962306a36Sopenharmony_ci	if (!attr->set)
128062306a36Sopenharmony_ci		return -EACCES;
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci	ret = mutex_lock_interruptible(&attr->mutex);
128362306a36Sopenharmony_ci	if (ret)
128462306a36Sopenharmony_ci		return ret;
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_ci	ret = -EFAULT;
128762306a36Sopenharmony_ci	size = min(sizeof(attr->set_buf) - 1, len);
128862306a36Sopenharmony_ci	if (copy_from_user(attr->set_buf, buf, size))
128962306a36Sopenharmony_ci		goto out;
129062306a36Sopenharmony_ci
129162306a36Sopenharmony_ci	attr->set_buf[size] = '\0';
129262306a36Sopenharmony_ci	if (is_signed)
129362306a36Sopenharmony_ci		ret = kstrtoll(attr->set_buf, 0, &val);
129462306a36Sopenharmony_ci	else
129562306a36Sopenharmony_ci		ret = kstrtoull(attr->set_buf, 0, &val);
129662306a36Sopenharmony_ci	if (ret)
129762306a36Sopenharmony_ci		goto out;
129862306a36Sopenharmony_ci	ret = attr->set(attr->data, val);
129962306a36Sopenharmony_ci	if (ret == 0)
130062306a36Sopenharmony_ci		ret = len; /* on success, claim we got the whole input */
130162306a36Sopenharmony_ciout:
130262306a36Sopenharmony_ci	mutex_unlock(&attr->mutex);
130362306a36Sopenharmony_ci	return ret;
130462306a36Sopenharmony_ci}
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_cissize_t simple_attr_write(struct file *file, const char __user *buf,
130762306a36Sopenharmony_ci			  size_t len, loff_t *ppos)
130862306a36Sopenharmony_ci{
130962306a36Sopenharmony_ci	return simple_attr_write_xsigned(file, buf, len, ppos, false);
131062306a36Sopenharmony_ci}
131162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(simple_attr_write);
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_cissize_t simple_attr_write_signed(struct file *file, const char __user *buf,
131462306a36Sopenharmony_ci			  size_t len, loff_t *ppos)
131562306a36Sopenharmony_ci{
131662306a36Sopenharmony_ci	return simple_attr_write_xsigned(file, buf, len, ppos, true);
131762306a36Sopenharmony_ci}
131862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(simple_attr_write_signed);
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_ci/**
132162306a36Sopenharmony_ci * generic_fh_to_dentry - generic helper for the fh_to_dentry export operation
132262306a36Sopenharmony_ci * @sb:		filesystem to do the file handle conversion on
132362306a36Sopenharmony_ci * @fid:	file handle to convert
132462306a36Sopenharmony_ci * @fh_len:	length of the file handle in bytes
132562306a36Sopenharmony_ci * @fh_type:	type of file handle
132662306a36Sopenharmony_ci * @get_inode:	filesystem callback to retrieve inode
132762306a36Sopenharmony_ci *
132862306a36Sopenharmony_ci * This function decodes @fid as long as it has one of the well-known
132962306a36Sopenharmony_ci * Linux filehandle types and calls @get_inode on it to retrieve the
133062306a36Sopenharmony_ci * inode for the object specified in the file handle.
133162306a36Sopenharmony_ci */
133262306a36Sopenharmony_cistruct dentry *generic_fh_to_dentry(struct super_block *sb, struct fid *fid,
133362306a36Sopenharmony_ci		int fh_len, int fh_type, struct inode *(*get_inode)
133462306a36Sopenharmony_ci			(struct super_block *sb, u64 ino, u32 gen))
133562306a36Sopenharmony_ci{
133662306a36Sopenharmony_ci	struct inode *inode = NULL;
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	if (fh_len < 2)
133962306a36Sopenharmony_ci		return NULL;
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ci	switch (fh_type) {
134262306a36Sopenharmony_ci	case FILEID_INO32_GEN:
134362306a36Sopenharmony_ci	case FILEID_INO32_GEN_PARENT:
134462306a36Sopenharmony_ci		inode = get_inode(sb, fid->i32.ino, fid->i32.gen);
134562306a36Sopenharmony_ci		break;
134662306a36Sopenharmony_ci	}
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	return d_obtain_alias(inode);
134962306a36Sopenharmony_ci}
135062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(generic_fh_to_dentry);
135162306a36Sopenharmony_ci
135262306a36Sopenharmony_ci/**
135362306a36Sopenharmony_ci * generic_fh_to_parent - generic helper for the fh_to_parent export operation
135462306a36Sopenharmony_ci * @sb:		filesystem to do the file handle conversion on
135562306a36Sopenharmony_ci * @fid:	file handle to convert
135662306a36Sopenharmony_ci * @fh_len:	length of the file handle in bytes
135762306a36Sopenharmony_ci * @fh_type:	type of file handle
135862306a36Sopenharmony_ci * @get_inode:	filesystem callback to retrieve inode
135962306a36Sopenharmony_ci *
136062306a36Sopenharmony_ci * This function decodes @fid as long as it has one of the well-known
136162306a36Sopenharmony_ci * Linux filehandle types and calls @get_inode on it to retrieve the
136262306a36Sopenharmony_ci * inode for the _parent_ object specified in the file handle if it
136362306a36Sopenharmony_ci * is specified in the file handle, or NULL otherwise.
136462306a36Sopenharmony_ci */
136562306a36Sopenharmony_cistruct dentry *generic_fh_to_parent(struct super_block *sb, struct fid *fid,
136662306a36Sopenharmony_ci		int fh_len, int fh_type, struct inode *(*get_inode)
136762306a36Sopenharmony_ci			(struct super_block *sb, u64 ino, u32 gen))
136862306a36Sopenharmony_ci{
136962306a36Sopenharmony_ci	struct inode *inode = NULL;
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	if (fh_len <= 2)
137262306a36Sopenharmony_ci		return NULL;
137362306a36Sopenharmony_ci
137462306a36Sopenharmony_ci	switch (fh_type) {
137562306a36Sopenharmony_ci	case FILEID_INO32_GEN_PARENT:
137662306a36Sopenharmony_ci		inode = get_inode(sb, fid->i32.parent_ino,
137762306a36Sopenharmony_ci				  (fh_len > 3 ? fid->i32.parent_gen : 0));
137862306a36Sopenharmony_ci		break;
137962306a36Sopenharmony_ci	}
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci	return d_obtain_alias(inode);
138262306a36Sopenharmony_ci}
138362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(generic_fh_to_parent);
138462306a36Sopenharmony_ci
138562306a36Sopenharmony_ci/**
138662306a36Sopenharmony_ci * __generic_file_fsync - generic fsync implementation for simple filesystems
138762306a36Sopenharmony_ci *
138862306a36Sopenharmony_ci * @file:	file to synchronize
138962306a36Sopenharmony_ci * @start:	start offset in bytes
139062306a36Sopenharmony_ci * @end:	end offset in bytes (inclusive)
139162306a36Sopenharmony_ci * @datasync:	only synchronize essential metadata if true
139262306a36Sopenharmony_ci *
139362306a36Sopenharmony_ci * This is a generic implementation of the fsync method for simple
139462306a36Sopenharmony_ci * filesystems which track all non-inode metadata in the buffers list
139562306a36Sopenharmony_ci * hanging off the address_space structure.
139662306a36Sopenharmony_ci */
139762306a36Sopenharmony_ciint __generic_file_fsync(struct file *file, loff_t start, loff_t end,
139862306a36Sopenharmony_ci				 int datasync)
139962306a36Sopenharmony_ci{
140062306a36Sopenharmony_ci	struct inode *inode = file->f_mapping->host;
140162306a36Sopenharmony_ci	int err;
140262306a36Sopenharmony_ci	int ret;
140362306a36Sopenharmony_ci
140462306a36Sopenharmony_ci	err = file_write_and_wait_range(file, start, end);
140562306a36Sopenharmony_ci	if (err)
140662306a36Sopenharmony_ci		return err;
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci	inode_lock(inode);
140962306a36Sopenharmony_ci	ret = sync_mapping_buffers(inode->i_mapping);
141062306a36Sopenharmony_ci	if (!(inode->i_state & I_DIRTY_ALL))
141162306a36Sopenharmony_ci		goto out;
141262306a36Sopenharmony_ci	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
141362306a36Sopenharmony_ci		goto out;
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	err = sync_inode_metadata(inode, 1);
141662306a36Sopenharmony_ci	if (ret == 0)
141762306a36Sopenharmony_ci		ret = err;
141862306a36Sopenharmony_ci
141962306a36Sopenharmony_ciout:
142062306a36Sopenharmony_ci	inode_unlock(inode);
142162306a36Sopenharmony_ci	/* check and advance again to catch errors after syncing out buffers */
142262306a36Sopenharmony_ci	err = file_check_and_advance_wb_err(file);
142362306a36Sopenharmony_ci	if (ret == 0)
142462306a36Sopenharmony_ci		ret = err;
142562306a36Sopenharmony_ci	return ret;
142662306a36Sopenharmony_ci}
142762306a36Sopenharmony_ciEXPORT_SYMBOL(__generic_file_fsync);
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci/**
143062306a36Sopenharmony_ci * generic_file_fsync - generic fsync implementation for simple filesystems
143162306a36Sopenharmony_ci *			with flush
143262306a36Sopenharmony_ci * @file:	file to synchronize
143362306a36Sopenharmony_ci * @start:	start offset in bytes
143462306a36Sopenharmony_ci * @end:	end offset in bytes (inclusive)
143562306a36Sopenharmony_ci * @datasync:	only synchronize essential metadata if true
143662306a36Sopenharmony_ci *
143762306a36Sopenharmony_ci */
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_ciint generic_file_fsync(struct file *file, loff_t start, loff_t end,
144062306a36Sopenharmony_ci		       int datasync)
144162306a36Sopenharmony_ci{
144262306a36Sopenharmony_ci	struct inode *inode = file->f_mapping->host;
144362306a36Sopenharmony_ci	int err;
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci	err = __generic_file_fsync(file, start, end, datasync);
144662306a36Sopenharmony_ci	if (err)
144762306a36Sopenharmony_ci		return err;
144862306a36Sopenharmony_ci	return blkdev_issue_flush(inode->i_sb->s_bdev);
144962306a36Sopenharmony_ci}
145062306a36Sopenharmony_ciEXPORT_SYMBOL(generic_file_fsync);
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci/**
145362306a36Sopenharmony_ci * generic_check_addressable - Check addressability of file system
145462306a36Sopenharmony_ci * @blocksize_bits:	log of file system block size
145562306a36Sopenharmony_ci * @num_blocks:		number of blocks in file system
145662306a36Sopenharmony_ci *
145762306a36Sopenharmony_ci * Determine whether a file system with @num_blocks blocks (and a
145862306a36Sopenharmony_ci * block size of 2**@blocksize_bits) is addressable by the sector_t
145962306a36Sopenharmony_ci * and page cache of the system.  Return 0 if so and -EFBIG otherwise.
146062306a36Sopenharmony_ci */
146162306a36Sopenharmony_ciint generic_check_addressable(unsigned blocksize_bits, u64 num_blocks)
146262306a36Sopenharmony_ci{
146362306a36Sopenharmony_ci	u64 last_fs_block = num_blocks - 1;
146462306a36Sopenharmony_ci	u64 last_fs_page =
146562306a36Sopenharmony_ci		last_fs_block >> (PAGE_SHIFT - blocksize_bits);
146662306a36Sopenharmony_ci
146762306a36Sopenharmony_ci	if (unlikely(num_blocks == 0))
146862306a36Sopenharmony_ci		return 0;
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	if ((blocksize_bits < 9) || (blocksize_bits > PAGE_SHIFT))
147162306a36Sopenharmony_ci		return -EINVAL;
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ci	if ((last_fs_block > (sector_t)(~0ULL) >> (blocksize_bits - 9)) ||
147462306a36Sopenharmony_ci	    (last_fs_page > (pgoff_t)(~0ULL))) {
147562306a36Sopenharmony_ci		return -EFBIG;
147662306a36Sopenharmony_ci	}
147762306a36Sopenharmony_ci	return 0;
147862306a36Sopenharmony_ci}
147962306a36Sopenharmony_ciEXPORT_SYMBOL(generic_check_addressable);
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci/*
148262306a36Sopenharmony_ci * No-op implementation of ->fsync for in-memory filesystems.
148362306a36Sopenharmony_ci */
148462306a36Sopenharmony_ciint noop_fsync(struct file *file, loff_t start, loff_t end, int datasync)
148562306a36Sopenharmony_ci{
148662306a36Sopenharmony_ci	return 0;
148762306a36Sopenharmony_ci}
148862306a36Sopenharmony_ciEXPORT_SYMBOL(noop_fsync);
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_cissize_t noop_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
149162306a36Sopenharmony_ci{
149262306a36Sopenharmony_ci	/*
149362306a36Sopenharmony_ci	 * iomap based filesystems support direct I/O without need for
149462306a36Sopenharmony_ci	 * this callback. However, it still needs to be set in
149562306a36Sopenharmony_ci	 * inode->a_ops so that open/fcntl know that direct I/O is
149662306a36Sopenharmony_ci	 * generally supported.
149762306a36Sopenharmony_ci	 */
149862306a36Sopenharmony_ci	return -EINVAL;
149962306a36Sopenharmony_ci}
150062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(noop_direct_IO);
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci/* Because kfree isn't assignment-compatible with void(void*) ;-/ */
150362306a36Sopenharmony_civoid kfree_link(void *p)
150462306a36Sopenharmony_ci{
150562306a36Sopenharmony_ci	kfree(p);
150662306a36Sopenharmony_ci}
150762306a36Sopenharmony_ciEXPORT_SYMBOL(kfree_link);
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_cistruct inode *alloc_anon_inode(struct super_block *s)
151062306a36Sopenharmony_ci{
151162306a36Sopenharmony_ci	static const struct address_space_operations anon_aops = {
151262306a36Sopenharmony_ci		.dirty_folio	= noop_dirty_folio,
151362306a36Sopenharmony_ci	};
151462306a36Sopenharmony_ci	struct inode *inode = new_inode_pseudo(s);
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ci	if (!inode)
151762306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_ci	inode->i_ino = get_next_ino();
152062306a36Sopenharmony_ci	inode->i_mapping->a_ops = &anon_aops;
152162306a36Sopenharmony_ci
152262306a36Sopenharmony_ci	/*
152362306a36Sopenharmony_ci	 * Mark the inode dirty from the very beginning,
152462306a36Sopenharmony_ci	 * that way it will never be moved to the dirty
152562306a36Sopenharmony_ci	 * list because mark_inode_dirty() will think
152662306a36Sopenharmony_ci	 * that it already _is_ on the dirty list.
152762306a36Sopenharmony_ci	 */
152862306a36Sopenharmony_ci	inode->i_state = I_DIRTY;
152962306a36Sopenharmony_ci	inode->i_mode = S_IRUSR | S_IWUSR;
153062306a36Sopenharmony_ci	inode->i_uid = current_fsuid();
153162306a36Sopenharmony_ci	inode->i_gid = current_fsgid();
153262306a36Sopenharmony_ci	inode->i_flags |= S_PRIVATE;
153362306a36Sopenharmony_ci	simple_inode_init_ts(inode);
153462306a36Sopenharmony_ci	return inode;
153562306a36Sopenharmony_ci}
153662306a36Sopenharmony_ciEXPORT_SYMBOL(alloc_anon_inode);
153762306a36Sopenharmony_ci
153862306a36Sopenharmony_ci/**
153962306a36Sopenharmony_ci * simple_nosetlease - generic helper for prohibiting leases
154062306a36Sopenharmony_ci * @filp: file pointer
154162306a36Sopenharmony_ci * @arg: type of lease to obtain
154262306a36Sopenharmony_ci * @flp: new lease supplied for insertion
154362306a36Sopenharmony_ci * @priv: private data for lm_setup operation
154462306a36Sopenharmony_ci *
154562306a36Sopenharmony_ci * Generic helper for filesystems that do not wish to allow leases to be set.
154662306a36Sopenharmony_ci * All arguments are ignored and it just returns -EINVAL.
154762306a36Sopenharmony_ci */
154862306a36Sopenharmony_ciint
154962306a36Sopenharmony_cisimple_nosetlease(struct file *filp, int arg, struct file_lock **flp,
155062306a36Sopenharmony_ci		  void **priv)
155162306a36Sopenharmony_ci{
155262306a36Sopenharmony_ci	return -EINVAL;
155362306a36Sopenharmony_ci}
155462306a36Sopenharmony_ciEXPORT_SYMBOL(simple_nosetlease);
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci/**
155762306a36Sopenharmony_ci * simple_get_link - generic helper to get the target of "fast" symlinks
155862306a36Sopenharmony_ci * @dentry: not used here
155962306a36Sopenharmony_ci * @inode: the symlink inode
156062306a36Sopenharmony_ci * @done: not used here
156162306a36Sopenharmony_ci *
156262306a36Sopenharmony_ci * Generic helper for filesystems to use for symlink inodes where a pointer to
156362306a36Sopenharmony_ci * the symlink target is stored in ->i_link.  NOTE: this isn't normally called,
156462306a36Sopenharmony_ci * since as an optimization the path lookup code uses any non-NULL ->i_link
156562306a36Sopenharmony_ci * directly, without calling ->get_link().  But ->get_link() still must be set,
156662306a36Sopenharmony_ci * to mark the inode_operations as being for a symlink.
156762306a36Sopenharmony_ci *
156862306a36Sopenharmony_ci * Return: the symlink target
156962306a36Sopenharmony_ci */
157062306a36Sopenharmony_ciconst char *simple_get_link(struct dentry *dentry, struct inode *inode,
157162306a36Sopenharmony_ci			    struct delayed_call *done)
157262306a36Sopenharmony_ci{
157362306a36Sopenharmony_ci	return inode->i_link;
157462306a36Sopenharmony_ci}
157562306a36Sopenharmony_ciEXPORT_SYMBOL(simple_get_link);
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_ciconst struct inode_operations simple_symlink_inode_operations = {
157862306a36Sopenharmony_ci	.get_link = simple_get_link,
157962306a36Sopenharmony_ci};
158062306a36Sopenharmony_ciEXPORT_SYMBOL(simple_symlink_inode_operations);
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci/*
158362306a36Sopenharmony_ci * Operations for a permanently empty directory.
158462306a36Sopenharmony_ci */
158562306a36Sopenharmony_cistatic struct dentry *empty_dir_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
158662306a36Sopenharmony_ci{
158762306a36Sopenharmony_ci	return ERR_PTR(-ENOENT);
158862306a36Sopenharmony_ci}
158962306a36Sopenharmony_ci
159062306a36Sopenharmony_cistatic int empty_dir_getattr(struct mnt_idmap *idmap,
159162306a36Sopenharmony_ci			     const struct path *path, struct kstat *stat,
159262306a36Sopenharmony_ci			     u32 request_mask, unsigned int query_flags)
159362306a36Sopenharmony_ci{
159462306a36Sopenharmony_ci	struct inode *inode = d_inode(path->dentry);
159562306a36Sopenharmony_ci	generic_fillattr(&nop_mnt_idmap, request_mask, inode, stat);
159662306a36Sopenharmony_ci	return 0;
159762306a36Sopenharmony_ci}
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_cistatic int empty_dir_setattr(struct mnt_idmap *idmap,
160062306a36Sopenharmony_ci			     struct dentry *dentry, struct iattr *attr)
160162306a36Sopenharmony_ci{
160262306a36Sopenharmony_ci	return -EPERM;
160362306a36Sopenharmony_ci}
160462306a36Sopenharmony_ci
160562306a36Sopenharmony_cistatic ssize_t empty_dir_listxattr(struct dentry *dentry, char *list, size_t size)
160662306a36Sopenharmony_ci{
160762306a36Sopenharmony_ci	return -EOPNOTSUPP;
160862306a36Sopenharmony_ci}
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_cistatic const struct inode_operations empty_dir_inode_operations = {
161162306a36Sopenharmony_ci	.lookup		= empty_dir_lookup,
161262306a36Sopenharmony_ci	.permission	= generic_permission,
161362306a36Sopenharmony_ci	.setattr	= empty_dir_setattr,
161462306a36Sopenharmony_ci	.getattr	= empty_dir_getattr,
161562306a36Sopenharmony_ci	.listxattr	= empty_dir_listxattr,
161662306a36Sopenharmony_ci};
161762306a36Sopenharmony_ci
161862306a36Sopenharmony_cistatic loff_t empty_dir_llseek(struct file *file, loff_t offset, int whence)
161962306a36Sopenharmony_ci{
162062306a36Sopenharmony_ci	/* An empty directory has two entries . and .. at offsets 0 and 1 */
162162306a36Sopenharmony_ci	return generic_file_llseek_size(file, offset, whence, 2, 2);
162262306a36Sopenharmony_ci}
162362306a36Sopenharmony_ci
162462306a36Sopenharmony_cistatic int empty_dir_readdir(struct file *file, struct dir_context *ctx)
162562306a36Sopenharmony_ci{
162662306a36Sopenharmony_ci	dir_emit_dots(file, ctx);
162762306a36Sopenharmony_ci	return 0;
162862306a36Sopenharmony_ci}
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_cistatic const struct file_operations empty_dir_operations = {
163162306a36Sopenharmony_ci	.llseek		= empty_dir_llseek,
163262306a36Sopenharmony_ci	.read		= generic_read_dir,
163362306a36Sopenharmony_ci	.iterate_shared	= empty_dir_readdir,
163462306a36Sopenharmony_ci	.fsync		= noop_fsync,
163562306a36Sopenharmony_ci};
163662306a36Sopenharmony_ci
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_civoid make_empty_dir_inode(struct inode *inode)
163962306a36Sopenharmony_ci{
164062306a36Sopenharmony_ci	set_nlink(inode, 2);
164162306a36Sopenharmony_ci	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
164262306a36Sopenharmony_ci	inode->i_uid = GLOBAL_ROOT_UID;
164362306a36Sopenharmony_ci	inode->i_gid = GLOBAL_ROOT_GID;
164462306a36Sopenharmony_ci	inode->i_rdev = 0;
164562306a36Sopenharmony_ci	inode->i_size = 0;
164662306a36Sopenharmony_ci	inode->i_blkbits = PAGE_SHIFT;
164762306a36Sopenharmony_ci	inode->i_blocks = 0;
164862306a36Sopenharmony_ci
164962306a36Sopenharmony_ci	inode->i_op = &empty_dir_inode_operations;
165062306a36Sopenharmony_ci	inode->i_opflags &= ~IOP_XATTR;
165162306a36Sopenharmony_ci	inode->i_fop = &empty_dir_operations;
165262306a36Sopenharmony_ci}
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_cibool is_empty_dir_inode(struct inode *inode)
165562306a36Sopenharmony_ci{
165662306a36Sopenharmony_ci	return (inode->i_fop == &empty_dir_operations) &&
165762306a36Sopenharmony_ci		(inode->i_op == &empty_dir_inode_operations);
165862306a36Sopenharmony_ci}
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_UNICODE)
166162306a36Sopenharmony_ci/**
166262306a36Sopenharmony_ci * generic_ci_d_compare - generic d_compare implementation for casefolding filesystems
166362306a36Sopenharmony_ci * @dentry:	dentry whose name we are checking against
166462306a36Sopenharmony_ci * @len:	len of name of dentry
166562306a36Sopenharmony_ci * @str:	str pointer to name of dentry
166662306a36Sopenharmony_ci * @name:	Name to compare against
166762306a36Sopenharmony_ci *
166862306a36Sopenharmony_ci * Return: 0 if names match, 1 if mismatch, or -ERRNO
166962306a36Sopenharmony_ci */
167062306a36Sopenharmony_cistatic int generic_ci_d_compare(const struct dentry *dentry, unsigned int len,
167162306a36Sopenharmony_ci				const char *str, const struct qstr *name)
167262306a36Sopenharmony_ci{
167362306a36Sopenharmony_ci	const struct dentry *parent = READ_ONCE(dentry->d_parent);
167462306a36Sopenharmony_ci	const struct inode *dir = READ_ONCE(parent->d_inode);
167562306a36Sopenharmony_ci	const struct super_block *sb = dentry->d_sb;
167662306a36Sopenharmony_ci	const struct unicode_map *um = sb->s_encoding;
167762306a36Sopenharmony_ci	struct qstr qstr = QSTR_INIT(str, len);
167862306a36Sopenharmony_ci	char strbuf[DNAME_INLINE_LEN];
167962306a36Sopenharmony_ci	int ret;
168062306a36Sopenharmony_ci
168162306a36Sopenharmony_ci	if (!dir || !IS_CASEFOLDED(dir))
168262306a36Sopenharmony_ci		goto fallback;
168362306a36Sopenharmony_ci	/*
168462306a36Sopenharmony_ci	 * If the dentry name is stored in-line, then it may be concurrently
168562306a36Sopenharmony_ci	 * modified by a rename.  If this happens, the VFS will eventually retry
168662306a36Sopenharmony_ci	 * the lookup, so it doesn't matter what ->d_compare() returns.
168762306a36Sopenharmony_ci	 * However, it's unsafe to call utf8_strncasecmp() with an unstable
168862306a36Sopenharmony_ci	 * string.  Therefore, we have to copy the name into a temporary buffer.
168962306a36Sopenharmony_ci	 */
169062306a36Sopenharmony_ci	if (len <= DNAME_INLINE_LEN - 1) {
169162306a36Sopenharmony_ci		memcpy(strbuf, str, len);
169262306a36Sopenharmony_ci		strbuf[len] = 0;
169362306a36Sopenharmony_ci		qstr.name = strbuf;
169462306a36Sopenharmony_ci		/* prevent compiler from optimizing out the temporary buffer */
169562306a36Sopenharmony_ci		barrier();
169662306a36Sopenharmony_ci	}
169762306a36Sopenharmony_ci	ret = utf8_strncasecmp(um, name, &qstr);
169862306a36Sopenharmony_ci	if (ret >= 0)
169962306a36Sopenharmony_ci		return ret;
170062306a36Sopenharmony_ci
170162306a36Sopenharmony_ci	if (sb_has_strict_encoding(sb))
170262306a36Sopenharmony_ci		return -EINVAL;
170362306a36Sopenharmony_cifallback:
170462306a36Sopenharmony_ci	if (len != name->len)
170562306a36Sopenharmony_ci		return 1;
170662306a36Sopenharmony_ci	return !!memcmp(str, name->name, len);
170762306a36Sopenharmony_ci}
170862306a36Sopenharmony_ci
170962306a36Sopenharmony_ci/**
171062306a36Sopenharmony_ci * generic_ci_d_hash - generic d_hash implementation for casefolding filesystems
171162306a36Sopenharmony_ci * @dentry:	dentry of the parent directory
171262306a36Sopenharmony_ci * @str:	qstr of name whose hash we should fill in
171362306a36Sopenharmony_ci *
171462306a36Sopenharmony_ci * Return: 0 if hash was successful or unchanged, and -EINVAL on error
171562306a36Sopenharmony_ci */
171662306a36Sopenharmony_cistatic int generic_ci_d_hash(const struct dentry *dentry, struct qstr *str)
171762306a36Sopenharmony_ci{
171862306a36Sopenharmony_ci	const struct inode *dir = READ_ONCE(dentry->d_inode);
171962306a36Sopenharmony_ci	struct super_block *sb = dentry->d_sb;
172062306a36Sopenharmony_ci	const struct unicode_map *um = sb->s_encoding;
172162306a36Sopenharmony_ci	int ret = 0;
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci	if (!dir || !IS_CASEFOLDED(dir))
172462306a36Sopenharmony_ci		return 0;
172562306a36Sopenharmony_ci
172662306a36Sopenharmony_ci	ret = utf8_casefold_hash(um, dentry, str);
172762306a36Sopenharmony_ci	if (ret < 0 && sb_has_strict_encoding(sb))
172862306a36Sopenharmony_ci		return -EINVAL;
172962306a36Sopenharmony_ci	return 0;
173062306a36Sopenharmony_ci}
173162306a36Sopenharmony_ci
173262306a36Sopenharmony_cistatic const struct dentry_operations generic_ci_dentry_ops = {
173362306a36Sopenharmony_ci	.d_hash = generic_ci_d_hash,
173462306a36Sopenharmony_ci	.d_compare = generic_ci_d_compare,
173562306a36Sopenharmony_ci};
173662306a36Sopenharmony_ci#endif
173762306a36Sopenharmony_ci
173862306a36Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION
173962306a36Sopenharmony_cistatic const struct dentry_operations generic_encrypted_dentry_ops = {
174062306a36Sopenharmony_ci	.d_revalidate = fscrypt_d_revalidate,
174162306a36Sopenharmony_ci};
174262306a36Sopenharmony_ci#endif
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci#if defined(CONFIG_FS_ENCRYPTION) && IS_ENABLED(CONFIG_UNICODE)
174562306a36Sopenharmony_cistatic const struct dentry_operations generic_encrypted_ci_dentry_ops = {
174662306a36Sopenharmony_ci	.d_hash = generic_ci_d_hash,
174762306a36Sopenharmony_ci	.d_compare = generic_ci_d_compare,
174862306a36Sopenharmony_ci	.d_revalidate = fscrypt_d_revalidate,
174962306a36Sopenharmony_ci};
175062306a36Sopenharmony_ci#endif
175162306a36Sopenharmony_ci
175262306a36Sopenharmony_ci/**
175362306a36Sopenharmony_ci * generic_set_encrypted_ci_d_ops - helper for setting d_ops for given dentry
175462306a36Sopenharmony_ci * @dentry:	dentry to set ops on
175562306a36Sopenharmony_ci *
175662306a36Sopenharmony_ci * Casefolded directories need d_hash and d_compare set, so that the dentries
175762306a36Sopenharmony_ci * contained in them are handled case-insensitively.  Note that these operations
175862306a36Sopenharmony_ci * are needed on the parent directory rather than on the dentries in it, and
175962306a36Sopenharmony_ci * while the casefolding flag can be toggled on and off on an empty directory,
176062306a36Sopenharmony_ci * dentry_operations can't be changed later.  As a result, if the filesystem has
176162306a36Sopenharmony_ci * casefolding support enabled at all, we have to give all dentries the
176262306a36Sopenharmony_ci * casefolding operations even if their inode doesn't have the casefolding flag
176362306a36Sopenharmony_ci * currently (and thus the casefolding ops would be no-ops for now).
176462306a36Sopenharmony_ci *
176562306a36Sopenharmony_ci * Encryption works differently in that the only dentry operation it needs is
176662306a36Sopenharmony_ci * d_revalidate, which it only needs on dentries that have the no-key name flag.
176762306a36Sopenharmony_ci * The no-key flag can't be set "later", so we don't have to worry about that.
176862306a36Sopenharmony_ci *
176962306a36Sopenharmony_ci * Finally, to maximize compatibility with overlayfs (which isn't compatible
177062306a36Sopenharmony_ci * with certain dentry operations) and to avoid taking an unnecessary
177162306a36Sopenharmony_ci * performance hit, we use custom dentry_operations for each possible
177262306a36Sopenharmony_ci * combination rather than always installing all operations.
177362306a36Sopenharmony_ci */
177462306a36Sopenharmony_civoid generic_set_encrypted_ci_d_ops(struct dentry *dentry)
177562306a36Sopenharmony_ci{
177662306a36Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION
177762306a36Sopenharmony_ci	bool needs_encrypt_ops = dentry->d_flags & DCACHE_NOKEY_NAME;
177862306a36Sopenharmony_ci#endif
177962306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_UNICODE)
178062306a36Sopenharmony_ci	bool needs_ci_ops = dentry->d_sb->s_encoding;
178162306a36Sopenharmony_ci#endif
178262306a36Sopenharmony_ci#if defined(CONFIG_FS_ENCRYPTION) && IS_ENABLED(CONFIG_UNICODE)
178362306a36Sopenharmony_ci	if (needs_encrypt_ops && needs_ci_ops) {
178462306a36Sopenharmony_ci		d_set_d_op(dentry, &generic_encrypted_ci_dentry_ops);
178562306a36Sopenharmony_ci		return;
178662306a36Sopenharmony_ci	}
178762306a36Sopenharmony_ci#endif
178862306a36Sopenharmony_ci#ifdef CONFIG_FS_ENCRYPTION
178962306a36Sopenharmony_ci	if (needs_encrypt_ops) {
179062306a36Sopenharmony_ci		d_set_d_op(dentry, &generic_encrypted_dentry_ops);
179162306a36Sopenharmony_ci		return;
179262306a36Sopenharmony_ci	}
179362306a36Sopenharmony_ci#endif
179462306a36Sopenharmony_ci#if IS_ENABLED(CONFIG_UNICODE)
179562306a36Sopenharmony_ci	if (needs_ci_ops) {
179662306a36Sopenharmony_ci		d_set_d_op(dentry, &generic_ci_dentry_ops);
179762306a36Sopenharmony_ci		return;
179862306a36Sopenharmony_ci	}
179962306a36Sopenharmony_ci#endif
180062306a36Sopenharmony_ci}
180162306a36Sopenharmony_ciEXPORT_SYMBOL(generic_set_encrypted_ci_d_ops);
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci/**
180462306a36Sopenharmony_ci * inode_maybe_inc_iversion - increments i_version
180562306a36Sopenharmony_ci * @inode: inode with the i_version that should be updated
180662306a36Sopenharmony_ci * @force: increment the counter even if it's not necessary?
180762306a36Sopenharmony_ci *
180862306a36Sopenharmony_ci * Every time the inode is modified, the i_version field must be seen to have
180962306a36Sopenharmony_ci * changed by any observer.
181062306a36Sopenharmony_ci *
181162306a36Sopenharmony_ci * If "force" is set or the QUERIED flag is set, then ensure that we increment
181262306a36Sopenharmony_ci * the value, and clear the queried flag.
181362306a36Sopenharmony_ci *
181462306a36Sopenharmony_ci * In the common case where neither is set, then we can return "false" without
181562306a36Sopenharmony_ci * updating i_version.
181662306a36Sopenharmony_ci *
181762306a36Sopenharmony_ci * If this function returns false, and no other metadata has changed, then we
181862306a36Sopenharmony_ci * can avoid logging the metadata.
181962306a36Sopenharmony_ci */
182062306a36Sopenharmony_cibool inode_maybe_inc_iversion(struct inode *inode, bool force)
182162306a36Sopenharmony_ci{
182262306a36Sopenharmony_ci	u64 cur, new;
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci	/*
182562306a36Sopenharmony_ci	 * The i_version field is not strictly ordered with any other inode
182662306a36Sopenharmony_ci	 * information, but the legacy inode_inc_iversion code used a spinlock
182762306a36Sopenharmony_ci	 * to serialize increments.
182862306a36Sopenharmony_ci	 *
182962306a36Sopenharmony_ci	 * Here, we add full memory barriers to ensure that any de-facto
183062306a36Sopenharmony_ci	 * ordering with other info is preserved.
183162306a36Sopenharmony_ci	 *
183262306a36Sopenharmony_ci	 * This barrier pairs with the barrier in inode_query_iversion()
183362306a36Sopenharmony_ci	 */
183462306a36Sopenharmony_ci	smp_mb();
183562306a36Sopenharmony_ci	cur = inode_peek_iversion_raw(inode);
183662306a36Sopenharmony_ci	do {
183762306a36Sopenharmony_ci		/* If flag is clear then we needn't do anything */
183862306a36Sopenharmony_ci		if (!force && !(cur & I_VERSION_QUERIED))
183962306a36Sopenharmony_ci			return false;
184062306a36Sopenharmony_ci
184162306a36Sopenharmony_ci		/* Since lowest bit is flag, add 2 to avoid it */
184262306a36Sopenharmony_ci		new = (cur & ~I_VERSION_QUERIED) + I_VERSION_INCREMENT;
184362306a36Sopenharmony_ci	} while (!atomic64_try_cmpxchg(&inode->i_version, &cur, new));
184462306a36Sopenharmony_ci	return true;
184562306a36Sopenharmony_ci}
184662306a36Sopenharmony_ciEXPORT_SYMBOL(inode_maybe_inc_iversion);
184762306a36Sopenharmony_ci
184862306a36Sopenharmony_ci/**
184962306a36Sopenharmony_ci * inode_query_iversion - read i_version for later use
185062306a36Sopenharmony_ci * @inode: inode from which i_version should be read
185162306a36Sopenharmony_ci *
185262306a36Sopenharmony_ci * Read the inode i_version counter. This should be used by callers that wish
185362306a36Sopenharmony_ci * to store the returned i_version for later comparison. This will guarantee
185462306a36Sopenharmony_ci * that a later query of the i_version will result in a different value if
185562306a36Sopenharmony_ci * anything has changed.
185662306a36Sopenharmony_ci *
185762306a36Sopenharmony_ci * In this implementation, we fetch the current value, set the QUERIED flag and
185862306a36Sopenharmony_ci * then try to swap it into place with a cmpxchg, if it wasn't already set. If
185962306a36Sopenharmony_ci * that fails, we try again with the newly fetched value from the cmpxchg.
186062306a36Sopenharmony_ci */
186162306a36Sopenharmony_ciu64 inode_query_iversion(struct inode *inode)
186262306a36Sopenharmony_ci{
186362306a36Sopenharmony_ci	u64 cur, new;
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_ci	cur = inode_peek_iversion_raw(inode);
186662306a36Sopenharmony_ci	do {
186762306a36Sopenharmony_ci		/* If flag is already set, then no need to swap */
186862306a36Sopenharmony_ci		if (cur & I_VERSION_QUERIED) {
186962306a36Sopenharmony_ci			/*
187062306a36Sopenharmony_ci			 * This barrier (and the implicit barrier in the
187162306a36Sopenharmony_ci			 * cmpxchg below) pairs with the barrier in
187262306a36Sopenharmony_ci			 * inode_maybe_inc_iversion().
187362306a36Sopenharmony_ci			 */
187462306a36Sopenharmony_ci			smp_mb();
187562306a36Sopenharmony_ci			break;
187662306a36Sopenharmony_ci		}
187762306a36Sopenharmony_ci
187862306a36Sopenharmony_ci		new = cur | I_VERSION_QUERIED;
187962306a36Sopenharmony_ci	} while (!atomic64_try_cmpxchg(&inode->i_version, &cur, new));
188062306a36Sopenharmony_ci	return cur >> I_VERSION_QUERIED_SHIFT;
188162306a36Sopenharmony_ci}
188262306a36Sopenharmony_ciEXPORT_SYMBOL(inode_query_iversion);
188362306a36Sopenharmony_ci
188462306a36Sopenharmony_cissize_t direct_write_fallback(struct kiocb *iocb, struct iov_iter *iter,
188562306a36Sopenharmony_ci		ssize_t direct_written, ssize_t buffered_written)
188662306a36Sopenharmony_ci{
188762306a36Sopenharmony_ci	struct address_space *mapping = iocb->ki_filp->f_mapping;
188862306a36Sopenharmony_ci	loff_t pos = iocb->ki_pos - buffered_written;
188962306a36Sopenharmony_ci	loff_t end = iocb->ki_pos - 1;
189062306a36Sopenharmony_ci	int err;
189162306a36Sopenharmony_ci
189262306a36Sopenharmony_ci	/*
189362306a36Sopenharmony_ci	 * If the buffered write fallback returned an error, we want to return
189462306a36Sopenharmony_ci	 * the number of bytes which were written by direct I/O, or the error
189562306a36Sopenharmony_ci	 * code if that was zero.
189662306a36Sopenharmony_ci	 *
189762306a36Sopenharmony_ci	 * Note that this differs from normal direct-io semantics, which will
189862306a36Sopenharmony_ci	 * return -EFOO even if some bytes were written.
189962306a36Sopenharmony_ci	 */
190062306a36Sopenharmony_ci	if (unlikely(buffered_written < 0)) {
190162306a36Sopenharmony_ci		if (direct_written)
190262306a36Sopenharmony_ci			return direct_written;
190362306a36Sopenharmony_ci		return buffered_written;
190462306a36Sopenharmony_ci	}
190562306a36Sopenharmony_ci
190662306a36Sopenharmony_ci	/*
190762306a36Sopenharmony_ci	 * We need to ensure that the page cache pages are written to disk and
190862306a36Sopenharmony_ci	 * invalidated to preserve the expected O_DIRECT semantics.
190962306a36Sopenharmony_ci	 */
191062306a36Sopenharmony_ci	err = filemap_write_and_wait_range(mapping, pos, end);
191162306a36Sopenharmony_ci	if (err < 0) {
191262306a36Sopenharmony_ci		/*
191362306a36Sopenharmony_ci		 * We don't know how much we wrote, so just return the number of
191462306a36Sopenharmony_ci		 * bytes which were direct-written
191562306a36Sopenharmony_ci		 */
191662306a36Sopenharmony_ci		iocb->ki_pos -= buffered_written;
191762306a36Sopenharmony_ci		if (direct_written)
191862306a36Sopenharmony_ci			return direct_written;
191962306a36Sopenharmony_ci		return err;
192062306a36Sopenharmony_ci	}
192162306a36Sopenharmony_ci	invalidate_mapping_pages(mapping, pos >> PAGE_SHIFT, end >> PAGE_SHIFT);
192262306a36Sopenharmony_ci	return direct_written + buffered_written;
192362306a36Sopenharmony_ci}
192462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(direct_write_fallback);
192562306a36Sopenharmony_ci
192662306a36Sopenharmony_ci/**
192762306a36Sopenharmony_ci * simple_inode_init_ts - initialize the timestamps for a new inode
192862306a36Sopenharmony_ci * @inode: inode to be initialized
192962306a36Sopenharmony_ci *
193062306a36Sopenharmony_ci * When a new inode is created, most filesystems set the timestamps to the
193162306a36Sopenharmony_ci * current time. Add a helper to do this.
193262306a36Sopenharmony_ci */
193362306a36Sopenharmony_cistruct timespec64 simple_inode_init_ts(struct inode *inode)
193462306a36Sopenharmony_ci{
193562306a36Sopenharmony_ci	struct timespec64 ts = inode_set_ctime_current(inode);
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	inode_set_atime_to_ts(inode, ts);
193862306a36Sopenharmony_ci	inode_set_mtime_to_ts(inode, ts);
193962306a36Sopenharmony_ci	return ts;
194062306a36Sopenharmony_ci}
194162306a36Sopenharmony_ciEXPORT_SYMBOL(simple_inode_init_ts);
1942