blob: 813db17084943d212d18f8dd058e41873726ba8b [file] [log] [blame]
Thomas Gleixner2874c5f2019-05-27 08:55:01 +02001// SPDX-License-Identifier: GPL-2.0-or-later
Linus Torvalds1da177e2005-04-16 15:20:36 -07002/* dir.c: AFS filesystem directory handling
3 *
David Howellsf3ddee82018-04-06 14:17:25 +01004 * Copyright (C) 2002, 2018 Red Hat, Inc. All Rights Reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 * Written by David Howells (dhowells@redhat.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 */
7
8#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -07009#include <linux/fs.h>
Nick Piggin34286d62011-01-07 17:49:57 +110010#include <linux/namei.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070011#include <linux/pagemap.h>
David Howellsf3ddee82018-04-06 14:17:25 +010012#include <linux/swap.h>
David Howells00d3b7a2007-04-26 15:57:07 -070013#include <linux/ctype.h>
Alexey Dobriyane8edc6e2007-05-21 01:22:52 +040014#include <linux/sched.h>
David Howellsf3ddee82018-04-06 14:17:25 +010015#include <linux/task_io_accounting_ops.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070016#include "internal.h"
David Howellsa58823a2019-05-09 15:16:10 +010017#include "afs_fs.h"
David Howells4ea219a2018-04-06 14:17:25 +010018#include "xdr_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070019
David Howells260a9802007-04-26 15:59:35 -070020static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
Al Viro00cd8dd2012-06-10 17:13:09 -040021 unsigned int flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -070022static int afs_dir_open(struct inode *inode, struct file *file);
Al Viro1bbae9f2013-05-22 16:31:14 -040023static int afs_readdir(struct file *file, struct dir_context *ctx);
Al Viro0b728e12012-06-10 16:03:43 -040024static int afs_d_revalidate(struct dentry *dentry, unsigned int flags);
Nick Pigginfe15ce42011-01-07 17:49:23 +110025static int afs_d_delete(const struct dentry *dentry);
David Howells79ddbfa2019-04-25 14:26:51 +010026static void afs_d_iput(struct dentry *dentry, struct inode *inode);
David Howells5cf9dd52018-04-09 21:12:31 +010027static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name, int nlen,
David Howellsafefdbb2006-10-03 01:13:46 -070028 loff_t fpos, u64 ino, unsigned dtype);
David Howells5cf9dd52018-04-09 21:12:31 +010029static int afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen,
30 loff_t fpos, u64 ino, unsigned dtype);
Al Viro4acdaf22011-07-26 01:42:34 -040031static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -040032 bool excl);
Al Viro18bb1db2011-07-26 01:41:39 -040033static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
David Howells260a9802007-04-26 15:59:35 -070034static int afs_rmdir(struct inode *dir, struct dentry *dentry);
35static int afs_unlink(struct inode *dir, struct dentry *dentry);
36static int afs_link(struct dentry *from, struct inode *dir,
37 struct dentry *dentry);
38static int afs_symlink(struct inode *dir, struct dentry *dentry,
39 const char *content);
40static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
Miklos Szeredi1cd66c92016-09-27 11:03:58 +020041 struct inode *new_dir, struct dentry *new_dentry,
42 unsigned int flags);
David Howellsf3ddee82018-04-06 14:17:25 +010043static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags);
44static void afs_dir_invalidatepage(struct page *page, unsigned int offset,
45 unsigned int length);
46
47static int afs_dir_set_page_dirty(struct page *page)
48{
49 BUG(); /* This should never happen. */
50}
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Arjan van de Ven4b6f5d22006-03-28 01:56:42 -080052const struct file_operations afs_dir_file_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070053 .open = afs_dir_open,
David Howells00d3b7a2007-04-26 15:57:07 -070054 .release = afs_release,
Al Viro29884ef2016-05-10 14:27:44 -040055 .iterate_shared = afs_readdir,
David Howellse8d6c552007-07-15 23:40:12 -070056 .lock = afs_lock,
Christoph Hellwig3222a3e2008-09-03 21:53:01 +020057 .llseek = generic_file_llseek,
Linus Torvalds1da177e2005-04-16 15:20:36 -070058};
59
Arjan van de Ven754661f2007-02-12 00:55:38 -080060const struct inode_operations afs_dir_inode_operations = {
David Howells260a9802007-04-26 15:59:35 -070061 .create = afs_create,
62 .lookup = afs_lookup,
63 .link = afs_link,
64 .unlink = afs_unlink,
65 .symlink = afs_symlink,
66 .mkdir = afs_mkdir,
67 .rmdir = afs_rmdir,
Miklos Szeredi2773bf02016-09-27 11:03:58 +020068 .rename = afs_rename,
David Howells00d3b7a2007-04-26 15:57:07 -070069 .permission = afs_permission,
David Howells416351f2007-05-09 02:33:45 -070070 .getattr = afs_getattr,
David Howells31143d52007-05-09 02:33:46 -070071 .setattr = afs_setattr,
David Howellsd3e3b7ea2017-07-06 15:50:27 +010072 .listxattr = afs_listxattr,
Linus Torvalds1da177e2005-04-16 15:20:36 -070073};
74
David Howellsf3ddee82018-04-06 14:17:25 +010075const struct address_space_operations afs_dir_aops = {
76 .set_page_dirty = afs_dir_set_page_dirty,
77 .releasepage = afs_dir_releasepage,
78 .invalidatepage = afs_dir_invalidatepage,
79};
80
Al Virod61dcce2011-01-12 20:04:20 -050081const struct dentry_operations afs_fs_dentry_operations = {
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 .d_revalidate = afs_d_revalidate,
83 .d_delete = afs_d_delete,
David Howells260a9802007-04-26 15:59:35 -070084 .d_release = afs_d_release,
David Howellsd18610b2011-01-14 19:04:05 +000085 .d_automount = afs_d_automount,
David Howells79ddbfa2019-04-25 14:26:51 +010086 .d_iput = afs_d_iput,
Linus Torvalds1da177e2005-04-16 15:20:36 -070087};
88
David Howells5cf9dd52018-04-09 21:12:31 +010089struct afs_lookup_one_cookie {
90 struct dir_context ctx;
91 struct qstr name;
92 bool found;
93 struct afs_fid fid;
94};
95
David Howells260a9802007-04-26 15:59:35 -070096struct afs_lookup_cookie {
David Howells5cf9dd52018-04-09 21:12:31 +010097 struct dir_context ctx;
98 struct qstr name;
99 bool found;
100 bool one_only;
101 unsigned short nr_fids;
David Howells39db9812019-05-14 12:33:10 +0100102 struct inode **inodes;
David Howells87182752019-05-09 16:17:05 +0100103 struct afs_status_cb *statuses;
David Howells5cf9dd52018-04-09 21:12:31 +0100104 struct afs_fid fids[50];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105};
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107/*
108 * check that a directory page is valid
109 */
David Howellsf3ddee82018-04-06 14:17:25 +0100110static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page,
111 loff_t i_size)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112{
David Howells00317632018-04-06 14:17:25 +0100113 struct afs_xdr_dir_page *dbuf;
David Howellsf3ddee82018-04-06 14:17:25 +0100114 loff_t latter, off;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 int tmp, qty;
116
David Howellsdab17c12017-11-02 15:27:52 +0000117 /* Determine how many magic numbers there should be in this page, but
118 * we must take care because the directory may change size under us.
119 */
120 off = page_offset(page);
David Howellsdab17c12017-11-02 15:27:52 +0000121 if (i_size <= off)
122 goto checked;
123
124 latter = i_size - off;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125 if (latter >= PAGE_SIZE)
126 qty = PAGE_SIZE;
127 else
128 qty = latter;
David Howells00317632018-04-06 14:17:25 +0100129 qty /= sizeof(union afs_xdr_dir_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130
131 /* check them */
David Howells63a46812018-04-06 14:17:25 +0100132 dbuf = kmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133 for (tmp = 0; tmp < qty; tmp++) {
David Howells00317632018-04-06 14:17:25 +0100134 if (dbuf->blocks[tmp].hdr.magic != AFS_DIR_MAGIC) {
David Howellsdab17c12017-11-02 15:27:52 +0000135 printk("kAFS: %s(%lx): bad magic %d/%d is %04hx\n",
David Howellsf3ddee82018-04-06 14:17:25 +0100136 __func__, dvnode->vfs_inode.i_ino, tmp, qty,
David Howells00317632018-04-06 14:17:25 +0100137 ntohs(dbuf->blocks[tmp].hdr.magic));
David Howellsf3ddee82018-04-06 14:17:25 +0100138 trace_afs_dir_check_failed(dvnode, off, i_size);
David Howells63a46812018-04-06 14:17:25 +0100139 kunmap(page);
David Howellsf51375c2018-10-20 00:57:57 +0100140 trace_afs_file_error(dvnode, -EIO, afs_file_error_dir_bad_magic);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141 goto error;
142 }
David Howells63a46812018-04-06 14:17:25 +0100143
144 /* Make sure each block is NUL terminated so we can reasonably
145 * use string functions on it. The filenames in the page
146 * *should* be NUL-terminated anyway.
147 */
148 ((u8 *)&dbuf->blocks[tmp])[AFS_DIR_BLOCK_SIZE - 1] = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149 }
150
David Howells63a46812018-04-06 14:17:25 +0100151 kunmap(page);
152
David Howellsdab17c12017-11-02 15:27:52 +0000153checked:
David Howellsf3ddee82018-04-06 14:17:25 +0100154 afs_stat_v(dvnode, n_read_dir);
Al Virobe5b82d2016-04-22 15:06:44 -0400155 return true;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700156
David Howellsec268152007-04-26 15:49:28 -0700157error:
Al Virobe5b82d2016-04-22 15:06:44 -0400158 return false;
David Howellsec268152007-04-26 15:49:28 -0700159}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160
Linus Torvalds1da177e2005-04-16 15:20:36 -0700161/*
David Howells445b1022019-04-25 14:26:51 +0100162 * Check the contents of a directory that we've just read.
163 */
164static bool afs_dir_check_pages(struct afs_vnode *dvnode, struct afs_read *req)
165{
166 struct afs_xdr_dir_page *dbuf;
167 unsigned int i, j, qty = PAGE_SIZE / sizeof(union afs_xdr_dir_block);
168
169 for (i = 0; i < req->nr_pages; i++)
170 if (!afs_dir_check_page(dvnode, req->pages[i], req->actual_len))
171 goto bad;
172 return true;
173
174bad:
175 pr_warn("DIR %llx:%llx f=%llx l=%llx al=%llx r=%llx\n",
176 dvnode->fid.vid, dvnode->fid.vnode,
177 req->file_size, req->len, req->actual_len, req->remain);
178 pr_warn("DIR %llx %x %x %x\n",
179 req->pos, req->index, req->nr_pages, req->offset);
180
181 for (i = 0; i < req->nr_pages; i++) {
182 dbuf = kmap(req->pages[i]);
183 for (j = 0; j < qty; j++) {
184 union afs_xdr_dir_block *block = &dbuf->blocks[j];
185
186 pr_warn("[%02x] %32phN\n", i * qty + j, block);
187 }
188 kunmap(req->pages[i]);
189 }
190 return false;
191}
192
193/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194 * open an AFS directory file
195 */
196static int afs_dir_open(struct inode *inode, struct file *file)
197{
198 _enter("{%lu}", inode->i_ino);
199
David Howells00317632018-04-06 14:17:25 +0100200 BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
201 BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202
David Howells08e0e7c2007-04-26 15:55:03 -0700203 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700204 return -ENOENT;
205
David Howells00d3b7a2007-04-26 15:57:07 -0700206 return afs_open(inode, file);
David Howellsec268152007-04-26 15:49:28 -0700207}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Linus Torvalds1da177e2005-04-16 15:20:36 -0700209/*
David Howellsf3ddee82018-04-06 14:17:25 +0100210 * Read the directory into the pagecache in one go, scrubbing the previous
211 * contents. The list of pages is returned, pinning them so that they don't
212 * get reclaimed during the iteration.
213 */
214static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
David Howellsb61f7dc2018-04-27 20:46:22 +0100215 __acquires(&dvnode->validate_lock)
David Howellsf3ddee82018-04-06 14:17:25 +0100216{
217 struct afs_read *req;
218 loff_t i_size;
219 int nr_pages, nr_inline, i, n;
220 int ret = -ENOMEM;
221
222retry:
223 i_size = i_size_read(&dvnode->vfs_inode);
224 if (i_size < 2048)
David Howellsf51375c2018-10-20 00:57:57 +0100225 return ERR_PTR(afs_bad(dvnode, afs_file_error_dir_small));
226 if (i_size > 2048 * 1024) {
227 trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big);
David Howellsf3ddee82018-04-06 14:17:25 +0100228 return ERR_PTR(-EFBIG);
David Howellsf51375c2018-10-20 00:57:57 +0100229 }
David Howellsf3ddee82018-04-06 14:17:25 +0100230
231 _enter("%llu", i_size);
232
233 /* Get a request record to hold the page list. We want to hold it
234 * inline if we can, but we don't want to make an order 1 allocation.
235 */
236 nr_pages = (i_size + PAGE_SIZE - 1) / PAGE_SIZE;
237 nr_inline = nr_pages;
238 if (nr_inline > (PAGE_SIZE - sizeof(*req)) / sizeof(struct page *))
239 nr_inline = 0;
240
Zhengyuan Liuee102582019-06-20 18:12:17 +0100241 req = kzalloc(struct_size(req, array, nr_inline), GFP_KERNEL);
David Howellsf3ddee82018-04-06 14:17:25 +0100242 if (!req)
243 return ERR_PTR(-ENOMEM);
244
245 refcount_set(&req->usage, 1);
246 req->nr_pages = nr_pages;
247 req->actual_len = i_size; /* May change */
248 req->len = nr_pages * PAGE_SIZE; /* We can ask for more than there is */
249 req->data_version = dvnode->status.data_version; /* May change */
250 if (nr_inline > 0) {
251 req->pages = req->array;
252 } else {
253 req->pages = kcalloc(nr_pages, sizeof(struct page *),
254 GFP_KERNEL);
255 if (!req->pages)
256 goto error;
257 }
258
259 /* Get a list of all the pages that hold or will hold the directory
260 * content. We need to fill in any gaps that we might find where the
261 * memory reclaimer has been at work. If there are any gaps, we will
262 * need to reread the entire directory contents.
263 */
264 i = 0;
265 do {
266 n = find_get_pages_contig(dvnode->vfs_inode.i_mapping, i,
267 req->nr_pages - i,
268 req->pages + i);
269 _debug("find %u at %u/%u", n, i, req->nr_pages);
270 if (n == 0) {
271 gfp_t gfp = dvnode->vfs_inode.i_mapping->gfp_mask;
272
273 if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
274 afs_stat_v(dvnode, n_inval);
275
276 ret = -ENOMEM;
277 req->pages[i] = __page_cache_alloc(gfp);
278 if (!req->pages[i])
279 goto error;
280 ret = add_to_page_cache_lru(req->pages[i],
281 dvnode->vfs_inode.i_mapping,
282 i, gfp);
283 if (ret < 0)
284 goto error;
285
286 set_page_private(req->pages[i], 1);
287 SetPagePrivate(req->pages[i]);
288 unlock_page(req->pages[i]);
289 i++;
290 } else {
291 i += n;
292 }
293 } while (i < req->nr_pages);
294
295 /* If we're going to reload, we need to lock all the pages to prevent
296 * races.
297 */
David Howellsb61f7dc2018-04-27 20:46:22 +0100298 ret = -ERESTARTSYS;
299 if (down_read_killable(&dvnode->validate_lock) < 0)
300 goto error;
301
302 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
303 goto success;
304
305 up_read(&dvnode->validate_lock);
306 if (down_write_killable(&dvnode->validate_lock) < 0)
307 goto error;
308
David Howellsf3ddee82018-04-06 14:17:25 +0100309 if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
David Howells99987c562019-04-25 14:26:51 +0100310 trace_afs_reload_dir(dvnode);
David Howellsf3ddee82018-04-06 14:17:25 +0100311 ret = afs_fetch_data(dvnode, key, req);
312 if (ret < 0)
David Howellsb61f7dc2018-04-27 20:46:22 +0100313 goto error_unlock;
David Howellsf3ddee82018-04-06 14:17:25 +0100314
315 task_io_account_read(PAGE_SIZE * req->nr_pages);
316
317 if (req->len < req->file_size)
318 goto content_has_grown;
319
320 /* Validate the data we just read. */
321 ret = -EIO;
David Howells445b1022019-04-25 14:26:51 +0100322 if (!afs_dir_check_pages(dvnode, req))
323 goto error_unlock;
David Howellsf3ddee82018-04-06 14:17:25 +0100324
325 // TODO: Trim excess pages
326
327 set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags);
328 }
329
David Howellsb61f7dc2018-04-27 20:46:22 +0100330 downgrade_write(&dvnode->validate_lock);
David Howellsf3ddee82018-04-06 14:17:25 +0100331success:
David Howellsf3ddee82018-04-06 14:17:25 +0100332 return req;
333
David Howellsf3ddee82018-04-06 14:17:25 +0100334error_unlock:
David Howellsb61f7dc2018-04-27 20:46:22 +0100335 up_write(&dvnode->validate_lock);
David Howellsf3ddee82018-04-06 14:17:25 +0100336error:
337 afs_put_read(req);
338 _leave(" = %d", ret);
339 return ERR_PTR(ret);
340
341content_has_grown:
David Howellsb61f7dc2018-04-27 20:46:22 +0100342 up_write(&dvnode->validate_lock);
David Howellsf3ddee82018-04-06 14:17:25 +0100343 afs_put_read(req);
344 goto retry;
345}
346
347/*
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 * deal with one block in an AFS directory
349 */
David Howellsf51375c2018-10-20 00:57:57 +0100350static int afs_dir_iterate_block(struct afs_vnode *dvnode,
351 struct dir_context *ctx,
David Howells00317632018-04-06 14:17:25 +0100352 union afs_xdr_dir_block *block,
Al Viro1bbae9f2013-05-22 16:31:14 -0400353 unsigned blkoff)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354{
David Howells00317632018-04-06 14:17:25 +0100355 union afs_xdr_dirent *dire;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 unsigned offset, next, curr;
357 size_t nlen;
Al Viro1bbae9f2013-05-22 16:31:14 -0400358 int tmp;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359
Al Viro1bbae9f2013-05-22 16:31:14 -0400360 _enter("%u,%x,%p,,",(unsigned)ctx->pos,blkoff,block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700361
David Howells00317632018-04-06 14:17:25 +0100362 curr = (ctx->pos - blkoff) / sizeof(union afs_xdr_dirent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363
364 /* walk through the block, an entry at a time */
David Howells4ea219a2018-04-06 14:17:25 +0100365 for (offset = (blkoff == 0 ? AFS_DIR_RESV_BLOCKS0 : AFS_DIR_RESV_BLOCKS);
366 offset < AFS_DIR_SLOTS_PER_BLOCK;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700367 offset = next
368 ) {
369 next = offset + 1;
370
371 /* skip entries marked unused in the bitmap */
David Howells00317632018-04-06 14:17:25 +0100372 if (!(block->hdr.bitmap[offset / 8] &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700373 (1 << (offset % 8)))) {
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -0800374 _debug("ENT[%zu.%u]: unused",
David Howells00317632018-04-06 14:17:25 +0100375 blkoff / sizeof(union afs_xdr_dir_block), offset);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700376 if (offset >= curr)
Al Viro1bbae9f2013-05-22 16:31:14 -0400377 ctx->pos = blkoff +
David Howells00317632018-04-06 14:17:25 +0100378 next * sizeof(union afs_xdr_dirent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700379 continue;
380 }
381
382 /* got a valid entry */
383 dire = &block->dirents[offset];
384 nlen = strnlen(dire->u.name,
385 sizeof(*block) -
David Howells00317632018-04-06 14:17:25 +0100386 offset * sizeof(union afs_xdr_dirent));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -0800388 _debug("ENT[%zu.%u]: %s %zu \"%s\"",
David Howells00317632018-04-06 14:17:25 +0100389 blkoff / sizeof(union afs_xdr_dir_block), offset,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390 (offset < curr ? "skip" : "fill"),
391 nlen, dire->u.name);
392
393 /* work out where the next possible entry is */
David Howells00317632018-04-06 14:17:25 +0100394 for (tmp = nlen; tmp > 15; tmp -= sizeof(union afs_xdr_dirent)) {
David Howells4ea219a2018-04-06 14:17:25 +0100395 if (next >= AFS_DIR_SLOTS_PER_BLOCK) {
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -0800396 _debug("ENT[%zu.%u]:"
Linus Torvalds1da177e2005-04-16 15:20:36 -0700397 " %u travelled beyond end dir block"
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -0800398 " (len %u/%zu)",
David Howells00317632018-04-06 14:17:25 +0100399 blkoff / sizeof(union afs_xdr_dir_block),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700400 offset, next, tmp, nlen);
David Howellsf51375c2018-10-20 00:57:57 +0100401 return afs_bad(dvnode, afs_file_error_dir_over_end);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402 }
David Howells00317632018-04-06 14:17:25 +0100403 if (!(block->hdr.bitmap[next / 8] &
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404 (1 << (next % 8)))) {
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -0800405 _debug("ENT[%zu.%u]:"
406 " %u unmarked extension (len %u/%zu)",
David Howells00317632018-04-06 14:17:25 +0100407 blkoff / sizeof(union afs_xdr_dir_block),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700408 offset, next, tmp, nlen);
David Howellsf51375c2018-10-20 00:57:57 +0100409 return afs_bad(dvnode, afs_file_error_dir_unmarked_ext);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700410 }
411
Alexey Dobriyan5b5e0922017-02-27 14:30:02 -0800412 _debug("ENT[%zu.%u]: ext %u/%zu",
David Howells00317632018-04-06 14:17:25 +0100413 blkoff / sizeof(union afs_xdr_dir_block),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700414 next, tmp, nlen);
415 next++;
416 }
417
418 /* skip if starts before the current position */
419 if (offset < curr)
420 continue;
421
422 /* found the next entry */
Al Viro1bbae9f2013-05-22 16:31:14 -0400423 if (!dir_emit(ctx, dire->u.name, nlen,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 ntohl(dire->u.vnode),
David Howells5cf9dd52018-04-09 21:12:31 +0100425 (ctx->actor == afs_lookup_filldir ||
426 ctx->actor == afs_lookup_one_filldir)?
Al Viro1bbae9f2013-05-22 16:31:14 -0400427 ntohl(dire->u.unique) : DT_UNKNOWN)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 _leave(" = 0 [full]");
429 return 0;
430 }
431
David Howells00317632018-04-06 14:17:25 +0100432 ctx->pos = blkoff + next * sizeof(union afs_xdr_dirent);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433 }
434
435 _leave(" = 1 [more]");
436 return 1;
David Howellsec268152007-04-26 15:49:28 -0700437}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439/*
David Howells08e0e7c2007-04-26 15:55:03 -0700440 * iterate through the data blob that lists the contents of an AFS directory
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441 */
Al Viro1bbae9f2013-05-22 16:31:14 -0400442static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
David Howells9dd0b822019-07-30 14:38:52 +0100443 struct key *key, afs_dataversion_t *_dir_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444{
David Howellsf3ddee82018-04-06 14:17:25 +0100445 struct afs_vnode *dvnode = AFS_FS_I(dir);
David Howells00317632018-04-06 14:17:25 +0100446 struct afs_xdr_dir_page *dbuf;
447 union afs_xdr_dir_block *dblock;
David Howellsf3ddee82018-04-06 14:17:25 +0100448 struct afs_read *req;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449 struct page *page;
450 unsigned blkoff, limit;
451 int ret;
452
Al Viro1bbae9f2013-05-22 16:31:14 -0400453 _enter("{%lu},%u,,", dir->i_ino, (unsigned)ctx->pos);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454
David Howells08e0e7c2007-04-26 15:55:03 -0700455 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 _leave(" = -ESTALE");
457 return -ESTALE;
458 }
459
David Howellsf3ddee82018-04-06 14:17:25 +0100460 req = afs_read_dir(dvnode, key);
461 if (IS_ERR(req))
462 return PTR_ERR(req);
David Howells9dd0b822019-07-30 14:38:52 +0100463 *_dir_version = req->data_version;
David Howellsf3ddee82018-04-06 14:17:25 +0100464
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 /* round the file position up to the next entry boundary */
David Howells00317632018-04-06 14:17:25 +0100466 ctx->pos += sizeof(union afs_xdr_dirent) - 1;
467 ctx->pos &= ~(sizeof(union afs_xdr_dirent) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468
469 /* walk through the blocks in sequence */
470 ret = 0;
David Howellsf3ddee82018-04-06 14:17:25 +0100471 while (ctx->pos < req->actual_len) {
David Howells00317632018-04-06 14:17:25 +0100472 blkoff = ctx->pos & ~(sizeof(union afs_xdr_dir_block) - 1);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700473
David Howellsf3ddee82018-04-06 14:17:25 +0100474 /* Fetch the appropriate page from the directory and re-add it
475 * to the LRU.
476 */
477 page = req->pages[blkoff / PAGE_SIZE];
478 if (!page) {
David Howellsf51375c2018-10-20 00:57:57 +0100479 ret = afs_bad(dvnode, afs_file_error_dir_missing_page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700480 break;
481 }
David Howellsf3ddee82018-04-06 14:17:25 +0100482 mark_page_accessed(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700483
484 limit = blkoff & ~(PAGE_SIZE - 1);
485
David Howellsf3ddee82018-04-06 14:17:25 +0100486 dbuf = kmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 /* deal with the individual blocks stashed on this page */
489 do {
490 dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /
David Howells00317632018-04-06 14:17:25 +0100491 sizeof(union afs_xdr_dir_block)];
David Howellsf51375c2018-10-20 00:57:57 +0100492 ret = afs_dir_iterate_block(dvnode, ctx, dblock, blkoff);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 if (ret != 1) {
David Howellsf3ddee82018-04-06 14:17:25 +0100494 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 goto out;
496 }
497
David Howells00317632018-04-06 14:17:25 +0100498 blkoff += sizeof(union afs_xdr_dir_block);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700499
Al Viro1bbae9f2013-05-22 16:31:14 -0400500 } while (ctx->pos < dir->i_size && blkoff < limit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501
David Howellsf3ddee82018-04-06 14:17:25 +0100502 kunmap(page);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 ret = 0;
504 }
505
David Howellsec268152007-04-26 15:49:28 -0700506out:
David Howellsb61f7dc2018-04-27 20:46:22 +0100507 up_read(&dvnode->validate_lock);
David Howellsf3ddee82018-04-06 14:17:25 +0100508 afs_put_read(req);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 _leave(" = %d", ret);
510 return ret;
David Howellsec268152007-04-26 15:49:28 -0700511}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512
Linus Torvalds1da177e2005-04-16 15:20:36 -0700513/*
514 * read an AFS directory
515 */
Al Viro1bbae9f2013-05-22 16:31:14 -0400516static int afs_readdir(struct file *file, struct dir_context *ctx)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517{
David Howells9dd0b822019-07-30 14:38:52 +0100518 afs_dataversion_t dir_version;
519
520 return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file),
521 &dir_version);
David Howellsec268152007-04-26 15:49:28 -0700522}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524/*
David Howells5cf9dd52018-04-09 21:12:31 +0100525 * Search the directory for a single name
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
527 * uniquifier through dtype
528 */
David Howells5cf9dd52018-04-09 21:12:31 +0100529static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
530 int nlen, loff_t fpos, u64 ino, unsigned dtype)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531{
David Howells5cf9dd52018-04-09 21:12:31 +0100532 struct afs_lookup_one_cookie *cookie =
533 container_of(ctx, struct afs_lookup_one_cookie, ctx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534
Al Viro1bbae9f2013-05-22 16:31:14 -0400535 _enter("{%s,%u},%s,%u,,%llu,%u",
536 cookie->name.name, cookie->name.len, name, nlen,
David S. Millerba3e0e12007-04-26 16:06:22 -0700537 (unsigned long long) ino, dtype);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538
David Howells08e0e7c2007-04-26 15:55:03 -0700539 /* insanity checks first */
David Howells00317632018-04-06 14:17:25 +0100540 BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
541 BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
David Howells08e0e7c2007-04-26 15:55:03 -0700542
Al Viro1bbae9f2013-05-22 16:31:14 -0400543 if (cookie->name.len != nlen ||
544 memcmp(cookie->name.name, name, nlen) != 0) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545 _leave(" = 0 [no]");
546 return 0;
547 }
548
549 cookie->fid.vnode = ino;
550 cookie->fid.unique = dtype;
551 cookie->found = 1;
552
553 _leave(" = -1 [found]");
554 return -1;
David Howellsec268152007-04-26 15:49:28 -0700555}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557/*
David Howells5cf9dd52018-04-09 21:12:31 +0100558 * Do a lookup of a single name in a directory
David Howells260a9802007-04-26 15:59:35 -0700559 * - just returns the FID the dentry name maps to if found
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 */
David Howells5cf9dd52018-04-09 21:12:31 +0100561static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
David Howells9dd0b822019-07-30 14:38:52 +0100562 struct afs_fid *fid, struct key *key,
563 afs_dataversion_t *_dir_version)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564{
Al Viro1bbae9f2013-05-22 16:31:14 -0400565 struct afs_super_info *as = dir->i_sb->s_fs_info;
David Howells5cf9dd52018-04-09 21:12:31 +0100566 struct afs_lookup_one_cookie cookie = {
567 .ctx.actor = afs_lookup_one_filldir,
Al Viro1bbae9f2013-05-22 16:31:14 -0400568 .name = dentry->d_name,
569 .fid.vid = as->volume->vid
570 };
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571 int ret;
572
Al Viroa4555892014-10-21 20:11:25 -0400573 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575 /* search the directory */
David Howells9dd0b822019-07-30 14:38:52 +0100576 ret = afs_dir_iterate(dir, &cookie.ctx, key, _dir_version);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 if (ret < 0) {
David Howells08e0e7c2007-04-26 15:55:03 -0700578 _leave(" = %d [iter]", ret);
579 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580 }
581
582 ret = -ENOENT;
583 if (!cookie.found) {
David Howells08e0e7c2007-04-26 15:55:03 -0700584 _leave(" = -ENOENT [not found]");
585 return -ENOENT;
586 }
587
588 *fid = cookie.fid;
David Howells3b6492d2018-10-20 00:57:57 +0100589 _leave(" = 0 { vn=%llu u=%u }", fid->vnode, fid->unique);
David Howells08e0e7c2007-04-26 15:55:03 -0700590 return 0;
591}
592
593/*
David Howells5cf9dd52018-04-09 21:12:31 +0100594 * search the directory for a name
595 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
596 * uniquifier through dtype
597 */
598static int afs_lookup_filldir(struct dir_context *ctx, const char *name,
599 int nlen, loff_t fpos, u64 ino, unsigned dtype)
600{
601 struct afs_lookup_cookie *cookie =
602 container_of(ctx, struct afs_lookup_cookie, ctx);
603 int ret;
604
605 _enter("{%s,%u},%s,%u,,%llu,%u",
606 cookie->name.name, cookie->name.len, name, nlen,
607 (unsigned long long) ino, dtype);
608
609 /* insanity checks first */
David Howells00317632018-04-06 14:17:25 +0100610 BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
611 BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
David Howells5cf9dd52018-04-09 21:12:31 +0100612
613 if (cookie->found) {
614 if (cookie->nr_fids < 50) {
615 cookie->fids[cookie->nr_fids].vnode = ino;
616 cookie->fids[cookie->nr_fids].unique = dtype;
617 cookie->nr_fids++;
618 }
619 } else if (cookie->name.len == nlen &&
620 memcmp(cookie->name.name, name, nlen) == 0) {
621 cookie->fids[0].vnode = ino;
622 cookie->fids[0].unique = dtype;
623 cookie->found = 1;
624 if (cookie->one_only)
625 return -1;
626 }
627
628 ret = cookie->nr_fids >= 50 ? -1 : 0;
629 _leave(" = %d", ret);
630 return ret;
631}
632
633/*
634 * Do a lookup in a directory. We make use of bulk lookup to query a slew of
635 * files in one go and create inodes for them. The inode of the file we were
636 * asked for is returned.
637 */
638static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
639 struct key *key)
640{
641 struct afs_lookup_cookie *cookie;
David Howellsf6424042019-05-13 16:14:32 +0100642 struct afs_cb_interest *dcbi, *cbi = NULL;
David Howells5cf9dd52018-04-09 21:12:31 +0100643 struct afs_super_info *as = dir->i_sb->s_fs_info;
David Howells87182752019-05-09 16:17:05 +0100644 struct afs_status_cb *scb;
David Howellsb8359152019-05-14 12:23:43 +0100645 struct afs_iget_data iget_data;
David Howells5cf9dd52018-04-09 21:12:31 +0100646 struct afs_fs_cursor fc;
David Howellsf6424042019-05-13 16:14:32 +0100647 struct afs_server *server;
David Howells39db9812019-05-14 12:33:10 +0100648 struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
649 struct inode *inode = NULL, *ti;
David Howells9dd0b822019-07-30 14:38:52 +0100650 afs_dataversion_t data_version = READ_ONCE(dvnode->status.data_version);
David Howells5cf9dd52018-04-09 21:12:31 +0100651 int ret, i;
652
653 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
654
655 cookie = kzalloc(sizeof(struct afs_lookup_cookie), GFP_KERNEL);
656 if (!cookie)
657 return ERR_PTR(-ENOMEM);
658
659 cookie->ctx.actor = afs_lookup_filldir;
660 cookie->name = dentry->d_name;
661 cookie->nr_fids = 1; /* slot 0 is saved for the fid we actually want */
662
663 read_seqlock_excl(&dvnode->cb_lock);
David Howellsf6424042019-05-13 16:14:32 +0100664 dcbi = rcu_dereference_protected(dvnode->cb_interest,
665 lockdep_is_held(&dvnode->cb_lock.lock));
666 if (dcbi) {
667 server = dcbi->server;
668 if (server &&
669 test_bit(AFS_SERVER_FL_NO_IBULK, &server->flags))
670 cookie->one_only = true;
671 }
David Howells5cf9dd52018-04-09 21:12:31 +0100672 read_sequnlock_excl(&dvnode->cb_lock);
673
674 for (i = 0; i < 50; i++)
675 cookie->fids[i].vid = as->volume->vid;
676
677 /* search the directory */
David Howells9dd0b822019-07-30 14:38:52 +0100678 ret = afs_dir_iterate(dir, &cookie->ctx, key, &data_version);
David Howells5cf9dd52018-04-09 21:12:31 +0100679 if (ret < 0) {
680 inode = ERR_PTR(ret);
681 goto out;
682 }
683
David Howells9dd0b822019-07-30 14:38:52 +0100684 dentry->d_fsdata = (void *)(unsigned long)data_version;
685
David Howells5cf9dd52018-04-09 21:12:31 +0100686 inode = ERR_PTR(-ENOENT);
687 if (!cookie->found)
688 goto out;
689
690 /* Check to see if we already have an inode for the primary fid. */
David Howellsb8359152019-05-14 12:23:43 +0100691 iget_data.fid = cookie->fids[0];
692 iget_data.volume = dvnode->volume;
693 iget_data.cb_v_break = dvnode->volume->cb_v_break;
694 iget_data.cb_s_break = 0;
695 inode = ilookup5(dir->i_sb, cookie->fids[0].vnode,
696 afs_iget5_test, &iget_data);
David Howells5cf9dd52018-04-09 21:12:31 +0100697 if (inode)
698 goto out;
699
700 /* Need space for examining all the selected files */
701 inode = ERR_PTR(-ENOMEM);
David Howells87182752019-05-09 16:17:05 +0100702 cookie->statuses = kvcalloc(cookie->nr_fids, sizeof(struct afs_status_cb),
703 GFP_KERNEL);
David Howells5cf9dd52018-04-09 21:12:31 +0100704 if (!cookie->statuses)
705 goto out;
706
David Howells39db9812019-05-14 12:33:10 +0100707 cookie->inodes = kcalloc(cookie->nr_fids, sizeof(struct inode *),
708 GFP_KERNEL);
709 if (!cookie->inodes)
710 goto out_s;
711
712 for (i = 1; i < cookie->nr_fids; i++) {
713 scb = &cookie->statuses[i];
714
715 /* Find any inodes that already exist and get their
716 * callback counters.
717 */
718 iget_data.fid = cookie->fids[i];
719 ti = ilookup5_nowait(dir->i_sb, iget_data.fid.vnode,
720 afs_iget5_test, &iget_data);
721 if (!IS_ERR_OR_NULL(ti)) {
722 vnode = AFS_FS_I(ti);
723 scb->cb_break = afs_calc_vnode_cb_break(vnode);
724 cookie->inodes[i] = ti;
725 }
726 }
727
David Howells5cf9dd52018-04-09 21:12:31 +0100728 /* Try FS.InlineBulkStatus first. Abort codes for the individual
729 * lookups contained therein are stored in the reply without aborting
730 * the whole operation.
731 */
732 if (cookie->one_only)
733 goto no_inline_bulk_status;
734
735 inode = ERR_PTR(-ERESTARTSYS);
David Howells20b83912019-05-08 16:16:31 +0100736 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
David Howells5cf9dd52018-04-09 21:12:31 +0100737 while (afs_select_fileserver(&fc)) {
738 if (test_bit(AFS_SERVER_FL_NO_IBULK,
739 &fc.cbi->server->flags)) {
740 fc.ac.abort_code = RX_INVALID_OPERATION;
741 fc.ac.error = -ECONNABORTED;
742 break;
743 }
David Howellsb8359152019-05-14 12:23:43 +0100744 iget_data.cb_v_break = dvnode->volume->cb_v_break;
745 iget_data.cb_s_break = fc.cbi->server->cb_s_break;
David Howells5cf9dd52018-04-09 21:12:31 +0100746 afs_fs_inline_bulk_status(&fc,
747 afs_v2net(dvnode),
748 cookie->fids,
749 cookie->statuses,
David Howells5cf9dd52018-04-09 21:12:31 +0100750 cookie->nr_fids, NULL);
751 }
752
753 if (fc.ac.error == 0)
754 cbi = afs_get_cb_interest(fc.cbi);
755 if (fc.ac.abort_code == RX_INVALID_OPERATION)
756 set_bit(AFS_SERVER_FL_NO_IBULK, &fc.cbi->server->flags);
757 inode = ERR_PTR(afs_end_vnode_operation(&fc));
758 }
759
760 if (!IS_ERR(inode))
761 goto success;
762 if (fc.ac.abort_code != RX_INVALID_OPERATION)
763 goto out_c;
764
765no_inline_bulk_status:
766 /* We could try FS.BulkStatus next, but this aborts the entire op if
767 * any of the lookups fails - so, for the moment, revert to
768 * FS.FetchStatus for just the primary fid.
769 */
David Howells5cf9dd52018-04-09 21:12:31 +0100770 inode = ERR_PTR(-ERESTARTSYS);
David Howells20b83912019-05-08 16:16:31 +0100771 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
David Howells5cf9dd52018-04-09 21:12:31 +0100772 while (afs_select_fileserver(&fc)) {
David Howellsb8359152019-05-14 12:23:43 +0100773 iget_data.cb_v_break = dvnode->volume->cb_v_break;
774 iget_data.cb_s_break = fc.cbi->server->cb_s_break;
David Howells87182752019-05-09 16:17:05 +0100775 scb = &cookie->statuses[0];
David Howells5cf9dd52018-04-09 21:12:31 +0100776 afs_fs_fetch_status(&fc,
777 afs_v2net(dvnode),
778 cookie->fids,
David Howellsa58823a2019-05-09 15:16:10 +0100779 scb,
David Howells5cf9dd52018-04-09 21:12:31 +0100780 NULL);
781 }
782
783 if (fc.ac.error == 0)
784 cbi = afs_get_cb_interest(fc.cbi);
785 inode = ERR_PTR(afs_end_vnode_operation(&fc));
786 }
787
788 if (IS_ERR(inode))
789 goto out_c;
790
David Howells5cf9dd52018-04-09 21:12:31 +0100791success:
792 /* Turn all the files into inodes and save the first one - which is the
793 * one we actually want.
794 */
David Howells87182752019-05-09 16:17:05 +0100795 scb = &cookie->statuses[0];
796 if (scb->status.abort_code != 0)
797 inode = ERR_PTR(afs_abort_to_error(scb->status.abort_code));
David Howells5cf9dd52018-04-09 21:12:31 +0100798
799 for (i = 0; i < cookie->nr_fids; i++) {
David Howells87182752019-05-09 16:17:05 +0100800 struct afs_status_cb *scb = &cookie->statuses[i];
David Howells39db9812019-05-14 12:33:10 +0100801
802 if (!scb->have_status && !scb->have_error)
803 continue;
804
805 if (cookie->inodes[i]) {
David Howellsa28f2392019-11-14 18:41:03 +0000806 struct afs_vnode *iv = AFS_FS_I(cookie->inodes[i]);
807
808 if (test_bit(AFS_VNODE_UNSET, &iv->flags))
809 continue;
810
811 afs_vnode_commit_status(&fc, iv,
David Howells39db9812019-05-14 12:33:10 +0100812 scb->cb_break, NULL, scb);
813 continue;
814 }
David Howells5cf9dd52018-04-09 21:12:31 +0100815
David Howells87182752019-05-09 16:17:05 +0100816 if (scb->status.abort_code != 0)
David Howells5cf9dd52018-04-09 21:12:31 +0100817 continue;
818
David Howellsb8359152019-05-14 12:23:43 +0100819 iget_data.fid = cookie->fids[i];
820 ti = afs_iget(dir->i_sb, key, &iget_data, scb, cbi, dvnode);
David Howells39db9812019-05-14 12:33:10 +0100821 if (!IS_ERR(ti))
822 afs_cache_permit(AFS_FS_I(ti), key,
823 0 /* Assume vnode->cb_break is 0 */ +
824 iget_data.cb_v_break,
825 scb);
David Howells5cf9dd52018-04-09 21:12:31 +0100826 if (i == 0) {
827 inode = ti;
828 } else {
829 if (!IS_ERR(ti))
830 iput(ti);
831 }
832 }
833
834out_c:
835 afs_put_cb_interest(afs_v2net(dvnode), cbi);
David Howells39db9812019-05-14 12:33:10 +0100836 if (cookie->inodes) {
837 for (i = 0; i < cookie->nr_fids; i++)
838 iput(cookie->inodes[i]);
839 kfree(cookie->inodes);
840 }
841out_s:
David Howells87182752019-05-09 16:17:05 +0100842 kvfree(cookie->statuses);
David Howells5cf9dd52018-04-09 21:12:31 +0100843out:
844 kfree(cookie);
845 return inode;
846}
847
848/*
David Howells6f8880d2018-04-09 21:12:31 +0100849 * Look up an entry in a directory with @sys substitution.
850 */
851static struct dentry *afs_lookup_atsys(struct inode *dir, struct dentry *dentry,
852 struct key *key)
853{
854 struct afs_sysnames *subs;
855 struct afs_net *net = afs_i2net(dir);
856 struct dentry *ret;
857 char *buf, *p, *name;
858 int len, i;
859
860 _enter("");
861
862 ret = ERR_PTR(-ENOMEM);
863 p = buf = kmalloc(AFSNAMEMAX, GFP_KERNEL);
864 if (!buf)
865 goto out_p;
866 if (dentry->d_name.len > 4) {
867 memcpy(p, dentry->d_name.name, dentry->d_name.len - 4);
868 p += dentry->d_name.len - 4;
869 }
870
871 /* There is an ordered list of substitutes that we have to try. */
872 read_lock(&net->sysnames_lock);
873 subs = net->sysnames;
874 refcount_inc(&subs->usage);
875 read_unlock(&net->sysnames_lock);
876
877 for (i = 0; i < subs->nr; i++) {
878 name = subs->subs[i];
879 len = dentry->d_name.len - 4 + strlen(name);
880 if (len >= AFSNAMEMAX) {
881 ret = ERR_PTR(-ENAMETOOLONG);
882 goto out_s;
883 }
884
885 strcpy(p, name);
886 ret = lookup_one_len(buf, dentry->d_parent, len);
887 if (IS_ERR(ret) || d_is_positive(ret))
888 goto out_s;
889 dput(ret);
890 }
891
892 /* We don't want to d_add() the @sys dentry here as we don't want to
893 * the cached dentry to hide changes to the sysnames list.
894 */
895 ret = NULL;
896out_s:
897 afs_put_sysnames(subs);
898 kfree(buf);
899out_p:
900 key_put(key);
901 return ret;
902}
903
904/*
David Howells08e0e7c2007-04-26 15:55:03 -0700905 * look up an entry in a directory
906 */
David Howells260a9802007-04-26 15:59:35 -0700907static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
Al Viro00cd8dd2012-06-10 17:13:09 -0400908 unsigned int flags)
David Howells08e0e7c2007-04-26 15:55:03 -0700909{
David Howells5cf9dd52018-04-09 21:12:31 +0100910 struct afs_vnode *dvnode = AFS_FS_I(dir);
David Howells40a708b2020-01-14 16:16:25 +0000911 struct afs_fid fid = {};
David Howells08e0e7c2007-04-26 15:55:03 -0700912 struct inode *inode;
Al Viro34b2a882018-06-24 10:43:51 -0400913 struct dentry *d;
David Howells00d3b7a2007-04-26 15:57:07 -0700914 struct key *key;
David Howells08e0e7c2007-04-26 15:55:03 -0700915 int ret;
916
David Howells3b6492d2018-10-20 00:57:57 +0100917 _enter("{%llx:%llu},%p{%pd},",
David Howells5cf9dd52018-04-09 21:12:31 +0100918 dvnode->fid.vid, dvnode->fid.vnode, dentry, dentry);
David Howells260a9802007-04-26 15:59:35 -0700919
David Howells2b0143b2015-03-17 22:25:59 +0000920 ASSERTCMP(d_inode(dentry), ==, NULL);
David Howells08e0e7c2007-04-26 15:55:03 -0700921
David Howells45222b92007-05-10 22:22:20 -0700922 if (dentry->d_name.len >= AFSNAMEMAX) {
David Howells08e0e7c2007-04-26 15:55:03 -0700923 _leave(" = -ENAMETOOLONG");
924 return ERR_PTR(-ENAMETOOLONG);
925 }
926
David Howells5cf9dd52018-04-09 21:12:31 +0100927 if (test_bit(AFS_VNODE_DELETED, &dvnode->flags)) {
David Howells08e0e7c2007-04-26 15:55:03 -0700928 _leave(" = -ESTALE");
929 return ERR_PTR(-ESTALE);
930 }
931
David Howells5cf9dd52018-04-09 21:12:31 +0100932 key = afs_request_key(dvnode->volume->cell);
David Howells00d3b7a2007-04-26 15:57:07 -0700933 if (IS_ERR(key)) {
934 _leave(" = %ld [key]", PTR_ERR(key));
David Howellse231c2e2008-02-07 00:15:26 -0800935 return ERR_CAST(key);
David Howells00d3b7a2007-04-26 15:57:07 -0700936 }
937
David Howells5cf9dd52018-04-09 21:12:31 +0100938 ret = afs_validate(dvnode, key);
David Howells08e0e7c2007-04-26 15:55:03 -0700939 if (ret < 0) {
David Howells00d3b7a2007-04-26 15:57:07 -0700940 key_put(key);
David Howells260a9802007-04-26 15:59:35 -0700941 _leave(" = %d [val]", ret);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700942 return ERR_PTR(ret);
943 }
944
David Howells6f8880d2018-04-09 21:12:31 +0100945 if (dentry->d_name.len >= 4 &&
946 dentry->d_name.name[dentry->d_name.len - 4] == '@' &&
947 dentry->d_name.name[dentry->d_name.len - 3] == 's' &&
948 dentry->d_name.name[dentry->d_name.len - 2] == 'y' &&
949 dentry->d_name.name[dentry->d_name.len - 1] == 's')
950 return afs_lookup_atsys(dir, dentry, key);
951
David Howellsd55b4da2018-04-06 14:17:24 +0100952 afs_stat_v(dvnode, n_lookup);
David Howells5cf9dd52018-04-09 21:12:31 +0100953 inode = afs_do_lookup(dir, dentry, key);
David Howells00d3b7a2007-04-26 15:57:07 -0700954 key_put(key);
Al Viro34b2a882018-06-24 10:43:51 -0400955 if (inode == ERR_PTR(-ENOENT)) {
956 inode = afs_try_auto_mntpt(dentry, dir);
Al Viro34b2a882018-06-24 10:43:51 -0400957 } else {
958 dentry->d_fsdata =
959 (void *)(unsigned long)dvnode->status.data_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700960 }
David Howells40a708b2020-01-14 16:16:25 +0000961
962 if (!IS_ERR_OR_NULL(inode))
963 fid = AFS_FS_I(inode)->fid;
964
Al Viro34b2a882018-06-24 10:43:51 -0400965 d = d_splice_alias(inode, dentry);
David Howells80548b02019-04-25 14:26:51 +0100966 if (!IS_ERR_OR_NULL(d)) {
Al Viro34b2a882018-06-24 10:43:51 -0400967 d->d_fsdata = dentry->d_fsdata;
David Howells40a708b2020-01-14 16:16:25 +0000968 trace_afs_lookup(dvnode, &d->d_name, &fid);
David Howells80548b02019-04-25 14:26:51 +0100969 } else {
David Howells40a708b2020-01-14 16:16:25 +0000970 trace_afs_lookup(dvnode, &dentry->d_name, &fid);
David Howells80548b02019-04-25 14:26:51 +0100971 }
Al Viro34b2a882018-06-24 10:43:51 -0400972 return d;
David Howellsec268152007-04-26 15:49:28 -0700973}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975/*
David Howellsa0753c22019-05-20 08:48:46 +0100976 * Check the validity of a dentry under RCU conditions.
977 */
978static int afs_d_revalidate_rcu(struct dentry *dentry)
979{
980 struct afs_vnode *dvnode, *vnode;
981 struct dentry *parent;
982 struct inode *dir, *inode;
983 long dir_version, de_version;
984
985 _enter("%p", dentry);
986
987 /* Check the parent directory is still valid first. */
988 parent = READ_ONCE(dentry->d_parent);
989 dir = d_inode_rcu(parent);
990 if (!dir)
991 return -ECHILD;
992 dvnode = AFS_FS_I(dir);
993 if (test_bit(AFS_VNODE_DELETED, &dvnode->flags))
994 return -ECHILD;
995
996 if (!afs_check_validity(dvnode))
997 return -ECHILD;
998
999 /* We only need to invalidate a dentry if the server's copy changed
1000 * behind our back. If we made the change, it's no problem. Note that
1001 * on a 32-bit system, we only have 32 bits in the dentry to store the
1002 * version.
1003 */
1004 dir_version = (long)READ_ONCE(dvnode->status.data_version);
1005 de_version = (long)READ_ONCE(dentry->d_fsdata);
1006 if (de_version != dir_version) {
1007 dir_version = (long)READ_ONCE(dvnode->invalid_before);
1008 if (de_version - dir_version < 0)
1009 return -ECHILD;
1010 }
1011
1012 /* Check to see if the vnode referred to by the dentry still
1013 * has a callback.
1014 */
1015 if (d_really_is_positive(dentry)) {
1016 inode = d_inode_rcu(dentry);
1017 if (inode) {
1018 vnode = AFS_FS_I(inode);
1019 if (!afs_check_validity(vnode))
1020 return -ECHILD;
1021 }
1022 }
1023
1024 return 1; /* Still valid */
1025}
1026
1027/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 * check that a dentry lookup hit has found a valid entry
1029 * - NOTE! the hit can be a negative hit too, so we can't assume we have an
1030 * inode
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 */
Al Viro0b728e12012-06-10 16:03:43 -04001032static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033{
David Howells260a9802007-04-26 15:59:35 -07001034 struct afs_vnode *vnode, *dir;
Artem Bityutskiydd0d9a42009-07-09 10:44:30 +01001035 struct afs_fid uninitialized_var(fid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 struct dentry *parent;
David Howellsc435ee32017-11-02 15:27:49 +00001037 struct inode *inode;
David Howells00d3b7a2007-04-26 15:57:07 -07001038 struct key *key;
David Howells9dd0b822019-07-30 14:38:52 +01001039 afs_dataversion_t dir_version;
1040 long de_version;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 int ret;
1042
Al Viro0b728e12012-06-10 16:03:43 -04001043 if (flags & LOOKUP_RCU)
David Howellsa0753c22019-05-20 08:48:46 +01001044 return afs_d_revalidate_rcu(dentry);
Nick Piggin34286d62011-01-07 17:49:57 +11001045
David Howellsc435ee32017-11-02 15:27:49 +00001046 if (d_really_is_positive(dentry)) {
1047 vnode = AFS_FS_I(d_inode(dentry));
David Howells3b6492d2018-10-20 00:57:57 +01001048 _enter("{v={%llx:%llu} n=%pd fl=%lx},",
Al Viroa4555892014-10-21 20:11:25 -04001049 vnode->fid.vid, vnode->fid.vnode, dentry,
David Howells260a9802007-04-26 15:59:35 -07001050 vnode->flags);
David Howellsc435ee32017-11-02 15:27:49 +00001051 } else {
Al Viroa4555892014-10-21 20:11:25 -04001052 _enter("{neg n=%pd}", dentry);
David Howellsc435ee32017-11-02 15:27:49 +00001053 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054
David Howells260a9802007-04-26 15:59:35 -07001055 key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell);
David Howells00d3b7a2007-04-26 15:57:07 -07001056 if (IS_ERR(key))
1057 key = NULL;
1058
David Howellsc435ee32017-11-02 15:27:49 +00001059 if (d_really_is_positive(dentry)) {
1060 inode = d_inode(dentry);
1061 if (inode) {
1062 vnode = AFS_FS_I(inode);
1063 afs_validate(vnode, key);
1064 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
1065 goto out_bad;
1066 }
1067 }
1068
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 /* lock down the parent dentry so we can peer at it */
David Howells08e0e7c2007-04-26 15:55:03 -07001070 parent = dget_parent(dentry);
David Howells2b0143b2015-03-17 22:25:59 +00001071 dir = AFS_FS_I(d_inode(parent));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072
David Howells260a9802007-04-26 15:59:35 -07001073 /* validate the parent directory */
David Howellsc435ee32017-11-02 15:27:49 +00001074 afs_validate(dir, key);
David Howells260a9802007-04-26 15:59:35 -07001075
1076 if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
Al Viroa4555892014-10-21 20:11:25 -04001077 _debug("%pd: parent dir deleted", dentry);
David Howellsc435ee32017-11-02 15:27:49 +00001078 goto out_bad_parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 }
1080
David Howellsa4ff7402018-04-06 14:17:24 +01001081 /* We only need to invalidate a dentry if the server's copy changed
1082 * behind our back. If we made the change, it's no problem. Note that
1083 * on a 32-bit system, we only have 32 bits in the dentry to store the
1084 * version.
1085 */
David Howells9dd0b822019-07-30 14:38:52 +01001086 dir_version = dir->status.data_version;
David Howellsa4ff7402018-04-06 14:17:24 +01001087 de_version = (long)dentry->d_fsdata;
David Howells9dd0b822019-07-30 14:38:52 +01001088 if (de_version == (long)dir_version)
David Howells5dc84852019-07-30 14:38:51 +01001089 goto out_valid_noupdate;
David Howellsa4ff7402018-04-06 14:17:24 +01001090
David Howells9dd0b822019-07-30 14:38:52 +01001091 dir_version = dir->invalid_before;
1092 if (de_version - (long)dir_version >= 0)
David Howellsa4ff7402018-04-06 14:17:24 +01001093 goto out_valid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094
David Howells260a9802007-04-26 15:59:35 -07001095 _debug("dir modified");
David Howellsd55b4da2018-04-06 14:17:24 +01001096 afs_stat_v(dir, n_reval);
David Howells260a9802007-04-26 15:59:35 -07001097
1098 /* search the directory for this vnode */
David Howells9dd0b822019-07-30 14:38:52 +01001099 ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key, &dir_version);
David Howells260a9802007-04-26 15:59:35 -07001100 switch (ret) {
1101 case 0:
1102 /* the filename maps to something */
David Howells2b0143b2015-03-17 22:25:59 +00001103 if (d_really_is_negative(dentry))
David Howellsc435ee32017-11-02 15:27:49 +00001104 goto out_bad_parent;
1105 inode = d_inode(dentry);
1106 if (is_bad_inode(inode)) {
Al Viroa4555892014-10-21 20:11:25 -04001107 printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
1108 dentry);
David Howellsc435ee32017-11-02 15:27:49 +00001109 goto out_bad_parent;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110 }
1111
David Howellsc435ee32017-11-02 15:27:49 +00001112 vnode = AFS_FS_I(inode);
1113
Linus Torvalds1da177e2005-04-16 15:20:36 -07001114 /* if the vnode ID has changed, then the dirent points to a
1115 * different file */
David Howells08e0e7c2007-04-26 15:55:03 -07001116 if (fid.vnode != vnode->fid.vnode) {
David Howells3b6492d2018-10-20 00:57:57 +01001117 _debug("%pd: dirent changed [%llu != %llu]",
Al Viroa4555892014-10-21 20:11:25 -04001118 dentry, fid.vnode,
David Howells08e0e7c2007-04-26 15:55:03 -07001119 vnode->fid.vnode);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001120 goto not_found;
1121 }
1122
1123 /* if the vnode ID uniqifier has changed, then the file has
David Howells260a9802007-04-26 15:59:35 -07001124 * been deleted and replaced, and the original vnode ID has
1125 * been reused */
David Howells08e0e7c2007-04-26 15:55:03 -07001126 if (fid.unique != vnode->fid.unique) {
Al Viroa4555892014-10-21 20:11:25 -04001127 _debug("%pd: file deleted (uq %u -> %u I:%u)",
1128 dentry, fid.unique,
Jean Noel Cordenner7a224222008-01-28 23:58:27 -05001129 vnode->fid.unique,
David Howellsc435ee32017-11-02 15:27:49 +00001130 vnode->vfs_inode.i_generation);
1131 write_seqlock(&vnode->cb_lock);
David Howells08e0e7c2007-04-26 15:55:03 -07001132 set_bit(AFS_VNODE_DELETED, &vnode->flags);
David Howellsc435ee32017-11-02 15:27:49 +00001133 write_sequnlock(&vnode->cb_lock);
David Howells260a9802007-04-26 15:59:35 -07001134 goto not_found;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 }
David Howells260a9802007-04-26 15:59:35 -07001136 goto out_valid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137
David Howells260a9802007-04-26 15:59:35 -07001138 case -ENOENT:
1139 /* the filename is unknown */
Al Viroa4555892014-10-21 20:11:25 -04001140 _debug("%pd: dirent not found", dentry);
David Howells2b0143b2015-03-17 22:25:59 +00001141 if (d_really_is_positive(dentry))
David Howells260a9802007-04-26 15:59:35 -07001142 goto not_found;
1143 goto out_valid;
David Howells08e0e7c2007-04-26 15:55:03 -07001144
David Howells260a9802007-04-26 15:59:35 -07001145 default:
Al Viroa4555892014-10-21 20:11:25 -04001146 _debug("failed to iterate dir %pd: %d",
1147 parent, ret);
David Howellsc435ee32017-11-02 15:27:49 +00001148 goto out_bad_parent;
David Howells08e0e7c2007-04-26 15:55:03 -07001149 }
1150
David Howellsec268152007-04-26 15:49:28 -07001151out_valid:
David Howells9dd0b822019-07-30 14:38:52 +01001152 dentry->d_fsdata = (void *)(unsigned long)dir_version;
David Howells5dc84852019-07-30 14:38:51 +01001153out_valid_noupdate:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 dput(parent);
David Howells00d3b7a2007-04-26 15:57:07 -07001155 key_put(key);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156 _leave(" = 1 [valid]");
1157 return 1;
1158
1159 /* the dirent, if it exists, now points to a different vnode */
David Howellsec268152007-04-26 15:49:28 -07001160not_found:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 spin_lock(&dentry->d_lock);
1162 dentry->d_flags |= DCACHE_NFSFS_RENAMED;
1163 spin_unlock(&dentry->d_lock);
1164
David Howellsc435ee32017-11-02 15:27:49 +00001165out_bad_parent:
Al Viroa4555892014-10-21 20:11:25 -04001166 _debug("dropping dentry %pd2", dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167 dput(parent);
David Howellsc435ee32017-11-02 15:27:49 +00001168out_bad:
David Howells00d3b7a2007-04-26 15:57:07 -07001169 key_put(key);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170
1171 _leave(" = 0 [bad]");
1172 return 0;
David Howellsec268152007-04-26 15:49:28 -07001173}
Linus Torvalds1da177e2005-04-16 15:20:36 -07001174
Linus Torvalds1da177e2005-04-16 15:20:36 -07001175/*
1176 * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't
1177 * sleep)
1178 * - called from dput() when d_count is going to 0.
1179 * - return 1 to request dentry be unhashed, 0 otherwise
1180 */
Nick Pigginfe15ce42011-01-07 17:49:23 +11001181static int afs_d_delete(const struct dentry *dentry)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182{
Al Viroa4555892014-10-21 20:11:25 -04001183 _enter("%pd", dentry);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184
1185 if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
1186 goto zap;
1187
David Howells2b0143b2015-03-17 22:25:59 +00001188 if (d_really_is_positive(dentry) &&
1189 (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(d_inode(dentry))->flags) ||
1190 test_bit(AFS_VNODE_PSEUDODIR, &AFS_FS_I(d_inode(dentry))->flags)))
wangleibec5eb62010-08-11 09:38:04 +01001191 goto zap;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192
1193 _leave(" = 0 [keep]");
1194 return 0;
1195
David Howellsec268152007-04-26 15:49:28 -07001196zap:
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 _leave(" = 1 [zap]");
1198 return 1;
David Howellsec268152007-04-26 15:49:28 -07001199}
David Howells260a9802007-04-26 15:59:35 -07001200
1201/*
David Howells79ddbfa2019-04-25 14:26:51 +01001202 * Clean up sillyrename files on dentry removal.
1203 */
1204static void afs_d_iput(struct dentry *dentry, struct inode *inode)
1205{
1206 if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
1207 afs_silly_iput(dentry, inode);
1208 iput(inode);
1209}
1210
1211/*
David Howells260a9802007-04-26 15:59:35 -07001212 * handle dentry release
1213 */
David Howells66c7e1d2018-04-06 14:17:25 +01001214void afs_d_release(struct dentry *dentry)
David Howells260a9802007-04-26 15:59:35 -07001215{
Al Viroa4555892014-10-21 20:11:25 -04001216 _enter("%pd", dentry);
David Howells260a9802007-04-26 15:59:35 -07001217}
1218
1219/*
David Howellsd2ddc772017-11-02 15:27:50 +00001220 * Create a new inode for create/mkdir/symlink
1221 */
1222static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
1223 struct dentry *new_dentry,
David Howellsb8359152019-05-14 12:23:43 +01001224 struct afs_iget_data *new_data,
David Howellsa58823a2019-05-09 15:16:10 +01001225 struct afs_status_cb *new_scb)
David Howellsd2ddc772017-11-02 15:27:50 +00001226{
David Howells5a813272018-04-06 14:17:26 +01001227 struct afs_vnode *vnode;
David Howellsd2ddc772017-11-02 15:27:50 +00001228 struct inode *inode;
1229
1230 if (fc->ac.error < 0)
1231 return;
1232
1233 inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key,
David Howellsb8359152019-05-14 12:23:43 +01001234 new_data, new_scb, fc->cbi, fc->vnode);
David Howellsd2ddc772017-11-02 15:27:50 +00001235 if (IS_ERR(inode)) {
1236 /* ENOMEM or EINTR at a really inconvenient time - just abandon
1237 * the new directory on the server.
1238 */
1239 fc->ac.error = PTR_ERR(inode);
1240 return;
1241 }
1242
David Howells5a813272018-04-06 14:17:26 +01001243 vnode = AFS_FS_I(inode);
1244 set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
David Howellsa58823a2019-05-09 15:16:10 +01001245 if (fc->ac.error == 0)
1246 afs_cache_permit(vnode, fc->key, vnode->cb_break, new_scb);
David Howells73116df2018-11-13 23:20:35 +00001247 d_instantiate(new_dentry, inode);
David Howellsd2ddc772017-11-02 15:27:50 +00001248}
1249
David Howellsb8359152019-05-14 12:23:43 +01001250static void afs_prep_for_new_inode(struct afs_fs_cursor *fc,
1251 struct afs_iget_data *iget_data)
1252{
1253 iget_data->volume = fc->vnode->volume;
1254 iget_data->cb_v_break = fc->vnode->volume->cb_v_break;
1255 iget_data->cb_s_break = fc->cbi->server->cb_s_break;
1256}
1257
David Howellsd2ddc772017-11-02 15:27:50 +00001258/*
David Howells9dd0b822019-07-30 14:38:52 +01001259 * Note that a dentry got changed. We need to set d_fsdata to the data version
1260 * number derived from the result of the operation. It doesn't matter if
1261 * d_fsdata goes backwards as we'll just revalidate.
1262 */
1263static void afs_update_dentry_version(struct afs_fs_cursor *fc,
1264 struct dentry *dentry,
1265 struct afs_status_cb *scb)
1266{
1267 if (fc->ac.error == 0)
1268 dentry->d_fsdata =
1269 (void *)(unsigned long)scb->status.data_version;
1270}
1271
1272/*
David Howells260a9802007-04-26 15:59:35 -07001273 * create a directory on an AFS filesystem
1274 */
Al Viro18bb1db2011-07-26 01:41:39 -04001275static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
David Howells260a9802007-04-26 15:59:35 -07001276{
David Howellsb8359152019-05-14 12:23:43 +01001277 struct afs_iget_data iget_data;
David Howellsa58823a2019-05-09 15:16:10 +01001278 struct afs_status_cb *scb;
David Howellsd2ddc772017-11-02 15:27:50 +00001279 struct afs_fs_cursor fc;
David Howellsd2ddc772017-11-02 15:27:50 +00001280 struct afs_vnode *dvnode = AFS_FS_I(dir);
David Howells260a9802007-04-26 15:59:35 -07001281 struct key *key;
1282 int ret;
1283
David Howellsd2ddc772017-11-02 15:27:50 +00001284 mode |= S_IFDIR;
David Howells260a9802007-04-26 15:59:35 -07001285
David Howells3b6492d2018-10-20 00:57:57 +01001286 _enter("{%llx:%llu},{%pd},%ho",
Al Viroa4555892014-10-21 20:11:25 -04001287 dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
David Howells260a9802007-04-26 15:59:35 -07001288
David Howellsa58823a2019-05-09 15:16:10 +01001289 ret = -ENOMEM;
1290 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1291 if (!scb)
1292 goto error;
1293
David Howells260a9802007-04-26 15:59:35 -07001294 key = afs_request_key(dvnode->volume->cell);
1295 if (IS_ERR(key)) {
1296 ret = PTR_ERR(key);
David Howellsa58823a2019-05-09 15:16:10 +01001297 goto error_scb;
David Howells260a9802007-04-26 15:59:35 -07001298 }
1299
David Howellsd2ddc772017-11-02 15:27:50 +00001300 ret = -ERESTARTSYS;
David Howells20b83912019-05-08 16:16:31 +01001301 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
David Howellsa58823a2019-05-09 15:16:10 +01001302 afs_dataversion_t data_version = dvnode->status.data_version + 1;
1303
David Howellsd2ddc772017-11-02 15:27:50 +00001304 while (afs_select_fileserver(&fc)) {
David Howells68251f02018-05-12 22:31:33 +01001305 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Howellsb8359152019-05-14 12:23:43 +01001306 afs_prep_for_new_inode(&fc, &iget_data);
David Howellsa58823a2019-05-09 15:16:10 +01001307 afs_fs_create(&fc, dentry->d_name.name, mode,
David Howellsb8359152019-05-14 12:23:43 +01001308 &scb[0], &iget_data.fid, &scb[1]);
David Howellsd2ddc772017-11-02 15:27:50 +00001309 }
David Howells260a9802007-04-26 15:59:35 -07001310
David Howellsa58823a2019-05-09 15:16:10 +01001311 afs_check_for_remote_deletion(&fc, dvnode);
1312 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1313 &data_version, &scb[0]);
David Howells9dd0b822019-07-30 14:38:52 +01001314 afs_update_dentry_version(&fc, dentry, &scb[0]);
David Howellsb8359152019-05-14 12:23:43 +01001315 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
David Howellsd2ddc772017-11-02 15:27:50 +00001316 ret = afs_end_vnode_operation(&fc);
1317 if (ret < 0)
1318 goto error_key;
David Howells4433b692017-11-20 22:41:00 +00001319 } else {
1320 goto error_key;
David Howells260a9802007-04-26 15:59:35 -07001321 }
1322
David Howells63a46812018-04-06 14:17:25 +01001323 if (ret == 0 &&
1324 test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
David Howellsb8359152019-05-14 12:23:43 +01001325 afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
David Howells63a46812018-04-06 14:17:25 +01001326 afs_edit_dir_for_create);
1327
David Howells260a9802007-04-26 15:59:35 -07001328 key_put(key);
David Howellsa58823a2019-05-09 15:16:10 +01001329 kfree(scb);
David Howells260a9802007-04-26 15:59:35 -07001330 _leave(" = 0");
1331 return 0;
1332
David Howellsd2ddc772017-11-02 15:27:50 +00001333error_key:
David Howells260a9802007-04-26 15:59:35 -07001334 key_put(key);
David Howellsa58823a2019-05-09 15:16:10 +01001335error_scb:
1336 kfree(scb);
David Howells260a9802007-04-26 15:59:35 -07001337error:
1338 d_drop(dentry);
1339 _leave(" = %d", ret);
1340 return ret;
1341}
1342
1343/*
David Howellsd2ddc772017-11-02 15:27:50 +00001344 * Remove a subdir from a directory.
David Howells260a9802007-04-26 15:59:35 -07001345 */
David Howellsd2ddc772017-11-02 15:27:50 +00001346static void afs_dir_remove_subdir(struct dentry *dentry)
David Howells260a9802007-04-26 15:59:35 -07001347{
David Howells2b0143b2015-03-17 22:25:59 +00001348 if (d_really_is_positive(dentry)) {
David Howellsd2ddc772017-11-02 15:27:50 +00001349 struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
1350
David Howells260a9802007-04-26 15:59:35 -07001351 clear_nlink(&vnode->vfs_inode);
1352 set_bit(AFS_VNODE_DELETED, &vnode->flags);
David Howellsc435ee32017-11-02 15:27:49 +00001353 clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
David Howells63a46812018-04-06 14:17:25 +01001354 clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
David Howells260a9802007-04-26 15:59:35 -07001355 }
David Howells260a9802007-04-26 15:59:35 -07001356}
1357
1358/*
David Howellsd2ddc772017-11-02 15:27:50 +00001359 * remove a directory from an AFS filesystem
David Howells260a9802007-04-26 15:59:35 -07001360 */
David Howellsd2ddc772017-11-02 15:27:50 +00001361static int afs_rmdir(struct inode *dir, struct dentry *dentry)
David Howells260a9802007-04-26 15:59:35 -07001362{
David Howellsa58823a2019-05-09 15:16:10 +01001363 struct afs_status_cb *scb;
David Howellsd2ddc772017-11-02 15:27:50 +00001364 struct afs_fs_cursor fc;
David Howellsf58db832018-10-20 00:57:58 +01001365 struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
David Howells260a9802007-04-26 15:59:35 -07001366 struct key *key;
1367 int ret;
1368
David Howells3b6492d2018-10-20 00:57:57 +01001369 _enter("{%llx:%llu},{%pd}",
Al Viroa4555892014-10-21 20:11:25 -04001370 dvnode->fid.vid, dvnode->fid.vnode, dentry);
David Howells260a9802007-04-26 15:59:35 -07001371
David Howellsa58823a2019-05-09 15:16:10 +01001372 scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
1373 if (!scb)
1374 return -ENOMEM;
1375
David Howells260a9802007-04-26 15:59:35 -07001376 key = afs_request_key(dvnode->volume->cell);
1377 if (IS_ERR(key)) {
1378 ret = PTR_ERR(key);
1379 goto error;
1380 }
1381
David Howellsf58db832018-10-20 00:57:58 +01001382 /* Try to make sure we have a callback promise on the victim. */
1383 if (d_really_is_positive(dentry)) {
1384 vnode = AFS_FS_I(d_inode(dentry));
1385 ret = afs_validate(vnode, key);
1386 if (ret < 0)
1387 goto error_key;
1388 }
1389
David Howells79ddbfa2019-04-25 14:26:51 +01001390 if (vnode) {
1391 ret = down_write_killable(&vnode->rmdir_lock);
1392 if (ret < 0)
1393 goto error_key;
1394 }
1395
David Howellsd2ddc772017-11-02 15:27:50 +00001396 ret = -ERESTARTSYS;
David Howells20b83912019-05-08 16:16:31 +01001397 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
David Howellsa58823a2019-05-09 15:16:10 +01001398 afs_dataversion_t data_version = dvnode->status.data_version + 1;
1399
David Howellsd2ddc772017-11-02 15:27:50 +00001400 while (afs_select_fileserver(&fc)) {
David Howells68251f02018-05-12 22:31:33 +01001401 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Howellsa58823a2019-05-09 15:16:10 +01001402 afs_fs_remove(&fc, vnode, dentry->d_name.name, true, scb);
David Howellsd2ddc772017-11-02 15:27:50 +00001403 }
David Howells260a9802007-04-26 15:59:35 -07001404
David Howellsa58823a2019-05-09 15:16:10 +01001405 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1406 &data_version, scb);
David Howells9dd0b822019-07-30 14:38:52 +01001407 afs_update_dentry_version(&fc, dentry, scb);
David Howellsd2ddc772017-11-02 15:27:50 +00001408 ret = afs_end_vnode_operation(&fc);
David Howells63a46812018-04-06 14:17:25 +01001409 if (ret == 0) {
David Howellsd2ddc772017-11-02 15:27:50 +00001410 afs_dir_remove_subdir(dentry);
David Howells63a46812018-04-06 14:17:25 +01001411 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1412 afs_edit_dir_remove(dvnode, &dentry->d_name,
1413 afs_edit_dir_for_rmdir);
1414 }
David Howells260a9802007-04-26 15:59:35 -07001415 }
1416
David Howells79ddbfa2019-04-25 14:26:51 +01001417 if (vnode)
1418 up_write(&vnode->rmdir_lock);
David Howellsf58db832018-10-20 00:57:58 +01001419error_key:
David Howells260a9802007-04-26 15:59:35 -07001420 key_put(key);
David Howellsd2ddc772017-11-02 15:27:50 +00001421error:
David Howellsa58823a2019-05-09 15:16:10 +01001422 kfree(scb);
David Howellsd2ddc772017-11-02 15:27:50 +00001423 return ret;
1424}
David Howells260a9802007-04-26 15:59:35 -07001425
David Howellsd2ddc772017-11-02 15:27:50 +00001426/*
1427 * Remove a link to a file or symlink from a directory.
1428 *
1429 * If the file was not deleted due to excess hard links, the fileserver will
1430 * break the callback promise on the file - if it had one - before it returns
1431 * to us, and if it was deleted, it won't
1432 *
1433 * However, if we didn't have a callback promise outstanding, or it was
1434 * outstanding on a different server, then it won't break it either...
1435 */
David Howellsa38a7552019-05-14 12:29:11 +01001436static int afs_dir_remove_link(struct afs_vnode *dvnode, struct dentry *dentry,
1437 struct key *key)
David Howellsd2ddc772017-11-02 15:27:50 +00001438{
1439 int ret = 0;
1440
1441 if (d_really_is_positive(dentry)) {
1442 struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
1443
David Howells30062bd2018-10-20 00:57:58 +01001444 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
1445 /* Already done */
David Howellsa38a7552019-05-14 12:29:11 +01001446 } else if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
1447 write_seqlock(&vnode->cb_lock);
David Howells440fbc32018-01-02 10:02:19 +00001448 drop_nlink(&vnode->vfs_inode);
1449 if (vnode->vfs_inode.i_nlink == 0) {
1450 set_bit(AFS_VNODE_DELETED, &vnode->flags);
David Howells051d2522019-06-20 18:12:16 +01001451 __afs_break_callback(vnode, afs_cb_break_for_unlink);
David Howells440fbc32018-01-02 10:02:19 +00001452 }
David Howellsa38a7552019-05-14 12:29:11 +01001453 write_sequnlock(&vnode->cb_lock);
David Howellsd2ddc772017-11-02 15:27:50 +00001454 ret = 0;
David Howells440fbc32018-01-02 10:02:19 +00001455 } else {
David Howells051d2522019-06-20 18:12:16 +01001456 afs_break_callback(vnode, afs_cb_break_for_unlink);
David Howells440fbc32018-01-02 10:02:19 +00001457
1458 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
1459 kdebug("AFS_VNODE_DELETED");
1460
1461 ret = afs_validate(vnode, key);
1462 if (ret == -ESTALE)
1463 ret = 0;
1464 }
David Howellsd2ddc772017-11-02 15:27:50 +00001465 _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);
1466 }
1467
1468 return ret;
1469}
1470
1471/*
1472 * Remove a file or symlink from an AFS filesystem.
1473 */
1474static int afs_unlink(struct inode *dir, struct dentry *dentry)
1475{
1476 struct afs_fs_cursor fc;
David Howellsa58823a2019-05-09 15:16:10 +01001477 struct afs_status_cb *scb;
David Howellsfa59f522019-06-20 18:12:16 +01001478 struct afs_vnode *dvnode = AFS_FS_I(dir);
1479 struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
David Howellsd2ddc772017-11-02 15:27:50 +00001480 struct key *key;
David Howells79ddbfa2019-04-25 14:26:51 +01001481 bool need_rehash = false;
David Howellsd2ddc772017-11-02 15:27:50 +00001482 int ret;
1483
David Howells3b6492d2018-10-20 00:57:57 +01001484 _enter("{%llx:%llu},{%pd}",
David Howellsd2ddc772017-11-02 15:27:50 +00001485 dvnode->fid.vid, dvnode->fid.vnode, dentry);
1486
1487 if (dentry->d_name.len >= AFSNAMEMAX)
1488 return -ENAMETOOLONG;
1489
David Howellsa58823a2019-05-09 15:16:10 +01001490 ret = -ENOMEM;
1491 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1492 if (!scb)
1493 goto error;
1494
David Howellsd2ddc772017-11-02 15:27:50 +00001495 key = afs_request_key(dvnode->volume->cell);
1496 if (IS_ERR(key)) {
1497 ret = PTR_ERR(key);
David Howellsa58823a2019-05-09 15:16:10 +01001498 goto error_scb;
David Howellsd2ddc772017-11-02 15:27:50 +00001499 }
1500
1501 /* Try to make sure we have a callback promise on the victim. */
David Howellsfa59f522019-06-20 18:12:16 +01001502 ret = afs_validate(vnode, key);
1503 if (ret < 0)
1504 goto error_key;
David Howellsd2ddc772017-11-02 15:27:50 +00001505
David Howells79ddbfa2019-04-25 14:26:51 +01001506 spin_lock(&dentry->d_lock);
David Howellsfa59f522019-06-20 18:12:16 +01001507 if (d_count(dentry) > 1) {
David Howells79ddbfa2019-04-25 14:26:51 +01001508 spin_unlock(&dentry->d_lock);
1509 /* Start asynchronous writeout of the inode */
1510 write_inode_now(d_inode(dentry), 0);
1511 ret = afs_sillyrename(dvnode, vnode, dentry, key);
1512 goto error_key;
1513 }
1514 if (!d_unhashed(dentry)) {
1515 /* Prevent a race with RCU lookup. */
1516 __d_drop(dentry);
1517 need_rehash = true;
1518 }
1519 spin_unlock(&dentry->d_lock);
1520
David Howellsd2ddc772017-11-02 15:27:50 +00001521 ret = -ERESTARTSYS;
David Howells20b83912019-05-08 16:16:31 +01001522 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
David Howellsa58823a2019-05-09 15:16:10 +01001523 afs_dataversion_t data_version = dvnode->status.data_version + 1;
David Howellsa38a7552019-05-14 12:29:11 +01001524 afs_dataversion_t data_version_2 = vnode->status.data_version;
David Howellsa58823a2019-05-09 15:16:10 +01001525
David Howellsd2ddc772017-11-02 15:27:50 +00001526 while (afs_select_fileserver(&fc)) {
David Howells68251f02018-05-12 22:31:33 +01001527 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Howellsa38a7552019-05-14 12:29:11 +01001528 fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
David Howells30062bd2018-10-20 00:57:58 +01001529
1530 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) &&
1531 !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) {
1532 yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name,
David Howellsa58823a2019-05-09 15:16:10 +01001533 &scb[0], &scb[1]);
David Howells30062bd2018-10-20 00:57:58 +01001534 if (fc.ac.error != -ECONNABORTED ||
1535 fc.ac.abort_code != RXGEN_OPCODE)
1536 continue;
1537 set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags);
1538 }
1539
David Howellsa58823a2019-05-09 15:16:10 +01001540 afs_fs_remove(&fc, vnode, dentry->d_name.name, false, &scb[0]);
David Howellsd2ddc772017-11-02 15:27:50 +00001541 }
1542
David Howellsa58823a2019-05-09 15:16:10 +01001543 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1544 &data_version, &scb[0]);
David Howellsa38a7552019-05-14 12:29:11 +01001545 afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
1546 &data_version_2, &scb[1]);
David Howells9dd0b822019-07-30 14:38:52 +01001547 afs_update_dentry_version(&fc, dentry, &scb[0]);
David Howellsd2ddc772017-11-02 15:27:50 +00001548 ret = afs_end_vnode_operation(&fc);
David Howellsa38a7552019-05-14 12:29:11 +01001549 if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
1550 ret = afs_dir_remove_link(dvnode, dentry, key);
David Howells63a46812018-04-06 14:17:25 +01001551 if (ret == 0 &&
1552 test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1553 afs_edit_dir_remove(dvnode, &dentry->d_name,
1554 afs_edit_dir_for_unlink);
David Howellsd2ddc772017-11-02 15:27:50 +00001555 }
1556
David Howells79ddbfa2019-04-25 14:26:51 +01001557 if (need_rehash && ret < 0 && ret != -ENOENT)
1558 d_rehash(dentry);
1559
David Howellsd2ddc772017-11-02 15:27:50 +00001560error_key:
David Howells260a9802007-04-26 15:59:35 -07001561 key_put(key);
David Howellsa58823a2019-05-09 15:16:10 +01001562error_scb:
1563 kfree(scb);
David Howells260a9802007-04-26 15:59:35 -07001564error:
1565 _leave(" = %d", ret);
1566 return ret;
1567}
1568
1569/*
1570 * create a regular file on an AFS filesystem
1571 */
Al Viro4acdaf22011-07-26 01:42:34 -04001572static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
Al Viroebfc3b42012-06-10 18:05:36 -04001573 bool excl)
David Howells260a9802007-04-26 15:59:35 -07001574{
David Howellsb8359152019-05-14 12:23:43 +01001575 struct afs_iget_data iget_data;
David Howellsd2ddc772017-11-02 15:27:50 +00001576 struct afs_fs_cursor fc;
David Howellsa58823a2019-05-09 15:16:10 +01001577 struct afs_status_cb *scb;
Colin Ian King43dd3882017-11-20 13:58:20 +00001578 struct afs_vnode *dvnode = AFS_FS_I(dir);
David Howells260a9802007-04-26 15:59:35 -07001579 struct key *key;
1580 int ret;
1581
David Howellsd2ddc772017-11-02 15:27:50 +00001582 mode |= S_IFREG;
David Howells260a9802007-04-26 15:59:35 -07001583
David Howells3b6492d2018-10-20 00:57:57 +01001584 _enter("{%llx:%llu},{%pd},%ho,",
Al Viroa4555892014-10-21 20:11:25 -04001585 dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
David Howells260a9802007-04-26 15:59:35 -07001586
David Howellsd2ddc772017-11-02 15:27:50 +00001587 ret = -ENAMETOOLONG;
1588 if (dentry->d_name.len >= AFSNAMEMAX)
1589 goto error;
1590
David Howells260a9802007-04-26 15:59:35 -07001591 key = afs_request_key(dvnode->volume->cell);
1592 if (IS_ERR(key)) {
1593 ret = PTR_ERR(key);
1594 goto error;
1595 }
1596
David Howellsa58823a2019-05-09 15:16:10 +01001597 ret = -ENOMEM;
1598 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1599 if (!scb)
1600 goto error_scb;
1601
David Howellsd2ddc772017-11-02 15:27:50 +00001602 ret = -ERESTARTSYS;
David Howells20b83912019-05-08 16:16:31 +01001603 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
David Howellsa58823a2019-05-09 15:16:10 +01001604 afs_dataversion_t data_version = dvnode->status.data_version + 1;
1605
David Howellsd2ddc772017-11-02 15:27:50 +00001606 while (afs_select_fileserver(&fc)) {
David Howells68251f02018-05-12 22:31:33 +01001607 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Howellsb8359152019-05-14 12:23:43 +01001608 afs_prep_for_new_inode(&fc, &iget_data);
David Howellsa58823a2019-05-09 15:16:10 +01001609 afs_fs_create(&fc, dentry->d_name.name, mode,
David Howellsb8359152019-05-14 12:23:43 +01001610 &scb[0], &iget_data.fid, &scb[1]);
David Howellsd2ddc772017-11-02 15:27:50 +00001611 }
David Howells260a9802007-04-26 15:59:35 -07001612
David Howellsa58823a2019-05-09 15:16:10 +01001613 afs_check_for_remote_deletion(&fc, dvnode);
1614 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1615 &data_version, &scb[0]);
David Howells9dd0b822019-07-30 14:38:52 +01001616 afs_update_dentry_version(&fc, dentry, &scb[0]);
David Howellsb8359152019-05-14 12:23:43 +01001617 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
David Howellsd2ddc772017-11-02 15:27:50 +00001618 ret = afs_end_vnode_operation(&fc);
1619 if (ret < 0)
1620 goto error_key;
David Howells4433b692017-11-20 22:41:00 +00001621 } else {
1622 goto error_key;
David Howells260a9802007-04-26 15:59:35 -07001623 }
1624
David Howells63a46812018-04-06 14:17:25 +01001625 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
David Howellsb8359152019-05-14 12:23:43 +01001626 afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
David Howells63a46812018-04-06 14:17:25 +01001627 afs_edit_dir_for_create);
1628
David Howellsa58823a2019-05-09 15:16:10 +01001629 kfree(scb);
David Howells260a9802007-04-26 15:59:35 -07001630 key_put(key);
1631 _leave(" = 0");
1632 return 0;
1633
David Howellsa58823a2019-05-09 15:16:10 +01001634error_scb:
1635 kfree(scb);
David Howellsd2ddc772017-11-02 15:27:50 +00001636error_key:
David Howells260a9802007-04-26 15:59:35 -07001637 key_put(key);
1638error:
1639 d_drop(dentry);
1640 _leave(" = %d", ret);
1641 return ret;
1642}
1643
1644/*
1645 * create a hard link between files in an AFS filesystem
1646 */
1647static int afs_link(struct dentry *from, struct inode *dir,
1648 struct dentry *dentry)
1649{
David Howellsd2ddc772017-11-02 15:27:50 +00001650 struct afs_fs_cursor fc;
David Howellsa58823a2019-05-09 15:16:10 +01001651 struct afs_status_cb *scb;
1652 struct afs_vnode *dvnode = AFS_FS_I(dir);
1653 struct afs_vnode *vnode = AFS_FS_I(d_inode(from));
David Howells260a9802007-04-26 15:59:35 -07001654 struct key *key;
1655 int ret;
1656
David Howells3b6492d2018-10-20 00:57:57 +01001657 _enter("{%llx:%llu},{%llx:%llu},{%pd}",
David Howells260a9802007-04-26 15:59:35 -07001658 vnode->fid.vid, vnode->fid.vnode,
1659 dvnode->fid.vid, dvnode->fid.vnode,
Al Viroa4555892014-10-21 20:11:25 -04001660 dentry);
David Howells260a9802007-04-26 15:59:35 -07001661
David Howellsd2ddc772017-11-02 15:27:50 +00001662 ret = -ENAMETOOLONG;
1663 if (dentry->d_name.len >= AFSNAMEMAX)
1664 goto error;
1665
David Howellsa58823a2019-05-09 15:16:10 +01001666 ret = -ENOMEM;
1667 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1668 if (!scb)
1669 goto error;
1670
David Howells260a9802007-04-26 15:59:35 -07001671 key = afs_request_key(dvnode->volume->cell);
1672 if (IS_ERR(key)) {
1673 ret = PTR_ERR(key);
David Howellsa58823a2019-05-09 15:16:10 +01001674 goto error_scb;
David Howells260a9802007-04-26 15:59:35 -07001675 }
1676
David Howellsd2ddc772017-11-02 15:27:50 +00001677 ret = -ERESTARTSYS;
David Howells20b83912019-05-08 16:16:31 +01001678 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
David Howellsa58823a2019-05-09 15:16:10 +01001679 afs_dataversion_t data_version = dvnode->status.data_version + 1;
1680
David Howellsd2ddc772017-11-02 15:27:50 +00001681 if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) {
1682 afs_end_vnode_operation(&fc);
David Howellsbc1527d2017-11-20 23:04:08 +00001683 goto error_key;
David Howellsd2ddc772017-11-02 15:27:50 +00001684 }
David Howells260a9802007-04-26 15:59:35 -07001685
David Howellsd2ddc772017-11-02 15:27:50 +00001686 while (afs_select_fileserver(&fc)) {
David Howells68251f02018-05-12 22:31:33 +01001687 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1688 fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
David Howellsa58823a2019-05-09 15:16:10 +01001689 afs_fs_link(&fc, vnode, dentry->d_name.name,
1690 &scb[0], &scb[1]);
David Howellsd2ddc772017-11-02 15:27:50 +00001691 }
1692
David Howellsa58823a2019-05-09 15:16:10 +01001693 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1694 &data_version, &scb[0]);
1695 afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
1696 NULL, &scb[1]);
David Howellsd2ddc772017-11-02 15:27:50 +00001697 ihold(&vnode->vfs_inode);
David Howells9dd0b822019-07-30 14:38:52 +01001698 afs_update_dentry_version(&fc, dentry, &scb[0]);
David Howellsd2ddc772017-11-02 15:27:50 +00001699 d_instantiate(dentry, &vnode->vfs_inode);
1700
1701 mutex_unlock(&vnode->io_lock);
1702 ret = afs_end_vnode_operation(&fc);
1703 if (ret < 0)
1704 goto error_key;
David Howells4433b692017-11-20 22:41:00 +00001705 } else {
1706 goto error_key;
David Howellsd2ddc772017-11-02 15:27:50 +00001707 }
1708
David Howells63a46812018-04-06 14:17:25 +01001709 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1710 afs_edit_dir_add(dvnode, &dentry->d_name, &vnode->fid,
1711 afs_edit_dir_for_link);
1712
David Howells260a9802007-04-26 15:59:35 -07001713 key_put(key);
David Howellsa58823a2019-05-09 15:16:10 +01001714 kfree(scb);
David Howells260a9802007-04-26 15:59:35 -07001715 _leave(" = 0");
1716 return 0;
1717
David Howellsd2ddc772017-11-02 15:27:50 +00001718error_key:
David Howells260a9802007-04-26 15:59:35 -07001719 key_put(key);
David Howellsa58823a2019-05-09 15:16:10 +01001720error_scb:
1721 kfree(scb);
David Howells260a9802007-04-26 15:59:35 -07001722error:
1723 d_drop(dentry);
1724 _leave(" = %d", ret);
1725 return ret;
1726}
1727
1728/*
1729 * create a symlink in an AFS filesystem
1730 */
1731static int afs_symlink(struct inode *dir, struct dentry *dentry,
1732 const char *content)
1733{
David Howellsb8359152019-05-14 12:23:43 +01001734 struct afs_iget_data iget_data;
David Howellsd2ddc772017-11-02 15:27:50 +00001735 struct afs_fs_cursor fc;
David Howellsa58823a2019-05-09 15:16:10 +01001736 struct afs_status_cb *scb;
David Howellsd2ddc772017-11-02 15:27:50 +00001737 struct afs_vnode *dvnode = AFS_FS_I(dir);
David Howells260a9802007-04-26 15:59:35 -07001738 struct key *key;
1739 int ret;
1740
David Howells3b6492d2018-10-20 00:57:57 +01001741 _enter("{%llx:%llu},{%pd},%s",
Al Viroa4555892014-10-21 20:11:25 -04001742 dvnode->fid.vid, dvnode->fid.vnode, dentry,
David Howells260a9802007-04-26 15:59:35 -07001743 content);
1744
David Howellsd2ddc772017-11-02 15:27:50 +00001745 ret = -ENAMETOOLONG;
1746 if (dentry->d_name.len >= AFSNAMEMAX)
1747 goto error;
1748
David Howells260a9802007-04-26 15:59:35 -07001749 ret = -EINVAL;
David Howells45222b92007-05-10 22:22:20 -07001750 if (strlen(content) >= AFSPATHMAX)
David Howells260a9802007-04-26 15:59:35 -07001751 goto error;
1752
David Howellsa58823a2019-05-09 15:16:10 +01001753 ret = -ENOMEM;
1754 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1755 if (!scb)
1756 goto error;
1757
David Howells260a9802007-04-26 15:59:35 -07001758 key = afs_request_key(dvnode->volume->cell);
1759 if (IS_ERR(key)) {
1760 ret = PTR_ERR(key);
David Howellsa58823a2019-05-09 15:16:10 +01001761 goto error_scb;
David Howells260a9802007-04-26 15:59:35 -07001762 }
1763
David Howellsd2ddc772017-11-02 15:27:50 +00001764 ret = -ERESTARTSYS;
David Howells20b83912019-05-08 16:16:31 +01001765 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
David Howellsa58823a2019-05-09 15:16:10 +01001766 afs_dataversion_t data_version = dvnode->status.data_version + 1;
1767
David Howellsd2ddc772017-11-02 15:27:50 +00001768 while (afs_select_fileserver(&fc)) {
David Howells68251f02018-05-12 22:31:33 +01001769 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Howellsb8359152019-05-14 12:23:43 +01001770 afs_prep_for_new_inode(&fc, &iget_data);
David Howellsa58823a2019-05-09 15:16:10 +01001771 afs_fs_symlink(&fc, dentry->d_name.name, content,
David Howellsb8359152019-05-14 12:23:43 +01001772 &scb[0], &iget_data.fid, &scb[1]);
David Howellsd2ddc772017-11-02 15:27:50 +00001773 }
David Howells260a9802007-04-26 15:59:35 -07001774
David Howellsa58823a2019-05-09 15:16:10 +01001775 afs_check_for_remote_deletion(&fc, dvnode);
1776 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1777 &data_version, &scb[0]);
David Howells9dd0b822019-07-30 14:38:52 +01001778 afs_update_dentry_version(&fc, dentry, &scb[0]);
David Howellsb8359152019-05-14 12:23:43 +01001779 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
David Howellsd2ddc772017-11-02 15:27:50 +00001780 ret = afs_end_vnode_operation(&fc);
1781 if (ret < 0)
1782 goto error_key;
David Howells4433b692017-11-20 22:41:00 +00001783 } else {
1784 goto error_key;
David Howells260a9802007-04-26 15:59:35 -07001785 }
1786
David Howells63a46812018-04-06 14:17:25 +01001787 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
David Howellsb8359152019-05-14 12:23:43 +01001788 afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
David Howells63a46812018-04-06 14:17:25 +01001789 afs_edit_dir_for_symlink);
1790
David Howells260a9802007-04-26 15:59:35 -07001791 key_put(key);
David Howellsa58823a2019-05-09 15:16:10 +01001792 kfree(scb);
David Howells260a9802007-04-26 15:59:35 -07001793 _leave(" = 0");
1794 return 0;
1795
David Howellsd2ddc772017-11-02 15:27:50 +00001796error_key:
David Howells260a9802007-04-26 15:59:35 -07001797 key_put(key);
David Howellsa58823a2019-05-09 15:16:10 +01001798error_scb:
1799 kfree(scb);
David Howells260a9802007-04-26 15:59:35 -07001800error:
1801 d_drop(dentry);
1802 _leave(" = %d", ret);
1803 return ret;
1804}
1805
1806/*
1807 * rename a file in an AFS filesystem and/or move it between directories
1808 */
1809static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
Miklos Szeredi1cd66c92016-09-27 11:03:58 +02001810 struct inode *new_dir, struct dentry *new_dentry,
1811 unsigned int flags)
David Howells260a9802007-04-26 15:59:35 -07001812{
David Howellsd2ddc772017-11-02 15:27:50 +00001813 struct afs_fs_cursor fc;
David Howellsa58823a2019-05-09 15:16:10 +01001814 struct afs_status_cb *scb;
David Howells260a9802007-04-26 15:59:35 -07001815 struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
David Howells79ddbfa2019-04-25 14:26:51 +01001816 struct dentry *tmp = NULL, *rehash = NULL;
1817 struct inode *new_inode;
David Howells260a9802007-04-26 15:59:35 -07001818 struct key *key;
David Howells63a46812018-04-06 14:17:25 +01001819 bool new_negative = d_is_negative(new_dentry);
David Howells260a9802007-04-26 15:59:35 -07001820 int ret;
1821
Miklos Szeredi1cd66c92016-09-27 11:03:58 +02001822 if (flags)
1823 return -EINVAL;
1824
David Howells79ddbfa2019-04-25 14:26:51 +01001825 /* Don't allow silly-rename files be moved around. */
1826 if (old_dentry->d_flags & DCACHE_NFSFS_RENAMED)
1827 return -EINVAL;
1828
David Howells2b0143b2015-03-17 22:25:59 +00001829 vnode = AFS_FS_I(d_inode(old_dentry));
David Howells260a9802007-04-26 15:59:35 -07001830 orig_dvnode = AFS_FS_I(old_dir);
1831 new_dvnode = AFS_FS_I(new_dir);
1832
David Howells3b6492d2018-10-20 00:57:57 +01001833 _enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}",
David Howells260a9802007-04-26 15:59:35 -07001834 orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
1835 vnode->fid.vid, vnode->fid.vnode,
1836 new_dvnode->fid.vid, new_dvnode->fid.vnode,
Al Viroa4555892014-10-21 20:11:25 -04001837 new_dentry);
David Howells260a9802007-04-26 15:59:35 -07001838
David Howellsa58823a2019-05-09 15:16:10 +01001839 ret = -ENOMEM;
1840 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1841 if (!scb)
1842 goto error;
1843
David Howells260a9802007-04-26 15:59:35 -07001844 key = afs_request_key(orig_dvnode->volume->cell);
1845 if (IS_ERR(key)) {
1846 ret = PTR_ERR(key);
David Howellsa58823a2019-05-09 15:16:10 +01001847 goto error_scb;
David Howells260a9802007-04-26 15:59:35 -07001848 }
1849
David Howells79ddbfa2019-04-25 14:26:51 +01001850 /* For non-directories, check whether the target is busy and if so,
1851 * make a copy of the dentry and then do a silly-rename. If the
1852 * silly-rename succeeds, the copied dentry is hashed and becomes the
1853 * new target.
1854 */
1855 if (d_is_positive(new_dentry) && !d_is_dir(new_dentry)) {
1856 /* To prevent any new references to the target during the
1857 * rename, we unhash the dentry in advance.
1858 */
1859 if (!d_unhashed(new_dentry)) {
1860 d_drop(new_dentry);
1861 rehash = new_dentry;
1862 }
1863
1864 if (d_count(new_dentry) > 2) {
1865 /* copy the target dentry's name */
1866 ret = -ENOMEM;
1867 tmp = d_alloc(new_dentry->d_parent,
1868 &new_dentry->d_name);
1869 if (!tmp)
1870 goto error_rehash;
1871
1872 ret = afs_sillyrename(new_dvnode,
1873 AFS_FS_I(d_inode(new_dentry)),
1874 new_dentry, key);
1875 if (ret)
1876 goto error_rehash;
1877
1878 new_dentry = tmp;
1879 rehash = NULL;
1880 new_negative = true;
David Howells79ddbfa2019-04-25 14:26:51 +01001881 }
1882 }
1883
David Howells9dd0b822019-07-30 14:38:52 +01001884 /* This bit is potentially nasty as there's a potential race with
1885 * afs_d_revalidate{,_rcu}(). We have to change d_fsdata on the dentry
1886 * to reflect it's new parent's new data_version after the op, but
1887 * d_revalidate may see old_dentry between the op having taken place
1888 * and the version being updated.
1889 *
1890 * So drop the old_dentry for now to make other threads go through
1891 * lookup instead - which we hold a lock against.
1892 */
1893 d_drop(old_dentry);
1894
David Howellsd2ddc772017-11-02 15:27:50 +00001895 ret = -ERESTARTSYS;
David Howells20b83912019-05-08 16:16:31 +01001896 if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
David Howellsa58823a2019-05-09 15:16:10 +01001897 afs_dataversion_t orig_data_version;
1898 afs_dataversion_t new_data_version;
1899 struct afs_status_cb *new_scb = &scb[1];
1900
1901 orig_data_version = orig_dvnode->status.data_version + 1;
1902
David Howellsd2ddc772017-11-02 15:27:50 +00001903 if (orig_dvnode != new_dvnode) {
1904 if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) {
1905 afs_end_vnode_operation(&fc);
David Howells9dd0b822019-07-30 14:38:52 +01001906 goto error_rehash_old;
David Howellsd2ddc772017-11-02 15:27:50 +00001907 }
David Howells37c0bbb2019-07-30 14:38:51 +01001908 new_data_version = new_dvnode->status.data_version + 1;
David Howellsa58823a2019-05-09 15:16:10 +01001909 } else {
1910 new_data_version = orig_data_version;
1911 new_scb = &scb[0];
David Howellsd2ddc772017-11-02 15:27:50 +00001912 }
David Howellsa58823a2019-05-09 15:16:10 +01001913
David Howellsd2ddc772017-11-02 15:27:50 +00001914 while (afs_select_fileserver(&fc)) {
David Howells68251f02018-05-12 22:31:33 +01001915 fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode);
1916 fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
David Howellsd2ddc772017-11-02 15:27:50 +00001917 afs_fs_rename(&fc, old_dentry->d_name.name,
David Howells63a46812018-04-06 14:17:25 +01001918 new_dvnode, new_dentry->d_name.name,
David Howellsa58823a2019-05-09 15:16:10 +01001919 &scb[0], new_scb);
David Howellsd2ddc772017-11-02 15:27:50 +00001920 }
1921
David Howellsa58823a2019-05-09 15:16:10 +01001922 afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break,
1923 &orig_data_version, &scb[0]);
1924 if (new_dvnode != orig_dvnode) {
1925 afs_vnode_commit_status(&fc, new_dvnode, fc.cb_break_2,
1926 &new_data_version, &scb[1]);
David Howellsd2ddc772017-11-02 15:27:50 +00001927 mutex_unlock(&new_dvnode->io_lock);
David Howellsa58823a2019-05-09 15:16:10 +01001928 }
David Howellsd2ddc772017-11-02 15:27:50 +00001929 ret = afs_end_vnode_operation(&fc);
1930 if (ret < 0)
David Howells9dd0b822019-07-30 14:38:52 +01001931 goto error_rehash_old;
David Howellsd2ddc772017-11-02 15:27:50 +00001932 }
1933
David Howells63a46812018-04-06 14:17:25 +01001934 if (ret == 0) {
David Howells79ddbfa2019-04-25 14:26:51 +01001935 if (rehash)
1936 d_rehash(rehash);
David Howells63a46812018-04-06 14:17:25 +01001937 if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags))
1938 afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
David Howells79ddbfa2019-04-25 14:26:51 +01001939 afs_edit_dir_for_rename_0);
David Howells63a46812018-04-06 14:17:25 +01001940
1941 if (!new_negative &&
1942 test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
1943 afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
David Howells79ddbfa2019-04-25 14:26:51 +01001944 afs_edit_dir_for_rename_1);
David Howells63a46812018-04-06 14:17:25 +01001945
1946 if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
1947 afs_edit_dir_add(new_dvnode, &new_dentry->d_name,
David Howells79ddbfa2019-04-25 14:26:51 +01001948 &vnode->fid, afs_edit_dir_for_rename_2);
1949
1950 new_inode = d_inode(new_dentry);
1951 if (new_inode) {
1952 spin_lock(&new_inode->i_lock);
1953 if (new_inode->i_nlink > 0)
1954 drop_nlink(new_inode);
1955 spin_unlock(&new_inode->i_lock);
1956 }
David Howells9dd0b822019-07-30 14:38:52 +01001957
1958 /* Now we can update d_fsdata on the dentries to reflect their
1959 * new parent's data_version.
1960 *
1961 * Note that if we ever implement RENAME_EXCHANGE, we'll have
1962 * to update both dentries with opposing dir versions.
1963 */
1964 if (new_dvnode != orig_dvnode) {
1965 afs_update_dentry_version(&fc, old_dentry, &scb[1]);
1966 afs_update_dentry_version(&fc, new_dentry, &scb[1]);
1967 } else {
1968 afs_update_dentry_version(&fc, old_dentry, &scb[0]);
1969 afs_update_dentry_version(&fc, new_dentry, &scb[0]);
1970 }
David Howells79ddbfa2019-04-25 14:26:51 +01001971 d_move(old_dentry, new_dentry);
1972 goto error_tmp;
David Howells63a46812018-04-06 14:17:25 +01001973 }
1974
David Howells9dd0b822019-07-30 14:38:52 +01001975error_rehash_old:
1976 d_rehash(new_dentry);
David Howells79ddbfa2019-04-25 14:26:51 +01001977error_rehash:
1978 if (rehash)
1979 d_rehash(rehash);
1980error_tmp:
1981 if (tmp)
1982 dput(tmp);
David Howells260a9802007-04-26 15:59:35 -07001983 key_put(key);
David Howellsa58823a2019-05-09 15:16:10 +01001984error_scb:
1985 kfree(scb);
David Howells260a9802007-04-26 15:59:35 -07001986error:
David Howells260a9802007-04-26 15:59:35 -07001987 _leave(" = %d", ret);
1988 return ret;
1989}
David Howellsf3ddee82018-04-06 14:17:25 +01001990
1991/*
1992 * Release a directory page and clean up its private state if it's not busy
1993 * - return true if the page can now be released, false if not
1994 */
1995static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags)
1996{
1997 struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);
1998
David Howells3b6492d2018-10-20 00:57:57 +01001999 _enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
David Howellsf3ddee82018-04-06 14:17:25 +01002000
2001 set_page_private(page, 0);
2002 ClearPagePrivate(page);
2003
2004 /* The directory will need reloading. */
2005 if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
2006 afs_stat_v(dvnode, n_relpg);
2007 return 1;
2008}
2009
2010/*
2011 * invalidate part or all of a page
2012 * - release a page and clean up its private data if offset is 0 (indicating
2013 * the entire page)
2014 */
2015static void afs_dir_invalidatepage(struct page *page, unsigned int offset,
2016 unsigned int length)
2017{
2018 struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);
2019
2020 _enter("{%lu},%u,%u", page->index, offset, length);
2021
2022 BUG_ON(!PageLocked(page));
2023
2024 /* The directory will need reloading. */
2025 if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
2026 afs_stat_v(dvnode, n_inval);
2027
2028 /* we clean up only if the entire page is being invalidated */
2029 if (offset == 0 && length == PAGE_SIZE) {
2030 set_page_private(page, 0);
2031 ClearPagePrivate(page);
2032 }
2033}