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