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) }