VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
2874c5fd28426 (Thomas Gleixner     2019-05-27 08:55:01 +0200    1) // SPDX-License-Identifier: GPL-2.0-or-later
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700    2) /* dir.c: AFS filesystem directory handling
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700    3)  *
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100    4)  * Copyright (C) 2002, 2018 Red Hat, Inc. All Rights Reserved.
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700    5)  * Written by David Howells (dhowells@redhat.com)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700    6)  */
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700    7) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700    8) #include <linux/kernel.h>
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700    9) #include <linux/fs.h>
34286d6662308 (Nicholas Piggin     2011-01-07 17:49:57 +1100   10) #include <linux/namei.h>
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   11) #include <linux/pagemap.h>
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   12) #include <linux/swap.h>
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700   13) #include <linux/ctype.h>
e8edc6e03a5c8 (Alexey Dobriyan     2007-05-21 01:22:52 +0400   14) #include <linux/sched.h>
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   15) #include <linux/task_io_accounting_ops.h>
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   16) #include "internal.h"
a58823ac45896 (David Howells       2019-05-09 15:16:10 +0100   17) #include "afs_fs.h"
4ea219a839bf8 (David Howells       2018-04-06 14:17:25 +0100   18) #include "xdr_fs.h"
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   19) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   20) static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
00cd8dd3bf95f (Al Viro             2012-06-10 17:13:09 -0400   21) 				 unsigned int flags);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   22) static int afs_dir_open(struct inode *inode, struct file *file);
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400   23) static int afs_readdir(struct file *file, struct dir_context *ctx);
0b728e1911cbe (Al Viro             2012-06-10 16:03:43 -0400   24) static int afs_d_revalidate(struct dentry *dentry, unsigned int flags);
fe15ce446beb3 (Nicholas Piggin     2011-01-07 17:49:23 +1100   25) static int afs_d_delete(const struct dentry *dentry);
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100   26) static void afs_d_iput(struct dentry *dentry, struct inode *inode);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   27) static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name, int nlen,
afefdbb28a0a2 (David Howells       2006-10-03 01:13:46 -0700   28) 				  loff_t fpos, u64 ino, unsigned dtype);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   29) static int afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen,
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   30) 			      loff_t fpos, u64 ino, unsigned dtype);
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100   31) static int afs_create(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100   32) 		      struct dentry *dentry, umode_t mode, bool excl);
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100   33) static int afs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100   34) 		     struct dentry *dentry, umode_t mode);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   35) static int afs_rmdir(struct inode *dir, struct dentry *dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   36) static int afs_unlink(struct inode *dir, struct dentry *dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   37) static int afs_link(struct dentry *from, struct inode *dir,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   38) 		    struct dentry *dentry);
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100   39) static int afs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100   40) 		       struct dentry *dentry, const char *content);
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100   41) static int afs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100   42) 		      struct dentry *old_dentry, struct inode *new_dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100   43) 		      struct dentry *new_dentry, unsigned int flags);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   44) static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   45) static void afs_dir_invalidatepage(struct page *page, unsigned int offset,
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   46) 				   unsigned int length);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   47) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   48) static int afs_dir_set_page_dirty(struct page *page)
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   49) {
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   50) 	BUG(); /* This should never happen. */
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   51) }
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   52) 
4b6f5d20b04dc (Arjan van de Ven    2006-03-28 01:56:42 -0800   53) const struct file_operations afs_dir_file_operations = {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   54) 	.open		= afs_dir_open,
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700   55) 	.release	= afs_release,
29884eff1f0f7 (Al Viro             2016-05-10 14:27:44 -0400   56) 	.iterate_shared	= afs_readdir,
e8d6c554126b8 (David Howells       2007-07-15 23:40:12 -0700   57) 	.lock		= afs_lock,
3222a3e55f402 (Christoph Hellwig   2008-09-03 21:53:01 +0200   58) 	.llseek		= generic_file_llseek,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   59) };
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   60) 
754661f143e70 (Arjan van de Ven    2007-02-12 00:55:38 -0800   61) const struct inode_operations afs_dir_inode_operations = {
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   62) 	.create		= afs_create,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   63) 	.lookup		= afs_lookup,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   64) 	.link		= afs_link,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   65) 	.unlink		= afs_unlink,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   66) 	.symlink	= afs_symlink,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   67) 	.mkdir		= afs_mkdir,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   68) 	.rmdir		= afs_rmdir,
2773bf00aeb9b (Miklos Szeredi      2016-09-27 11:03:58 +0200   69) 	.rename		= afs_rename,
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700   70) 	.permission	= afs_permission,
416351f28d2b3 (David Howells       2007-05-09 02:33:45 -0700   71) 	.getattr	= afs_getattr,
31143d5d515ec (David Howells       2007-05-09 02:33:46 -0700   72) 	.setattr	= afs_setattr,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   73) };
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   74) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   75) const struct address_space_operations afs_dir_aops = {
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   76) 	.set_page_dirty	= afs_dir_set_page_dirty,
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   77) 	.releasepage	= afs_dir_releasepage,
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   78) 	.invalidatepage	= afs_dir_invalidatepage,
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   79) };
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100   80) 
d61dcce2977d9 (Al Viro             2011-01-12 20:04:20 -0500   81) const struct dentry_operations afs_fs_dentry_operations = {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   82) 	.d_revalidate	= afs_d_revalidate,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   83) 	.d_delete	= afs_d_delete,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   84) 	.d_release	= afs_d_release,
d18610b0ce9eb (David Howells       2011-01-14 19:04:05 +0000   85) 	.d_automount	= afs_d_automount,
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100   86) 	.d_iput		= afs_d_iput,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   87) };
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700   88) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   89) struct afs_lookup_one_cookie {
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   90) 	struct dir_context	ctx;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   91) 	struct qstr		name;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   92) 	bool			found;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   93) 	struct afs_fid		fid;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   94) };
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   95) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700   96) struct afs_lookup_cookie {
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   97) 	struct dir_context	ctx;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   98) 	struct qstr		name;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100   99) 	bool			found;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  100) 	bool			one_only;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  101) 	unsigned short		nr_fids;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  102) 	struct afs_fid		fids[50];
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  103) };
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  104) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  105) /*
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  106)  * Drop the refs that we're holding on the pages we were reading into.  We've
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  107)  * got refs on the first nr_pages pages.
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  108)  */
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  109) static void afs_dir_read_cleanup(struct afs_read *req)
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  110) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  111) 	struct address_space *mapping = req->vnode->vfs_inode.i_mapping;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  112) 	struct page *page;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  113) 	pgoff_t last = req->nr_pages - 1;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  114) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  115) 	XA_STATE(xas, &mapping->i_pages, 0);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  116) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  117) 	if (unlikely(!req->nr_pages))
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  118) 		return;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  119) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  120) 	rcu_read_lock();
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  121) 	xas_for_each(&xas, page, last) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  122) 		if (xas_retry(&xas, page))
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  123) 			continue;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  124) 		BUG_ON(xa_is_value(page));
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  125) 		BUG_ON(PageCompound(page));
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  126) 		ASSERTCMP(page->mapping, ==, mapping);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  127) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  128) 		put_page(page);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  129) 	}
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  130) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  131) 	rcu_read_unlock();
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  132) }
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  133) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  134) /*
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  135)  * check that a directory page is valid
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  136)  */
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  137) static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page,
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  138) 			       loff_t i_size)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  139) {
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  140) 	struct afs_xdr_dir_page *dbuf;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  141) 	loff_t latter, off;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  142) 	int tmp, qty;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  143) 
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  144) 	/* Determine how many magic numbers there should be in this page, but
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  145) 	 * we must take care because the directory may change size under us.
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  146) 	 */
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  147) 	off = page_offset(page);
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  148) 	if (i_size <= off)
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  149) 		goto checked;
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  150) 
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  151) 	latter = i_size - off;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  152) 	if (latter >= PAGE_SIZE)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  153) 		qty = PAGE_SIZE;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  154) 	else
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  155) 		qty = latter;
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  156) 	qty /= sizeof(union afs_xdr_dir_block);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  157) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  158) 	/* check them */
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  159) 	dbuf = kmap_atomic(page);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  160) 	for (tmp = 0; tmp < qty; tmp++) {
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  161) 		if (dbuf->blocks[tmp].hdr.magic != AFS_DIR_MAGIC) {
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  162) 			printk("kAFS: %s(%lx): bad magic %d/%d is %04hx\n",
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  163) 			       __func__, dvnode->vfs_inode.i_ino, tmp, qty,
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  164) 			       ntohs(dbuf->blocks[tmp].hdr.magic));
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  165) 			trace_afs_dir_check_failed(dvnode, off, i_size);
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100  166) 			kunmap(page);
f51375cd9e1ad (David Howells       2018-10-20 00:57:57 +0100  167) 			trace_afs_file_error(dvnode, -EIO, afs_file_error_dir_bad_magic);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  168) 			goto error;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  169) 		}
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100  170) 
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100  171) 		/* Make sure each block is NUL terminated so we can reasonably
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100  172) 		 * use string functions on it.  The filenames in the page
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100  173) 		 * *should* be NUL-terminated anyway.
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100  174) 		 */
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100  175) 		((u8 *)&dbuf->blocks[tmp])[AFS_DIR_BLOCK_SIZE - 1] = 0;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  176) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  177) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  178) 	kunmap_atomic(dbuf);
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100  179) 
dab17c1add5c5 (David Howells       2017-11-02 15:27:52 +0000  180) checked:
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  181) 	afs_stat_v(dvnode, n_read_dir);
be5b82dbfec2a (Al Viro             2016-04-22 15:06:44 -0400  182) 	return true;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  183) 
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700  184) error:
be5b82dbfec2a (Al Viro             2016-04-22 15:06:44 -0400  185) 	return false;
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700  186) }
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  187) 
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  188) /*
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  189)  * Dump the contents of a directory.
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  190)  */
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  191) static void afs_dir_dump(struct afs_vnode *dvnode, struct afs_read *req)
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  192) {
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  193) 	struct afs_xdr_dir_page *dbuf;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  194) 	struct address_space *mapping = dvnode->vfs_inode.i_mapping;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  195) 	struct page *page;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  196) 	unsigned int i, qty = PAGE_SIZE / sizeof(union afs_xdr_dir_block);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  197) 	pgoff_t last = req->nr_pages - 1;
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  198) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  199) 	XA_STATE(xas, &mapping->i_pages, 0);
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  200) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  201) 	pr_warn("DIR %llx:%llx f=%llx l=%llx al=%llx\n",
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  202) 		dvnode->fid.vid, dvnode->fid.vnode,
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  203) 		req->file_size, req->len, req->actual_len);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  204) 	pr_warn("DIR %llx %x %zx %zx\n",
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  205) 		req->pos, req->nr_pages,
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  206) 		req->iter->iov_offset,  iov_iter_count(req->iter));
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  207) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  208) 	xas_for_each(&xas, page, last) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  209) 		if (xas_retry(&xas, page))
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  210) 			continue;
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  211) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  212) 		BUG_ON(PageCompound(page));
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  213) 		BUG_ON(page->mapping != mapping);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  214) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  215) 		dbuf = kmap_atomic(page);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  216) 		for (i = 0; i < qty; i++) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  217) 			union afs_xdr_dir_block *block = &dbuf->blocks[i];
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  218) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  219) 			pr_warn("[%02lx] %32phN\n", page->index * qty + i, block);
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  220) 		}
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  221) 		kunmap_atomic(dbuf);
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  222) 	}
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  223) }
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  224) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  225) /*
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  226)  * Check all the pages in a directory.  All the pages are held pinned.
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  227)  */
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  228) static int afs_dir_check(struct afs_vnode *dvnode, struct afs_read *req)
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  229) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  230) 	struct address_space *mapping = dvnode->vfs_inode.i_mapping;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  231) 	struct page *page;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  232) 	pgoff_t last = req->nr_pages - 1;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  233) 	int ret = 0;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  234) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  235) 	XA_STATE(xas, &mapping->i_pages, 0);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  236) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  237) 	if (unlikely(!req->nr_pages))
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  238) 		return 0;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  239) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  240) 	rcu_read_lock();
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  241) 	xas_for_each(&xas, page, last) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  242) 		if (xas_retry(&xas, page))
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  243) 			continue;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  244) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  245) 		BUG_ON(PageCompound(page));
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  246) 		BUG_ON(page->mapping != mapping);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  247) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  248) 		if (!afs_dir_check_page(dvnode, page, req->file_size)) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  249) 			afs_dir_dump(dvnode, req);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  250) 			ret = -EIO;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  251) 			break;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  252) 		}
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  253) 	}
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  254) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  255) 	rcu_read_unlock();
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  256) 	return ret;
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  257) }
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  258) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  259) /*
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  260)  * open an AFS directory file
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  261)  */
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  262) static int afs_dir_open(struct inode *inode, struct file *file)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  263) {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  264) 	_enter("{%lu}", inode->i_ino);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  265) 
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  266) 	BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  267) 	BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  268) 
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  269) 	if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  270) 		return -ENOENT;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  271) 
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700  272) 	return afs_open(inode, file);
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700  273) }
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  274) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  275) /*
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  276)  * Read the directory into the pagecache in one go, scrubbing the previous
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  277)  * contents.  The list of pages is returned, pinning them so that they don't
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  278)  * get reclaimed during the iteration.
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  279)  */
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  280) static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  281) 	__acquires(&dvnode->validate_lock)
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  282) {
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  283) 	struct afs_read *req;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  284) 	loff_t i_size;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  285) 	int nr_pages, i, n;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  286) 	int ret;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  287) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  288) 	_enter("");
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  289) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  290) 	req = kzalloc(sizeof(*req), GFP_KERNEL);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  291) 	if (!req)
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  292) 		return ERR_PTR(-ENOMEM);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  293) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  294) 	refcount_set(&req->usage, 1);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  295) 	req->vnode = dvnode;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  296) 	req->key = key_get(key);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  297) 	req->cleanup = afs_dir_read_cleanup;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  298) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  299) expand:
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  300) 	i_size = i_size_read(&dvnode->vfs_inode);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  301) 	if (i_size < 2048) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  302) 		ret = afs_bad(dvnode, afs_file_error_dir_small);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  303) 		goto error;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  304) 	}
f51375cd9e1ad (David Howells       2018-10-20 00:57:57 +0100  305) 	if (i_size > 2048 * 1024) {
f51375cd9e1ad (David Howells       2018-10-20 00:57:57 +0100  306) 		trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  307) 		ret = -EFBIG;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  308) 		goto error;
f51375cd9e1ad (David Howells       2018-10-20 00:57:57 +0100  309) 	}
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  310) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  311) 	_enter("%llu", i_size);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  312) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  313) 	nr_pages = (i_size + PAGE_SIZE - 1) / PAGE_SIZE;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  314) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  315) 	req->actual_len = i_size; /* May change */
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  316) 	req->len = nr_pages * PAGE_SIZE; /* We can ask for more than there is */
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  317) 	req->data_version = dvnode->status.data_version; /* May change */
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  318) 	iov_iter_xarray(&req->def_iter, READ, &dvnode->vfs_inode.i_mapping->i_pages,
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  319) 			0, i_size);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  320) 	req->iter = &req->def_iter;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  321) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  322) 	/* Fill in any gaps that we might find where the memory reclaimer has
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  323) 	 * been at work and pin all the pages.  If there are any gaps, we will
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  324) 	 * need to reread the entire directory contents.
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  325) 	 */
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  326) 	i = req->nr_pages;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  327) 	while (i < nr_pages) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  328) 		struct page *pages[8], *page;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  329) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  330) 		n = find_get_pages_contig(dvnode->vfs_inode.i_mapping, i,
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  331) 					  min_t(unsigned int, nr_pages - i,
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  332) 						ARRAY_SIZE(pages)),
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  333) 					  pages);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  334) 		_debug("find %u at %u/%u", n, i, nr_pages);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  335) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  336) 		if (n == 0) {
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  337) 			gfp_t gfp = dvnode->vfs_inode.i_mapping->gfp_mask;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  338) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  339) 			if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  340) 				afs_stat_v(dvnode, n_inval);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  341) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  342) 			ret = -ENOMEM;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  343) 			page = __page_cache_alloc(gfp);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  344) 			if (!page)
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  345) 				goto error;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  346) 			ret = add_to_page_cache_lru(page,
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  347) 						    dvnode->vfs_inode.i_mapping,
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  348) 						    i, gfp);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  349) 			if (ret < 0)
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  350) 				goto error;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  351) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  352) 			attach_page_private(page, (void *)1);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  353) 			unlock_page(page);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  354) 			req->nr_pages++;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  355) 			i++;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  356) 		} else {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  357) 			req->nr_pages += n;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  358) 			i += n;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  359) 		}
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  360) 	}
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  361) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  362) 	/* If we're going to reload, we need to lock all the pages to prevent
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  363) 	 * races.
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  364) 	 */
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  365) 	ret = -ERESTARTSYS;
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  366) 	if (down_read_killable(&dvnode->validate_lock) < 0)
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  367) 		goto error;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  368) 
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  369) 	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  370) 		goto success;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  371) 
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  372) 	up_read(&dvnode->validate_lock);
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  373) 	if (down_write_killable(&dvnode->validate_lock) < 0)
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  374) 		goto error;
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  375) 
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  376) 	if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
99987c560046e (David Howells       2019-04-25 14:26:51 +0100  377) 		trace_afs_reload_dir(dvnode);
c69bf479baa61 (David Howells       2020-02-06 14:22:27 +0000  378) 		ret = afs_fetch_data(dvnode, req);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  379) 		if (ret < 0)
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  380) 			goto error_unlock;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  381) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  382) 		task_io_account_read(PAGE_SIZE * req->nr_pages);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  383) 
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  384) 		if (req->len < req->file_size) {
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  385) 			/* The content has grown, so we need to expand the
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  386) 			 * buffer.
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  387) 			 */
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  388) 			up_write(&dvnode->validate_lock);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  389) 			goto expand;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  390) 		}
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  391) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  392) 		/* Validate the data we just read. */
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  393) 		ret = afs_dir_check(dvnode, req);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  394) 		if (ret < 0)
445b10289f766 (David Howells       2019-04-25 14:26:51 +0100  395) 			goto error_unlock;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  396) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  397) 		// TODO: Trim excess pages
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  398) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  399) 		set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  400) 	}
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  401) 
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  402) 	downgrade_write(&dvnode->validate_lock);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  403) success:
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  404) 	return req;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  405) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  406) error_unlock:
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  407) 	up_write(&dvnode->validate_lock);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  408) error:
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  409) 	afs_put_read(req);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  410) 	_leave(" = %d", ret);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  411) 	return ERR_PTR(ret);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  412) }
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  413) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  414) /*
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  415)  * deal with one block in an AFS directory
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  416)  */
f51375cd9e1ad (David Howells       2018-10-20 00:57:57 +0100  417) static int afs_dir_iterate_block(struct afs_vnode *dvnode,
f51375cd9e1ad (David Howells       2018-10-20 00:57:57 +0100  418) 				 struct dir_context *ctx,
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  419) 				 union afs_xdr_dir_block *block,
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  420) 				 unsigned blkoff)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  421) {
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  422) 	union afs_xdr_dirent *dire;
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  423) 	unsigned offset, next, curr, nr_slots;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  424) 	size_t nlen;
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  425) 	int tmp;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  426) 
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  427) 	_enter("%u,%x,%p,,",(unsigned)ctx->pos,blkoff,block);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  428) 
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  429) 	curr = (ctx->pos - blkoff) / sizeof(union afs_xdr_dirent);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  430) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  431) 	/* walk through the block, an entry at a time */
4ea219a839bf8 (David Howells       2018-04-06 14:17:25 +0100  432) 	for (offset = (blkoff == 0 ? AFS_DIR_RESV_BLOCKS0 : AFS_DIR_RESV_BLOCKS);
4ea219a839bf8 (David Howells       2018-04-06 14:17:25 +0100  433) 	     offset < AFS_DIR_SLOTS_PER_BLOCK;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  434) 	     offset = next
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  435) 	     ) {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  436) 		/* skip entries marked unused in the bitmap */
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  437) 		if (!(block->hdr.bitmap[offset / 8] &
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  438) 		      (1 << (offset % 8)))) {
5b5e0928f742c (Alexey Dobriyan     2017-02-27 14:30:02 -0800  439) 			_debug("ENT[%zu.%u]: unused",
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  440) 			       blkoff / sizeof(union afs_xdr_dir_block), offset);
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  441) 			next = offset + 1;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  442) 			if (offset >= curr)
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  443) 				ctx->pos = blkoff +
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  444) 					next * sizeof(union afs_xdr_dirent);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  445) 			continue;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  446) 		}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  447) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  448) 		/* got a valid entry */
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  449) 		dire = &block->dirents[offset];
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  450) 		nlen = strnlen(dire->u.name,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  451) 			       sizeof(*block) -
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  452) 			       offset * sizeof(union afs_xdr_dirent));
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  453) 		if (nlen > AFSNAMEMAX - 1) {
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  454) 			_debug("ENT[%zu]: name too long (len %u/%zu)",
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  455) 			       blkoff / sizeof(union afs_xdr_dir_block),
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  456) 			       offset, nlen);
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  457) 			return afs_bad(dvnode, afs_file_error_dir_name_too_long);
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  458) 		}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  459) 
5b5e0928f742c (Alexey Dobriyan     2017-02-27 14:30:02 -0800  460) 		_debug("ENT[%zu.%u]: %s %zu \"%s\"",
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  461) 		       blkoff / sizeof(union afs_xdr_dir_block), offset,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  462) 		       (offset < curr ? "skip" : "fill"),
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  463) 		       nlen, dire->u.name);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  464) 
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  465) 		nr_slots = afs_dir_calc_slots(nlen);
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  466) 		next = offset + nr_slots;
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  467) 		if (next > AFS_DIR_SLOTS_PER_BLOCK) {
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  468) 			_debug("ENT[%zu.%u]:"
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  469) 			       " %u extends beyond end dir block"
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  470) 			       " (len %zu)",
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  471) 			       blkoff / sizeof(union afs_xdr_dir_block),
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  472) 			       offset, next, nlen);
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  473) 			return afs_bad(dvnode, afs_file_error_dir_over_end);
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  474) 		}
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  475) 
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  476) 		/* Check that the name-extension dirents are all allocated */
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  477) 		for (tmp = 1; tmp < nr_slots; tmp++) {
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  478) 			unsigned int ix = offset + tmp;
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  479) 			if (!(block->hdr.bitmap[ix / 8] & (1 << (ix % 8)))) {
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  480) 				_debug("ENT[%zu.u]:"
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  481) 				       " %u unmarked extension (%u/%u)",
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  482) 				       blkoff / sizeof(union afs_xdr_dir_block),
366911cd762db (David Howells       2020-12-23 10:39:57 +0000  483) 				       offset, tmp, nr_slots);
f51375cd9e1ad (David Howells       2018-10-20 00:57:57 +0100  484) 				return afs_bad(dvnode, afs_file_error_dir_unmarked_ext);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  485) 			}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  486) 		}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  487) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  488) 		/* skip if starts before the current position */
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  489) 		if (offset < curr)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  490) 			continue;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  491) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  492) 		/* found the next entry */
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  493) 		if (!dir_emit(ctx, dire->u.name, nlen,
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  494) 			      ntohl(dire->u.vnode),
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  495) 			      (ctx->actor == afs_lookup_filldir ||
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  496) 			       ctx->actor == afs_lookup_one_filldir)?
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  497) 			      ntohl(dire->u.unique) : DT_UNKNOWN)) {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  498) 			_leave(" = 0 [full]");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  499) 			return 0;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  500) 		}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  501) 
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  502) 		ctx->pos = blkoff + next * sizeof(union afs_xdr_dirent);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  503) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  504) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  505) 	_leave(" = 1 [more]");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  506) 	return 1;
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700  507) }
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  508) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  509) /*
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  510)  * iterate through the data blob that lists the contents of an AFS directory
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  511)  */
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  512) static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  513) 			   struct key *key, afs_dataversion_t *_dir_version)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  514) {
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  515) 	struct afs_vnode *dvnode = AFS_FS_I(dir);
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  516) 	struct afs_xdr_dir_page *dbuf;
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  517) 	union afs_xdr_dir_block *dblock;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  518) 	struct afs_read *req;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  519) 	struct page *page;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  520) 	unsigned blkoff, limit;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  521) 	void __rcu **slot;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  522) 	int ret;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  523) 
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  524) 	_enter("{%lu},%u,,", dir->i_ino, (unsigned)ctx->pos);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  525) 
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  526) 	if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  527) 		_leave(" = -ESTALE");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  528) 		return -ESTALE;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  529) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  530) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  531) 	req = afs_read_dir(dvnode, key);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  532) 	if (IS_ERR(req))
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  533) 		return PTR_ERR(req);
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  534) 	*_dir_version = req->data_version;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  535) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  536) 	/* round the file position up to the next entry boundary */
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  537) 	ctx->pos += sizeof(union afs_xdr_dirent) - 1;
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  538) 	ctx->pos &= ~(sizeof(union afs_xdr_dirent) - 1);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  539) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  540) 	/* walk through the blocks in sequence */
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  541) 	ret = 0;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  542) 	while (ctx->pos < req->actual_len) {
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  543) 		blkoff = ctx->pos & ~(sizeof(union afs_xdr_dir_block) - 1);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  544) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  545) 		/* Fetch the appropriate page from the directory and re-add it
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  546) 		 * to the LRU.  We have all the pages pinned with an extra ref.
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  547) 		 */
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  548) 		rcu_read_lock();
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  549) 		page = NULL;
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  550) 		slot = radix_tree_lookup_slot(&dvnode->vfs_inode.i_mapping->i_pages,
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  551) 					      blkoff / PAGE_SIZE);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  552) 		if (slot)
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  553) 			page = radix_tree_deref_slot(slot);
c450846461f88 (David Howells       2020-02-06 14:22:28 +0000  554) 		rcu_read_unlock();
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  555) 		if (!page) {
f51375cd9e1ad (David Howells       2018-10-20 00:57:57 +0100  556) 			ret = afs_bad(dvnode, afs_file_error_dir_missing_page);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  557) 			break;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  558) 		}
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  559) 		mark_page_accessed(page);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  560) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  561) 		limit = blkoff & ~(PAGE_SIZE - 1);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  562) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  563) 		dbuf = kmap(page);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  564) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  565) 		/* deal with the individual blocks stashed on this page */
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  566) 		do {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  567) 			dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  568) 					       sizeof(union afs_xdr_dir_block)];
f51375cd9e1ad (David Howells       2018-10-20 00:57:57 +0100  569) 			ret = afs_dir_iterate_block(dvnode, ctx, dblock, blkoff);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  570) 			if (ret != 1) {
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  571) 				kunmap(page);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  572) 				goto out;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  573) 			}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  574) 
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  575) 			blkoff += sizeof(union afs_xdr_dir_block);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  576) 
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  577) 		} while (ctx->pos < dir->i_size && blkoff < limit);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  578) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  579) 		kunmap(page);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  580) 		ret = 0;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  581) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  582) 
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700  583) out:
b61f7dcf4eb26 (David Howells       2018-04-27 20:46:22 +0100  584) 	up_read(&dvnode->validate_lock);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100  585) 	afs_put_read(req);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  586) 	_leave(" = %d", ret);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  587) 	return ret;
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700  588) }
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  589) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  590) /*
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  591)  * read an AFS directory
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  592)  */
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  593) static int afs_readdir(struct file *file, struct dir_context *ctx)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  594) {
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  595) 	afs_dataversion_t dir_version;
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  596) 
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  597) 	return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file),
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  598) 			       &dir_version);
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700  599) }
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  600) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  601) /*
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  602)  * Search the directory for a single name
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  603)  * - if afs_dir_iterate_block() spots this function, it'll pass the FID
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  604)  *   uniquifier through dtype
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  605)  */
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  606) static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  607) 				  int nlen, loff_t fpos, u64 ino, unsigned dtype)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  608) {
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  609) 	struct afs_lookup_one_cookie *cookie =
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  610) 		container_of(ctx, struct afs_lookup_one_cookie, ctx);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  611) 
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  612) 	_enter("{%s,%u},%s,%u,,%llu,%u",
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  613) 	       cookie->name.name, cookie->name.len, name, nlen,
ba3e0e1accd8d (David S. Miller     2007-04-26 16:06:22 -0700  614) 	       (unsigned long long) ino, dtype);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  615) 
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  616) 	/* insanity checks first */
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  617) 	BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  618) 	BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  619) 
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  620) 	if (cookie->name.len != nlen ||
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  621) 	    memcmp(cookie->name.name, name, nlen) != 0) {
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  622) 		_leave(" = 0 [no]");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  623) 		return 0;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  624) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  625) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  626) 	cookie->fid.vnode = ino;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  627) 	cookie->fid.unique = dtype;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  628) 	cookie->found = 1;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  629) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  630) 	_leave(" = -1 [found]");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  631) 	return -1;
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700  632) }
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  633) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  634) /*
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  635)  * Do a lookup of a single name in a directory
260a980317dac (David Howells       2007-04-26 15:59:35 -0700  636)  * - just returns the FID the dentry name maps to if found
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  637)  */
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  638) static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  639) 			     struct afs_fid *fid, struct key *key,
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  640) 			     afs_dataversion_t *_dir_version)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  641) {
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  642) 	struct afs_super_info *as = dir->i_sb->s_fs_info;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  643) 	struct afs_lookup_one_cookie cookie = {
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  644) 		.ctx.actor = afs_lookup_one_filldir,
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  645) 		.name = dentry->d_name,
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  646) 		.fid.vid = as->volume->vid
1bbae9f818609 (Al Viro             2013-05-22 16:31:14 -0400  647) 	};
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  648) 	int ret;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  649) 
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400  650) 	_enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  651) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  652) 	/* search the directory */
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  653) 	ret = afs_dir_iterate(dir, &cookie.ctx, key, _dir_version);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  654) 	if (ret < 0) {
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  655) 		_leave(" = %d [iter]", ret);
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  656) 		return ret;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  657) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  658) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  659) 	ret = -ENOENT;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  660) 	if (!cookie.found) {
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  661) 		_leave(" = -ENOENT [not found]");
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  662) 		return -ENOENT;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  663) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700  664) 
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  665) 	*fid = cookie.fid;
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100  666) 	_leave(" = 0 { vn=%llu u=%u }", fid->vnode, fid->unique);
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  667) 	return 0;
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  668) }
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700  669) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  670) /*
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  671)  * search the directory for a name
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  672)  * - if afs_dir_iterate_block() spots this function, it'll pass the FID
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  673)  *   uniquifier through dtype
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  674)  */
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  675) static int afs_lookup_filldir(struct dir_context *ctx, const char *name,
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  676) 			      int nlen, loff_t fpos, u64 ino, unsigned dtype)
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  677) {
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  678) 	struct afs_lookup_cookie *cookie =
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  679) 		container_of(ctx, struct afs_lookup_cookie, ctx);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  680) 	int ret;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  681) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  682) 	_enter("{%s,%u},%s,%u,,%llu,%u",
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  683) 	       cookie->name.name, cookie->name.len, name, nlen,
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  684) 	       (unsigned long long) ino, dtype);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  685) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  686) 	/* insanity checks first */
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  687) 	BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
0031763698d19 (David Howells       2018-04-06 14:17:25 +0100  688) 	BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  689) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  690) 	if (cookie->found) {
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  691) 		if (cookie->nr_fids < 50) {
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  692) 			cookie->fids[cookie->nr_fids].vnode	= ino;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  693) 			cookie->fids[cookie->nr_fids].unique	= dtype;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  694) 			cookie->nr_fids++;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  695) 		}
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  696) 	} else if (cookie->name.len == nlen &&
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  697) 		   memcmp(cookie->name.name, name, nlen) == 0) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  698) 		cookie->fids[1].vnode	= ino;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  699) 		cookie->fids[1].unique	= dtype;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  700) 		cookie->found = 1;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  701) 		if (cookie->one_only)
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  702) 			return -1;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  703) 	}
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  704) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  705) 	ret = cookie->nr_fids >= 50 ? -1 : 0;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  706) 	_leave(" = %d", ret);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  707) 	return ret;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  708) }
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  709) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  710) /*
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  711)  * Deal with the result of a successful lookup operation.  Turn all the files
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  712)  * into inodes and save the first one - which is the one we actually want.
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  713)  */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  714) static void afs_do_lookup_success(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  715) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  716) 	struct afs_vnode_param *vp;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  717) 	struct afs_vnode *vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  718) 	struct inode *inode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  719) 	u32 abort_code;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  720) 	int i;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  721) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  722) 	_enter("");
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  723) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  724) 	for (i = 0; i < op->nr_files; i++) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  725) 		switch (i) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  726) 		case 0:
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  727) 			vp = &op->file[0];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  728) 			abort_code = vp->scb.status.abort_code;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  729) 			if (abort_code != 0) {
44767c353127c (David Howells       2020-06-16 00:25:56 +0100  730) 				op->ac.abort_code = abort_code;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  731) 				op->error = afs_abort_to_error(abort_code);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  732) 			}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  733) 			break;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  734) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  735) 		case 1:
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  736) 			vp = &op->file[1];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  737) 			break;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  738) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  739) 		default:
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  740) 			vp = &op->more_files[i - 2];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  741) 			break;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  742) 		}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  743) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  744) 		if (!vp->scb.have_status && !vp->scb.have_error)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  745) 			continue;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  746) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  747) 		_debug("do [%u]", i);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  748) 		if (vp->vnode) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  749) 			if (!test_bit(AFS_VNODE_UNSET, &vp->vnode->flags))
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  750) 				afs_vnode_commit_status(op, vp);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  751) 		} else if (vp->scb.status.abort_code == 0) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  752) 			inode = afs_iget(op, vp);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  753) 			if (!IS_ERR(inode)) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  754) 				vnode = AFS_FS_I(inode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  755) 				afs_cache_permit(vnode, op->key,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  756) 						 0 /* Assume vnode->cb_break is 0 */ +
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  757) 						 op->cb_v_break,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  758) 						 &vp->scb);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  759) 				vp->vnode = vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  760) 				vp->put_vnode = true;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  761) 			}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  762) 		} else {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  763) 			_debug("- abort %d %llx:%llx.%x",
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  764) 			       vp->scb.status.abort_code,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  765) 			       vp->fid.vid, vp->fid.vnode, vp->fid.unique);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  766) 		}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  767) 	}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  768) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  769) 	_leave("");
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  770) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  771) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  772) static const struct afs_operation_ops afs_inline_bulk_status_operation = {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  773) 	.issue_afs_rpc	= afs_fs_inline_bulk_status,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  774) 	.issue_yfs_rpc	= yfs_fs_inline_bulk_status,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  775) 	.success	= afs_do_lookup_success,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  776) };
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  777) 
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100  778) static const struct afs_operation_ops afs_lookup_fetch_status_operation = {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  779) 	.issue_afs_rpc	= afs_fs_fetch_status,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  780) 	.issue_yfs_rpc	= yfs_fs_fetch_status,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  781) 	.success	= afs_do_lookup_success,
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100  782) 	.aborted	= afs_check_for_remote_deletion,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  783) };
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  784) 
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  785) /*
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  786)  * See if we know that the server we expect to use doesn't support
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  787)  * FS.InlineBulkStatus.
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  788)  */
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  789) static bool afs_server_supports_ibulk(struct afs_vnode *dvnode)
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  790) {
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  791) 	struct afs_server_list *slist;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  792) 	struct afs_volume *volume = dvnode->volume;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  793) 	struct afs_server *server;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  794) 	bool ret = true;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  795) 	int i;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  796) 
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  797) 	if (!test_bit(AFS_VOLUME_MAYBE_NO_IBULK, &volume->flags))
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  798) 		return true;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  799) 
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  800) 	rcu_read_lock();
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  801) 	slist = rcu_dereference(volume->servers);
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  802) 
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  803) 	for (i = 0; i < slist->nr_servers; i++) {
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  804) 		server = slist->servers[i].server;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  805) 		if (server == dvnode->cb_server) {
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  806) 			if (test_bit(AFS_SERVER_FL_NO_IBULK, &server->flags))
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  807) 				ret = false;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  808) 			break;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  809) 		}
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  810) 	}
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  811) 
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  812) 	rcu_read_unlock();
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  813) 	return ret;
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  814) }
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  815) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  816) /*
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  817)  * Do a lookup in a directory.  We make use of bulk lookup to query a slew of
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  818)  * files in one go and create inodes for them.  The inode of the file we were
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  819)  * asked for is returned.
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  820)  */
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  821) static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  822) 				   struct key *key)
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  823) {
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  824) 	struct afs_lookup_cookie *cookie;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  825) 	struct afs_vnode_param *vp;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  826) 	struct afs_operation *op;
39db9815da489 (David Howells       2019-05-14 12:33:10 +0100  827) 	struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
39db9815da489 (David Howells       2019-05-14 12:33:10 +0100  828) 	struct inode *inode = NULL, *ti;
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  829) 	afs_dataversion_t data_version = READ_ONCE(dvnode->status.data_version);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  830) 	long ret;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  831) 	int i;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  832) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  833) 	_enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  834) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  835) 	cookie = kzalloc(sizeof(struct afs_lookup_cookie), GFP_KERNEL);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  836) 	if (!cookie)
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  837) 		return ERR_PTR(-ENOMEM);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  838) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  839) 	for (i = 0; i < ARRAY_SIZE(cookie->fids); i++)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  840) 		cookie->fids[i].vid = dvnode->fid.vid;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  841) 	cookie->ctx.actor = afs_lookup_filldir;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  842) 	cookie->name = dentry->d_name;
13fcc6356a945 (David Howells       2020-04-16 14:20:32 +0100  843) 	cookie->nr_fids = 2; /* slot 0 is saved for the fid we actually want
13fcc6356a945 (David Howells       2020-04-16 14:20:32 +0100  844) 			      * and slot 1 for the directory */
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  845) 
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  846) 	if (!afs_server_supports_ibulk(dvnode))
20325960f8750 (David Howells       2020-04-30 01:03:49 +0100  847) 		cookie->one_only = true;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  848) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  849) 	/* search the directory */
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  850) 	ret = afs_dir_iterate(dir, &cookie->ctx, key, &data_version);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  851) 	if (ret < 0)
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  852) 		goto out;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  853) 
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  854) 	dentry->d_fsdata = (void *)(unsigned long)data_version;
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100  855) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  856) 	ret = -ENOENT;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  857) 	if (!cookie->found)
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  858) 		goto out;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  859) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  860) 	/* Check to see if we already have an inode for the primary fid. */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  861) 	inode = ilookup5(dir->i_sb, cookie->fids[1].vnode,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  862) 			 afs_ilookup5_test_by_fid, &cookie->fids[1]);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  863) 	if (inode)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  864) 		goto out; /* We do */
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  865) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  866) 	/* Okay, we didn't find it.  We need to query the server - and whilst
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  867) 	 * we're doing that, we're going to attempt to look up a bunch of other
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  868) 	 * vnodes also.
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  869) 	 */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  870) 	op = afs_alloc_operation(NULL, dvnode->volume);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  871) 	if (IS_ERR(op)) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  872) 		ret = PTR_ERR(op);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  873) 		goto out;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  874) 	}
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  875) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  876) 	afs_op_set_vnode(op, 0, dvnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  877) 	afs_op_set_fid(op, 1, &cookie->fids[1]);
13fcc6356a945 (David Howells       2020-04-16 14:20:32 +0100  878) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  879) 	op->nr_files = cookie->nr_fids;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  880) 	_debug("nr_files %u", op->nr_files);
39db9815da489 (David Howells       2019-05-14 12:33:10 +0100  881) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  882) 	/* Need space for examining all the selected files */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  883) 	op->error = -ENOMEM;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  884) 	if (op->nr_files > 2) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  885) 		op->more_files = kvcalloc(op->nr_files - 2,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  886) 					  sizeof(struct afs_vnode_param),
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  887) 					  GFP_KERNEL);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  888) 		if (!op->more_files)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  889) 			goto out_op;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  890) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  891) 		for (i = 2; i < op->nr_files; i++) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  892) 			vp = &op->more_files[i - 2];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  893) 			vp->fid = cookie->fids[i];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  894) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  895) 			/* Find any inodes that already exist and get their
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  896) 			 * callback counters.
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  897) 			 */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  898) 			ti = ilookup5_nowait(dir->i_sb, vp->fid.vnode,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  899) 					     afs_ilookup5_test_by_fid, &vp->fid);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  900) 			if (!IS_ERR_OR_NULL(ti)) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  901) 				vnode = AFS_FS_I(ti);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  902) 				vp->dv_before = vnode->status.data_version;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  903) 				vp->cb_break_before = afs_calc_vnode_cb_break(vnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  904) 				vp->vnode = vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  905) 				vp->put_vnode = true;
a9e5c87ca7443 (David Howells       2020-11-22 13:13:45 +0000  906) 				vp->speculative = true; /* vnode not locked */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  907) 			}
39db9815da489 (David Howells       2019-05-14 12:33:10 +0100  908) 		}
39db9815da489 (David Howells       2019-05-14 12:33:10 +0100  909) 	}
39db9815da489 (David Howells       2019-05-14 12:33:10 +0100  910) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  911) 	/* Try FS.InlineBulkStatus first.  Abort codes for the individual
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  912) 	 * lookups contained therein are stored in the reply without aborting
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  913) 	 * the whole operation.
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  914) 	 */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  915) 	op->error = -ENOTSUPP;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  916) 	if (!cookie->one_only) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  917) 		op->ops = &afs_inline_bulk_status_operation;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  918) 		afs_begin_vnode_operation(op);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  919) 		afs_wait_for_operation(op);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  920) 	}
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  921) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  922) 	if (op->error == -ENOTSUPP) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  923) 		/* We could try FS.BulkStatus next, but this aborts the entire
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  924) 		 * op if any of the lookups fails - so, for the moment, revert
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  925) 		 * to FS.FetchStatus for op->file[1].
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  926) 		 */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  927) 		op->fetch_status.which = 1;
f8ea5c7bceeb6 (David Howells       2020-06-19 00:01:28 +0100  928) 		op->ops = &afs_lookup_fetch_status_operation;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  929) 		afs_begin_vnode_operation(op);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  930) 		afs_wait_for_operation(op);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  931) 	}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  932) 	inode = ERR_PTR(op->error);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  933) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  934) out_op:
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  935) 	if (op->error == 0) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  936) 		inode = &op->file[1].vnode->vfs_inode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  937) 		op->file[1].vnode = NULL;
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  938) 	}
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  939) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  940) 	if (op->file[0].scb.have_status)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  941) 		dentry->d_fsdata = (void *)(unsigned long)op->file[0].scb.status.data_version;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  942) 	else
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  943) 		dentry->d_fsdata = (void *)(unsigned long)op->file[0].dv_before;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  944) 	ret = afs_put_operation(op);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  945) out:
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  946) 	kfree(cookie);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  947) 	_leave("");
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100  948) 	return inode ?: ERR_PTR(ret);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  949) }
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100  950) 
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  951) /*
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  952)  * Look up an entry in a directory with @sys substitution.
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  953)  */
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  954) static struct dentry *afs_lookup_atsys(struct inode *dir, struct dentry *dentry,
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  955) 				       struct key *key)
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  956) {
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  957) 	struct afs_sysnames *subs;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  958) 	struct afs_net *net = afs_i2net(dir);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  959) 	struct dentry *ret;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  960) 	char *buf, *p, *name;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  961) 	int len, i;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  962) 
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  963) 	_enter("");
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  964) 
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  965) 	ret = ERR_PTR(-ENOMEM);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  966) 	p = buf = kmalloc(AFSNAMEMAX, GFP_KERNEL);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  967) 	if (!buf)
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  968) 		goto out_p;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  969) 	if (dentry->d_name.len > 4) {
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  970) 		memcpy(p, dentry->d_name.name, dentry->d_name.len - 4);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  971) 		p += dentry->d_name.len - 4;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  972) 	}
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  973) 
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  974) 	/* There is an ordered list of substitutes that we have to try. */
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  975) 	read_lock(&net->sysnames_lock);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  976) 	subs = net->sysnames;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  977) 	refcount_inc(&subs->usage);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  978) 	read_unlock(&net->sysnames_lock);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  979) 
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  980) 	for (i = 0; i < subs->nr; i++) {
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  981) 		name = subs->subs[i];
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  982) 		len = dentry->d_name.len - 4 + strlen(name);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  983) 		if (len >= AFSNAMEMAX) {
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  984) 			ret = ERR_PTR(-ENAMETOOLONG);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  985) 			goto out_s;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  986) 		}
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  987) 
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  988) 		strcpy(p, name);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  989) 		ret = lookup_one_len(buf, dentry->d_parent, len);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  990) 		if (IS_ERR(ret) || d_is_positive(ret))
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  991) 			goto out_s;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  992) 		dput(ret);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  993) 	}
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  994) 
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  995) 	/* We don't want to d_add() the @sys dentry here as we don't want to
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  996) 	 * the cached dentry to hide changes to the sysnames list.
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  997) 	 */
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  998) 	ret = NULL;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100  999) out_s:
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1000) 	afs_put_sysnames(subs);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1001) 	kfree(buf);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1002) out_p:
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1003) 	key_put(key);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1004) 	return ret;
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1005) }
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1006) 
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1007) /*
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1008)  * look up an entry in a directory
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1009)  */
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1010) static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
00cd8dd3bf95f (Al Viro             2012-06-10 17:13:09 -0400 1011) 				 unsigned int flags)
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1012) {
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100 1013) 	struct afs_vnode *dvnode = AFS_FS_I(dir);
40a708bd622b7 (David Howells       2020-01-14 16:16:25 +0000 1014) 	struct afs_fid fid = {};
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1015) 	struct inode *inode;
34b2a88fb4aa4 (Al Viro             2018-06-24 10:43:51 -0400 1016) 	struct dentry *d;
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1017) 	struct key *key;
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1018) 	int ret;
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1019) 
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 1020) 	_enter("{%llx:%llu},%p{%pd},",
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100 1021) 	       dvnode->fid.vid, dvnode->fid.vnode, dentry, dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1022) 
2b0143b5c986b (David Howells       2015-03-17 22:25:59 +0000 1023) 	ASSERTCMP(d_inode(dentry), ==, NULL);
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1024) 
45222b9e02fb2 (David Howells       2007-05-10 22:22:20 -0700 1025) 	if (dentry->d_name.len >= AFSNAMEMAX) {
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1026) 		_leave(" = -ENAMETOOLONG");
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1027) 		return ERR_PTR(-ENAMETOOLONG);
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1028) 	}
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1029) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100 1030) 	if (test_bit(AFS_VNODE_DELETED, &dvnode->flags)) {
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1031) 		_leave(" = -ESTALE");
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1032) 		return ERR_PTR(-ESTALE);
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1033) 	}
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1034) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100 1035) 	key = afs_request_key(dvnode->volume->cell);
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1036) 	if (IS_ERR(key)) {
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1037) 		_leave(" = %ld [key]", PTR_ERR(key));
e231c2ee64eb1 (David Howells       2008-02-07 00:15:26 -0800 1038) 		return ERR_CAST(key);
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1039) 	}
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1040) 
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100 1041) 	ret = afs_validate(dvnode, key);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1042) 	if (ret < 0) {
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1043) 		key_put(key);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1044) 		_leave(" = %d [val]", ret);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1045) 		return ERR_PTR(ret);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1046) 	}
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1047) 
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1048) 	if (dentry->d_name.len >= 4 &&
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1049) 	    dentry->d_name.name[dentry->d_name.len - 4] == '@' &&
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1050) 	    dentry->d_name.name[dentry->d_name.len - 3] == 's' &&
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1051) 	    dentry->d_name.name[dentry->d_name.len - 2] == 'y' &&
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1052) 	    dentry->d_name.name[dentry->d_name.len - 1] == 's')
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1053) 		return afs_lookup_atsys(dir, dentry, key);
6f8880d8e6815 (David Howells       2018-04-09 21:12:31 +0100 1054) 
d55b4da4331ef (David Howells       2018-04-06 14:17:24 +0100 1055) 	afs_stat_v(dvnode, n_lookup);
5cf9dd55a0ec2 (David Howells       2018-04-09 21:12:31 +0100 1056) 	inode = afs_do_lookup(dir, dentry, key);
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1057) 	key_put(key);
f52b83b0b1c40 (David Howells       2020-01-14 16:16:54 +0000 1058) 	if (inode == ERR_PTR(-ENOENT))
34b2a88fb4aa4 (Al Viro             2018-06-24 10:43:51 -0400 1059) 		inode = afs_try_auto_mntpt(dentry, dir);
40a708bd622b7 (David Howells       2020-01-14 16:16:25 +0000 1060) 
40a708bd622b7 (David Howells       2020-01-14 16:16:25 +0000 1061) 	if (!IS_ERR_OR_NULL(inode))
40a708bd622b7 (David Howells       2020-01-14 16:16:25 +0000 1062) 		fid = AFS_FS_I(inode)->fid;
40a708bd622b7 (David Howells       2020-01-14 16:16:25 +0000 1063) 
fed79fd783402 (David Howells       2020-06-09 16:25:02 +0100 1064) 	_debug("splice %p", dentry->d_inode);
34b2a88fb4aa4 (Al Viro             2018-06-24 10:43:51 -0400 1065) 	d = d_splice_alias(inode, dentry);
80548b03991f5 (David Howells       2019-04-25 14:26:51 +0100 1066) 	if (!IS_ERR_OR_NULL(d)) {
34b2a88fb4aa4 (Al Viro             2018-06-24 10:43:51 -0400 1067) 		d->d_fsdata = dentry->d_fsdata;
40a708bd622b7 (David Howells       2020-01-14 16:16:25 +0000 1068) 		trace_afs_lookup(dvnode, &d->d_name, &fid);
80548b03991f5 (David Howells       2019-04-25 14:26:51 +0100 1069) 	} else {
40a708bd622b7 (David Howells       2020-01-14 16:16:25 +0000 1070) 		trace_afs_lookup(dvnode, &dentry->d_name, &fid);
80548b03991f5 (David Howells       2019-04-25 14:26:51 +0100 1071) 	}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1072) 	_leave("");
34b2a88fb4aa4 (Al Viro             2018-06-24 10:43:51 -0400 1073) 	return d;
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700 1074) }
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1075) 
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1076) /*
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1077)  * Check the validity of a dentry under RCU conditions.
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1078)  */
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1079) static int afs_d_revalidate_rcu(struct dentry *dentry)
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1080) {
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1081) 	struct afs_vnode *dvnode, *vnode;
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1082) 	struct dentry *parent;
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1083) 	struct inode *dir, *inode;
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1084) 	long dir_version, de_version;
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1085) 
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1086) 	_enter("%p", dentry);
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1087) 
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1088) 	/* Check the parent directory is still valid first. */
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1089) 	parent = READ_ONCE(dentry->d_parent);
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1090) 	dir = d_inode_rcu(parent);
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1091) 	if (!dir)
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1092) 		return -ECHILD;
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1093) 	dvnode = AFS_FS_I(dir);
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1094) 	if (test_bit(AFS_VNODE_DELETED, &dvnode->flags))
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1095) 		return -ECHILD;
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1096) 
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1097) 	if (!afs_check_validity(dvnode))
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1098) 		return -ECHILD;
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1099) 
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1100) 	/* We only need to invalidate a dentry if the server's copy changed
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1101) 	 * behind our back.  If we made the change, it's no problem.  Note that
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1102) 	 * on a 32-bit system, we only have 32 bits in the dentry to store the
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1103) 	 * version.
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1104) 	 */
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1105) 	dir_version = (long)READ_ONCE(dvnode->status.data_version);
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1106) 	de_version = (long)READ_ONCE(dentry->d_fsdata);
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1107) 	if (de_version != dir_version) {
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1108) 		dir_version = (long)READ_ONCE(dvnode->invalid_before);
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1109) 		if (de_version - dir_version < 0)
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1110) 			return -ECHILD;
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1111) 	}
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1112) 
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1113) 	/* Check to see if the vnode referred to by the dentry still
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1114) 	 * has a callback.
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1115) 	 */
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1116) 	if (d_really_is_positive(dentry)) {
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1117) 		inode = d_inode_rcu(dentry);
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1118) 		if (inode) {
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1119) 			vnode = AFS_FS_I(inode);
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1120) 			if (!afs_check_validity(vnode))
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1121) 				return -ECHILD;
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1122) 		}
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1123) 	}
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1124) 
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1125) 	return 1; /* Still valid */
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1126) }
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1127) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1128) /*
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1129)  * check that a dentry lookup hit has found a valid entry
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1130)  * - NOTE! the hit can be a negative hit too, so we can't assume we have an
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1131)  *   inode
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1132)  */
0b728e1911cbe (Al Viro             2012-06-10 16:03:43 -0400 1133) static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1134) {
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1135) 	struct afs_vnode *vnode, *dir;
3f649ab728cda (Kees Cook           2020-06-03 13:09:38 -0700 1136) 	struct afs_fid fid;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1137) 	struct dentry *parent;
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1138) 	struct inode *inode;
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1139) 	struct key *key;
40fc81027f892 (David Howells       2020-04-11 08:50:45 +0100 1140) 	afs_dataversion_t dir_version, invalid_before;
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 1141) 	long de_version;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1142) 	int ret;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1143) 
0b728e1911cbe (Al Viro             2012-06-10 16:03:43 -0400 1144) 	if (flags & LOOKUP_RCU)
a0753c29004f4 (David Howells       2019-05-20 08:48:46 +0100 1145) 		return afs_d_revalidate_rcu(dentry);
34286d6662308 (Nicholas Piggin     2011-01-07 17:49:57 +1100 1146) 
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1147) 	if (d_really_is_positive(dentry)) {
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1148) 		vnode = AFS_FS_I(d_inode(dentry));
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 1149) 		_enter("{v={%llx:%llu} n=%pd fl=%lx},",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1150) 		       vnode->fid.vid, vnode->fid.vnode, dentry,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1151) 		       vnode->flags);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1152) 	} else {
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1153) 		_enter("{neg n=%pd}", dentry);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1154) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1155) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1156) 	key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell);
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1157) 	if (IS_ERR(key))
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1158) 		key = NULL;
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1159) 
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1160) 	if (d_really_is_positive(dentry)) {
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1161) 		inode = d_inode(dentry);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1162) 		if (inode) {
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1163) 			vnode = AFS_FS_I(inode);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1164) 			afs_validate(vnode, key);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1165) 			if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1166) 				goto out_bad;
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1167) 		}
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1168) 	}
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1169) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1170) 	/* lock down the parent dentry so we can peer at it */
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1171) 	parent = dget_parent(dentry);
2b0143b5c986b (David Howells       2015-03-17 22:25:59 +0000 1172) 	dir = AFS_FS_I(d_inode(parent));
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1173) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1174) 	/* validate the parent directory */
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1175) 	afs_validate(dir, key);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1176) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1177) 	if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1178) 		_debug("%pd: parent dir deleted", dentry);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1179) 		goto out_bad_parent;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1180) 	}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1181) 
a4ff7401fbfa0 (David Howells       2018-04-06 14:17:24 +0100 1182) 	/* We only need to invalidate a dentry if the server's copy changed
a4ff7401fbfa0 (David Howells       2018-04-06 14:17:24 +0100 1183) 	 * behind our back.  If we made the change, it's no problem.  Note that
a4ff7401fbfa0 (David Howells       2018-04-06 14:17:24 +0100 1184) 	 * on a 32-bit system, we only have 32 bits in the dentry to store the
a4ff7401fbfa0 (David Howells       2018-04-06 14:17:24 +0100 1185) 	 * version.
a4ff7401fbfa0 (David Howells       2018-04-06 14:17:24 +0100 1186) 	 */
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 1187) 	dir_version = dir->status.data_version;
a4ff7401fbfa0 (David Howells       2018-04-06 14:17:24 +0100 1188) 	de_version = (long)dentry->d_fsdata;
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 1189) 	if (de_version == (long)dir_version)
5dc84855b0fc7 (David Howells       2019-07-30 14:38:51 +0100 1190) 		goto out_valid_noupdate;
a4ff7401fbfa0 (David Howells       2018-04-06 14:17:24 +0100 1191) 
40fc81027f892 (David Howells       2020-04-11 08:50:45 +0100 1192) 	invalid_before = dir->invalid_before;
40fc81027f892 (David Howells       2020-04-11 08:50:45 +0100 1193) 	if (de_version - (long)invalid_before >= 0)
a4ff7401fbfa0 (David Howells       2018-04-06 14:17:24 +0100 1194) 		goto out_valid;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1195) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1196) 	_debug("dir modified");
d55b4da4331ef (David Howells       2018-04-06 14:17:24 +0100 1197) 	afs_stat_v(dir, n_reval);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1198) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1199) 	/* search the directory for this vnode */
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 1200) 	ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key, &dir_version);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1201) 	switch (ret) {
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1202) 	case 0:
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1203) 		/* the filename maps to something */
2b0143b5c986b (David Howells       2015-03-17 22:25:59 +0000 1204) 		if (d_really_is_negative(dentry))
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1205) 			goto out_bad_parent;
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1206) 		inode = d_inode(dentry);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1207) 		if (is_bad_inode(inode)) {
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1208) 			printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1209) 			       dentry);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1210) 			goto out_bad_parent;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1211) 		}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1212) 
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1213) 		vnode = AFS_FS_I(inode);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1214) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1215) 		/* if the vnode ID has changed, then the dirent points to a
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1216) 		 * different file */
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1217) 		if (fid.vnode != vnode->fid.vnode) {
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 1218) 			_debug("%pd: dirent changed [%llu != %llu]",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1219) 			       dentry, fid.vnode,
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1220) 			       vnode->fid.vnode);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1221) 			goto not_found;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1222) 		}
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1223) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1224) 		/* if the vnode ID uniqifier has changed, then the file has
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1225) 		 * been deleted and replaced, and the original vnode ID has
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1226) 		 * been reused */
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1227) 		if (fid.unique != vnode->fid.unique) {
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1228) 			_debug("%pd: file deleted (uq %u -> %u I:%u)",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1229) 			       dentry, fid.unique,
7a224228ed79d (Jean Noel Cordenner 2008-01-28 23:58:27 -0500 1230) 			       vnode->fid.unique,
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1231) 			       vnode->vfs_inode.i_generation);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1232) 			write_seqlock(&vnode->cb_lock);
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1233) 			set_bit(AFS_VNODE_DELETED, &vnode->flags);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1234) 			write_sequnlock(&vnode->cb_lock);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1235) 			goto not_found;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1236) 		}
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1237) 		goto out_valid;
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1238) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1239) 	case -ENOENT:
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1240) 		/* the filename is unknown */
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1241) 		_debug("%pd: dirent not found", dentry);
2b0143b5c986b (David Howells       2015-03-17 22:25:59 +0000 1242) 		if (d_really_is_positive(dentry))
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1243) 			goto not_found;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1244) 		goto out_valid;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1245) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1246) 	default:
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1247) 		_debug("failed to iterate dir %pd: %d",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1248) 		       parent, ret);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1249) 		goto out_bad_parent;
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1250) 	}
08e0e7c82eead (David Howells       2007-04-26 15:55:03 -0700 1251) 
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700 1252) out_valid:
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 1253) 	dentry->d_fsdata = (void *)(unsigned long)dir_version;
5dc84855b0fc7 (David Howells       2019-07-30 14:38:51 +0100 1254) out_valid_noupdate:
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1255) 	dput(parent);
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1256) 	key_put(key);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1257) 	_leave(" = 1 [valid]");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1258) 	return 1;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1259) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1260) 	/* the dirent, if it exists, now points to a different vnode */
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700 1261) not_found:
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1262) 	spin_lock(&dentry->d_lock);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1263) 	dentry->d_flags |= DCACHE_NFSFS_RENAMED;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1264) 	spin_unlock(&dentry->d_lock);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1265) 
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1266) out_bad_parent:
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1267) 	_debug("dropping dentry %pd2", dentry);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1268) 	dput(parent);
c435ee34551e1 (David Howells       2017-11-02 15:27:49 +0000 1269) out_bad:
00d3b7a4533e3 (David Howells       2007-04-26 15:57:07 -0700 1270) 	key_put(key);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1271) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1272) 	_leave(" = 0 [bad]");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1273) 	return 0;
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700 1274) }
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1275) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1276) /*
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1277)  * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1278)  * sleep)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1279)  * - called from dput() when d_count is going to 0.
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1280)  * - return 1 to request dentry be unhashed, 0 otherwise
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1281)  */
fe15ce446beb3 (Nicholas Piggin     2011-01-07 17:49:23 +1100 1282) static int afs_d_delete(const struct dentry *dentry)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1283) {
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1284) 	_enter("%pd", dentry);
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1285) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1286) 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1287) 		goto zap;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1288) 
2b0143b5c986b (David Howells       2015-03-17 22:25:59 +0000 1289) 	if (d_really_is_positive(dentry) &&
2b0143b5c986b (David Howells       2015-03-17 22:25:59 +0000 1290) 	    (test_bit(AFS_VNODE_DELETED,   &AFS_FS_I(d_inode(dentry))->flags) ||
2b0143b5c986b (David Howells       2015-03-17 22:25:59 +0000 1291) 	     test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(d_inode(dentry))->flags)))
bec5eb6141308 (wanglei             2010-08-11 09:38:04 +0100 1292) 		goto zap;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1293) 
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1294) 	_leave(" = 0 [keep]");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1295) 	return 0;
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1296) 
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700 1297) zap:
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1298) 	_leave(" = 1 [zap]");
^1da177e4c3f4 (Linus Torvalds      2005-04-16 15:20:36 -0700 1299) 	return 1;
ec26815ad847d (David Howells       2007-04-26 15:49:28 -0700 1300) }
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1301) 
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1302) /*
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1303)  * Clean up sillyrename files on dentry removal.
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1304)  */
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1305) static void afs_d_iput(struct dentry *dentry, struct inode *inode)
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1306) {
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1307) 	if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1308) 		afs_silly_iput(dentry, inode);
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1309) 	iput(inode);
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1310) }
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1311) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1312) /*
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1313)  * handle dentry release
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1314)  */
66c7e1d319a5b (David Howells       2018-04-06 14:17:25 +0100 1315) void afs_d_release(struct dentry *dentry)
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1316) {
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1317) 	_enter("%pd", dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1318) }
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1319) 
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1320) void afs_check_for_remote_deletion(struct afs_operation *op)
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1321) {
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1322) 	struct afs_vnode *vnode = op->file[0].vnode;
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1323) 
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1324) 	switch (op->ac.abort_code) {
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1325) 	case VNOVNODE:
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1326) 		set_bit(AFS_VNODE_DELETED, &vnode->flags);
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1327) 		afs_break_callback(vnode, afs_cb_break_for_deleted);
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1328) 	}
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1329) }
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1330) 
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1331) /*
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1332)  * Create a new inode for create/mkdir/symlink
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1333)  */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1334) static void afs_vnode_new_inode(struct afs_operation *op)
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1335) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1336) 	struct afs_vnode_param *vp = &op->file[1];
5a8132761609b (David Howells       2018-04-06 14:17:26 +0100 1337) 	struct afs_vnode *vnode;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1338) 	struct inode *inode;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1339) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1340) 	_enter("");
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1341) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1342) 	ASSERTCMP(op->error, ==, 0);
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1343) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1344) 	inode = afs_iget(op, vp);
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1345) 	if (IS_ERR(inode)) {
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1346) 		/* ENOMEM or EINTR at a really inconvenient time - just abandon
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1347) 		 * the new directory on the server.
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1348) 		 */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1349) 		op->error = PTR_ERR(inode);
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1350) 		return;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1351) 	}
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1352) 
5a8132761609b (David Howells       2018-04-06 14:17:26 +0100 1353) 	vnode = AFS_FS_I(inode);
5a8132761609b (David Howells       2018-04-06 14:17:26 +0100 1354) 	set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1355) 	if (!op->error)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1356) 		afs_cache_permit(vnode, op->key, vnode->cb_break, &vp->scb);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1357) 	d_instantiate(op->dentry, inode);
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1358) }
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1359) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1360) static void afs_create_success(struct afs_operation *op)
b8359153252d4 (David Howells       2019-05-14 12:23:43 +0100 1361) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1362) 	_enter("op=%08x", op->debug_id);
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1363) 	op->ctime = op->file[0].scb.status.mtime_client;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1364) 	afs_vnode_commit_status(op, &op->file[0]);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1365) 	afs_update_dentry_version(op, &op->file[0], op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1366) 	afs_vnode_new_inode(op);
b8359153252d4 (David Howells       2019-05-14 12:23:43 +0100 1367) }
b8359153252d4 (David Howells       2019-05-14 12:23:43 +0100 1368) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1369) static void afs_create_edit_dir(struct afs_operation *op)
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 1370) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1371) 	struct afs_vnode_param *dvp = &op->file[0];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1372) 	struct afs_vnode_param *vp = &op->file[1];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1373) 	struct afs_vnode *dvnode = dvp->vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1374) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1375) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1376) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1377) 	down_write(&dvnode->validate_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1378) 	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1379) 	    dvnode->status.data_version == dvp->dv_before + dvp->dv_delta)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1380) 		afs_edit_dir_add(dvnode, &op->dentry->d_name, &vp->fid,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1381) 				 op->create.reason);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1382) 	up_write(&dvnode->validate_lock);
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 1383) }
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 1384) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1385) static void afs_create_put(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1386) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1387) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1388) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1389) 	if (op->error)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1390) 		d_drop(op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1391) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1392) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1393) static const struct afs_operation_ops afs_mkdir_operation = {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1394) 	.issue_afs_rpc	= afs_fs_make_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1395) 	.issue_yfs_rpc	= yfs_fs_make_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1396) 	.success	= afs_create_success,
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1397) 	.aborted	= afs_check_for_remote_deletion,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1398) 	.edit_dir	= afs_create_edit_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1399) 	.put		= afs_create_put,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1400) };
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1401) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1402) /*
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1403)  * create a directory on an AFS filesystem
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1404)  */
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100 1405) static int afs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100 1406) 		     struct dentry *dentry, umode_t mode)
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1407) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1408) 	struct afs_operation *op;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1409) 	struct afs_vnode *dvnode = AFS_FS_I(dir);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1410) 
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 1411) 	_enter("{%llx:%llu},{%pd},%ho",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1412) 	       dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1413) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1414) 	op = afs_alloc_operation(NULL, dvnode->volume);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1415) 	if (IS_ERR(op)) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1416) 		d_drop(dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1417) 		return PTR_ERR(op);
2105c2820d366 (David Howells       2020-04-10 15:23:27 +0100 1418) 	}
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100 1419) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1420) 	afs_op_set_vnode(op, 0, dvnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1421) 	op->file[0].dv_delta = 1;
22650f1481265 (David Howells       2021-04-30 13:47:08 +0100 1422) 	op->file[0].modification = true;
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1423) 	op->file[0].update_ctime = true;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1424) 	op->dentry	= dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1425) 	op->create.mode	= S_IFDIR | mode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1426) 	op->create.reason = afs_edit_dir_for_mkdir;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1427) 	op->ops		= &afs_mkdir_operation;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1428) 	return afs_do_sync_operation(op);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1429) }
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1430) 
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1431) /*
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1432)  * Remove a subdir from a directory.
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1433)  */
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1434) static void afs_dir_remove_subdir(struct dentry *dentry)
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1435) {
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1436) 	if (d_really_is_positive(dentry)) {
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1437) 		struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1438) 
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1439) 		clear_nlink(&vnode->vfs_inode);
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1440) 		set_bit(AFS_VNODE_DELETED, &vnode->flags);
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1441) 		clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100 1442) 		clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1443) 	}
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1444) }
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1445) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1446) static void afs_rmdir_success(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1447) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1448) 	_enter("op=%08x", op->debug_id);
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1449) 	op->ctime = op->file[0].scb.status.mtime_client;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1450) 	afs_vnode_commit_status(op, &op->file[0]);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1451) 	afs_update_dentry_version(op, &op->file[0], op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1452) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1453) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1454) static void afs_rmdir_edit_dir(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1455) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1456) 	struct afs_vnode_param *dvp = &op->file[0];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1457) 	struct afs_vnode *dvnode = dvp->vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1458) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1459) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1460) 	afs_dir_remove_subdir(op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1461) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1462) 	down_write(&dvnode->validate_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1463) 	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1464) 	    dvnode->status.data_version == dvp->dv_before + dvp->dv_delta)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1465) 		afs_edit_dir_remove(dvnode, &op->dentry->d_name,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1466) 				    afs_edit_dir_for_rmdir);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1467) 	up_write(&dvnode->validate_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1468) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1469) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1470) static void afs_rmdir_put(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1471) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1472) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1473) 	if (op->file[1].vnode)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1474) 		up_write(&op->file[1].vnode->rmdir_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1475) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1476) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1477) static const struct afs_operation_ops afs_rmdir_operation = {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1478) 	.issue_afs_rpc	= afs_fs_remove_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1479) 	.issue_yfs_rpc	= yfs_fs_remove_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1480) 	.success	= afs_rmdir_success,
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1481) 	.aborted	= afs_check_for_remote_deletion,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1482) 	.edit_dir	= afs_rmdir_edit_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1483) 	.put		= afs_rmdir_put,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1484) };
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1485) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1486) /*
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1487)  * remove a directory from an AFS filesystem
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1488)  */
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1489) static int afs_rmdir(struct inode *dir, struct dentry *dentry)
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1490) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1491) 	struct afs_operation *op;
f58db83fd3325 (David Howells       2018-10-20 00:57:58 +0100 1492) 	struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1493) 	int ret;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1494) 
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 1495) 	_enter("{%llx:%llu},{%pd}",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1496) 	       dvnode->fid.vid, dvnode->fid.vnode, dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1497) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1498) 	op = afs_alloc_operation(NULL, dvnode->volume);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1499) 	if (IS_ERR(op))
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1500) 		return PTR_ERR(op);
a58823ac45896 (David Howells       2019-05-09 15:16:10 +0100 1501) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1502) 	afs_op_set_vnode(op, 0, dvnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1503) 	op->file[0].dv_delta = 1;
22650f1481265 (David Howells       2021-04-30 13:47:08 +0100 1504) 	op->file[0].modification = true;
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1505) 	op->file[0].update_ctime = true;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1506) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1507) 	op->dentry	= dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1508) 	op->ops		= &afs_rmdir_operation;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1509) 
f58db83fd3325 (David Howells       2018-10-20 00:57:58 +0100 1510) 	/* Try to make sure we have a callback promise on the victim. */
f58db83fd3325 (David Howells       2018-10-20 00:57:58 +0100 1511) 	if (d_really_is_positive(dentry)) {
f58db83fd3325 (David Howells       2018-10-20 00:57:58 +0100 1512) 		vnode = AFS_FS_I(d_inode(dentry));
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1513) 		ret = afs_validate(vnode, op->key);
f58db83fd3325 (David Howells       2018-10-20 00:57:58 +0100 1514) 		if (ret < 0)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1515) 			goto error;
f58db83fd3325 (David Howells       2018-10-20 00:57:58 +0100 1516) 	}
f58db83fd3325 (David Howells       2018-10-20 00:57:58 +0100 1517) 
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1518) 	if (vnode) {
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1519) 		ret = down_write_killable(&vnode->rmdir_lock);
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1520) 		if (ret < 0)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1521) 			goto error;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1522) 		op->file[1].vnode = vnode;
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1523) 	}
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1524) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1525) 	return afs_do_sync_operation(op);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1526) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1527) error:
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1528) 	return afs_put_operation(op);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1529) }
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1530) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1531) /*
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1532)  * Remove a link to a file or symlink from a directory.
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1533)  *
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1534)  * If the file was not deleted due to excess hard links, the fileserver will
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1535)  * break the callback promise on the file - if it had one - before it returns
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1536)  * to us, and if it was deleted, it won't
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1537)  *
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1538)  * However, if we didn't have a callback promise outstanding, or it was
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1539)  * outstanding on a different server, then it won't break it either...
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1540)  */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1541) static void afs_dir_remove_link(struct afs_operation *op)
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1542) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1543) 	struct afs_vnode *dvnode = op->file[0].vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1544) 	struct afs_vnode *vnode = op->file[1].vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1545) 	struct dentry *dentry = op->dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1546) 	int ret;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1547) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1548) 	if (op->error != 0 ||
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1549) 	    (op->file[1].scb.have_status && op->file[1].scb.have_error))
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1550) 		return;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1551) 	if (d_really_is_positive(dentry))
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1552) 		return;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1553) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1554) 	if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1555) 		/* Already done */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1556) 	} else if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1557) 		write_seqlock(&vnode->cb_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1558) 		drop_nlink(&vnode->vfs_inode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1559) 		if (vnode->vfs_inode.i_nlink == 0) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1560) 			set_bit(AFS_VNODE_DELETED, &vnode->flags);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1561) 			__afs_break_callback(vnode, afs_cb_break_for_unlink);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1562) 		}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1563) 		write_sequnlock(&vnode->cb_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1564) 	} else {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1565) 		afs_break_callback(vnode, afs_cb_break_for_unlink);
440fbc3a8a694 (David Howells       2018-01-02 10:02:19 +0000 1566) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1567) 		if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1568) 			_debug("AFS_VNODE_DELETED");
440fbc3a8a694 (David Howells       2018-01-02 10:02:19 +0000 1569) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1570) 		ret = afs_validate(vnode, op->key);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1571) 		if (ret != -ESTALE)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1572) 			op->error = ret;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1573) 	}
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1574) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1575) 	_debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, op->error);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1576) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1577) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1578) static void afs_unlink_success(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1579) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1580) 	_enter("op=%08x", op->debug_id);
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1581) 	op->ctime = op->file[0].scb.status.mtime_client;
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1582) 	afs_check_dir_conflict(op, &op->file[0]);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1583) 	afs_vnode_commit_status(op, &op->file[0]);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1584) 	afs_vnode_commit_status(op, &op->file[1]);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1585) 	afs_update_dentry_version(op, &op->file[0], op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1586) 	afs_dir_remove_link(op);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1587) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1588) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1589) static void afs_unlink_edit_dir(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1590) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1591) 	struct afs_vnode_param *dvp = &op->file[0];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1592) 	struct afs_vnode *dvnode = dvp->vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1593) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1594) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1595) 	down_write(&dvnode->validate_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1596) 	if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1597) 	    dvnode->status.data_version == dvp->dv_before + dvp->dv_delta)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1598) 		afs_edit_dir_remove(dvnode, &op->dentry->d_name,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1599) 				    afs_edit_dir_for_unlink);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1600) 	up_write(&dvnode->validate_lock);
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1601) }
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1602) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1603) static void afs_unlink_put(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1604) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1605) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1606) 	if (op->unlink.need_rehash && op->error < 0 && op->error != -ENOENT)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1607) 		d_rehash(op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1608) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1609) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1610) static const struct afs_operation_ops afs_unlink_operation = {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1611) 	.issue_afs_rpc	= afs_fs_remove_file,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1612) 	.issue_yfs_rpc	= yfs_fs_remove_file,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1613) 	.success	= afs_unlink_success,
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1614) 	.aborted	= afs_check_for_remote_deletion,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1615) 	.edit_dir	= afs_unlink_edit_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1616) 	.put		= afs_unlink_put,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1617) };
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1618) 
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1619) /*
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1620)  * Remove a file or symlink from an AFS filesystem.
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1621)  */
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1622) static int afs_unlink(struct inode *dir, struct dentry *dentry)
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1623) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1624) 	struct afs_operation *op;
fa59f52f5b141 (David Howells       2019-06-20 18:12:16 +0100 1625) 	struct afs_vnode *dvnode = AFS_FS_I(dir);
fa59f52f5b141 (David Howells       2019-06-20 18:12:16 +0100 1626) 	struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1627) 	int ret;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1628) 
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 1629) 	_enter("{%llx:%llu},{%pd}",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1630) 	       dvnode->fid.vid, dvnode->fid.vnode, dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1631) 
45222b9e02fb2 (David Howells       2007-05-10 22:22:20 -0700 1632) 	if (dentry->d_name.len >= AFSNAMEMAX)
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1633) 		return -ENAMETOOLONG;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1634) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1635) 	op = afs_alloc_operation(NULL, dvnode->volume);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1636) 	if (IS_ERR(op))
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1637) 		return PTR_ERR(op);
a58823ac45896 (David Howells       2019-05-09 15:16:10 +0100 1638) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1639) 	afs_op_set_vnode(op, 0, dvnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1640) 	op->file[0].dv_delta = 1;
22650f1481265 (David Howells       2021-04-30 13:47:08 +0100 1641) 	op->file[0].modification = true;
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1642) 	op->file[0].update_ctime = true;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1643) 
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1644) 	/* Try to make sure we have a callback promise on the victim. */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1645) 	ret = afs_validate(vnode, op->key);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1646) 	if (ret < 0) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1647) 		op->error = ret;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1648) 		goto error;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1649) 	}
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1650) 
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1651) 	spin_lock(&dentry->d_lock);
fa59f52f5b141 (David Howells       2019-06-20 18:12:16 +0100 1652) 	if (d_count(dentry) > 1) {
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1653) 		spin_unlock(&dentry->d_lock);
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1654) 		/* Start asynchronous writeout of the inode */
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1655) 		write_inode_now(d_inode(dentry), 0);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1656) 		op->error = afs_sillyrename(dvnode, vnode, dentry, op->key);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1657) 		goto error;
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1658) 	}
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1659) 	if (!d_unhashed(dentry)) {
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1660) 		/* Prevent a race with RCU lookup. */
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1661) 		__d_drop(dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1662) 		op->unlink.need_rehash = true;
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1663) 	}
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1664) 	spin_unlock(&dentry->d_lock);
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1665) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1666) 	op->file[1].vnode = vnode;
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1667) 	op->file[1].update_ctime = true;
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1668) 	op->file[1].op_unlinked = true;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1669) 	op->dentry	= dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1670) 	op->ops		= &afs_unlink_operation;
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1671) 	afs_begin_vnode_operation(op);
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1672) 	afs_wait_for_operation(op);
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1673) 
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1674) 	/* If there was a conflict with a third party, check the status of the
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1675) 	 * unlinked vnode.
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1676) 	 */
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1677) 	if (op->error == 0 && (op->flags & AFS_OPERATION_DIR_CONFLICT)) {
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1678) 		op->file[1].update_ctime = false;
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1679) 		op->fetch_status.which = 1;
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1680) 		op->ops = &afs_fetch_status_operation;
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1681) 		afs_begin_vnode_operation(op);
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1682) 		afs_wait_for_operation(op);
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1683) 	}
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1684) 
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1685) 	return afs_put_operation(op);
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1686) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1687) error:
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1688) 	return afs_put_operation(op);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1689) }
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1690) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1691) static const struct afs_operation_ops afs_create_operation = {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1692) 	.issue_afs_rpc	= afs_fs_create_file,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1693) 	.issue_yfs_rpc	= yfs_fs_create_file,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1694) 	.success	= afs_create_success,
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1695) 	.aborted	= afs_check_for_remote_deletion,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1696) 	.edit_dir	= afs_create_edit_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1697) 	.put		= afs_create_put,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1698) };
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1699) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1700) /*
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1701)  * create a regular file on an AFS filesystem
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1702)  */
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100 1703) static int afs_create(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100 1704) 		      struct dentry *dentry, umode_t mode, bool excl)
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1705) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1706) 	struct afs_operation *op;
43dd388b21c72 (Colin Ian King      2017-11-20 13:58:20 +0000 1707) 	struct afs_vnode *dvnode = AFS_FS_I(dir);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1708) 	int ret = -ENAMETOOLONG;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1709) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1710) 	_enter("{%llx:%llu},{%pd},%ho",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1711) 	       dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1712) 
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1713) 	if (dentry->d_name.len >= AFSNAMEMAX)
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1714) 		goto error;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1715) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1716) 	op = afs_alloc_operation(NULL, dvnode->volume);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1717) 	if (IS_ERR(op)) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1718) 		ret = PTR_ERR(op);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1719) 		goto error;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1720) 	}
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1721) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1722) 	afs_op_set_vnode(op, 0, dvnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1723) 	op->file[0].dv_delta = 1;
22650f1481265 (David Howells       2021-04-30 13:47:08 +0100 1724) 	op->file[0].modification = true;
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1725) 	op->file[0].update_ctime = true;
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100 1726) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1727) 	op->dentry	= dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1728) 	op->create.mode	= S_IFREG | mode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1729) 	op->create.reason = afs_edit_dir_for_create;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1730) 	op->ops		= &afs_create_operation;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1731) 	return afs_do_sync_operation(op);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1732) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1733) error:
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1734) 	d_drop(dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1735) 	_leave(" = %d", ret);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1736) 	return ret;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1737) }
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1738) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1739) static void afs_link_success(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1740) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1741) 	struct afs_vnode_param *dvp = &op->file[0];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1742) 	struct afs_vnode_param *vp = &op->file[1];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1743) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1744) 	_enter("op=%08x", op->debug_id);
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1745) 	op->ctime = dvp->scb.status.mtime_client;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1746) 	afs_vnode_commit_status(op, dvp);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1747) 	afs_vnode_commit_status(op, vp);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1748) 	afs_update_dentry_version(op, dvp, op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1749) 	if (op->dentry_2->d_parent == op->dentry->d_parent)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1750) 		afs_update_dentry_version(op, dvp, op->dentry_2);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1751) 	ihold(&vp->vnode->vfs_inode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1752) 	d_instantiate(op->dentry, &vp->vnode->vfs_inode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1753) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1754) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1755) static void afs_link_put(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1756) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1757) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1758) 	if (op->error)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1759) 		d_drop(op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1760) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1761) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1762) static const struct afs_operation_ops afs_link_operation = {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1763) 	.issue_afs_rpc	= afs_fs_link,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1764) 	.issue_yfs_rpc	= yfs_fs_link,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1765) 	.success	= afs_link_success,
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1766) 	.aborted	= afs_check_for_remote_deletion,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1767) 	.edit_dir	= afs_create_edit_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1768) 	.put		= afs_link_put,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1769) };
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1770) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1771) /*
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1772)  * create a hard link between files in an AFS filesystem
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1773)  */
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1774) static int afs_link(struct dentry *from, struct inode *dir,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1775) 		    struct dentry *dentry)
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1776) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1777) 	struct afs_operation *op;
a58823ac45896 (David Howells       2019-05-09 15:16:10 +0100 1778) 	struct afs_vnode *dvnode = AFS_FS_I(dir);
a58823ac45896 (David Howells       2019-05-09 15:16:10 +0100 1779) 	struct afs_vnode *vnode = AFS_FS_I(d_inode(from));
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1780) 	int ret = -ENAMETOOLONG;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1781) 
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 1782) 	_enter("{%llx:%llu},{%llx:%llu},{%pd}",
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1783) 	       vnode->fid.vid, vnode->fid.vnode,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1784) 	       dvnode->fid.vid, dvnode->fid.vnode,
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1785) 	       dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1786) 
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1787) 	if (dentry->d_name.len >= AFSNAMEMAX)
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1788) 		goto error;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1789) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1790) 	op = afs_alloc_operation(NULL, dvnode->volume);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1791) 	if (IS_ERR(op)) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1792) 		ret = PTR_ERR(op);
a58823ac45896 (David Howells       2019-05-09 15:16:10 +0100 1793) 		goto error;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1794) 	}
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1795) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1796) 	afs_op_set_vnode(op, 0, dvnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1797) 	afs_op_set_vnode(op, 1, vnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1798) 	op->file[0].dv_delta = 1;
22650f1481265 (David Howells       2021-04-30 13:47:08 +0100 1799) 	op->file[0].modification = true;
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1800) 	op->file[0].update_ctime = true;
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1801) 	op->file[1].update_ctime = true;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1802) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1803) 	op->dentry		= dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1804) 	op->dentry_2		= from;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1805) 	op->ops			= &afs_link_operation;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1806) 	op->create.reason	= afs_edit_dir_for_link;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1807) 	return afs_do_sync_operation(op);
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100 1808) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1809) error:
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1810) 	d_drop(dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1811) 	_leave(" = %d", ret);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1812) 	return ret;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1813) }
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1814) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1815) static const struct afs_operation_ops afs_symlink_operation = {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1816) 	.issue_afs_rpc	= afs_fs_symlink,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1817) 	.issue_yfs_rpc	= yfs_fs_symlink,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1818) 	.success	= afs_create_success,
728279a5a1fd9 (David Howells       2020-06-16 00:34:09 +0100 1819) 	.aborted	= afs_check_for_remote_deletion,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1820) 	.edit_dir	= afs_create_edit_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1821) 	.put		= afs_create_put,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1822) };
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1823) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1824) /*
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1825)  * create a symlink in an AFS filesystem
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1826)  */
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100 1827) static int afs_symlink(struct user_namespace *mnt_userns, struct inode *dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100 1828) 		       struct dentry *dentry, const char *content)
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1829) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1830) 	struct afs_operation *op;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1831) 	struct afs_vnode *dvnode = AFS_FS_I(dir);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1832) 	int ret;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1833) 
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 1834) 	_enter("{%llx:%llu},{%pd},%s",
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1835) 	       dvnode->fid.vid, dvnode->fid.vnode, dentry,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1836) 	       content);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1837) 
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1838) 	ret = -ENAMETOOLONG;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1839) 	if (dentry->d_name.len >= AFSNAMEMAX)
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1840) 		goto error;
d2ddc776a4581 (David Howells       2017-11-02 15:27:50 +0000 1841) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1842) 	ret = -EINVAL;
45222b9e02fb2 (David Howells       2007-05-10 22:22:20 -0700 1843) 	if (strlen(content) >= AFSPATHMAX)
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1844) 		goto error;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1845) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1846) 	op = afs_alloc_operation(NULL, dvnode->volume);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1847) 	if (IS_ERR(op)) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1848) 		ret = PTR_ERR(op);
a58823ac45896 (David Howells       2019-05-09 15:16:10 +0100 1849) 		goto error;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1850) 	}
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1851) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1852) 	afs_op_set_vnode(op, 0, dvnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1853) 	op->file[0].dv_delta = 1;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1854) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1855) 	op->dentry		= dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1856) 	op->ops			= &afs_symlink_operation;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1857) 	op->create.reason	= afs_edit_dir_for_symlink;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1858) 	op->create.symlink	= content;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1859) 	return afs_do_sync_operation(op);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1860) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1861) error:
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1862) 	d_drop(dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1863) 	_leave(" = %d", ret);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1864) 	return ret;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1865) }
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1866) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1867) static void afs_rename_success(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1868) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1869) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1870) 
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1871) 	op->ctime = op->file[0].scb.status.mtime_client;
b6489a49f7b71 (David Howells       2020-06-15 17:36:58 +0100 1872) 	afs_check_dir_conflict(op, &op->file[1]);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1873) 	afs_vnode_commit_status(op, &op->file[0]);
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1874) 	if (op->file[1].vnode != op->file[0].vnode) {
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1875) 		op->ctime = op->file[1].scb.status.mtime_client;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1876) 		afs_vnode_commit_status(op, &op->file[1]);
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1877) 	}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1878) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1879) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1880) static void afs_rename_edit_dir(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1881) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1882) 	struct afs_vnode_param *orig_dvp = &op->file[0];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1883) 	struct afs_vnode_param *new_dvp = &op->file[1];
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1884) 	struct afs_vnode *orig_dvnode = orig_dvp->vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1885) 	struct afs_vnode *new_dvnode = new_dvp->vnode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1886) 	struct afs_vnode *vnode = AFS_FS_I(d_inode(op->dentry));
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1887) 	struct dentry *old_dentry = op->dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1888) 	struct dentry *new_dentry = op->dentry_2;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1889) 	struct inode *new_inode;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1890) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1891) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1892) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1893) 	if (op->rename.rehash) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1894) 		d_rehash(op->rename.rehash);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1895) 		op->rename.rehash = NULL;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1896) 	}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1897) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1898) 	down_write(&orig_dvnode->validate_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1899) 	if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags) &&
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1900) 	    orig_dvnode->status.data_version == orig_dvp->dv_before + orig_dvp->dv_delta)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1901) 		afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1902) 				    afs_edit_dir_for_rename_0);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1903) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1904) 	if (new_dvnode != orig_dvnode) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1905) 		up_write(&orig_dvnode->validate_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1906) 		down_write(&new_dvnode->validate_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1907) 	}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1908) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1909) 	if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags) &&
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1910) 	    new_dvnode->status.data_version == new_dvp->dv_before + new_dvp->dv_delta) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1911) 		if (!op->rename.new_negative)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1912) 			afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1913) 					    afs_edit_dir_for_rename_1);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1914) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1915) 		afs_edit_dir_add(new_dvnode, &new_dentry->d_name,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1916) 				 &vnode->fid, afs_edit_dir_for_rename_2);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1917) 	}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1918) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1919) 	new_inode = d_inode(new_dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1920) 	if (new_inode) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1921) 		spin_lock(&new_inode->i_lock);
f610a5a29c3cf (David Howells       2021-05-27 11:24:33 +0100 1922) 		if (S_ISDIR(new_inode->i_mode))
f610a5a29c3cf (David Howells       2021-05-27 11:24:33 +0100 1923) 			clear_nlink(new_inode);
f610a5a29c3cf (David Howells       2021-05-27 11:24:33 +0100 1924) 		else if (new_inode->i_nlink > 0)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1925) 			drop_nlink(new_inode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1926) 		spin_unlock(&new_inode->i_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1927) 	}
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1928) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1929) 	/* Now we can update d_fsdata on the dentries to reflect their
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1930) 	 * new parent's data_version.
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1931) 	 *
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1932) 	 * Note that if we ever implement RENAME_EXCHANGE, we'll have
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1933) 	 * to update both dentries with opposing dir versions.
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1934) 	 */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1935) 	afs_update_dentry_version(op, new_dvp, op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1936) 	afs_update_dentry_version(op, new_dvp, op->dentry_2);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1937) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1938) 	d_move(old_dentry, new_dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1939) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1940) 	up_write(&new_dvnode->validate_lock);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1941) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1942) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1943) static void afs_rename_put(struct afs_operation *op)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1944) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1945) 	_enter("op=%08x", op->debug_id);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1946) 	if (op->rename.rehash)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1947) 		d_rehash(op->rename.rehash);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1948) 	dput(op->rename.tmp);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1949) 	if (op->error)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1950) 		d_rehash(op->dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1951) }
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1952) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1953) static const struct afs_operation_ops afs_rename_operation = {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1954) 	.issue_afs_rpc	= afs_fs_rename,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1955) 	.issue_yfs_rpc	= yfs_fs_rename,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1956) 	.success	= afs_rename_success,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1957) 	.edit_dir	= afs_rename_edit_dir,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1958) 	.put		= afs_rename_put,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1959) };
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1960) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1961) /*
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1962)  * rename a file in an AFS filesystem and/or move it between directories
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1963)  */
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100 1964) static int afs_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100 1965) 		      struct dentry *old_dentry, struct inode *new_dir,
549c7297717c3 (Christian Brauner   2021-01-21 14:19:43 +0100 1966) 		      struct dentry *new_dentry, unsigned int flags)
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1967) {
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1968) 	struct afs_operation *op;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1969) 	struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1970) 	int ret;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1971) 
1cd66c93ba8cd (Miklos Szeredi      2016-09-27 11:03:58 +0200 1972) 	if (flags)
1cd66c93ba8cd (Miklos Szeredi      2016-09-27 11:03:58 +0200 1973) 		return -EINVAL;
1cd66c93ba8cd (Miklos Szeredi      2016-09-27 11:03:58 +0200 1974) 
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1975) 	/* Don't allow silly-rename files be moved around. */
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1976) 	if (old_dentry->d_flags & DCACHE_NFSFS_RENAMED)
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1977) 		return -EINVAL;
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 1978) 
2b0143b5c986b (David Howells       2015-03-17 22:25:59 +0000 1979) 	vnode = AFS_FS_I(d_inode(old_dentry));
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1980) 	orig_dvnode = AFS_FS_I(old_dir);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1981) 	new_dvnode = AFS_FS_I(new_dir);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1982) 
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 1983) 	_enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}",
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1984) 	       orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1985) 	       vnode->fid.vid, vnode->fid.vnode,
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1986) 	       new_dvnode->fid.vid, new_dvnode->fid.vnode,
a455589f181e6 (Al Viro             2014-10-21 20:11:25 -0400 1987) 	       new_dentry);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 1988) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1989) 	op = afs_alloc_operation(NULL, orig_dvnode->volume);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1990) 	if (IS_ERR(op))
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1991) 		return PTR_ERR(op);
a58823ac45896 (David Howells       2019-05-09 15:16:10 +0100 1992) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1993) 	afs_op_set_vnode(op, 0, orig_dvnode);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1994) 	afs_op_set_vnode(op, 1, new_dvnode); /* May be same as orig_dvnode */
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1995) 	op->file[0].dv_delta = 1;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 1996) 	op->file[1].dv_delta = 1;
22650f1481265 (David Howells       2021-04-30 13:47:08 +0100 1997) 	op->file[0].modification = true;
22650f1481265 (David Howells       2021-04-30 13:47:08 +0100 1998) 	op->file[1].modification = true;
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 1999) 	op->file[0].update_ctime = true;
da8d07551275a (David Howells       2020-06-13 19:34:59 +0100 2000) 	op->file[1].update_ctime = true;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2001) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2002) 	op->dentry		= old_dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2003) 	op->dentry_2		= new_dentry;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2004) 	op->rename.new_negative	= d_is_negative(new_dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2005) 	op->ops			= &afs_rename_operation;
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 2006) 
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2007) 	/* For non-directories, check whether the target is busy and if so,
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2008) 	 * make a copy of the dentry and then do a silly-rename.  If the
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2009) 	 * silly-rename succeeds, the copied dentry is hashed and becomes the
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2010) 	 * new target.
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2011) 	 */
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2012) 	if (d_is_positive(new_dentry) && !d_is_dir(new_dentry)) {
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2013) 		/* To prevent any new references to the target during the
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2014) 		 * rename, we unhash the dentry in advance.
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2015) 		 */
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2016) 		if (!d_unhashed(new_dentry)) {
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2017) 			d_drop(new_dentry);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2018) 			op->rename.rehash = new_dentry;
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2019) 		}
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2020) 
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2021) 		if (d_count(new_dentry) > 2) {
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2022) 			/* copy the target dentry's name */
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2023) 			ret = -ENOMEM;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2024) 			op->rename.tmp = d_alloc(new_dentry->d_parent,
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2025) 						 &new_dentry->d_name);
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2026) 			if (!op->rename.tmp)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2027) 				goto error;
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2028) 
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2029) 			ret = afs_sillyrename(new_dvnode,
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2030) 					      AFS_FS_I(d_inode(new_dentry)),
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2031) 					      new_dentry, op->key);
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2032) 			if (ret)
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2033) 				goto error;
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2034) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2035) 			op->dentry_2 = op->rename.tmp;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2036) 			op->rename.rehash = NULL;
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2037) 			op->rename.new_negative = true;
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2038) 		}
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2039) 	}
79ddbfa500b37 (David Howells       2019-04-25 14:26:51 +0100 2040) 
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2041) 	/* This bit is potentially nasty as there's a potential race with
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2042) 	 * afs_d_revalidate{,_rcu}().  We have to change d_fsdata on the dentry
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2043) 	 * to reflect it's new parent's new data_version after the op, but
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2044) 	 * d_revalidate may see old_dentry between the op having taken place
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2045) 	 * and the version being updated.
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2046) 	 *
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2047) 	 * So drop the old_dentry for now to make other threads go through
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2048) 	 * lookup instead - which we hold a lock against.
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2049) 	 */
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2050) 	d_drop(old_dentry);
9dd0b82ef530c (David Howells       2019-07-30 14:38:52 +0100 2051) 
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2052) 	return afs_do_sync_operation(op);
63a4681ff39cb (David Howells       2018-04-06 14:17:25 +0100 2053) 
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 2054) error:
e49c7b2f6de7f (David Howells       2020-04-10 20:51:51 +0100 2055) 	return afs_put_operation(op);
260a980317dac (David Howells       2007-04-26 15:59:35 -0700 2056) }
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2057) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2058) /*
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2059)  * Release a directory page and clean up its private state if it's not busy
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2060)  * - return true if the page can now be released, false if not
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2061)  */
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2062) static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags)
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2063) {
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2064) 	struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2065) 
3b6492df4153b (David Howells       2018-10-20 00:57:57 +0100 2066) 	_enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2067) 
fa04a40b169fc (David Howells       2020-10-21 13:22:19 +0100 2068) 	detach_page_private(page);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2069) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2070) 	/* The directory will need reloading. */
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2071) 	if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2072) 		afs_stat_v(dvnode, n_relpg);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2073) 	return 1;
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2074) }
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2075) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2076) /*
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2077)  * invalidate part or all of a page
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2078)  * - release a page and clean up its private data if offset is 0 (indicating
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2079)  *   the entire page)
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2080)  */
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2081) static void afs_dir_invalidatepage(struct page *page, unsigned int offset,
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2082) 				   unsigned int length)
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2083) {
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2084) 	struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2085) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2086) 	_enter("{%lu},%u,%u", page->index, offset, length);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2087) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2088) 	BUG_ON(!PageLocked(page));
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2089) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2090) 	/* The directory will need reloading. */
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2091) 	if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2092) 		afs_stat_v(dvnode, n_inval);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2093) 
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2094) 	/* we clean up only if the entire page is being invalidated */
e87b03f5830ec (David Howells       2020-10-20 09:33:45 +0100 2095) 	if (offset == 0 && length == thp_size(page))
fa04a40b169fc (David Howells       2020-10-21 13:22:19 +0100 2096) 		detach_page_private(page);
f3ddee8dc4e2c (David Howells       2018-04-06 14:17:25 +0100 2097) }