blob: e7494cd49ce7bcab9ed7c8632facac9963248f91 [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001// SPDX-License-Identifier: GPL-2.0-or-later
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002/* dir.c: AFS filesystem directory handling
3 *
4 * Copyright (C) 2002, 2018 Red Hat, Inc. All Rights Reserved.
5 * Written by David Howells (dhowells@redhat.com)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00006 */
7
8#include <linux/kernel.h>
9#include <linux/fs.h>
10#include <linux/namei.h>
11#include <linux/pagemap.h>
12#include <linux/swap.h>
13#include <linux/ctype.h>
14#include <linux/sched.h>
15#include <linux/task_io_accounting_ops.h>
16#include "internal.h"
David Brazdil0f672f62019-12-10 10:32:29 +000017#include "afs_fs.h"
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000018#include "xdr_fs.h"
19
20static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
21 unsigned int flags);
22static int afs_dir_open(struct inode *inode, struct file *file);
23static int afs_readdir(struct file *file, struct dir_context *ctx);
24static int afs_d_revalidate(struct dentry *dentry, unsigned int flags);
25static int afs_d_delete(const struct dentry *dentry);
David Brazdil0f672f62019-12-10 10:32:29 +000026static void afs_d_iput(struct dentry *dentry, struct inode *inode);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000027static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name, int nlen,
28 loff_t fpos, u64 ino, unsigned dtype);
29static int afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen,
30 loff_t fpos, u64 ino, unsigned dtype);
31static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
32 bool excl);
33static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
34static 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,
41 struct inode *new_dir, struct dentry *new_dentry,
42 unsigned int flags);
43static 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}
51
52const struct file_operations afs_dir_file_operations = {
53 .open = afs_dir_open,
54 .release = afs_release,
55 .iterate_shared = afs_readdir,
56 .lock = afs_lock,
57 .llseek = generic_file_llseek,
58};
59
60const struct inode_operations afs_dir_inode_operations = {
61 .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,
68 .rename = afs_rename,
69 .permission = afs_permission,
70 .getattr = afs_getattr,
71 .setattr = afs_setattr,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000072};
73
74const struct address_space_operations afs_dir_aops = {
75 .set_page_dirty = afs_dir_set_page_dirty,
76 .releasepage = afs_dir_releasepage,
77 .invalidatepage = afs_dir_invalidatepage,
78};
79
80const struct dentry_operations afs_fs_dentry_operations = {
81 .d_revalidate = afs_d_revalidate,
82 .d_delete = afs_d_delete,
83 .d_release = afs_d_release,
84 .d_automount = afs_d_automount,
David Brazdil0f672f62019-12-10 10:32:29 +000085 .d_iput = afs_d_iput,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +000086};
87
88struct afs_lookup_one_cookie {
89 struct dir_context ctx;
90 struct qstr name;
91 bool found;
92 struct afs_fid fid;
93};
94
95struct afs_lookup_cookie {
96 struct dir_context ctx;
97 struct qstr name;
98 bool found;
99 bool one_only;
100 unsigned short nr_fids;
David Brazdil0f672f62019-12-10 10:32:29 +0000101 struct inode **inodes;
102 struct afs_status_cb *statuses;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000103 struct afs_fid fids[50];
104};
105
106/*
107 * check that a directory page is valid
108 */
109static bool afs_dir_check_page(struct afs_vnode *dvnode, struct page *page,
110 loff_t i_size)
111{
112 struct afs_xdr_dir_page *dbuf;
113 loff_t latter, off;
114 int tmp, qty;
115
116 /* Determine how many magic numbers there should be in this page, but
117 * we must take care because the directory may change size under us.
118 */
119 off = page_offset(page);
120 if (i_size <= off)
121 goto checked;
122
123 latter = i_size - off;
124 if (latter >= PAGE_SIZE)
125 qty = PAGE_SIZE;
126 else
127 qty = latter;
128 qty /= sizeof(union afs_xdr_dir_block);
129
130 /* check them */
131 dbuf = kmap(page);
132 for (tmp = 0; tmp < qty; tmp++) {
133 if (dbuf->blocks[tmp].hdr.magic != AFS_DIR_MAGIC) {
134 printk("kAFS: %s(%lx): bad magic %d/%d is %04hx\n",
135 __func__, dvnode->vfs_inode.i_ino, tmp, qty,
136 ntohs(dbuf->blocks[tmp].hdr.magic));
137 trace_afs_dir_check_failed(dvnode, off, i_size);
138 kunmap(page);
David Brazdil0f672f62019-12-10 10:32:29 +0000139 trace_afs_file_error(dvnode, -EIO, afs_file_error_dir_bad_magic);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000140 goto error;
141 }
142
143 /* Make sure each block is NUL terminated so we can reasonably
144 * use string functions on it. The filenames in the page
145 * *should* be NUL-terminated anyway.
146 */
147 ((u8 *)&dbuf->blocks[tmp])[AFS_DIR_BLOCK_SIZE - 1] = 0;
148 }
149
150 kunmap(page);
151
152checked:
153 afs_stat_v(dvnode, n_read_dir);
154 return true;
155
156error:
157 return false;
158}
159
160/*
David Brazdil0f672f62019-12-10 10:32:29 +0000161 * Check the contents of a directory that we've just read.
162 */
163static bool afs_dir_check_pages(struct afs_vnode *dvnode, struct afs_read *req)
164{
165 struct afs_xdr_dir_page *dbuf;
166 unsigned int i, j, qty = PAGE_SIZE / sizeof(union afs_xdr_dir_block);
167
168 for (i = 0; i < req->nr_pages; i++)
169 if (!afs_dir_check_page(dvnode, req->pages[i], req->actual_len))
170 goto bad;
171 return true;
172
173bad:
174 pr_warn("DIR %llx:%llx f=%llx l=%llx al=%llx r=%llx\n",
175 dvnode->fid.vid, dvnode->fid.vnode,
176 req->file_size, req->len, req->actual_len, req->remain);
177 pr_warn("DIR %llx %x %x %x\n",
178 req->pos, req->index, req->nr_pages, req->offset);
179
180 for (i = 0; i < req->nr_pages; i++) {
181 dbuf = kmap(req->pages[i]);
182 for (j = 0; j < qty; j++) {
183 union afs_xdr_dir_block *block = &dbuf->blocks[j];
184
185 pr_warn("[%02x] %32phN\n", i * qty + j, block);
186 }
187 kunmap(req->pages[i]);
188 }
189 return false;
190}
191
192/*
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000193 * open an AFS directory file
194 */
195static int afs_dir_open(struct inode *inode, struct file *file)
196{
197 _enter("{%lu}", inode->i_ino);
198
199 BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
200 BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
201
202 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(inode)->flags))
203 return -ENOENT;
204
205 return afs_open(inode, file);
206}
207
208/*
209 * Read the directory into the pagecache in one go, scrubbing the previous
210 * contents. The list of pages is returned, pinning them so that they don't
211 * get reclaimed during the iteration.
212 */
213static struct afs_read *afs_read_dir(struct afs_vnode *dvnode, struct key *key)
214 __acquires(&dvnode->validate_lock)
215{
216 struct afs_read *req;
217 loff_t i_size;
218 int nr_pages, nr_inline, i, n;
219 int ret = -ENOMEM;
220
221retry:
222 i_size = i_size_read(&dvnode->vfs_inode);
223 if (i_size < 2048)
David Brazdil0f672f62019-12-10 10:32:29 +0000224 return ERR_PTR(afs_bad(dvnode, afs_file_error_dir_small));
225 if (i_size > 2048 * 1024) {
226 trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000227 return ERR_PTR(-EFBIG);
David Brazdil0f672f62019-12-10 10:32:29 +0000228 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000229
230 _enter("%llu", i_size);
231
232 /* Get a request record to hold the page list. We want to hold it
233 * inline if we can, but we don't want to make an order 1 allocation.
234 */
235 nr_pages = (i_size + PAGE_SIZE - 1) / PAGE_SIZE;
236 nr_inline = nr_pages;
237 if (nr_inline > (PAGE_SIZE - sizeof(*req)) / sizeof(struct page *))
238 nr_inline = 0;
239
David Brazdil0f672f62019-12-10 10:32:29 +0000240 req = kzalloc(struct_size(req, array, nr_inline), GFP_KERNEL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000241 if (!req)
242 return ERR_PTR(-ENOMEM);
243
244 refcount_set(&req->usage, 1);
245 req->nr_pages = nr_pages;
246 req->actual_len = i_size; /* May change */
247 req->len = nr_pages * PAGE_SIZE; /* We can ask for more than there is */
248 req->data_version = dvnode->status.data_version; /* May change */
249 if (nr_inline > 0) {
250 req->pages = req->array;
251 } else {
252 req->pages = kcalloc(nr_pages, sizeof(struct page *),
253 GFP_KERNEL);
254 if (!req->pages)
255 goto error;
256 }
257
258 /* Get a list of all the pages that hold or will hold the directory
259 * content. We need to fill in any gaps that we might find where the
260 * memory reclaimer has been at work. If there are any gaps, we will
261 * need to reread the entire directory contents.
262 */
263 i = 0;
264 do {
265 n = find_get_pages_contig(dvnode->vfs_inode.i_mapping, i,
266 req->nr_pages - i,
267 req->pages + i);
268 _debug("find %u at %u/%u", n, i, req->nr_pages);
269 if (n == 0) {
270 gfp_t gfp = dvnode->vfs_inode.i_mapping->gfp_mask;
271
272 if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
273 afs_stat_v(dvnode, n_inval);
274
275 ret = -ENOMEM;
276 req->pages[i] = __page_cache_alloc(gfp);
277 if (!req->pages[i])
278 goto error;
279 ret = add_to_page_cache_lru(req->pages[i],
280 dvnode->vfs_inode.i_mapping,
281 i, gfp);
282 if (ret < 0)
283 goto error;
284
285 set_page_private(req->pages[i], 1);
286 SetPagePrivate(req->pages[i]);
287 unlock_page(req->pages[i]);
288 i++;
289 } else {
290 i += n;
291 }
292 } while (i < req->nr_pages);
293
294 /* If we're going to reload, we need to lock all the pages to prevent
295 * races.
296 */
297 ret = -ERESTARTSYS;
298 if (down_read_killable(&dvnode->validate_lock) < 0)
299 goto error;
300
301 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
302 goto success;
303
304 up_read(&dvnode->validate_lock);
305 if (down_write_killable(&dvnode->validate_lock) < 0)
306 goto error;
307
308 if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
David Brazdil0f672f62019-12-10 10:32:29 +0000309 trace_afs_reload_dir(dvnode);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000310 ret = afs_fetch_data(dvnode, key, req);
311 if (ret < 0)
312 goto error_unlock;
313
314 task_io_account_read(PAGE_SIZE * req->nr_pages);
315
316 if (req->len < req->file_size)
317 goto content_has_grown;
318
319 /* Validate the data we just read. */
320 ret = -EIO;
David Brazdil0f672f62019-12-10 10:32:29 +0000321 if (!afs_dir_check_pages(dvnode, req))
322 goto error_unlock;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000323
324 // TODO: Trim excess pages
325
326 set_bit(AFS_VNODE_DIR_VALID, &dvnode->flags);
327 }
328
329 downgrade_write(&dvnode->validate_lock);
330success:
331 return req;
332
333error_unlock:
334 up_write(&dvnode->validate_lock);
335error:
336 afs_put_read(req);
337 _leave(" = %d", ret);
338 return ERR_PTR(ret);
339
340content_has_grown:
341 up_write(&dvnode->validate_lock);
342 afs_put_read(req);
343 goto retry;
344}
345
346/*
347 * deal with one block in an AFS directory
348 */
David Brazdil0f672f62019-12-10 10:32:29 +0000349static int afs_dir_iterate_block(struct afs_vnode *dvnode,
350 struct dir_context *ctx,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000351 union afs_xdr_dir_block *block,
352 unsigned blkoff)
353{
354 union afs_xdr_dirent *dire;
355 unsigned offset, next, curr;
356 size_t nlen;
357 int tmp;
358
359 _enter("%u,%x,%p,,",(unsigned)ctx->pos,blkoff,block);
360
361 curr = (ctx->pos - blkoff) / sizeof(union afs_xdr_dirent);
362
363 /* walk through the block, an entry at a time */
364 for (offset = (blkoff == 0 ? AFS_DIR_RESV_BLOCKS0 : AFS_DIR_RESV_BLOCKS);
365 offset < AFS_DIR_SLOTS_PER_BLOCK;
366 offset = next
367 ) {
368 next = offset + 1;
369
370 /* skip entries marked unused in the bitmap */
371 if (!(block->hdr.bitmap[offset / 8] &
372 (1 << (offset % 8)))) {
373 _debug("ENT[%zu.%u]: unused",
374 blkoff / sizeof(union afs_xdr_dir_block), offset);
375 if (offset >= curr)
376 ctx->pos = blkoff +
377 next * sizeof(union afs_xdr_dirent);
378 continue;
379 }
380
381 /* got a valid entry */
382 dire = &block->dirents[offset];
383 nlen = strnlen(dire->u.name,
384 sizeof(*block) -
385 offset * sizeof(union afs_xdr_dirent));
386
387 _debug("ENT[%zu.%u]: %s %zu \"%s\"",
388 blkoff / sizeof(union afs_xdr_dir_block), offset,
389 (offset < curr ? "skip" : "fill"),
390 nlen, dire->u.name);
391
392 /* work out where the next possible entry is */
393 for (tmp = nlen; tmp > 15; tmp -= sizeof(union afs_xdr_dirent)) {
394 if (next >= AFS_DIR_SLOTS_PER_BLOCK) {
395 _debug("ENT[%zu.%u]:"
396 " %u travelled beyond end dir block"
397 " (len %u/%zu)",
398 blkoff / sizeof(union afs_xdr_dir_block),
399 offset, next, tmp, nlen);
David Brazdil0f672f62019-12-10 10:32:29 +0000400 return afs_bad(dvnode, afs_file_error_dir_over_end);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000401 }
402 if (!(block->hdr.bitmap[next / 8] &
403 (1 << (next % 8)))) {
404 _debug("ENT[%zu.%u]:"
405 " %u unmarked extension (len %u/%zu)",
406 blkoff / sizeof(union afs_xdr_dir_block),
407 offset, next, tmp, nlen);
David Brazdil0f672f62019-12-10 10:32:29 +0000408 return afs_bad(dvnode, afs_file_error_dir_unmarked_ext);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000409 }
410
411 _debug("ENT[%zu.%u]: ext %u/%zu",
412 blkoff / sizeof(union afs_xdr_dir_block),
413 next, tmp, nlen);
414 next++;
415 }
416
417 /* skip if starts before the current position */
418 if (offset < curr)
419 continue;
420
421 /* found the next entry */
422 if (!dir_emit(ctx, dire->u.name, nlen,
423 ntohl(dire->u.vnode),
424 (ctx->actor == afs_lookup_filldir ||
425 ctx->actor == afs_lookup_one_filldir)?
426 ntohl(dire->u.unique) : DT_UNKNOWN)) {
427 _leave(" = 0 [full]");
428 return 0;
429 }
430
431 ctx->pos = blkoff + next * sizeof(union afs_xdr_dirent);
432 }
433
434 _leave(" = 1 [more]");
435 return 1;
436}
437
438/*
439 * iterate through the data blob that lists the contents of an AFS directory
440 */
441static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
David Brazdil0f672f62019-12-10 10:32:29 +0000442 struct key *key, afs_dataversion_t *_dir_version)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000443{
444 struct afs_vnode *dvnode = AFS_FS_I(dir);
445 struct afs_xdr_dir_page *dbuf;
446 union afs_xdr_dir_block *dblock;
447 struct afs_read *req;
448 struct page *page;
449 unsigned blkoff, limit;
450 int ret;
451
452 _enter("{%lu},%u,,", dir->i_ino, (unsigned)ctx->pos);
453
454 if (test_bit(AFS_VNODE_DELETED, &AFS_FS_I(dir)->flags)) {
455 _leave(" = -ESTALE");
456 return -ESTALE;
457 }
458
459 req = afs_read_dir(dvnode, key);
460 if (IS_ERR(req))
461 return PTR_ERR(req);
David Brazdil0f672f62019-12-10 10:32:29 +0000462 *_dir_version = req->data_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000463
464 /* round the file position up to the next entry boundary */
465 ctx->pos += sizeof(union afs_xdr_dirent) - 1;
466 ctx->pos &= ~(sizeof(union afs_xdr_dirent) - 1);
467
468 /* walk through the blocks in sequence */
469 ret = 0;
470 while (ctx->pos < req->actual_len) {
471 blkoff = ctx->pos & ~(sizeof(union afs_xdr_dir_block) - 1);
472
473 /* Fetch the appropriate page from the directory and re-add it
474 * to the LRU.
475 */
476 page = req->pages[blkoff / PAGE_SIZE];
477 if (!page) {
David Brazdil0f672f62019-12-10 10:32:29 +0000478 ret = afs_bad(dvnode, afs_file_error_dir_missing_page);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000479 break;
480 }
481 mark_page_accessed(page);
482
483 limit = blkoff & ~(PAGE_SIZE - 1);
484
485 dbuf = kmap(page);
486
487 /* deal with the individual blocks stashed on this page */
488 do {
489 dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /
490 sizeof(union afs_xdr_dir_block)];
David Brazdil0f672f62019-12-10 10:32:29 +0000491 ret = afs_dir_iterate_block(dvnode, ctx, dblock, blkoff);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000492 if (ret != 1) {
493 kunmap(page);
494 goto out;
495 }
496
497 blkoff += sizeof(union afs_xdr_dir_block);
498
499 } while (ctx->pos < dir->i_size && blkoff < limit);
500
501 kunmap(page);
502 ret = 0;
503 }
504
505out:
506 up_read(&dvnode->validate_lock);
507 afs_put_read(req);
508 _leave(" = %d", ret);
509 return ret;
510}
511
512/*
513 * read an AFS directory
514 */
515static int afs_readdir(struct file *file, struct dir_context *ctx)
516{
David Brazdil0f672f62019-12-10 10:32:29 +0000517 afs_dataversion_t dir_version;
518
519 return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file),
520 &dir_version);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000521}
522
523/*
524 * Search the directory for a single name
525 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
526 * uniquifier through dtype
527 */
528static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name,
529 int nlen, loff_t fpos, u64 ino, unsigned dtype)
530{
531 struct afs_lookup_one_cookie *cookie =
532 container_of(ctx, struct afs_lookup_one_cookie, ctx);
533
534 _enter("{%s,%u},%s,%u,,%llu,%u",
535 cookie->name.name, cookie->name.len, name, nlen,
536 (unsigned long long) ino, dtype);
537
538 /* insanity checks first */
539 BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
540 BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
541
542 if (cookie->name.len != nlen ||
543 memcmp(cookie->name.name, name, nlen) != 0) {
544 _leave(" = 0 [no]");
545 return 0;
546 }
547
548 cookie->fid.vnode = ino;
549 cookie->fid.unique = dtype;
550 cookie->found = 1;
551
552 _leave(" = -1 [found]");
553 return -1;
554}
555
556/*
557 * Do a lookup of a single name in a directory
558 * - just returns the FID the dentry name maps to if found
559 */
560static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
David Brazdil0f672f62019-12-10 10:32:29 +0000561 struct afs_fid *fid, struct key *key,
562 afs_dataversion_t *_dir_version)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000563{
564 struct afs_super_info *as = dir->i_sb->s_fs_info;
565 struct afs_lookup_one_cookie cookie = {
566 .ctx.actor = afs_lookup_one_filldir,
567 .name = dentry->d_name,
568 .fid.vid = as->volume->vid
569 };
570 int ret;
571
572 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
573
574 /* search the directory */
David Brazdil0f672f62019-12-10 10:32:29 +0000575 ret = afs_dir_iterate(dir, &cookie.ctx, key, _dir_version);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000576 if (ret < 0) {
577 _leave(" = %d [iter]", ret);
578 return ret;
579 }
580
581 ret = -ENOENT;
582 if (!cookie.found) {
583 _leave(" = -ENOENT [not found]");
584 return -ENOENT;
585 }
586
587 *fid = cookie.fid;
David Brazdil0f672f62019-12-10 10:32:29 +0000588 _leave(" = 0 { vn=%llu u=%u }", fid->vnode, fid->unique);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000589 return 0;
590}
591
592/*
593 * search the directory for a name
594 * - if afs_dir_iterate_block() spots this function, it'll pass the FID
595 * uniquifier through dtype
596 */
597static int afs_lookup_filldir(struct dir_context *ctx, const char *name,
598 int nlen, loff_t fpos, u64 ino, unsigned dtype)
599{
600 struct afs_lookup_cookie *cookie =
601 container_of(ctx, struct afs_lookup_cookie, ctx);
602 int ret;
603
604 _enter("{%s,%u},%s,%u,,%llu,%u",
605 cookie->name.name, cookie->name.len, name, nlen,
606 (unsigned long long) ino, dtype);
607
608 /* insanity checks first */
609 BUILD_BUG_ON(sizeof(union afs_xdr_dir_block) != 2048);
610 BUILD_BUG_ON(sizeof(union afs_xdr_dirent) != 32);
611
612 if (cookie->found) {
613 if (cookie->nr_fids < 50) {
614 cookie->fids[cookie->nr_fids].vnode = ino;
615 cookie->fids[cookie->nr_fids].unique = dtype;
616 cookie->nr_fids++;
617 }
618 } else if (cookie->name.len == nlen &&
619 memcmp(cookie->name.name, name, nlen) == 0) {
620 cookie->fids[0].vnode = ino;
621 cookie->fids[0].unique = dtype;
622 cookie->found = 1;
623 if (cookie->one_only)
624 return -1;
625 }
626
627 ret = cookie->nr_fids >= 50 ? -1 : 0;
628 _leave(" = %d", ret);
629 return ret;
630}
631
632/*
633 * Do a lookup in a directory. We make use of bulk lookup to query a slew of
634 * files in one go and create inodes for them. The inode of the file we were
635 * asked for is returned.
636 */
637static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry,
638 struct key *key)
639{
640 struct afs_lookup_cookie *cookie;
David Brazdil0f672f62019-12-10 10:32:29 +0000641 struct afs_cb_interest *dcbi, *cbi = NULL;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000642 struct afs_super_info *as = dir->i_sb->s_fs_info;
David Brazdil0f672f62019-12-10 10:32:29 +0000643 struct afs_status_cb *scb;
644 struct afs_iget_data iget_data;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000645 struct afs_fs_cursor fc;
David Brazdil0f672f62019-12-10 10:32:29 +0000646 struct afs_server *server;
647 struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
648 struct inode *inode = NULL, *ti;
649 afs_dataversion_t data_version = READ_ONCE(dvnode->status.data_version);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000650 int ret, i;
651
652 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
653
654 cookie = kzalloc(sizeof(struct afs_lookup_cookie), GFP_KERNEL);
655 if (!cookie)
656 return ERR_PTR(-ENOMEM);
657
658 cookie->ctx.actor = afs_lookup_filldir;
659 cookie->name = dentry->d_name;
Olivier Deprez0e641232021-09-23 10:07:05 +0200660 cookie->nr_fids = 2; /* slot 0 is saved for the fid we actually want
661 * and slot 1 for the directory */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000662
663 read_seqlock_excl(&dvnode->cb_lock);
David Brazdil0f672f62019-12-10 10:32:29 +0000664 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 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000672 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 Brazdil0f672f62019-12-10 10:32:29 +0000678 ret = afs_dir_iterate(dir, &cookie->ctx, key, &data_version);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000679 if (ret < 0) {
680 inode = ERR_PTR(ret);
681 goto out;
682 }
683
David Brazdil0f672f62019-12-10 10:32:29 +0000684 dentry->d_fsdata = (void *)(unsigned long)data_version;
685
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000686 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 Brazdil0f672f62019-12-10 10:32:29 +0000691 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);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000697 if (inode)
698 goto out;
699
700 /* Need space for examining all the selected files */
701 inode = ERR_PTR(-ENOMEM);
David Brazdil0f672f62019-12-10 10:32:29 +0000702 cookie->statuses = kvcalloc(cookie->nr_fids, sizeof(struct afs_status_cb),
703 GFP_KERNEL);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000704 if (!cookie->statuses)
705 goto out;
706
David Brazdil0f672f62019-12-10 10:32:29 +0000707 cookie->inodes = kcalloc(cookie->nr_fids, sizeof(struct inode *),
708 GFP_KERNEL);
709 if (!cookie->inodes)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000710 goto out_s;
711
Olivier Deprez0e641232021-09-23 10:07:05 +0200712 cookie->fids[1] = dvnode->fid;
713 cookie->statuses[1].cb_break = afs_calc_vnode_cb_break(dvnode);
714 cookie->inodes[1] = igrab(&dvnode->vfs_inode);
715
716 for (i = 2; i < cookie->nr_fids; i++) {
David Brazdil0f672f62019-12-10 10:32:29 +0000717 scb = &cookie->statuses[i];
718
719 /* Find any inodes that already exist and get their
720 * callback counters.
721 */
722 iget_data.fid = cookie->fids[i];
723 ti = ilookup5_nowait(dir->i_sb, iget_data.fid.vnode,
724 afs_iget5_test, &iget_data);
725 if (!IS_ERR_OR_NULL(ti)) {
726 vnode = AFS_FS_I(ti);
727 scb->cb_break = afs_calc_vnode_cb_break(vnode);
728 cookie->inodes[i] = ti;
729 }
730 }
731
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000732 /* Try FS.InlineBulkStatus first. Abort codes for the individual
733 * lookups contained therein are stored in the reply without aborting
734 * the whole operation.
735 */
736 if (cookie->one_only)
737 goto no_inline_bulk_status;
738
739 inode = ERR_PTR(-ERESTARTSYS);
David Brazdil0f672f62019-12-10 10:32:29 +0000740 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000741 while (afs_select_fileserver(&fc)) {
742 if (test_bit(AFS_SERVER_FL_NO_IBULK,
743 &fc.cbi->server->flags)) {
744 fc.ac.abort_code = RX_INVALID_OPERATION;
745 fc.ac.error = -ECONNABORTED;
746 break;
747 }
David Brazdil0f672f62019-12-10 10:32:29 +0000748 iget_data.cb_v_break = dvnode->volume->cb_v_break;
749 iget_data.cb_s_break = fc.cbi->server->cb_s_break;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000750 afs_fs_inline_bulk_status(&fc,
751 afs_v2net(dvnode),
752 cookie->fids,
753 cookie->statuses,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000754 cookie->nr_fids, NULL);
755 }
756
757 if (fc.ac.error == 0)
758 cbi = afs_get_cb_interest(fc.cbi);
759 if (fc.ac.abort_code == RX_INVALID_OPERATION)
760 set_bit(AFS_SERVER_FL_NO_IBULK, &fc.cbi->server->flags);
761 inode = ERR_PTR(afs_end_vnode_operation(&fc));
762 }
763
764 if (!IS_ERR(inode))
765 goto success;
766 if (fc.ac.abort_code != RX_INVALID_OPERATION)
767 goto out_c;
768
769no_inline_bulk_status:
770 /* We could try FS.BulkStatus next, but this aborts the entire op if
771 * any of the lookups fails - so, for the moment, revert to
772 * FS.FetchStatus for just the primary fid.
773 */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000774 inode = ERR_PTR(-ERESTARTSYS);
David Brazdil0f672f62019-12-10 10:32:29 +0000775 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000776 while (afs_select_fileserver(&fc)) {
David Brazdil0f672f62019-12-10 10:32:29 +0000777 iget_data.cb_v_break = dvnode->volume->cb_v_break;
778 iget_data.cb_s_break = fc.cbi->server->cb_s_break;
779 scb = &cookie->statuses[0];
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000780 afs_fs_fetch_status(&fc,
781 afs_v2net(dvnode),
782 cookie->fids,
David Brazdil0f672f62019-12-10 10:32:29 +0000783 scb,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000784 NULL);
785 }
786
787 if (fc.ac.error == 0)
788 cbi = afs_get_cb_interest(fc.cbi);
789 inode = ERR_PTR(afs_end_vnode_operation(&fc));
790 }
791
792 if (IS_ERR(inode))
793 goto out_c;
794
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000795success:
796 /* Turn all the files into inodes and save the first one - which is the
797 * one we actually want.
798 */
David Brazdil0f672f62019-12-10 10:32:29 +0000799 scb = &cookie->statuses[0];
800 if (scb->status.abort_code != 0)
801 inode = ERR_PTR(afs_abort_to_error(scb->status.abort_code));
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000802
803 for (i = 0; i < cookie->nr_fids; i++) {
David Brazdil0f672f62019-12-10 10:32:29 +0000804 struct afs_status_cb *scb = &cookie->statuses[i];
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000805
David Brazdil0f672f62019-12-10 10:32:29 +0000806 if (!scb->have_status && !scb->have_error)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000807 continue;
808
David Brazdil0f672f62019-12-10 10:32:29 +0000809 if (cookie->inodes[i]) {
810 struct afs_vnode *iv = AFS_FS_I(cookie->inodes[i]);
811
812 if (test_bit(AFS_VNODE_UNSET, &iv->flags))
813 continue;
814
815 afs_vnode_commit_status(&fc, iv,
816 scb->cb_break, NULL, scb);
817 continue;
818 }
819
820 if (scb->status.abort_code != 0)
821 continue;
822
823 iget_data.fid = cookie->fids[i];
824 ti = afs_iget(dir->i_sb, key, &iget_data, scb, cbi, dvnode);
825 if (!IS_ERR(ti))
826 afs_cache_permit(AFS_FS_I(ti), key,
827 0 /* Assume vnode->cb_break is 0 */ +
828 iget_data.cb_v_break,
829 scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000830 if (i == 0) {
831 inode = ti;
832 } else {
833 if (!IS_ERR(ti))
834 iput(ti);
835 }
836 }
837
838out_c:
839 afs_put_cb_interest(afs_v2net(dvnode), cbi);
David Brazdil0f672f62019-12-10 10:32:29 +0000840 if (cookie->inodes) {
841 for (i = 0; i < cookie->nr_fids; i++)
842 iput(cookie->inodes[i]);
843 kfree(cookie->inodes);
844 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000845out_s:
David Brazdil0f672f62019-12-10 10:32:29 +0000846 kvfree(cookie->statuses);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000847out:
848 kfree(cookie);
849 return inode;
850}
851
852/*
853 * Look up an entry in a directory with @sys substitution.
854 */
855static struct dentry *afs_lookup_atsys(struct inode *dir, struct dentry *dentry,
856 struct key *key)
857{
858 struct afs_sysnames *subs;
859 struct afs_net *net = afs_i2net(dir);
860 struct dentry *ret;
861 char *buf, *p, *name;
862 int len, i;
863
864 _enter("");
865
866 ret = ERR_PTR(-ENOMEM);
867 p = buf = kmalloc(AFSNAMEMAX, GFP_KERNEL);
868 if (!buf)
869 goto out_p;
870 if (dentry->d_name.len > 4) {
871 memcpy(p, dentry->d_name.name, dentry->d_name.len - 4);
872 p += dentry->d_name.len - 4;
873 }
874
875 /* There is an ordered list of substitutes that we have to try. */
876 read_lock(&net->sysnames_lock);
877 subs = net->sysnames;
878 refcount_inc(&subs->usage);
879 read_unlock(&net->sysnames_lock);
880
881 for (i = 0; i < subs->nr; i++) {
882 name = subs->subs[i];
883 len = dentry->d_name.len - 4 + strlen(name);
884 if (len >= AFSNAMEMAX) {
885 ret = ERR_PTR(-ENAMETOOLONG);
886 goto out_s;
887 }
888
889 strcpy(p, name);
890 ret = lookup_one_len(buf, dentry->d_parent, len);
891 if (IS_ERR(ret) || d_is_positive(ret))
892 goto out_s;
893 dput(ret);
894 }
895
896 /* We don't want to d_add() the @sys dentry here as we don't want to
897 * the cached dentry to hide changes to the sysnames list.
898 */
899 ret = NULL;
900out_s:
901 afs_put_sysnames(subs);
902 kfree(buf);
903out_p:
904 key_put(key);
905 return ret;
906}
907
908/*
909 * look up an entry in a directory
910 */
911static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
912 unsigned int flags)
913{
914 struct afs_vnode *dvnode = AFS_FS_I(dir);
Olivier Deprez0e641232021-09-23 10:07:05 +0200915 struct afs_fid fid = {};
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000916 struct inode *inode;
917 struct dentry *d;
918 struct key *key;
919 int ret;
920
David Brazdil0f672f62019-12-10 10:32:29 +0000921 _enter("{%llx:%llu},%p{%pd},",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000922 dvnode->fid.vid, dvnode->fid.vnode, dentry, dentry);
923
924 ASSERTCMP(d_inode(dentry), ==, NULL);
925
926 if (dentry->d_name.len >= AFSNAMEMAX) {
927 _leave(" = -ENAMETOOLONG");
928 return ERR_PTR(-ENAMETOOLONG);
929 }
930
931 if (test_bit(AFS_VNODE_DELETED, &dvnode->flags)) {
932 _leave(" = -ESTALE");
933 return ERR_PTR(-ESTALE);
934 }
935
936 key = afs_request_key(dvnode->volume->cell);
937 if (IS_ERR(key)) {
938 _leave(" = %ld [key]", PTR_ERR(key));
939 return ERR_CAST(key);
940 }
941
942 ret = afs_validate(dvnode, key);
943 if (ret < 0) {
944 key_put(key);
945 _leave(" = %d [val]", ret);
946 return ERR_PTR(ret);
947 }
948
949 if (dentry->d_name.len >= 4 &&
950 dentry->d_name.name[dentry->d_name.len - 4] == '@' &&
951 dentry->d_name.name[dentry->d_name.len - 3] == 's' &&
952 dentry->d_name.name[dentry->d_name.len - 2] == 'y' &&
953 dentry->d_name.name[dentry->d_name.len - 1] == 's')
954 return afs_lookup_atsys(dir, dentry, key);
955
956 afs_stat_v(dvnode, n_lookup);
957 inode = afs_do_lookup(dir, dentry, key);
958 key_put(key);
Olivier Deprez0e641232021-09-23 10:07:05 +0200959 if (inode == ERR_PTR(-ENOENT))
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000960 inode = afs_try_auto_mntpt(dentry, dir);
Olivier Deprez0e641232021-09-23 10:07:05 +0200961
962 if (!IS_ERR_OR_NULL(inode))
963 fid = AFS_FS_I(inode)->fid;
964
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000965 d = d_splice_alias(inode, dentry);
David Brazdil0f672f62019-12-10 10:32:29 +0000966 if (!IS_ERR_OR_NULL(d)) {
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000967 d->d_fsdata = dentry->d_fsdata;
Olivier Deprez0e641232021-09-23 10:07:05 +0200968 trace_afs_lookup(dvnode, &d->d_name, &fid);
David Brazdil0f672f62019-12-10 10:32:29 +0000969 } else {
Olivier Deprez0e641232021-09-23 10:07:05 +0200970 trace_afs_lookup(dvnode, &dentry->d_name, &fid);
David Brazdil0f672f62019-12-10 10:32:29 +0000971 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +0000972 return d;
973}
974
975/*
David Brazdil0f672f62019-12-10 10:32:29 +0000976 * 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/*
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001028 * 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
1031 */
1032static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
1033{
1034 struct afs_vnode *vnode, *dir;
1035 struct afs_fid uninitialized_var(fid);
1036 struct dentry *parent;
1037 struct inode *inode;
1038 struct key *key;
Olivier Deprez0e641232021-09-23 10:07:05 +02001039 afs_dataversion_t dir_version, invalid_before;
David Brazdil0f672f62019-12-10 10:32:29 +00001040 long de_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001041 int ret;
1042
1043 if (flags & LOOKUP_RCU)
David Brazdil0f672f62019-12-10 10:32:29 +00001044 return afs_d_revalidate_rcu(dentry);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001045
1046 if (d_really_is_positive(dentry)) {
1047 vnode = AFS_FS_I(d_inode(dentry));
David Brazdil0f672f62019-12-10 10:32:29 +00001048 _enter("{v={%llx:%llu} n=%pd fl=%lx},",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001049 vnode->fid.vid, vnode->fid.vnode, dentry,
1050 vnode->flags);
1051 } else {
1052 _enter("{neg n=%pd}", dentry);
1053 }
1054
1055 key = afs_request_key(AFS_FS_S(dentry->d_sb)->volume->cell);
1056 if (IS_ERR(key))
1057 key = NULL;
1058
1059 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
1069 /* lock down the parent dentry so we can peer at it */
1070 parent = dget_parent(dentry);
1071 dir = AFS_FS_I(d_inode(parent));
1072
1073 /* validate the parent directory */
1074 afs_validate(dir, key);
1075
1076 if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
1077 _debug("%pd: parent dir deleted", dentry);
1078 goto out_bad_parent;
1079 }
1080
1081 /* 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 Brazdil0f672f62019-12-10 10:32:29 +00001086 dir_version = dir->status.data_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001087 de_version = (long)dentry->d_fsdata;
David Brazdil0f672f62019-12-10 10:32:29 +00001088 if (de_version == (long)dir_version)
1089 goto out_valid_noupdate;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001090
Olivier Deprez0e641232021-09-23 10:07:05 +02001091 invalid_before = dir->invalid_before;
1092 if (de_version - (long)invalid_before >= 0)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001093 goto out_valid;
1094
1095 _debug("dir modified");
1096 afs_stat_v(dir, n_reval);
1097
1098 /* search the directory for this vnode */
David Brazdil0f672f62019-12-10 10:32:29 +00001099 ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key, &dir_version);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001100 switch (ret) {
1101 case 0:
1102 /* the filename maps to something */
1103 if (d_really_is_negative(dentry))
1104 goto out_bad_parent;
1105 inode = d_inode(dentry);
1106 if (is_bad_inode(inode)) {
1107 printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
1108 dentry);
1109 goto out_bad_parent;
1110 }
1111
1112 vnode = AFS_FS_I(inode);
1113
1114 /* if the vnode ID has changed, then the dirent points to a
1115 * different file */
1116 if (fid.vnode != vnode->fid.vnode) {
David Brazdil0f672f62019-12-10 10:32:29 +00001117 _debug("%pd: dirent changed [%llu != %llu]",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001118 dentry, fid.vnode,
1119 vnode->fid.vnode);
1120 goto not_found;
1121 }
1122
1123 /* if the vnode ID uniqifier has changed, then the file has
1124 * been deleted and replaced, and the original vnode ID has
1125 * been reused */
1126 if (fid.unique != vnode->fid.unique) {
1127 _debug("%pd: file deleted (uq %u -> %u I:%u)",
1128 dentry, fid.unique,
1129 vnode->fid.unique,
1130 vnode->vfs_inode.i_generation);
1131 write_seqlock(&vnode->cb_lock);
1132 set_bit(AFS_VNODE_DELETED, &vnode->flags);
1133 write_sequnlock(&vnode->cb_lock);
1134 goto not_found;
1135 }
1136 goto out_valid;
1137
1138 case -ENOENT:
1139 /* the filename is unknown */
1140 _debug("%pd: dirent not found", dentry);
1141 if (d_really_is_positive(dentry))
1142 goto not_found;
1143 goto out_valid;
1144
1145 default:
1146 _debug("failed to iterate dir %pd: %d",
1147 parent, ret);
1148 goto out_bad_parent;
1149 }
1150
1151out_valid:
David Brazdil0f672f62019-12-10 10:32:29 +00001152 dentry->d_fsdata = (void *)(unsigned long)dir_version;
1153out_valid_noupdate:
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001154 dput(parent);
1155 key_put(key);
1156 _leave(" = 1 [valid]");
1157 return 1;
1158
1159 /* the dirent, if it exists, now points to a different vnode */
1160not_found:
1161 spin_lock(&dentry->d_lock);
1162 dentry->d_flags |= DCACHE_NFSFS_RENAMED;
1163 spin_unlock(&dentry->d_lock);
1164
1165out_bad_parent:
1166 _debug("dropping dentry %pd2", dentry);
1167 dput(parent);
1168out_bad:
1169 key_put(key);
1170
1171 _leave(" = 0 [bad]");
1172 return 0;
1173}
1174
1175/*
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 */
1181static int afs_d_delete(const struct dentry *dentry)
1182{
1183 _enter("%pd", dentry);
1184
1185 if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
1186 goto zap;
1187
1188 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)))
1191 goto zap;
1192
1193 _leave(" = 0 [keep]");
1194 return 0;
1195
1196zap:
1197 _leave(" = 1 [zap]");
1198 return 1;
1199}
1200
1201/*
David Brazdil0f672f62019-12-10 10:32:29 +00001202 * 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/*
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001212 * handle dentry release
1213 */
1214void afs_d_release(struct dentry *dentry)
1215{
1216 _enter("%pd", dentry);
1217}
1218
1219/*
1220 * 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 Brazdil0f672f62019-12-10 10:32:29 +00001224 struct afs_iget_data *new_data,
1225 struct afs_status_cb *new_scb)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001226{
1227 struct afs_vnode *vnode;
1228 struct inode *inode;
1229
1230 if (fc->ac.error < 0)
1231 return;
1232
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001233 inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key,
David Brazdil0f672f62019-12-10 10:32:29 +00001234 new_data, new_scb, fc->cbi, fc->vnode);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +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
1243 vnode = AFS_FS_I(inode);
1244 set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
David Brazdil0f672f62019-12-10 10:32:29 +00001245 if (fc->ac.error == 0)
1246 afs_cache_permit(vnode, fc->key, vnode->cb_break, new_scb);
1247 d_instantiate(new_dentry, inode);
1248}
1249
1250static 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
1258/*
1259 * 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;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001270}
1271
1272/*
1273 * create a directory on an AFS filesystem
1274 */
1275static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
1276{
David Brazdil0f672f62019-12-10 10:32:29 +00001277 struct afs_iget_data iget_data;
1278 struct afs_status_cb *scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001279 struct afs_fs_cursor fc;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001280 struct afs_vnode *dvnode = AFS_FS_I(dir);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001281 struct key *key;
Olivier Deprez0e641232021-09-23 10:07:05 +02001282 afs_dataversion_t data_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001283 int ret;
1284
1285 mode |= S_IFDIR;
1286
David Brazdil0f672f62019-12-10 10:32:29 +00001287 _enter("{%llx:%llu},{%pd},%ho",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001288 dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
1289
David Brazdil0f672f62019-12-10 10:32:29 +00001290 ret = -ENOMEM;
1291 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1292 if (!scb)
1293 goto error;
1294
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001295 key = afs_request_key(dvnode->volume->cell);
1296 if (IS_ERR(key)) {
1297 ret = PTR_ERR(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001298 goto error_scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001299 }
1300
1301 ret = -ERESTARTSYS;
David Brazdil0f672f62019-12-10 10:32:29 +00001302 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
Olivier Deprez0e641232021-09-23 10:07:05 +02001303 data_version = dvnode->status.data_version + 1;
David Brazdil0f672f62019-12-10 10:32:29 +00001304
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001305 while (afs_select_fileserver(&fc)) {
1306 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Brazdil0f672f62019-12-10 10:32:29 +00001307 afs_prep_for_new_inode(&fc, &iget_data);
1308 afs_fs_create(&fc, dentry->d_name.name, mode,
1309 &scb[0], &iget_data.fid, &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001310 }
1311
David Brazdil0f672f62019-12-10 10:32:29 +00001312 afs_check_for_remote_deletion(&fc, dvnode);
1313 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1314 &data_version, &scb[0]);
1315 afs_update_dentry_version(&fc, dentry, &scb[0]);
1316 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001317 ret = afs_end_vnode_operation(&fc);
1318 if (ret < 0)
1319 goto error_key;
1320 } else {
1321 goto error_key;
1322 }
1323
Olivier Deprez0e641232021-09-23 10:07:05 +02001324 if (ret == 0) {
1325 down_write(&dvnode->validate_lock);
1326 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
1327 dvnode->status.data_version == data_version)
1328 afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
1329 afs_edit_dir_for_create);
1330 up_write(&dvnode->validate_lock);
1331 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001332
1333 key_put(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001334 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001335 _leave(" = 0");
1336 return 0;
1337
1338error_key:
1339 key_put(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001340error_scb:
1341 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001342error:
1343 d_drop(dentry);
1344 _leave(" = %d", ret);
1345 return ret;
1346}
1347
1348/*
1349 * Remove a subdir from a directory.
1350 */
1351static void afs_dir_remove_subdir(struct dentry *dentry)
1352{
1353 if (d_really_is_positive(dentry)) {
1354 struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
1355
1356 clear_nlink(&vnode->vfs_inode);
1357 set_bit(AFS_VNODE_DELETED, &vnode->flags);
1358 clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
1359 clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags);
1360 }
1361}
1362
1363/*
1364 * remove a directory from an AFS filesystem
1365 */
1366static int afs_rmdir(struct inode *dir, struct dentry *dentry)
1367{
David Brazdil0f672f62019-12-10 10:32:29 +00001368 struct afs_status_cb *scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001369 struct afs_fs_cursor fc;
David Brazdil0f672f62019-12-10 10:32:29 +00001370 struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001371 struct key *key;
Olivier Deprez0e641232021-09-23 10:07:05 +02001372 afs_dataversion_t data_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001373 int ret;
1374
David Brazdil0f672f62019-12-10 10:32:29 +00001375 _enter("{%llx:%llu},{%pd}",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001376 dvnode->fid.vid, dvnode->fid.vnode, dentry);
1377
David Brazdil0f672f62019-12-10 10:32:29 +00001378 scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL);
1379 if (!scb)
1380 return -ENOMEM;
1381
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001382 key = afs_request_key(dvnode->volume->cell);
1383 if (IS_ERR(key)) {
1384 ret = PTR_ERR(key);
1385 goto error;
1386 }
1387
David Brazdil0f672f62019-12-10 10:32:29 +00001388 /* Try to make sure we have a callback promise on the victim. */
1389 if (d_really_is_positive(dentry)) {
1390 vnode = AFS_FS_I(d_inode(dentry));
1391 ret = afs_validate(vnode, key);
1392 if (ret < 0)
1393 goto error_key;
1394 }
1395
1396 if (vnode) {
1397 ret = down_write_killable(&vnode->rmdir_lock);
1398 if (ret < 0)
1399 goto error_key;
1400 }
1401
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001402 ret = -ERESTARTSYS;
David Brazdil0f672f62019-12-10 10:32:29 +00001403 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
Olivier Deprez0e641232021-09-23 10:07:05 +02001404 data_version = dvnode->status.data_version + 1;
David Brazdil0f672f62019-12-10 10:32:29 +00001405
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001406 while (afs_select_fileserver(&fc)) {
1407 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Brazdil0f672f62019-12-10 10:32:29 +00001408 afs_fs_remove(&fc, vnode, dentry->d_name.name, true, scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001409 }
1410
David Brazdil0f672f62019-12-10 10:32:29 +00001411 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1412 &data_version, scb);
1413 afs_update_dentry_version(&fc, dentry, scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001414 ret = afs_end_vnode_operation(&fc);
1415 if (ret == 0) {
1416 afs_dir_remove_subdir(dentry);
Olivier Deprez0e641232021-09-23 10:07:05 +02001417 down_write(&dvnode->validate_lock);
1418 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
1419 dvnode->status.data_version == data_version)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001420 afs_edit_dir_remove(dvnode, &dentry->d_name,
1421 afs_edit_dir_for_rmdir);
Olivier Deprez0e641232021-09-23 10:07:05 +02001422 up_write(&dvnode->validate_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001423 }
1424 }
1425
David Brazdil0f672f62019-12-10 10:32:29 +00001426 if (vnode)
1427 up_write(&vnode->rmdir_lock);
1428error_key:
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001429 key_put(key);
1430error:
David Brazdil0f672f62019-12-10 10:32:29 +00001431 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001432 return ret;
1433}
1434
1435/*
1436 * Remove a link to a file or symlink from a directory.
1437 *
1438 * If the file was not deleted due to excess hard links, the fileserver will
1439 * break the callback promise on the file - if it had one - before it returns
1440 * to us, and if it was deleted, it won't
1441 *
1442 * However, if we didn't have a callback promise outstanding, or it was
1443 * outstanding on a different server, then it won't break it either...
1444 */
David Brazdil0f672f62019-12-10 10:32:29 +00001445static int afs_dir_remove_link(struct afs_vnode *dvnode, struct dentry *dentry,
1446 struct key *key)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001447{
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001448 int ret = 0;
1449
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001450 if (d_really_is_positive(dentry)) {
1451 struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
1452
David Brazdil0f672f62019-12-10 10:32:29 +00001453 if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
1454 /* Already done */
1455 } else if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
1456 write_seqlock(&vnode->cb_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001457 drop_nlink(&vnode->vfs_inode);
1458 if (vnode->vfs_inode.i_nlink == 0) {
1459 set_bit(AFS_VNODE_DELETED, &vnode->flags);
David Brazdil0f672f62019-12-10 10:32:29 +00001460 __afs_break_callback(vnode, afs_cb_break_for_unlink);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001461 }
David Brazdil0f672f62019-12-10 10:32:29 +00001462 write_sequnlock(&vnode->cb_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001463 ret = 0;
1464 } else {
David Brazdil0f672f62019-12-10 10:32:29 +00001465 afs_break_callback(vnode, afs_cb_break_for_unlink);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001466
1467 if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
1468 kdebug("AFS_VNODE_DELETED");
1469
1470 ret = afs_validate(vnode, key);
1471 if (ret == -ESTALE)
1472 ret = 0;
1473 }
1474 _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);
1475 }
1476
1477 return ret;
1478}
1479
1480/*
1481 * Remove a file or symlink from an AFS filesystem.
1482 */
1483static int afs_unlink(struct inode *dir, struct dentry *dentry)
1484{
1485 struct afs_fs_cursor fc;
David Brazdil0f672f62019-12-10 10:32:29 +00001486 struct afs_status_cb *scb;
1487 struct afs_vnode *dvnode = AFS_FS_I(dir);
1488 struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001489 struct key *key;
David Brazdil0f672f62019-12-10 10:32:29 +00001490 bool need_rehash = false;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001491 int ret;
1492
David Brazdil0f672f62019-12-10 10:32:29 +00001493 _enter("{%llx:%llu},{%pd}",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001494 dvnode->fid.vid, dvnode->fid.vnode, dentry);
1495
1496 if (dentry->d_name.len >= AFSNAMEMAX)
1497 return -ENAMETOOLONG;
1498
David Brazdil0f672f62019-12-10 10:32:29 +00001499 ret = -ENOMEM;
1500 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1501 if (!scb)
1502 goto error;
1503
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001504 key = afs_request_key(dvnode->volume->cell);
1505 if (IS_ERR(key)) {
1506 ret = PTR_ERR(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001507 goto error_scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001508 }
1509
1510 /* Try to make sure we have a callback promise on the victim. */
David Brazdil0f672f62019-12-10 10:32:29 +00001511 ret = afs_validate(vnode, key);
1512 if (ret < 0)
1513 goto error_key;
1514
1515 spin_lock(&dentry->d_lock);
1516 if (d_count(dentry) > 1) {
1517 spin_unlock(&dentry->d_lock);
1518 /* Start asynchronous writeout of the inode */
1519 write_inode_now(d_inode(dentry), 0);
1520 ret = afs_sillyrename(dvnode, vnode, dentry, key);
1521 goto error_key;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001522 }
David Brazdil0f672f62019-12-10 10:32:29 +00001523 if (!d_unhashed(dentry)) {
1524 /* Prevent a race with RCU lookup. */
1525 __d_drop(dentry);
1526 need_rehash = true;
1527 }
1528 spin_unlock(&dentry->d_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001529
1530 ret = -ERESTARTSYS;
David Brazdil0f672f62019-12-10 10:32:29 +00001531 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
1532 afs_dataversion_t data_version = dvnode->status.data_version + 1;
1533 afs_dataversion_t data_version_2 = vnode->status.data_version;
1534
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001535 while (afs_select_fileserver(&fc)) {
1536 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Brazdil0f672f62019-12-10 10:32:29 +00001537 fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
1538
1539 if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) &&
1540 !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) {
1541 yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name,
1542 &scb[0], &scb[1]);
1543 if (fc.ac.error != -ECONNABORTED ||
1544 fc.ac.abort_code != RXGEN_OPCODE)
1545 continue;
1546 set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags);
1547 }
1548
1549 afs_fs_remove(&fc, vnode, dentry->d_name.name, false, &scb[0]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001550 }
1551
David Brazdil0f672f62019-12-10 10:32:29 +00001552 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1553 &data_version, &scb[0]);
1554 afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
1555 &data_version_2, &scb[1]);
1556 afs_update_dentry_version(&fc, dentry, &scb[0]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001557 ret = afs_end_vnode_operation(&fc);
David Brazdil0f672f62019-12-10 10:32:29 +00001558 if (ret == 0 && !(scb[1].have_status || scb[1].have_error))
1559 ret = afs_dir_remove_link(dvnode, dentry, key);
Olivier Deprez0e641232021-09-23 10:07:05 +02001560
1561 if (ret == 0) {
1562 down_write(&dvnode->validate_lock);
1563 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
1564 dvnode->status.data_version == data_version)
1565 afs_edit_dir_remove(dvnode, &dentry->d_name,
1566 afs_edit_dir_for_unlink);
1567 up_write(&dvnode->validate_lock);
1568 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001569 }
1570
David Brazdil0f672f62019-12-10 10:32:29 +00001571 if (need_rehash && ret < 0 && ret != -ENOENT)
1572 d_rehash(dentry);
1573
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001574error_key:
1575 key_put(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001576error_scb:
1577 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001578error:
1579 _leave(" = %d", ret);
1580 return ret;
1581}
1582
1583/*
1584 * create a regular file on an AFS filesystem
1585 */
1586static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
1587 bool excl)
1588{
David Brazdil0f672f62019-12-10 10:32:29 +00001589 struct afs_iget_data iget_data;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001590 struct afs_fs_cursor fc;
David Brazdil0f672f62019-12-10 10:32:29 +00001591 struct afs_status_cb *scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001592 struct afs_vnode *dvnode = AFS_FS_I(dir);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001593 struct key *key;
Olivier Deprez0e641232021-09-23 10:07:05 +02001594 afs_dataversion_t data_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001595 int ret;
1596
1597 mode |= S_IFREG;
1598
David Brazdil0f672f62019-12-10 10:32:29 +00001599 _enter("{%llx:%llu},{%pd},%ho,",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001600 dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
1601
1602 ret = -ENAMETOOLONG;
1603 if (dentry->d_name.len >= AFSNAMEMAX)
1604 goto error;
1605
1606 key = afs_request_key(dvnode->volume->cell);
1607 if (IS_ERR(key)) {
1608 ret = PTR_ERR(key);
1609 goto error;
1610 }
1611
David Brazdil0f672f62019-12-10 10:32:29 +00001612 ret = -ENOMEM;
1613 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1614 if (!scb)
1615 goto error_scb;
1616
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001617 ret = -ERESTARTSYS;
David Brazdil0f672f62019-12-10 10:32:29 +00001618 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
Olivier Deprez0e641232021-09-23 10:07:05 +02001619 data_version = dvnode->status.data_version + 1;
David Brazdil0f672f62019-12-10 10:32:29 +00001620
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001621 while (afs_select_fileserver(&fc)) {
1622 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Brazdil0f672f62019-12-10 10:32:29 +00001623 afs_prep_for_new_inode(&fc, &iget_data);
1624 afs_fs_create(&fc, dentry->d_name.name, mode,
1625 &scb[0], &iget_data.fid, &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001626 }
1627
David Brazdil0f672f62019-12-10 10:32:29 +00001628 afs_check_for_remote_deletion(&fc, dvnode);
1629 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1630 &data_version, &scb[0]);
1631 afs_update_dentry_version(&fc, dentry, &scb[0]);
1632 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001633 ret = afs_end_vnode_operation(&fc);
1634 if (ret < 0)
1635 goto error_key;
1636 } else {
1637 goto error_key;
1638 }
1639
Olivier Deprez0e641232021-09-23 10:07:05 +02001640 down_write(&dvnode->validate_lock);
1641 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
1642 dvnode->status.data_version == data_version)
David Brazdil0f672f62019-12-10 10:32:29 +00001643 afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001644 afs_edit_dir_for_create);
Olivier Deprez0e641232021-09-23 10:07:05 +02001645 up_write(&dvnode->validate_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001646
David Brazdil0f672f62019-12-10 10:32:29 +00001647 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001648 key_put(key);
1649 _leave(" = 0");
1650 return 0;
1651
David Brazdil0f672f62019-12-10 10:32:29 +00001652error_scb:
1653 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001654error_key:
1655 key_put(key);
1656error:
1657 d_drop(dentry);
1658 _leave(" = %d", ret);
1659 return ret;
1660}
1661
1662/*
1663 * create a hard link between files in an AFS filesystem
1664 */
1665static int afs_link(struct dentry *from, struct inode *dir,
1666 struct dentry *dentry)
1667{
1668 struct afs_fs_cursor fc;
David Brazdil0f672f62019-12-10 10:32:29 +00001669 struct afs_status_cb *scb;
1670 struct afs_vnode *dvnode = AFS_FS_I(dir);
1671 struct afs_vnode *vnode = AFS_FS_I(d_inode(from));
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001672 struct key *key;
Olivier Deprez0e641232021-09-23 10:07:05 +02001673 afs_dataversion_t data_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001674 int ret;
1675
David Brazdil0f672f62019-12-10 10:32:29 +00001676 _enter("{%llx:%llu},{%llx:%llu},{%pd}",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001677 vnode->fid.vid, vnode->fid.vnode,
1678 dvnode->fid.vid, dvnode->fid.vnode,
1679 dentry);
1680
1681 ret = -ENAMETOOLONG;
1682 if (dentry->d_name.len >= AFSNAMEMAX)
1683 goto error;
1684
David Brazdil0f672f62019-12-10 10:32:29 +00001685 ret = -ENOMEM;
1686 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1687 if (!scb)
1688 goto error;
1689
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001690 key = afs_request_key(dvnode->volume->cell);
1691 if (IS_ERR(key)) {
1692 ret = PTR_ERR(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001693 goto error_scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001694 }
1695
1696 ret = -ERESTARTSYS;
David Brazdil0f672f62019-12-10 10:32:29 +00001697 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
Olivier Deprez0e641232021-09-23 10:07:05 +02001698 data_version = dvnode->status.data_version + 1;
David Brazdil0f672f62019-12-10 10:32:29 +00001699
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001700 if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) {
1701 afs_end_vnode_operation(&fc);
1702 goto error_key;
1703 }
1704
1705 while (afs_select_fileserver(&fc)) {
1706 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1707 fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
David Brazdil0f672f62019-12-10 10:32:29 +00001708 afs_fs_link(&fc, vnode, dentry->d_name.name,
1709 &scb[0], &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001710 }
1711
David Brazdil0f672f62019-12-10 10:32:29 +00001712 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1713 &data_version, &scb[0]);
1714 afs_vnode_commit_status(&fc, vnode, fc.cb_break_2,
1715 NULL, &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001716 ihold(&vnode->vfs_inode);
David Brazdil0f672f62019-12-10 10:32:29 +00001717 afs_update_dentry_version(&fc, dentry, &scb[0]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001718 d_instantiate(dentry, &vnode->vfs_inode);
1719
1720 mutex_unlock(&vnode->io_lock);
1721 ret = afs_end_vnode_operation(&fc);
1722 if (ret < 0)
1723 goto error_key;
1724 } else {
1725 goto error_key;
1726 }
1727
Olivier Deprez0e641232021-09-23 10:07:05 +02001728 down_write(&dvnode->validate_lock);
1729 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
1730 dvnode->status.data_version == data_version)
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001731 afs_edit_dir_add(dvnode, &dentry->d_name, &vnode->fid,
1732 afs_edit_dir_for_link);
Olivier Deprez0e641232021-09-23 10:07:05 +02001733 up_write(&dvnode->validate_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001734
1735 key_put(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001736 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001737 _leave(" = 0");
1738 return 0;
1739
1740error_key:
1741 key_put(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001742error_scb:
1743 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001744error:
1745 d_drop(dentry);
1746 _leave(" = %d", ret);
1747 return ret;
1748}
1749
1750/*
1751 * create a symlink in an AFS filesystem
1752 */
1753static int afs_symlink(struct inode *dir, struct dentry *dentry,
1754 const char *content)
1755{
David Brazdil0f672f62019-12-10 10:32:29 +00001756 struct afs_iget_data iget_data;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001757 struct afs_fs_cursor fc;
David Brazdil0f672f62019-12-10 10:32:29 +00001758 struct afs_status_cb *scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001759 struct afs_vnode *dvnode = AFS_FS_I(dir);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001760 struct key *key;
Olivier Deprez0e641232021-09-23 10:07:05 +02001761 afs_dataversion_t data_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001762 int ret;
1763
David Brazdil0f672f62019-12-10 10:32:29 +00001764 _enter("{%llx:%llu},{%pd},%s",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001765 dvnode->fid.vid, dvnode->fid.vnode, dentry,
1766 content);
1767
1768 ret = -ENAMETOOLONG;
1769 if (dentry->d_name.len >= AFSNAMEMAX)
1770 goto error;
1771
1772 ret = -EINVAL;
1773 if (strlen(content) >= AFSPATHMAX)
1774 goto error;
1775
David Brazdil0f672f62019-12-10 10:32:29 +00001776 ret = -ENOMEM;
1777 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1778 if (!scb)
1779 goto error;
1780
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001781 key = afs_request_key(dvnode->volume->cell);
1782 if (IS_ERR(key)) {
1783 ret = PTR_ERR(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001784 goto error_scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001785 }
1786
1787 ret = -ERESTARTSYS;
David Brazdil0f672f62019-12-10 10:32:29 +00001788 if (afs_begin_vnode_operation(&fc, dvnode, key, true)) {
Olivier Deprez0e641232021-09-23 10:07:05 +02001789 data_version = dvnode->status.data_version + 1;
David Brazdil0f672f62019-12-10 10:32:29 +00001790
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001791 while (afs_select_fileserver(&fc)) {
1792 fc.cb_break = afs_calc_vnode_cb_break(dvnode);
David Brazdil0f672f62019-12-10 10:32:29 +00001793 afs_prep_for_new_inode(&fc, &iget_data);
1794 afs_fs_symlink(&fc, dentry->d_name.name, content,
1795 &scb[0], &iget_data.fid, &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001796 }
1797
David Brazdil0f672f62019-12-10 10:32:29 +00001798 afs_check_for_remote_deletion(&fc, dvnode);
1799 afs_vnode_commit_status(&fc, dvnode, fc.cb_break,
1800 &data_version, &scb[0]);
1801 afs_update_dentry_version(&fc, dentry, &scb[0]);
1802 afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001803 ret = afs_end_vnode_operation(&fc);
1804 if (ret < 0)
1805 goto error_key;
1806 } else {
1807 goto error_key;
1808 }
1809
Olivier Deprez0e641232021-09-23 10:07:05 +02001810 down_write(&dvnode->validate_lock);
1811 if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
1812 dvnode->status.data_version == data_version)
David Brazdil0f672f62019-12-10 10:32:29 +00001813 afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid,
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001814 afs_edit_dir_for_symlink);
Olivier Deprez0e641232021-09-23 10:07:05 +02001815 up_write(&dvnode->validate_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001816
1817 key_put(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001818 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001819 _leave(" = 0");
1820 return 0;
1821
1822error_key:
1823 key_put(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001824error_scb:
1825 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001826error:
1827 d_drop(dentry);
1828 _leave(" = %d", ret);
1829 return ret;
1830}
1831
1832/*
1833 * rename a file in an AFS filesystem and/or move it between directories
1834 */
1835static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
1836 struct inode *new_dir, struct dentry *new_dentry,
1837 unsigned int flags)
1838{
1839 struct afs_fs_cursor fc;
David Brazdil0f672f62019-12-10 10:32:29 +00001840 struct afs_status_cb *scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001841 struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
David Brazdil0f672f62019-12-10 10:32:29 +00001842 struct dentry *tmp = NULL, *rehash = NULL;
1843 struct inode *new_inode;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001844 struct key *key;
Olivier Deprez0e641232021-09-23 10:07:05 +02001845 afs_dataversion_t orig_data_version;
1846 afs_dataversion_t new_data_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001847 bool new_negative = d_is_negative(new_dentry);
1848 int ret;
1849
1850 if (flags)
1851 return -EINVAL;
1852
David Brazdil0f672f62019-12-10 10:32:29 +00001853 /* Don't allow silly-rename files be moved around. */
1854 if (old_dentry->d_flags & DCACHE_NFSFS_RENAMED)
1855 return -EINVAL;
1856
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001857 vnode = AFS_FS_I(d_inode(old_dentry));
1858 orig_dvnode = AFS_FS_I(old_dir);
1859 new_dvnode = AFS_FS_I(new_dir);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001860
David Brazdil0f672f62019-12-10 10:32:29 +00001861 _enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}",
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001862 orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
1863 vnode->fid.vid, vnode->fid.vnode,
1864 new_dvnode->fid.vid, new_dvnode->fid.vnode,
1865 new_dentry);
1866
David Brazdil0f672f62019-12-10 10:32:29 +00001867 ret = -ENOMEM;
1868 scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL);
1869 if (!scb)
1870 goto error;
1871
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001872 key = afs_request_key(orig_dvnode->volume->cell);
1873 if (IS_ERR(key)) {
1874 ret = PTR_ERR(key);
David Brazdil0f672f62019-12-10 10:32:29 +00001875 goto error_scb;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001876 }
1877
David Brazdil0f672f62019-12-10 10:32:29 +00001878 /* For non-directories, check whether the target is busy and if so,
1879 * make a copy of the dentry and then do a silly-rename. If the
1880 * silly-rename succeeds, the copied dentry is hashed and becomes the
1881 * new target.
1882 */
1883 if (d_is_positive(new_dentry) && !d_is_dir(new_dentry)) {
1884 /* To prevent any new references to the target during the
1885 * rename, we unhash the dentry in advance.
1886 */
1887 if (!d_unhashed(new_dentry)) {
1888 d_drop(new_dentry);
1889 rehash = new_dentry;
1890 }
1891
1892 if (d_count(new_dentry) > 2) {
1893 /* copy the target dentry's name */
1894 ret = -ENOMEM;
1895 tmp = d_alloc(new_dentry->d_parent,
1896 &new_dentry->d_name);
1897 if (!tmp)
1898 goto error_rehash;
1899
1900 ret = afs_sillyrename(new_dvnode,
1901 AFS_FS_I(d_inode(new_dentry)),
1902 new_dentry, key);
1903 if (ret)
1904 goto error_rehash;
1905
1906 new_dentry = tmp;
1907 rehash = NULL;
1908 new_negative = true;
1909 }
1910 }
1911
1912 /* This bit is potentially nasty as there's a potential race with
1913 * afs_d_revalidate{,_rcu}(). We have to change d_fsdata on the dentry
1914 * to reflect it's new parent's new data_version after the op, but
1915 * d_revalidate may see old_dentry between the op having taken place
1916 * and the version being updated.
1917 *
1918 * So drop the old_dentry for now to make other threads go through
1919 * lookup instead - which we hold a lock against.
1920 */
1921 d_drop(old_dentry);
1922
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001923 ret = -ERESTARTSYS;
David Brazdil0f672f62019-12-10 10:32:29 +00001924 if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) {
David Brazdil0f672f62019-12-10 10:32:29 +00001925 orig_data_version = orig_dvnode->status.data_version + 1;
1926
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001927 if (orig_dvnode != new_dvnode) {
1928 if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) {
1929 afs_end_vnode_operation(&fc);
David Brazdil0f672f62019-12-10 10:32:29 +00001930 goto error_rehash_old;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001931 }
David Brazdil0f672f62019-12-10 10:32:29 +00001932 new_data_version = new_dvnode->status.data_version + 1;
1933 } else {
1934 new_data_version = orig_data_version;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001935 }
David Brazdil0f672f62019-12-10 10:32:29 +00001936
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001937 while (afs_select_fileserver(&fc)) {
1938 fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode);
1939 fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
1940 afs_fs_rename(&fc, old_dentry->d_name.name,
1941 new_dvnode, new_dentry->d_name.name,
Olivier Deprez0e641232021-09-23 10:07:05 +02001942 &scb[0], &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001943 }
1944
David Brazdil0f672f62019-12-10 10:32:29 +00001945 afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break,
1946 &orig_data_version, &scb[0]);
1947 if (new_dvnode != orig_dvnode) {
1948 afs_vnode_commit_status(&fc, new_dvnode, fc.cb_break_2,
1949 &new_data_version, &scb[1]);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001950 mutex_unlock(&new_dvnode->io_lock);
David Brazdil0f672f62019-12-10 10:32:29 +00001951 }
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001952 ret = afs_end_vnode_operation(&fc);
1953 if (ret < 0)
David Brazdil0f672f62019-12-10 10:32:29 +00001954 goto error_rehash_old;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001955 }
1956
1957 if (ret == 0) {
David Brazdil0f672f62019-12-10 10:32:29 +00001958 if (rehash)
1959 d_rehash(rehash);
Olivier Deprez0e641232021-09-23 10:07:05 +02001960 down_write(&orig_dvnode->validate_lock);
1961 if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags) &&
1962 orig_dvnode->status.data_version == orig_data_version)
1963 afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
1964 afs_edit_dir_for_rename_0);
1965 if (orig_dvnode != new_dvnode) {
1966 up_write(&orig_dvnode->validate_lock);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001967
Olivier Deprez0e641232021-09-23 10:07:05 +02001968 down_write(&new_dvnode->validate_lock);
1969 }
1970 if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags) &&
1971 orig_dvnode->status.data_version == new_data_version) {
1972 if (!new_negative)
1973 afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
1974 afs_edit_dir_for_rename_1);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001975
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001976 afs_edit_dir_add(new_dvnode, &new_dentry->d_name,
David Brazdil0f672f62019-12-10 10:32:29 +00001977 &vnode->fid, afs_edit_dir_for_rename_2);
Olivier Deprez0e641232021-09-23 10:07:05 +02001978 }
David Brazdil0f672f62019-12-10 10:32:29 +00001979
1980 new_inode = d_inode(new_dentry);
1981 if (new_inode) {
1982 spin_lock(&new_inode->i_lock);
1983 if (new_inode->i_nlink > 0)
1984 drop_nlink(new_inode);
1985 spin_unlock(&new_inode->i_lock);
1986 }
1987
1988 /* Now we can update d_fsdata on the dentries to reflect their
1989 * new parent's data_version.
1990 *
1991 * Note that if we ever implement RENAME_EXCHANGE, we'll have
1992 * to update both dentries with opposing dir versions.
1993 */
Olivier Deprez0e641232021-09-23 10:07:05 +02001994 afs_update_dentry_version(&fc, old_dentry, &scb[1]);
1995 afs_update_dentry_version(&fc, new_dentry, &scb[1]);
David Brazdil0f672f62019-12-10 10:32:29 +00001996 d_move(old_dentry, new_dentry);
Olivier Deprez0e641232021-09-23 10:07:05 +02001997 up_write(&new_dvnode->validate_lock);
David Brazdil0f672f62019-12-10 10:32:29 +00001998 goto error_tmp;
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00001999 }
2000
David Brazdil0f672f62019-12-10 10:32:29 +00002001error_rehash_old:
2002 d_rehash(new_dentry);
2003error_rehash:
2004 if (rehash)
2005 d_rehash(rehash);
2006error_tmp:
2007 if (tmp)
2008 dput(tmp);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002009 key_put(key);
David Brazdil0f672f62019-12-10 10:32:29 +00002010error_scb:
2011 kfree(scb);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002012error:
2013 _leave(" = %d", ret);
2014 return ret;
2015}
2016
2017/*
2018 * Release a directory page and clean up its private state if it's not busy
2019 * - return true if the page can now be released, false if not
2020 */
2021static int afs_dir_releasepage(struct page *page, gfp_t gfp_flags)
2022{
2023 struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);
2024
David Brazdil0f672f62019-12-10 10:32:29 +00002025 _enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002026
2027 set_page_private(page, 0);
2028 ClearPagePrivate(page);
2029
2030 /* The directory will need reloading. */
2031 if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
2032 afs_stat_v(dvnode, n_relpg);
2033 return 1;
2034}
2035
2036/*
2037 * invalidate part or all of a page
2038 * - release a page and clean up its private data if offset is 0 (indicating
2039 * the entire page)
2040 */
2041static void afs_dir_invalidatepage(struct page *page, unsigned int offset,
2042 unsigned int length)
2043{
2044 struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);
2045
2046 _enter("{%lu},%u,%u", page->index, offset, length);
2047
2048 BUG_ON(!PageLocked(page));
2049
2050 /* The directory will need reloading. */
2051 if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
2052 afs_stat_v(dvnode, n_inval);
2053
2054 /* we clean up only if the entire page is being invalidated */
2055 if (offset == 0 && length == PAGE_SIZE) {
2056 set_page_private(page, 0);
2057 ClearPagePrivate(page);
2058 }
2059}