162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  linux/fs/bad_inode.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Copyright (C) 1997, Stephen Tweedie
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  Provide stub functions for unreadable inodes
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *  Fabian Frederick : August 2003 - All file operations assigned to EIO
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/fs.h>
1362306a36Sopenharmony_ci#include <linux/export.h>
1462306a36Sopenharmony_ci#include <linux/stat.h>
1562306a36Sopenharmony_ci#include <linux/time.h>
1662306a36Sopenharmony_ci#include <linux/namei.h>
1762306a36Sopenharmony_ci#include <linux/poll.h>
1862306a36Sopenharmony_ci#include <linux/fiemap.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic int bad_file_open(struct inode *inode, struct file *filp)
2162306a36Sopenharmony_ci{
2262306a36Sopenharmony_ci	return -EIO;
2362306a36Sopenharmony_ci}
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic const struct file_operations bad_file_ops =
2662306a36Sopenharmony_ci{
2762306a36Sopenharmony_ci	.open		= bad_file_open,
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistatic int bad_inode_create(struct mnt_idmap *idmap,
3162306a36Sopenharmony_ci			    struct inode *dir, struct dentry *dentry,
3262306a36Sopenharmony_ci			    umode_t mode, bool excl)
3362306a36Sopenharmony_ci{
3462306a36Sopenharmony_ci	return -EIO;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic struct dentry *bad_inode_lookup(struct inode *dir,
3862306a36Sopenharmony_ci			struct dentry *dentry, unsigned int flags)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	return ERR_PTR(-EIO);
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic int bad_inode_link (struct dentry *old_dentry, struct inode *dir,
4462306a36Sopenharmony_ci		struct dentry *dentry)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	return -EIO;
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic int bad_inode_unlink(struct inode *dir, struct dentry *dentry)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	return -EIO;
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic int bad_inode_symlink(struct mnt_idmap *idmap,
5562306a36Sopenharmony_ci			     struct inode *dir, struct dentry *dentry,
5662306a36Sopenharmony_ci			     const char *symname)
5762306a36Sopenharmony_ci{
5862306a36Sopenharmony_ci	return -EIO;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_cistatic int bad_inode_mkdir(struct mnt_idmap *idmap, struct inode *dir,
6262306a36Sopenharmony_ci			   struct dentry *dentry, umode_t mode)
6362306a36Sopenharmony_ci{
6462306a36Sopenharmony_ci	return -EIO;
6562306a36Sopenharmony_ci}
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_cistatic int bad_inode_rmdir (struct inode *dir, struct dentry *dentry)
6862306a36Sopenharmony_ci{
6962306a36Sopenharmony_ci	return -EIO;
7062306a36Sopenharmony_ci}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistatic int bad_inode_mknod(struct mnt_idmap *idmap, struct inode *dir,
7362306a36Sopenharmony_ci			   struct dentry *dentry, umode_t mode, dev_t rdev)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	return -EIO;
7662306a36Sopenharmony_ci}
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_cistatic int bad_inode_rename2(struct mnt_idmap *idmap,
7962306a36Sopenharmony_ci			     struct inode *old_dir, struct dentry *old_dentry,
8062306a36Sopenharmony_ci			     struct inode *new_dir, struct dentry *new_dentry,
8162306a36Sopenharmony_ci			     unsigned int flags)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	return -EIO;
8462306a36Sopenharmony_ci}
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic int bad_inode_readlink(struct dentry *dentry, char __user *buffer,
8762306a36Sopenharmony_ci		int buflen)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	return -EIO;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic int bad_inode_permission(struct mnt_idmap *idmap,
9362306a36Sopenharmony_ci				struct inode *inode, int mask)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	return -EIO;
9662306a36Sopenharmony_ci}
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistatic int bad_inode_getattr(struct mnt_idmap *idmap,
9962306a36Sopenharmony_ci			     const struct path *path, struct kstat *stat,
10062306a36Sopenharmony_ci			     u32 request_mask, unsigned int query_flags)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	return -EIO;
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic int bad_inode_setattr(struct mnt_idmap *idmap,
10662306a36Sopenharmony_ci			     struct dentry *direntry, struct iattr *attrs)
10762306a36Sopenharmony_ci{
10862306a36Sopenharmony_ci	return -EIO;
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic ssize_t bad_inode_listxattr(struct dentry *dentry, char *buffer,
11262306a36Sopenharmony_ci			size_t buffer_size)
11362306a36Sopenharmony_ci{
11462306a36Sopenharmony_ci	return -EIO;
11562306a36Sopenharmony_ci}
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_cistatic const char *bad_inode_get_link(struct dentry *dentry,
11862306a36Sopenharmony_ci				      struct inode *inode,
11962306a36Sopenharmony_ci				      struct delayed_call *done)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	return ERR_PTR(-EIO);
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_cistatic struct posix_acl *bad_inode_get_acl(struct inode *inode, int type, bool rcu)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	return ERR_PTR(-EIO);
12762306a36Sopenharmony_ci}
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_cistatic int bad_inode_fiemap(struct inode *inode,
13062306a36Sopenharmony_ci			    struct fiemap_extent_info *fieinfo, u64 start,
13162306a36Sopenharmony_ci			    u64 len)
13262306a36Sopenharmony_ci{
13362306a36Sopenharmony_ci	return -EIO;
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic int bad_inode_update_time(struct inode *inode, int flags)
13762306a36Sopenharmony_ci{
13862306a36Sopenharmony_ci	return -EIO;
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic int bad_inode_atomic_open(struct inode *inode, struct dentry *dentry,
14262306a36Sopenharmony_ci				 struct file *file, unsigned int open_flag,
14362306a36Sopenharmony_ci				 umode_t create_mode)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	return -EIO;
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic int bad_inode_tmpfile(struct mnt_idmap *idmap,
14962306a36Sopenharmony_ci			     struct inode *inode, struct file *file,
15062306a36Sopenharmony_ci			     umode_t mode)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	return -EIO;
15362306a36Sopenharmony_ci}
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_cistatic int bad_inode_set_acl(struct mnt_idmap *idmap,
15662306a36Sopenharmony_ci			     struct dentry *dentry, struct posix_acl *acl,
15762306a36Sopenharmony_ci			     int type)
15862306a36Sopenharmony_ci{
15962306a36Sopenharmony_ci	return -EIO;
16062306a36Sopenharmony_ci}
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic const struct inode_operations bad_inode_ops =
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	.create		= bad_inode_create,
16562306a36Sopenharmony_ci	.lookup		= bad_inode_lookup,
16662306a36Sopenharmony_ci	.link		= bad_inode_link,
16762306a36Sopenharmony_ci	.unlink		= bad_inode_unlink,
16862306a36Sopenharmony_ci	.symlink	= bad_inode_symlink,
16962306a36Sopenharmony_ci	.mkdir		= bad_inode_mkdir,
17062306a36Sopenharmony_ci	.rmdir		= bad_inode_rmdir,
17162306a36Sopenharmony_ci	.mknod		= bad_inode_mknod,
17262306a36Sopenharmony_ci	.rename		= bad_inode_rename2,
17362306a36Sopenharmony_ci	.readlink	= bad_inode_readlink,
17462306a36Sopenharmony_ci	.permission	= bad_inode_permission,
17562306a36Sopenharmony_ci	.getattr	= bad_inode_getattr,
17662306a36Sopenharmony_ci	.setattr	= bad_inode_setattr,
17762306a36Sopenharmony_ci	.listxattr	= bad_inode_listxattr,
17862306a36Sopenharmony_ci	.get_link	= bad_inode_get_link,
17962306a36Sopenharmony_ci	.get_inode_acl	= bad_inode_get_acl,
18062306a36Sopenharmony_ci	.fiemap		= bad_inode_fiemap,
18162306a36Sopenharmony_ci	.update_time	= bad_inode_update_time,
18262306a36Sopenharmony_ci	.atomic_open	= bad_inode_atomic_open,
18362306a36Sopenharmony_ci	.tmpfile	= bad_inode_tmpfile,
18462306a36Sopenharmony_ci	.set_acl	= bad_inode_set_acl,
18562306a36Sopenharmony_ci};
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci/*
18962306a36Sopenharmony_ci * When a filesystem is unable to read an inode due to an I/O error in
19062306a36Sopenharmony_ci * its read_inode() function, it can call make_bad_inode() to return a
19162306a36Sopenharmony_ci * set of stubs which will return EIO errors as required.
19262306a36Sopenharmony_ci *
19362306a36Sopenharmony_ci * We only need to do limited initialisation: all other fields are
19462306a36Sopenharmony_ci * preinitialised to zero automatically.
19562306a36Sopenharmony_ci */
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci/**
19862306a36Sopenharmony_ci *	make_bad_inode - mark an inode bad due to an I/O error
19962306a36Sopenharmony_ci *	@inode: Inode to mark bad
20062306a36Sopenharmony_ci *
20162306a36Sopenharmony_ci *	When an inode cannot be read due to a media or remote network
20262306a36Sopenharmony_ci *	failure this function makes the inode "bad" and causes I/O operations
20362306a36Sopenharmony_ci *	on it to fail from this point on.
20462306a36Sopenharmony_ci */
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_civoid make_bad_inode(struct inode *inode)
20762306a36Sopenharmony_ci{
20862306a36Sopenharmony_ci	remove_inode_hash(inode);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	inode->i_mode = S_IFREG;
21162306a36Sopenharmony_ci	inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode);
21262306a36Sopenharmony_ci	inode->i_op = &bad_inode_ops;
21362306a36Sopenharmony_ci	inode->i_opflags &= ~IOP_XATTR;
21462306a36Sopenharmony_ci	inode->i_fop = &bad_file_ops;
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ciEXPORT_SYMBOL(make_bad_inode);
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci/*
21962306a36Sopenharmony_ci * This tests whether an inode has been flagged as bad. The test uses
22062306a36Sopenharmony_ci * &bad_inode_ops to cover the case of invalidated inodes as well as
22162306a36Sopenharmony_ci * those created by make_bad_inode() above.
22262306a36Sopenharmony_ci */
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci/**
22562306a36Sopenharmony_ci *	is_bad_inode - is an inode errored
22662306a36Sopenharmony_ci *	@inode: inode to test
22762306a36Sopenharmony_ci *
22862306a36Sopenharmony_ci *	Returns true if the inode in question has been marked as bad.
22962306a36Sopenharmony_ci */
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cibool is_bad_inode(struct inode *inode)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	return (inode->i_op == &bad_inode_ops);
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ciEXPORT_SYMBOL(is_bad_inode);
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci/**
23962306a36Sopenharmony_ci * iget_failed - Mark an under-construction inode as dead and release it
24062306a36Sopenharmony_ci * @inode: The inode to discard
24162306a36Sopenharmony_ci *
24262306a36Sopenharmony_ci * Mark an under-construction inode as dead and release it.
24362306a36Sopenharmony_ci */
24462306a36Sopenharmony_civoid iget_failed(struct inode *inode)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	make_bad_inode(inode);
24762306a36Sopenharmony_ci	unlock_new_inode(inode);
24862306a36Sopenharmony_ci	iput(inode);
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ciEXPORT_SYMBOL(iget_failed);
251