hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/afs/dir.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* dir.c: AFS filesystem directory handling
23 *
34 * Copyright (C) 2002, 2018 Red Hat, Inc. All Rights Reserved.
45 * Written by David Howells (dhowells@redhat.com)
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 #include <linux/kernel.h>
....@@ -18,6 +14,7 @@
1814 #include <linux/sched.h>
1915 #include <linux/task_io_accounting_ops.h>
2016 #include "internal.h"
17
+#include "afs_fs.h"
2118 #include "xdr_fs.h"
2219
2320 static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
....@@ -26,6 +23,7 @@
2623 static int afs_readdir(struct file *file, struct dir_context *ctx);
2724 static int afs_d_revalidate(struct dentry *dentry, unsigned int flags);
2825 static int afs_d_delete(const struct dentry *dentry);
26
+static void afs_d_iput(struct dentry *dentry, struct inode *inode);
2927 static int afs_lookup_one_filldir(struct dir_context *ctx, const char *name, int nlen,
3028 loff_t fpos, u64 ino, unsigned dtype);
3129 static int afs_lookup_filldir(struct dir_context *ctx, const char *name, int nlen,
....@@ -71,7 +69,6 @@
7169 .permission = afs_permission,
7270 .getattr = afs_getattr,
7371 .setattr = afs_setattr,
74
- .listxattr = afs_listxattr,
7572 };
7673
7774 const struct address_space_operations afs_dir_aops = {
....@@ -85,6 +82,7 @@
8582 .d_delete = afs_d_delete,
8683 .d_release = afs_d_release,
8784 .d_automount = afs_d_automount,
85
+ .d_iput = afs_d_iput,
8886 };
8987
9088 struct afs_lookup_one_cookie {
....@@ -100,8 +98,6 @@
10098 bool found;
10199 bool one_only;
102100 unsigned short nr_fids;
103
- struct afs_file_status *statuses;
104
- struct afs_callback *callbacks;
105101 struct afs_fid fids[50];
106102 };
107103
....@@ -138,6 +134,7 @@
138134 ntohs(dbuf->blocks[tmp].hdr.magic));
139135 trace_afs_dir_check_failed(dvnode, off, i_size);
140136 kunmap(page);
137
+ trace_afs_file_error(dvnode, -EIO, afs_file_error_dir_bad_magic);
141138 goto error;
142139 }
143140
....@@ -155,6 +152,38 @@
155152 return true;
156153
157154 error:
155
+ return false;
156
+}
157
+
158
+/*
159
+ * Check the contents of a directory that we've just read.
160
+ */
161
+static bool afs_dir_check_pages(struct afs_vnode *dvnode, struct afs_read *req)
162
+{
163
+ struct afs_xdr_dir_page *dbuf;
164
+ unsigned int i, j, qty = PAGE_SIZE / sizeof(union afs_xdr_dir_block);
165
+
166
+ for (i = 0; i < req->nr_pages; i++)
167
+ if (!afs_dir_check_page(dvnode, req->pages[i], req->actual_len))
168
+ goto bad;
169
+ return true;
170
+
171
+bad:
172
+ pr_warn("DIR %llx:%llx f=%llx l=%llx al=%llx r=%llx\n",
173
+ dvnode->fid.vid, dvnode->fid.vnode,
174
+ req->file_size, req->len, req->actual_len, req->remain);
175
+ pr_warn("DIR %llx %x %x %x\n",
176
+ req->pos, req->index, req->nr_pages, req->offset);
177
+
178
+ for (i = 0; i < req->nr_pages; i++) {
179
+ dbuf = kmap(req->pages[i]);
180
+ for (j = 0; j < qty; j++) {
181
+ union afs_xdr_dir_block *block = &dbuf->blocks[j];
182
+
183
+ pr_warn("[%02x] %32phN\n", i * qty + j, block);
184
+ }
185
+ kunmap(req->pages[i]);
186
+ }
158187 return false;
159188 }
160189
....@@ -190,9 +219,11 @@
190219 retry:
191220 i_size = i_size_read(&dvnode->vfs_inode);
192221 if (i_size < 2048)
193
- return ERR_PTR(-EIO);
194
- if (i_size > 2048 * 1024)
222
+ return ERR_PTR(afs_bad(dvnode, afs_file_error_dir_small));
223
+ if (i_size > 2048 * 1024) {
224
+ trace_afs_file_error(dvnode, -EFBIG, afs_file_error_dir_big);
195225 return ERR_PTR(-EFBIG);
226
+ }
196227
197228 _enter("%llu", i_size);
198229
....@@ -204,8 +235,7 @@
204235 if (nr_inline > (PAGE_SIZE - sizeof(*req)) / sizeof(struct page *))
205236 nr_inline = 0;
206237
207
- req = kzalloc(sizeof(*req) + sizeof(struct page *) * nr_inline,
208
- GFP_KERNEL);
238
+ req = kzalloc(struct_size(req, array, nr_inline), GFP_KERNEL);
209239 if (!req)
210240 return ERR_PTR(-ENOMEM);
211241
....@@ -250,8 +280,7 @@
250280 if (ret < 0)
251281 goto error;
252282
253
- set_page_private(req->pages[i], 1);
254
- SetPagePrivate(req->pages[i]);
283
+ attach_page_private(req->pages[i], (void *)1);
255284 unlock_page(req->pages[i]);
256285 i++;
257286 } else {
....@@ -274,6 +303,7 @@
274303 goto error;
275304
276305 if (!test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
306
+ trace_afs_reload_dir(dvnode);
277307 ret = afs_fetch_data(dvnode, key, req);
278308 if (ret < 0)
279309 goto error_unlock;
....@@ -285,10 +315,8 @@
285315
286316 /* Validate the data we just read. */
287317 ret = -EIO;
288
- for (i = 0; i < req->nr_pages; i++)
289
- if (!afs_dir_check_page(dvnode, req->pages[i],
290
- req->actual_len))
291
- goto error_unlock;
318
+ if (!afs_dir_check_pages(dvnode, req))
319
+ goto error_unlock;
292320
293321 // TODO: Trim excess pages
294322
....@@ -315,7 +343,8 @@
315343 /*
316344 * deal with one block in an AFS directory
317345 */
318
-static int afs_dir_iterate_block(struct dir_context *ctx,
346
+static int afs_dir_iterate_block(struct afs_vnode *dvnode,
347
+ struct dir_context *ctx,
319348 union afs_xdr_dir_block *block,
320349 unsigned blkoff)
321350 {
....@@ -365,7 +394,7 @@
365394 " (len %u/%zu)",
366395 blkoff / sizeof(union afs_xdr_dir_block),
367396 offset, next, tmp, nlen);
368
- return -EIO;
397
+ return afs_bad(dvnode, afs_file_error_dir_over_end);
369398 }
370399 if (!(block->hdr.bitmap[next / 8] &
371400 (1 << (next % 8)))) {
....@@ -373,7 +402,7 @@
373402 " %u unmarked extension (len %u/%zu)",
374403 blkoff / sizeof(union afs_xdr_dir_block),
375404 offset, next, tmp, nlen);
376
- return -EIO;
405
+ return afs_bad(dvnode, afs_file_error_dir_unmarked_ext);
377406 }
378407
379408 _debug("ENT[%zu.%u]: ext %u/%zu",
....@@ -383,8 +412,11 @@
383412 }
384413
385414 /* skip if starts before the current position */
386
- if (offset < curr)
415
+ if (offset < curr) {
416
+ if (next > curr)
417
+ ctx->pos = blkoff + next * sizeof(union afs_xdr_dirent);
387418 continue;
419
+ }
388420
389421 /* found the next entry */
390422 if (!dir_emit(ctx, dire->u.name, nlen,
....@@ -407,7 +439,7 @@
407439 * iterate through the data blob that lists the contents of an AFS directory
408440 */
409441 static int afs_dir_iterate(struct inode *dir, struct dir_context *ctx,
410
- struct key *key)
442
+ struct key *key, afs_dataversion_t *_dir_version)
411443 {
412444 struct afs_vnode *dvnode = AFS_FS_I(dir);
413445 struct afs_xdr_dir_page *dbuf;
....@@ -427,6 +459,7 @@
427459 req = afs_read_dir(dvnode, key);
428460 if (IS_ERR(req))
429461 return PTR_ERR(req);
462
+ *_dir_version = req->data_version;
430463
431464 /* round the file position up to the next entry boundary */
432465 ctx->pos += sizeof(union afs_xdr_dirent) - 1;
....@@ -442,7 +475,7 @@
442475 */
443476 page = req->pages[blkoff / PAGE_SIZE];
444477 if (!page) {
445
- ret = -EIO;
478
+ ret = afs_bad(dvnode, afs_file_error_dir_missing_page);
446479 break;
447480 }
448481 mark_page_accessed(page);
....@@ -455,7 +488,7 @@
455488 do {
456489 dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) /
457490 sizeof(union afs_xdr_dir_block)];
458
- ret = afs_dir_iterate_block(ctx, dblock, blkoff);
491
+ ret = afs_dir_iterate_block(dvnode, ctx, dblock, blkoff);
459492 if (ret != 1) {
460493 kunmap(page);
461494 goto out;
....@@ -481,7 +514,10 @@
481514 */
482515 static int afs_readdir(struct file *file, struct dir_context *ctx)
483516 {
484
- return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file));
517
+ afs_dataversion_t dir_version;
518
+
519
+ return afs_dir_iterate(file_inode(file), ctx, afs_file_key(file),
520
+ &dir_version);
485521 }
486522
487523 /*
....@@ -522,7 +558,8 @@
522558 * - just returns the FID the dentry name maps to if found
523559 */
524560 static int afs_do_lookup_one(struct inode *dir, struct dentry *dentry,
525
- struct afs_fid *fid, struct key *key)
561
+ struct afs_fid *fid, struct key *key,
562
+ afs_dataversion_t *_dir_version)
526563 {
527564 struct afs_super_info *as = dir->i_sb->s_fs_info;
528565 struct afs_lookup_one_cookie cookie = {
....@@ -535,7 +572,7 @@
535572 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
536573
537574 /* search the directory */
538
- ret = afs_dir_iterate(dir, &cookie.ctx, key);
575
+ ret = afs_dir_iterate(dir, &cookie.ctx, key, _dir_version);
539576 if (ret < 0) {
540577 _leave(" = %d [iter]", ret);
541578 return ret;
....@@ -548,7 +585,7 @@
548585 }
549586
550587 *fid = cookie.fid;
551
- _leave(" = 0 { vn=%u u=%u }", fid->vnode, fid->unique);
588
+ _leave(" = 0 { vn=%llu u=%u }", fid->vnode, fid->unique);
552589 return 0;
553590 }
554591
....@@ -580,8 +617,8 @@
580617 }
581618 } else if (cookie->name.len == nlen &&
582619 memcmp(cookie->name.name, name, nlen) == 0) {
583
- cookie->fids[0].vnode = ino;
584
- cookie->fids[0].unique = dtype;
620
+ cookie->fids[1].vnode = ino;
621
+ cookie->fids[1].unique = dtype;
585622 cookie->found = 1;
586623 if (cookie->one_only)
587624 return -1;
....@@ -589,6 +626,112 @@
589626
590627 ret = cookie->nr_fids >= 50 ? -1 : 0;
591628 _leave(" = %d", ret);
629
+ return ret;
630
+}
631
+
632
+/*
633
+ * Deal with the result of a successful lookup operation. Turn all the files
634
+ * into inodes and save the first one - which is the one we actually want.
635
+ */
636
+static void afs_do_lookup_success(struct afs_operation *op)
637
+{
638
+ struct afs_vnode_param *vp;
639
+ struct afs_vnode *vnode;
640
+ struct inode *inode;
641
+ u32 abort_code;
642
+ int i;
643
+
644
+ _enter("");
645
+
646
+ for (i = 0; i < op->nr_files; i++) {
647
+ switch (i) {
648
+ case 0:
649
+ vp = &op->file[0];
650
+ abort_code = vp->scb.status.abort_code;
651
+ if (abort_code != 0) {
652
+ op->ac.abort_code = abort_code;
653
+ op->error = afs_abort_to_error(abort_code);
654
+ }
655
+ break;
656
+
657
+ case 1:
658
+ vp = &op->file[1];
659
+ break;
660
+
661
+ default:
662
+ vp = &op->more_files[i - 2];
663
+ break;
664
+ }
665
+
666
+ if (!vp->scb.have_status && !vp->scb.have_error)
667
+ continue;
668
+
669
+ _debug("do [%u]", i);
670
+ if (vp->vnode) {
671
+ if (!test_bit(AFS_VNODE_UNSET, &vp->vnode->flags))
672
+ afs_vnode_commit_status(op, vp);
673
+ } else if (vp->scb.status.abort_code == 0) {
674
+ inode = afs_iget(op, vp);
675
+ if (!IS_ERR(inode)) {
676
+ vnode = AFS_FS_I(inode);
677
+ afs_cache_permit(vnode, op->key,
678
+ 0 /* Assume vnode->cb_break is 0 */ +
679
+ op->cb_v_break,
680
+ &vp->scb);
681
+ vp->vnode = vnode;
682
+ vp->put_vnode = true;
683
+ }
684
+ } else {
685
+ _debug("- abort %d %llx:%llx.%x",
686
+ vp->scb.status.abort_code,
687
+ vp->fid.vid, vp->fid.vnode, vp->fid.unique);
688
+ }
689
+ }
690
+
691
+ _leave("");
692
+}
693
+
694
+static const struct afs_operation_ops afs_inline_bulk_status_operation = {
695
+ .issue_afs_rpc = afs_fs_inline_bulk_status,
696
+ .issue_yfs_rpc = yfs_fs_inline_bulk_status,
697
+ .success = afs_do_lookup_success,
698
+};
699
+
700
+static const struct afs_operation_ops afs_lookup_fetch_status_operation = {
701
+ .issue_afs_rpc = afs_fs_fetch_status,
702
+ .issue_yfs_rpc = yfs_fs_fetch_status,
703
+ .success = afs_do_lookup_success,
704
+ .aborted = afs_check_for_remote_deletion,
705
+};
706
+
707
+/*
708
+ * See if we know that the server we expect to use doesn't support
709
+ * FS.InlineBulkStatus.
710
+ */
711
+static bool afs_server_supports_ibulk(struct afs_vnode *dvnode)
712
+{
713
+ struct afs_server_list *slist;
714
+ struct afs_volume *volume = dvnode->volume;
715
+ struct afs_server *server;
716
+ bool ret = true;
717
+ int i;
718
+
719
+ if (!test_bit(AFS_VOLUME_MAYBE_NO_IBULK, &volume->flags))
720
+ return true;
721
+
722
+ rcu_read_lock();
723
+ slist = rcu_dereference(volume->servers);
724
+
725
+ for (i = 0; i < slist->nr_servers; i++) {
726
+ server = slist->servers[i].server;
727
+ if (server == dvnode->cb_server) {
728
+ if (test_bit(AFS_SERVER_FL_NO_IBULK, &server->flags))
729
+ ret = false;
730
+ break;
731
+ }
732
+ }
733
+
734
+ rcu_read_unlock();
592735 return ret;
593736 }
594737
....@@ -601,13 +744,13 @@
601744 struct key *key)
602745 {
603746 struct afs_lookup_cookie *cookie;
604
- struct afs_cb_interest *cbi = NULL;
605
- struct afs_super_info *as = dir->i_sb->s_fs_info;
606
- struct afs_iget_data data;
607
- struct afs_fs_cursor fc;
608
- struct afs_vnode *dvnode = AFS_FS_I(dir);
609
- struct inode *inode = NULL;
610
- int ret, i;
747
+ struct afs_vnode_param *vp;
748
+ struct afs_operation *op;
749
+ struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
750
+ struct inode *inode = NULL, *ti;
751
+ afs_dataversion_t data_version = READ_ONCE(dvnode->status.data_version);
752
+ long ret;
753
+ int i;
611754
612755 _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry);
613756
....@@ -615,147 +758,116 @@
615758 if (!cookie)
616759 return ERR_PTR(-ENOMEM);
617760
761
+ for (i = 0; i < ARRAY_SIZE(cookie->fids); i++)
762
+ cookie->fids[i].vid = dvnode->fid.vid;
618763 cookie->ctx.actor = afs_lookup_filldir;
619764 cookie->name = dentry->d_name;
620
- cookie->nr_fids = 1; /* slot 0 is saved for the fid we actually want */
765
+ cookie->nr_fids = 2; /* slot 0 is saved for the fid we actually want
766
+ * and slot 1 for the directory */
621767
622
- read_seqlock_excl(&dvnode->cb_lock);
623
- if (dvnode->cb_interest &&
624
- dvnode->cb_interest->server &&
625
- test_bit(AFS_SERVER_FL_NO_IBULK, &dvnode->cb_interest->server->flags))
768
+ if (!afs_server_supports_ibulk(dvnode))
626769 cookie->one_only = true;
627
- read_sequnlock_excl(&dvnode->cb_lock);
628
-
629
- for (i = 0; i < 50; i++)
630
- cookie->fids[i].vid = as->volume->vid;
631770
632771 /* search the directory */
633
- ret = afs_dir_iterate(dir, &cookie->ctx, key);
634
- if (ret < 0) {
635
- inode = ERR_PTR(ret);
772
+ ret = afs_dir_iterate(dir, &cookie->ctx, key, &data_version);
773
+ if (ret < 0)
636774 goto out;
637
- }
638775
639
- inode = ERR_PTR(-ENOENT);
776
+ dentry->d_fsdata = (void *)(unsigned long)data_version;
777
+
778
+ ret = -ENOENT;
640779 if (!cookie->found)
641780 goto out;
642781
643782 /* Check to see if we already have an inode for the primary fid. */
644
- data.volume = dvnode->volume;
645
- data.fid = cookie->fids[0];
646
- inode = ilookup5(dir->i_sb, cookie->fids[0].vnode, afs_iget5_test, &data);
783
+ inode = ilookup5(dir->i_sb, cookie->fids[1].vnode,
784
+ afs_ilookup5_test_by_fid, &cookie->fids[1]);
647785 if (inode)
786
+ goto out; /* We do */
787
+
788
+ /* Okay, we didn't find it. We need to query the server - and whilst
789
+ * we're doing that, we're going to attempt to look up a bunch of other
790
+ * vnodes also.
791
+ */
792
+ op = afs_alloc_operation(NULL, dvnode->volume);
793
+ if (IS_ERR(op)) {
794
+ ret = PTR_ERR(op);
648795 goto out;
796
+ }
797
+
798
+ afs_op_set_vnode(op, 0, dvnode);
799
+ afs_op_set_fid(op, 1, &cookie->fids[1]);
800
+
801
+ op->nr_files = cookie->nr_fids;
802
+ _debug("nr_files %u", op->nr_files);
649803
650804 /* Need space for examining all the selected files */
651
- inode = ERR_PTR(-ENOMEM);
652
- cookie->statuses = kcalloc(cookie->nr_fids, sizeof(struct afs_file_status),
653
- GFP_KERNEL);
654
- if (!cookie->statuses)
655
- goto out;
805
+ op->error = -ENOMEM;
806
+ if (op->nr_files > 2) {
807
+ op->more_files = kvcalloc(op->nr_files - 2,
808
+ sizeof(struct afs_vnode_param),
809
+ GFP_KERNEL);
810
+ if (!op->more_files)
811
+ goto out_op;
656812
657
- cookie->callbacks = kcalloc(cookie->nr_fids, sizeof(struct afs_callback),
658
- GFP_KERNEL);
659
- if (!cookie->callbacks)
660
- goto out_s;
813
+ for (i = 2; i < op->nr_files; i++) {
814
+ vp = &op->more_files[i - 2];
815
+ vp->fid = cookie->fids[i];
816
+
817
+ /* Find any inodes that already exist and get their
818
+ * callback counters.
819
+ */
820
+ ti = ilookup5_nowait(dir->i_sb, vp->fid.vnode,
821
+ afs_ilookup5_test_by_fid, &vp->fid);
822
+ if (!IS_ERR_OR_NULL(ti)) {
823
+ vnode = AFS_FS_I(ti);
824
+ vp->dv_before = vnode->status.data_version;
825
+ vp->cb_break_before = afs_calc_vnode_cb_break(vnode);
826
+ vp->vnode = vnode;
827
+ vp->put_vnode = true;
828
+ vp->speculative = true; /* vnode not locked */
829
+ }
830
+ }
831
+ }
661832
662833 /* Try FS.InlineBulkStatus first. Abort codes for the individual
663834 * lookups contained therein are stored in the reply without aborting
664835 * the whole operation.
665836 */
666
- if (cookie->one_only)
667
- goto no_inline_bulk_status;
668
-
669
- inode = ERR_PTR(-ERESTARTSYS);
670
- if (afs_begin_vnode_operation(&fc, dvnode, key)) {
671
- while (afs_select_fileserver(&fc)) {
672
- if (test_bit(AFS_SERVER_FL_NO_IBULK,
673
- &fc.cbi->server->flags)) {
674
- fc.ac.abort_code = RX_INVALID_OPERATION;
675
- fc.ac.error = -ECONNABORTED;
676
- break;
677
- }
678
- afs_fs_inline_bulk_status(&fc,
679
- afs_v2net(dvnode),
680
- cookie->fids,
681
- cookie->statuses,
682
- cookie->callbacks,
683
- cookie->nr_fids, NULL);
684
- }
685
-
686
- if (fc.ac.error == 0)
687
- cbi = afs_get_cb_interest(fc.cbi);
688
- if (fc.ac.abort_code == RX_INVALID_OPERATION)
689
- set_bit(AFS_SERVER_FL_NO_IBULK, &fc.cbi->server->flags);
690
- inode = ERR_PTR(afs_end_vnode_operation(&fc));
837
+ op->error = -ENOTSUPP;
838
+ if (!cookie->one_only) {
839
+ op->ops = &afs_inline_bulk_status_operation;
840
+ afs_begin_vnode_operation(op);
841
+ afs_wait_for_operation(op);
691842 }
692843
693
- if (!IS_ERR(inode))
694
- goto success;
695
- if (fc.ac.abort_code != RX_INVALID_OPERATION)
696
- goto out_c;
844
+ if (op->error == -ENOTSUPP) {
845
+ /* We could try FS.BulkStatus next, but this aborts the entire
846
+ * op if any of the lookups fails - so, for the moment, revert
847
+ * to FS.FetchStatus for op->file[1].
848
+ */
849
+ op->fetch_status.which = 1;
850
+ op->ops = &afs_lookup_fetch_status_operation;
851
+ afs_begin_vnode_operation(op);
852
+ afs_wait_for_operation(op);
853
+ }
854
+ inode = ERR_PTR(op->error);
697855
698
-no_inline_bulk_status:
699
- /* We could try FS.BulkStatus next, but this aborts the entire op if
700
- * any of the lookups fails - so, for the moment, revert to
701
- * FS.FetchStatus for just the primary fid.
702
- */
703
- cookie->nr_fids = 1;
704
- inode = ERR_PTR(-ERESTARTSYS);
705
- if (afs_begin_vnode_operation(&fc, dvnode, key)) {
706
- while (afs_select_fileserver(&fc)) {
707
- afs_fs_fetch_status(&fc,
708
- afs_v2net(dvnode),
709
- cookie->fids,
710
- cookie->statuses,
711
- cookie->callbacks,
712
- NULL);
713
- }
714
-
715
- if (fc.ac.error == 0)
716
- cbi = afs_get_cb_interest(fc.cbi);
717
- inode = ERR_PTR(afs_end_vnode_operation(&fc));
856
+out_op:
857
+ if (op->error == 0) {
858
+ inode = &op->file[1].vnode->vfs_inode;
859
+ op->file[1].vnode = NULL;
718860 }
719861
720
- if (IS_ERR(inode))
721
- goto out_c;
722
-
723
- for (i = 0; i < cookie->nr_fids; i++)
724
- cookie->statuses[i].abort_code = 0;
725
-
726
-success:
727
- /* Turn all the files into inodes and save the first one - which is the
728
- * one we actually want.
729
- */
730
- if (cookie->statuses[0].abort_code != 0)
731
- inode = ERR_PTR(afs_abort_to_error(cookie->statuses[0].abort_code));
732
-
733
- for (i = 0; i < cookie->nr_fids; i++) {
734
- struct inode *ti;
735
-
736
- if (cookie->statuses[i].abort_code != 0)
737
- continue;
738
-
739
- ti = afs_iget(dir->i_sb, key, &cookie->fids[i],
740
- &cookie->statuses[i],
741
- &cookie->callbacks[i],
742
- cbi);
743
- if (i == 0) {
744
- inode = ti;
745
- } else {
746
- if (!IS_ERR(ti))
747
- iput(ti);
748
- }
749
- }
750
-
751
-out_c:
752
- afs_put_cb_interest(afs_v2net(dvnode), cbi);
753
- kfree(cookie->callbacks);
754
-out_s:
755
- kfree(cookie->statuses);
862
+ if (op->file[0].scb.have_status)
863
+ dentry->d_fsdata = (void *)(unsigned long)op->file[0].scb.status.data_version;
864
+ else
865
+ dentry->d_fsdata = (void *)(unsigned long)op->file[0].dv_before;
866
+ ret = afs_put_operation(op);
756867 out:
757868 kfree(cookie);
758
- return inode;
869
+ _leave("");
870
+ return inode ?: ERR_PTR(ret);
759871 }
760872
761873 /*
....@@ -821,12 +933,13 @@
821933 unsigned int flags)
822934 {
823935 struct afs_vnode *dvnode = AFS_FS_I(dir);
936
+ struct afs_fid fid = {};
824937 struct inode *inode;
825938 struct dentry *d;
826939 struct key *key;
827940 int ret;
828941
829
- _enter("{%x:%u},%p{%pd},",
942
+ _enter("{%llx:%llu},%p{%pd},",
830943 dvnode->fid.vid, dvnode->fid.vnode, dentry, dentry);
831944
832945 ASSERTCMP(d_inode(dentry), ==, NULL);
....@@ -864,16 +977,62 @@
864977 afs_stat_v(dvnode, n_lookup);
865978 inode = afs_do_lookup(dir, dentry, key);
866979 key_put(key);
867
- if (inode == ERR_PTR(-ENOENT)) {
980
+ if (inode == ERR_PTR(-ENOENT))
868981 inode = afs_try_auto_mntpt(dentry, dir);
869
- } else {
870
- dentry->d_fsdata =
871
- (void *)(unsigned long)dvnode->status.data_version;
872
- }
982
+
983
+ if (!IS_ERR_OR_NULL(inode))
984
+ fid = AFS_FS_I(inode)->fid;
985
+
986
+ _debug("splice %p", dentry->d_inode);
873987 d = d_splice_alias(inode, dentry);
874
- if (!IS_ERR_OR_NULL(d))
988
+ if (!IS_ERR_OR_NULL(d)) {
875989 d->d_fsdata = dentry->d_fsdata;
990
+ trace_afs_lookup(dvnode, &d->d_name, &fid);
991
+ } else {
992
+ trace_afs_lookup(dvnode, &dentry->d_name, &fid);
993
+ }
994
+ _leave("");
876995 return d;
996
+}
997
+
998
+/*
999
+ * Check the validity of a dentry under RCU conditions.
1000
+ */
1001
+static int afs_d_revalidate_rcu(struct dentry *dentry)
1002
+{
1003
+ struct afs_vnode *dvnode;
1004
+ struct dentry *parent;
1005
+ struct inode *dir;
1006
+ long dir_version, de_version;
1007
+
1008
+ _enter("%p", dentry);
1009
+
1010
+ /* Check the parent directory is still valid first. */
1011
+ parent = READ_ONCE(dentry->d_parent);
1012
+ dir = d_inode_rcu(parent);
1013
+ if (!dir)
1014
+ return -ECHILD;
1015
+ dvnode = AFS_FS_I(dir);
1016
+ if (test_bit(AFS_VNODE_DELETED, &dvnode->flags))
1017
+ return -ECHILD;
1018
+
1019
+ if (!afs_check_validity(dvnode))
1020
+ return -ECHILD;
1021
+
1022
+ /* We only need to invalidate a dentry if the server's copy changed
1023
+ * behind our back. If we made the change, it's no problem. Note that
1024
+ * on a 32-bit system, we only have 32 bits in the dentry to store the
1025
+ * version.
1026
+ */
1027
+ dir_version = (long)READ_ONCE(dvnode->status.data_version);
1028
+ de_version = (long)READ_ONCE(dentry->d_fsdata);
1029
+ if (de_version != dir_version) {
1030
+ dir_version = (long)READ_ONCE(dvnode->invalid_before);
1031
+ if (de_version - dir_version < 0)
1032
+ return -ECHILD;
1033
+ }
1034
+
1035
+ return 1; /* Still valid */
8771036 }
8781037
8791038 /*
....@@ -884,19 +1043,20 @@
8841043 static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
8851044 {
8861045 struct afs_vnode *vnode, *dir;
887
- struct afs_fid uninitialized_var(fid);
1046
+ struct afs_fid fid;
8881047 struct dentry *parent;
8891048 struct inode *inode;
8901049 struct key *key;
891
- long dir_version, de_version;
1050
+ afs_dataversion_t dir_version, invalid_before;
1051
+ long de_version;
8921052 int ret;
8931053
8941054 if (flags & LOOKUP_RCU)
895
- return -ECHILD;
1055
+ return afs_d_revalidate_rcu(dentry);
8961056
8971057 if (d_really_is_positive(dentry)) {
8981058 vnode = AFS_FS_I(d_inode(dentry));
899
- _enter("{v={%x:%u} n=%pd fl=%lx},",
1059
+ _enter("{v={%llx:%llu} n=%pd fl=%lx},",
9001060 vnode->fid.vid, vnode->fid.vnode, dentry,
9011061 vnode->flags);
9021062 } else {
....@@ -907,17 +1067,7 @@
9071067 if (IS_ERR(key))
9081068 key = NULL;
9091069
910
- if (d_really_is_positive(dentry)) {
911
- inode = d_inode(dentry);
912
- if (inode) {
913
- vnode = AFS_FS_I(inode);
914
- afs_validate(vnode, key);
915
- if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
916
- goto out_bad;
917
- }
918
- }
919
-
920
- /* lock down the parent dentry so we can peer at it */
1070
+ /* Hold the parent dentry so we can peer at it */
9211071 parent = dget_parent(dentry);
9221072 dir = AFS_FS_I(d_inode(parent));
9231073
....@@ -926,7 +1076,7 @@
9261076
9271077 if (test_bit(AFS_VNODE_DELETED, &dir->flags)) {
9281078 _debug("%pd: parent dir deleted", dentry);
929
- goto out_bad_parent;
1079
+ goto not_found;
9301080 }
9311081
9321082 /* We only need to invalidate a dentry if the server's copy changed
....@@ -934,30 +1084,30 @@
9341084 * on a 32-bit system, we only have 32 bits in the dentry to store the
9351085 * version.
9361086 */
937
- dir_version = (long)dir->status.data_version;
1087
+ dir_version = dir->status.data_version;
9381088 de_version = (long)dentry->d_fsdata;
939
- if (de_version == dir_version)
1089
+ if (de_version == (long)dir_version)
9401090 goto out_valid_noupdate;
9411091
942
- dir_version = (long)dir->invalid_before;
943
- if (de_version - dir_version >= 0)
1092
+ invalid_before = dir->invalid_before;
1093
+ if (de_version - (long)invalid_before >= 0)
9441094 goto out_valid;
9451095
9461096 _debug("dir modified");
9471097 afs_stat_v(dir, n_reval);
9481098
9491099 /* search the directory for this vnode */
950
- ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key);
1100
+ ret = afs_do_lookup_one(&dir->vfs_inode, dentry, &fid, key, &dir_version);
9511101 switch (ret) {
9521102 case 0:
9531103 /* the filename maps to something */
9541104 if (d_really_is_negative(dentry))
955
- goto out_bad_parent;
1105
+ goto not_found;
9561106 inode = d_inode(dentry);
9571107 if (is_bad_inode(inode)) {
9581108 printk("kAFS: afs_d_revalidate: %pd2 has bad inode\n",
9591109 dentry);
960
- goto out_bad_parent;
1110
+ goto not_found;
9611111 }
9621112
9631113 vnode = AFS_FS_I(inode);
....@@ -965,7 +1115,7 @@
9651115 /* if the vnode ID has changed, then the dirent points to a
9661116 * different file */
9671117 if (fid.vnode != vnode->fid.vnode) {
968
- _debug("%pd: dirent changed [%u != %u]",
1118
+ _debug("%pd: dirent changed [%llu != %llu]",
9691119 dentry, fid.vnode,
9701120 vnode->fid.vnode);
9711121 goto not_found;
....@@ -979,9 +1129,6 @@
9791129 dentry, fid.unique,
9801130 vnode->fid.unique,
9811131 vnode->vfs_inode.i_generation);
982
- write_seqlock(&vnode->cb_lock);
983
- set_bit(AFS_VNODE_DELETED, &vnode->flags);
984
- write_sequnlock(&vnode->cb_lock);
9851132 goto not_found;
9861133 }
9871134 goto out_valid;
....@@ -996,27 +1143,20 @@
9961143 default:
9971144 _debug("failed to iterate dir %pd: %d",
9981145 parent, ret);
999
- goto out_bad_parent;
1146
+ goto not_found;
10001147 }
10011148
10021149 out_valid:
1003
- dentry->d_fsdata = (void *)dir_version;
1150
+ dentry->d_fsdata = (void *)(unsigned long)dir_version;
10041151 out_valid_noupdate:
10051152 dput(parent);
10061153 key_put(key);
10071154 _leave(" = 1 [valid]");
10081155 return 1;
10091156
1010
- /* the dirent, if it exists, now points to a different vnode */
10111157 not_found:
1012
- spin_lock(&dentry->d_lock);
1013
- dentry->d_flags |= DCACHE_NFSFS_RENAMED;
1014
- spin_unlock(&dentry->d_lock);
1015
-
1016
-out_bad_parent:
10171158 _debug("dropping dentry %pd2", dentry);
10181159 dput(parent);
1019
-out_bad:
10201160 key_put(key);
10211161
10221162 _leave(" = 0 [bad]");
....@@ -1050,6 +1190,16 @@
10501190 }
10511191
10521192 /*
1193
+ * Clean up sillyrename files on dentry removal.
1194
+ */
1195
+static void afs_d_iput(struct dentry *dentry, struct inode *inode)
1196
+{
1197
+ if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
1198
+ afs_silly_iput(dentry, inode);
1199
+ iput(inode);
1200
+}
1201
+
1202
+/*
10531203 * handle dentry release
10541204 */
10551205 void afs_d_release(struct dentry *dentry)
....@@ -1057,96 +1207,115 @@
10571207 _enter("%pd", dentry);
10581208 }
10591209
1210
+void afs_check_for_remote_deletion(struct afs_operation *op)
1211
+{
1212
+ struct afs_vnode *vnode = op->file[0].vnode;
1213
+
1214
+ switch (op->ac.abort_code) {
1215
+ case VNOVNODE:
1216
+ set_bit(AFS_VNODE_DELETED, &vnode->flags);
1217
+ afs_break_callback(vnode, afs_cb_break_for_deleted);
1218
+ }
1219
+}
1220
+
10601221 /*
10611222 * Create a new inode for create/mkdir/symlink
10621223 */
1063
-static void afs_vnode_new_inode(struct afs_fs_cursor *fc,
1064
- struct dentry *new_dentry,
1065
- struct afs_fid *newfid,
1066
- struct afs_file_status *newstatus,
1067
- struct afs_callback *newcb)
1224
+static void afs_vnode_new_inode(struct afs_operation *op)
10681225 {
1226
+ struct afs_vnode_param *vp = &op->file[1];
10691227 struct afs_vnode *vnode;
10701228 struct inode *inode;
10711229
1072
- if (fc->ac.error < 0)
1073
- return;
1230
+ _enter("");
10741231
1075
- d_drop(new_dentry);
1232
+ ASSERTCMP(op->error, ==, 0);
10761233
1077
- inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key,
1078
- newfid, newstatus, newcb, fc->cbi);
1234
+ inode = afs_iget(op, vp);
10791235 if (IS_ERR(inode)) {
10801236 /* ENOMEM or EINTR at a really inconvenient time - just abandon
10811237 * the new directory on the server.
10821238 */
1083
- fc->ac.error = PTR_ERR(inode);
1239
+ op->error = PTR_ERR(inode);
10841240 return;
10851241 }
10861242
10871243 vnode = AFS_FS_I(inode);
10881244 set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
1089
- d_add(new_dentry, inode);
1245
+ if (!op->error)
1246
+ afs_cache_permit(vnode, op->key, vnode->cb_break, &vp->scb);
1247
+ d_instantiate(op->dentry, inode);
10901248 }
1249
+
1250
+static void afs_create_success(struct afs_operation *op)
1251
+{
1252
+ _enter("op=%08x", op->debug_id);
1253
+ op->ctime = op->file[0].scb.status.mtime_client;
1254
+ afs_vnode_commit_status(op, &op->file[0]);
1255
+ afs_update_dentry_version(op, &op->file[0], op->dentry);
1256
+ afs_vnode_new_inode(op);
1257
+}
1258
+
1259
+static void afs_create_edit_dir(struct afs_operation *op)
1260
+{
1261
+ struct afs_vnode_param *dvp = &op->file[0];
1262
+ struct afs_vnode_param *vp = &op->file[1];
1263
+ struct afs_vnode *dvnode = dvp->vnode;
1264
+
1265
+ _enter("op=%08x", op->debug_id);
1266
+
1267
+ down_write(&dvnode->validate_lock);
1268
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
1269
+ dvnode->status.data_version == dvp->dv_before + dvp->dv_delta)
1270
+ afs_edit_dir_add(dvnode, &op->dentry->d_name, &vp->fid,
1271
+ op->create.reason);
1272
+ up_write(&dvnode->validate_lock);
1273
+}
1274
+
1275
+static void afs_create_put(struct afs_operation *op)
1276
+{
1277
+ _enter("op=%08x", op->debug_id);
1278
+
1279
+ if (op->error)
1280
+ d_drop(op->dentry);
1281
+}
1282
+
1283
+static const struct afs_operation_ops afs_mkdir_operation = {
1284
+ .issue_afs_rpc = afs_fs_make_dir,
1285
+ .issue_yfs_rpc = yfs_fs_make_dir,
1286
+ .success = afs_create_success,
1287
+ .aborted = afs_check_for_remote_deletion,
1288
+ .edit_dir = afs_create_edit_dir,
1289
+ .put = afs_create_put,
1290
+};
10911291
10921292 /*
10931293 * create a directory on an AFS filesystem
10941294 */
10951295 static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
10961296 {
1097
- struct afs_file_status newstatus;
1098
- struct afs_fs_cursor fc;
1099
- struct afs_callback newcb;
1297
+ struct afs_operation *op;
11001298 struct afs_vnode *dvnode = AFS_FS_I(dir);
1101
- struct afs_fid newfid;
1102
- struct key *key;
1103
- u64 data_version = dvnode->status.data_version;
1104
- int ret;
11051299
1106
- mode |= S_IFDIR;
1107
-
1108
- _enter("{%x:%u},{%pd},%ho",
1300
+ _enter("{%llx:%llu},{%pd},%ho",
11091301 dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
11101302
1111
- key = afs_request_key(dvnode->volume->cell);
1112
- if (IS_ERR(key)) {
1113
- ret = PTR_ERR(key);
1114
- goto error;
1303
+ op = afs_alloc_operation(NULL, dvnode->volume);
1304
+ if (IS_ERR(op)) {
1305
+ d_drop(dentry);
1306
+ return PTR_ERR(op);
11151307 }
11161308
1117
- ret = -ERESTARTSYS;
1118
- if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1119
- while (afs_select_fileserver(&fc)) {
1120
- fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1121
- afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
1122
- &newfid, &newstatus, &newcb);
1123
- }
1124
-
1125
- afs_check_for_remote_deletion(&fc, fc.vnode);
1126
- afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
1127
- afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, &newcb);
1128
- ret = afs_end_vnode_operation(&fc);
1129
- if (ret < 0)
1130
- goto error_key;
1131
- } else {
1132
- goto error_key;
1133
- }
1134
-
1135
- if (ret == 0 &&
1136
- test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1137
- afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
1138
- afs_edit_dir_for_create);
1139
-
1140
- key_put(key);
1141
- _leave(" = 0");
1142
- return 0;
1143
-
1144
-error_key:
1145
- key_put(key);
1146
-error:
1147
- d_drop(dentry);
1148
- _leave(" = %d", ret);
1149
- return ret;
1309
+ afs_op_set_vnode(op, 0, dvnode);
1310
+ op->file[0].dv_delta = 1;
1311
+ op->file[0].modification = true;
1312
+ op->file[0].update_ctime = true;
1313
+ op->dentry = dentry;
1314
+ op->create.mode = S_IFDIR | mode;
1315
+ op->create.reason = afs_edit_dir_for_mkdir;
1316
+ op->mtime = current_time(dir);
1317
+ op->ops = &afs_mkdir_operation;
1318
+ return afs_do_sync_operation(op);
11501319 }
11511320
11521321 /*
....@@ -1164,47 +1333,89 @@
11641333 }
11651334 }
11661335
1336
+static void afs_rmdir_success(struct afs_operation *op)
1337
+{
1338
+ _enter("op=%08x", op->debug_id);
1339
+ op->ctime = op->file[0].scb.status.mtime_client;
1340
+ afs_vnode_commit_status(op, &op->file[0]);
1341
+ afs_update_dentry_version(op, &op->file[0], op->dentry);
1342
+}
1343
+
1344
+static void afs_rmdir_edit_dir(struct afs_operation *op)
1345
+{
1346
+ struct afs_vnode_param *dvp = &op->file[0];
1347
+ struct afs_vnode *dvnode = dvp->vnode;
1348
+
1349
+ _enter("op=%08x", op->debug_id);
1350
+ afs_dir_remove_subdir(op->dentry);
1351
+
1352
+ down_write(&dvnode->validate_lock);
1353
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
1354
+ dvnode->status.data_version == dvp->dv_before + dvp->dv_delta)
1355
+ afs_edit_dir_remove(dvnode, &op->dentry->d_name,
1356
+ afs_edit_dir_for_rmdir);
1357
+ up_write(&dvnode->validate_lock);
1358
+}
1359
+
1360
+static void afs_rmdir_put(struct afs_operation *op)
1361
+{
1362
+ _enter("op=%08x", op->debug_id);
1363
+ if (op->file[1].vnode)
1364
+ up_write(&op->file[1].vnode->rmdir_lock);
1365
+}
1366
+
1367
+static const struct afs_operation_ops afs_rmdir_operation = {
1368
+ .issue_afs_rpc = afs_fs_remove_dir,
1369
+ .issue_yfs_rpc = yfs_fs_remove_dir,
1370
+ .success = afs_rmdir_success,
1371
+ .aborted = afs_check_for_remote_deletion,
1372
+ .edit_dir = afs_rmdir_edit_dir,
1373
+ .put = afs_rmdir_put,
1374
+};
1375
+
11671376 /*
11681377 * remove a directory from an AFS filesystem
11691378 */
11701379 static int afs_rmdir(struct inode *dir, struct dentry *dentry)
11711380 {
1172
- struct afs_fs_cursor fc;
1173
- struct afs_vnode *dvnode = AFS_FS_I(dir);
1174
- struct key *key;
1175
- u64 data_version = dvnode->status.data_version;
1381
+ struct afs_operation *op;
1382
+ struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
11761383 int ret;
11771384
1178
- _enter("{%x:%u},{%pd}",
1385
+ _enter("{%llx:%llu},{%pd}",
11791386 dvnode->fid.vid, dvnode->fid.vnode, dentry);
11801387
1181
- key = afs_request_key(dvnode->volume->cell);
1182
- if (IS_ERR(key)) {
1183
- ret = PTR_ERR(key);
1184
- goto error;
1388
+ op = afs_alloc_operation(NULL, dvnode->volume);
1389
+ if (IS_ERR(op))
1390
+ return PTR_ERR(op);
1391
+
1392
+ afs_op_set_vnode(op, 0, dvnode);
1393
+ op->file[0].dv_delta = 1;
1394
+ op->file[0].modification = true;
1395
+ op->file[0].update_ctime = true;
1396
+
1397
+ op->dentry = dentry;
1398
+ op->ops = &afs_rmdir_operation;
1399
+
1400
+ /* Try to make sure we have a callback promise on the victim. */
1401
+ if (d_really_is_positive(dentry)) {
1402
+ vnode = AFS_FS_I(d_inode(dentry));
1403
+ ret = afs_validate(vnode, op->key);
1404
+ if (ret < 0)
1405
+ goto error;
11851406 }
11861407
1187
- ret = -ERESTARTSYS;
1188
- if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1189
- while (afs_select_fileserver(&fc)) {
1190
- fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1191
- afs_fs_remove(&fc, dentry->d_name.name, true,
1192
- data_version);
1193
- }
1194
-
1195
- afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
1196
- ret = afs_end_vnode_operation(&fc);
1197
- if (ret == 0) {
1198
- afs_dir_remove_subdir(dentry);
1199
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1200
- afs_edit_dir_remove(dvnode, &dentry->d_name,
1201
- afs_edit_dir_for_rmdir);
1202
- }
1408
+ if (vnode) {
1409
+ ret = down_write_killable(&vnode->rmdir_lock);
1410
+ if (ret < 0)
1411
+ goto error;
1412
+ op->file[1].vnode = vnode;
12031413 }
12041414
1205
- key_put(key);
1415
+ return afs_do_sync_operation(op);
1416
+
12061417 error:
1207
- return ret;
1418
+ return afs_put_operation(op);
12081419 }
12091420
12101421 /*
....@@ -1217,102 +1428,164 @@
12171428 * However, if we didn't have a callback promise outstanding, or it was
12181429 * outstanding on a different server, then it won't break it either...
12191430 */
1220
-static int afs_dir_remove_link(struct dentry *dentry, struct key *key,
1221
- unsigned long d_version_before,
1222
- unsigned long d_version_after)
1431
+static void afs_dir_remove_link(struct afs_operation *op)
12231432 {
1224
- bool dir_valid;
1225
- int ret = 0;
1433
+ struct afs_vnode *dvnode = op->file[0].vnode;
1434
+ struct afs_vnode *vnode = op->file[1].vnode;
1435
+ struct dentry *dentry = op->dentry;
1436
+ int ret;
12261437
1227
- /* There were no intervening changes on the server if the version
1228
- * number we got back was incremented by exactly 1.
1229
- */
1230
- dir_valid = (d_version_after == d_version_before + 1);
1438
+ if (op->error != 0 ||
1439
+ (op->file[1].scb.have_status && op->file[1].scb.have_error))
1440
+ return;
1441
+ if (d_really_is_positive(dentry))
1442
+ return;
12311443
1232
- if (d_really_is_positive(dentry)) {
1233
- struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
1234
-
1235
- if (dir_valid) {
1236
- drop_nlink(&vnode->vfs_inode);
1237
- if (vnode->vfs_inode.i_nlink == 0) {
1238
- set_bit(AFS_VNODE_DELETED, &vnode->flags);
1239
- clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
1240
- }
1241
- ret = 0;
1242
- } else {
1243
- clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags);
1244
-
1245
- if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
1246
- kdebug("AFS_VNODE_DELETED");
1247
-
1248
- ret = afs_validate(vnode, key);
1249
- if (ret == -ESTALE)
1250
- ret = 0;
1444
+ if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
1445
+ /* Already done */
1446
+ } else if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) {
1447
+ write_seqlock(&vnode->cb_lock);
1448
+ drop_nlink(&vnode->vfs_inode);
1449
+ if (vnode->vfs_inode.i_nlink == 0) {
1450
+ set_bit(AFS_VNODE_DELETED, &vnode->flags);
1451
+ __afs_break_callback(vnode, afs_cb_break_for_unlink);
12511452 }
1252
- _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, ret);
1453
+ write_sequnlock(&vnode->cb_lock);
1454
+ } else {
1455
+ afs_break_callback(vnode, afs_cb_break_for_unlink);
1456
+
1457
+ if (test_bit(AFS_VNODE_DELETED, &vnode->flags))
1458
+ _debug("AFS_VNODE_DELETED");
1459
+
1460
+ ret = afs_validate(vnode, op->key);
1461
+ if (ret != -ESTALE)
1462
+ op->error = ret;
12531463 }
12541464
1255
- return ret;
1465
+ _debug("nlink %d [val %d]", vnode->vfs_inode.i_nlink, op->error);
12561466 }
1467
+
1468
+static void afs_unlink_success(struct afs_operation *op)
1469
+{
1470
+ _enter("op=%08x", op->debug_id);
1471
+ op->ctime = op->file[0].scb.status.mtime_client;
1472
+ afs_check_dir_conflict(op, &op->file[0]);
1473
+ afs_vnode_commit_status(op, &op->file[0]);
1474
+ afs_vnode_commit_status(op, &op->file[1]);
1475
+ afs_update_dentry_version(op, &op->file[0], op->dentry);
1476
+ afs_dir_remove_link(op);
1477
+}
1478
+
1479
+static void afs_unlink_edit_dir(struct afs_operation *op)
1480
+{
1481
+ struct afs_vnode_param *dvp = &op->file[0];
1482
+ struct afs_vnode *dvnode = dvp->vnode;
1483
+
1484
+ _enter("op=%08x", op->debug_id);
1485
+ down_write(&dvnode->validate_lock);
1486
+ if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags) &&
1487
+ dvnode->status.data_version == dvp->dv_before + dvp->dv_delta)
1488
+ afs_edit_dir_remove(dvnode, &op->dentry->d_name,
1489
+ afs_edit_dir_for_unlink);
1490
+ up_write(&dvnode->validate_lock);
1491
+}
1492
+
1493
+static void afs_unlink_put(struct afs_operation *op)
1494
+{
1495
+ _enter("op=%08x", op->debug_id);
1496
+ if (op->unlink.need_rehash && op->error < 0 && op->error != -ENOENT)
1497
+ d_rehash(op->dentry);
1498
+}
1499
+
1500
+static const struct afs_operation_ops afs_unlink_operation = {
1501
+ .issue_afs_rpc = afs_fs_remove_file,
1502
+ .issue_yfs_rpc = yfs_fs_remove_file,
1503
+ .success = afs_unlink_success,
1504
+ .aborted = afs_check_for_remote_deletion,
1505
+ .edit_dir = afs_unlink_edit_dir,
1506
+ .put = afs_unlink_put,
1507
+};
12571508
12581509 /*
12591510 * Remove a file or symlink from an AFS filesystem.
12601511 */
12611512 static int afs_unlink(struct inode *dir, struct dentry *dentry)
12621513 {
1263
- struct afs_fs_cursor fc;
1264
- struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
1265
- struct key *key;
1266
- unsigned long d_version = (unsigned long)dentry->d_fsdata;
1267
- u64 data_version = dvnode->status.data_version;
1514
+ struct afs_operation *op;
1515
+ struct afs_vnode *dvnode = AFS_FS_I(dir);
1516
+ struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));
12681517 int ret;
12691518
1270
- _enter("{%x:%u},{%pd}",
1519
+ _enter("{%llx:%llu},{%pd}",
12711520 dvnode->fid.vid, dvnode->fid.vnode, dentry);
12721521
12731522 if (dentry->d_name.len >= AFSNAMEMAX)
12741523 return -ENAMETOOLONG;
12751524
1276
- key = afs_request_key(dvnode->volume->cell);
1277
- if (IS_ERR(key)) {
1278
- ret = PTR_ERR(key);
1525
+ op = afs_alloc_operation(NULL, dvnode->volume);
1526
+ if (IS_ERR(op))
1527
+ return PTR_ERR(op);
1528
+
1529
+ afs_op_set_vnode(op, 0, dvnode);
1530
+ op->file[0].dv_delta = 1;
1531
+ op->file[0].modification = true;
1532
+ op->file[0].update_ctime = true;
1533
+
1534
+ /* Try to make sure we have a callback promise on the victim. */
1535
+ ret = afs_validate(vnode, op->key);
1536
+ if (ret < 0) {
1537
+ op->error = ret;
12791538 goto error;
12801539 }
12811540
1282
- /* Try to make sure we have a callback promise on the victim. */
1283
- if (d_really_is_positive(dentry)) {
1284
- vnode = AFS_FS_I(d_inode(dentry));
1285
- ret = afs_validate(vnode, key);
1286
- if (ret < 0)
1287
- goto error_key;
1541
+ spin_lock(&dentry->d_lock);
1542
+ if (d_count(dentry) > 1) {
1543
+ spin_unlock(&dentry->d_lock);
1544
+ /* Start asynchronous writeout of the inode */
1545
+ write_inode_now(d_inode(dentry), 0);
1546
+ op->error = afs_sillyrename(dvnode, vnode, dentry, op->key);
1547
+ goto error;
1548
+ }
1549
+ if (!d_unhashed(dentry)) {
1550
+ /* Prevent a race with RCU lookup. */
1551
+ __d_drop(dentry);
1552
+ op->unlink.need_rehash = true;
1553
+ }
1554
+ spin_unlock(&dentry->d_lock);
1555
+
1556
+ op->file[1].vnode = vnode;
1557
+ op->file[1].update_ctime = true;
1558
+ op->file[1].op_unlinked = true;
1559
+ op->dentry = dentry;
1560
+ op->ops = &afs_unlink_operation;
1561
+ afs_begin_vnode_operation(op);
1562
+ afs_wait_for_operation(op);
1563
+
1564
+ /* If there was a conflict with a third party, check the status of the
1565
+ * unlinked vnode.
1566
+ */
1567
+ if (op->error == 0 && (op->flags & AFS_OPERATION_DIR_CONFLICT)) {
1568
+ op->file[1].update_ctime = false;
1569
+ op->fetch_status.which = 1;
1570
+ op->ops = &afs_fetch_status_operation;
1571
+ afs_begin_vnode_operation(op);
1572
+ afs_wait_for_operation(op);
12881573 }
12891574
1290
- ret = -ERESTARTSYS;
1291
- if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1292
- while (afs_select_fileserver(&fc)) {
1293
- fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1294
- afs_fs_remove(&fc, dentry->d_name.name, false,
1295
- data_version);
1296
- }
1575
+ return afs_put_operation(op);
12971576
1298
- afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
1299
- ret = afs_end_vnode_operation(&fc);
1300
- if (ret == 0)
1301
- ret = afs_dir_remove_link(
1302
- dentry, key, d_version,
1303
- (unsigned long)dvnode->status.data_version);
1304
- if (ret == 0 &&
1305
- test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1306
- afs_edit_dir_remove(dvnode, &dentry->d_name,
1307
- afs_edit_dir_for_unlink);
1308
- }
1309
-
1310
-error_key:
1311
- key_put(key);
13121577 error:
1313
- _leave(" = %d", ret);
1314
- return ret;
1578
+ return afs_put_operation(op);
13151579 }
1580
+
1581
+static const struct afs_operation_ops afs_create_operation = {
1582
+ .issue_afs_rpc = afs_fs_create_file,
1583
+ .issue_yfs_rpc = yfs_fs_create_file,
1584
+ .success = afs_create_success,
1585
+ .aborted = afs_check_for_remote_deletion,
1586
+ .edit_dir = afs_create_edit_dir,
1587
+ .put = afs_create_put,
1588
+};
13161589
13171590 /*
13181591 * create a regular file on an AFS filesystem
....@@ -1320,63 +1593,71 @@
13201593 static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
13211594 bool excl)
13221595 {
1323
- struct afs_fs_cursor fc;
1324
- struct afs_file_status newstatus;
1325
- struct afs_callback newcb;
1596
+ struct afs_operation *op;
13261597 struct afs_vnode *dvnode = AFS_FS_I(dir);
1327
- struct afs_fid newfid;
1328
- struct key *key;
1329
- u64 data_version = dvnode->status.data_version;
1330
- int ret;
1598
+ int ret = -ENAMETOOLONG;
13311599
1332
- mode |= S_IFREG;
1333
-
1334
- _enter("{%x:%u},{%pd},%ho,",
1600
+ _enter("{%llx:%llu},{%pd},%ho",
13351601 dvnode->fid.vid, dvnode->fid.vnode, dentry, mode);
13361602
1337
- ret = -ENAMETOOLONG;
13381603 if (dentry->d_name.len >= AFSNAMEMAX)
13391604 goto error;
13401605
1341
- key = afs_request_key(dvnode->volume->cell);
1342
- if (IS_ERR(key)) {
1343
- ret = PTR_ERR(key);
1606
+ op = afs_alloc_operation(NULL, dvnode->volume);
1607
+ if (IS_ERR(op)) {
1608
+ ret = PTR_ERR(op);
13441609 goto error;
13451610 }
13461611
1347
- ret = -ERESTARTSYS;
1348
- if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1349
- while (afs_select_fileserver(&fc)) {
1350
- fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1351
- afs_fs_create(&fc, dentry->d_name.name, mode, data_version,
1352
- &newfid, &newstatus, &newcb);
1353
- }
1612
+ afs_op_set_vnode(op, 0, dvnode);
1613
+ op->file[0].dv_delta = 1;
1614
+ op->file[0].modification = true;
1615
+ op->file[0].update_ctime = true;
13541616
1355
- afs_check_for_remote_deletion(&fc, fc.vnode);
1356
- afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
1357
- afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, &newcb);
1358
- ret = afs_end_vnode_operation(&fc);
1359
- if (ret < 0)
1360
- goto error_key;
1361
- } else {
1362
- goto error_key;
1363
- }
1617
+ op->dentry = dentry;
1618
+ op->create.mode = S_IFREG | mode;
1619
+ op->create.reason = afs_edit_dir_for_create;
1620
+ op->mtime = current_time(dir);
1621
+ op->ops = &afs_create_operation;
1622
+ return afs_do_sync_operation(op);
13641623
1365
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1366
- afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
1367
- afs_edit_dir_for_create);
1368
-
1369
- key_put(key);
1370
- _leave(" = 0");
1371
- return 0;
1372
-
1373
-error_key:
1374
- key_put(key);
13751624 error:
13761625 d_drop(dentry);
13771626 _leave(" = %d", ret);
13781627 return ret;
13791628 }
1629
+
1630
+static void afs_link_success(struct afs_operation *op)
1631
+{
1632
+ struct afs_vnode_param *dvp = &op->file[0];
1633
+ struct afs_vnode_param *vp = &op->file[1];
1634
+
1635
+ _enter("op=%08x", op->debug_id);
1636
+ op->ctime = dvp->scb.status.mtime_client;
1637
+ afs_vnode_commit_status(op, dvp);
1638
+ afs_vnode_commit_status(op, vp);
1639
+ afs_update_dentry_version(op, dvp, op->dentry);
1640
+ if (op->dentry_2->d_parent == op->dentry->d_parent)
1641
+ afs_update_dentry_version(op, dvp, op->dentry_2);
1642
+ ihold(&vp->vnode->vfs_inode);
1643
+ d_instantiate(op->dentry, &vp->vnode->vfs_inode);
1644
+}
1645
+
1646
+static void afs_link_put(struct afs_operation *op)
1647
+{
1648
+ _enter("op=%08x", op->debug_id);
1649
+ if (op->error)
1650
+ d_drop(op->dentry);
1651
+}
1652
+
1653
+static const struct afs_operation_ops afs_link_operation = {
1654
+ .issue_afs_rpc = afs_fs_link,
1655
+ .issue_yfs_rpc = yfs_fs_link,
1656
+ .success = afs_link_success,
1657
+ .aborted = afs_check_for_remote_deletion,
1658
+ .edit_dir = afs_create_edit_dir,
1659
+ .put = afs_link_put,
1660
+};
13801661
13811662 /*
13821663 * create a hard link between files in an AFS filesystem
....@@ -1384,72 +1665,52 @@
13841665 static int afs_link(struct dentry *from, struct inode *dir,
13851666 struct dentry *dentry)
13861667 {
1387
- struct afs_fs_cursor fc;
1388
- struct afs_vnode *dvnode, *vnode;
1389
- struct key *key;
1390
- u64 data_version;
1391
- int ret;
1668
+ struct afs_operation *op;
1669
+ struct afs_vnode *dvnode = AFS_FS_I(dir);
1670
+ struct afs_vnode *vnode = AFS_FS_I(d_inode(from));
1671
+ int ret = -ENAMETOOLONG;
13921672
1393
- vnode = AFS_FS_I(d_inode(from));
1394
- dvnode = AFS_FS_I(dir);
1395
- data_version = dvnode->status.data_version;
1396
-
1397
- _enter("{%x:%u},{%x:%u},{%pd}",
1673
+ _enter("{%llx:%llu},{%llx:%llu},{%pd}",
13981674 vnode->fid.vid, vnode->fid.vnode,
13991675 dvnode->fid.vid, dvnode->fid.vnode,
14001676 dentry);
14011677
1402
- ret = -ENAMETOOLONG;
14031678 if (dentry->d_name.len >= AFSNAMEMAX)
14041679 goto error;
14051680
1406
- key = afs_request_key(dvnode->volume->cell);
1407
- if (IS_ERR(key)) {
1408
- ret = PTR_ERR(key);
1681
+ op = afs_alloc_operation(NULL, dvnode->volume);
1682
+ if (IS_ERR(op)) {
1683
+ ret = PTR_ERR(op);
14091684 goto error;
14101685 }
14111686
1412
- ret = -ERESTARTSYS;
1413
- if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1414
- if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) {
1415
- afs_end_vnode_operation(&fc);
1416
- goto error_key;
1417
- }
1687
+ afs_op_set_vnode(op, 0, dvnode);
1688
+ afs_op_set_vnode(op, 1, vnode);
1689
+ op->file[0].dv_delta = 1;
1690
+ op->file[0].modification = true;
1691
+ op->file[0].update_ctime = true;
1692
+ op->file[1].update_ctime = true;
14181693
1419
- while (afs_select_fileserver(&fc)) {
1420
- fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1421
- fc.cb_break_2 = afs_calc_vnode_cb_break(vnode);
1422
- afs_fs_link(&fc, vnode, dentry->d_name.name, data_version);
1423
- }
1694
+ op->dentry = dentry;
1695
+ op->dentry_2 = from;
1696
+ op->ops = &afs_link_operation;
1697
+ op->create.reason = afs_edit_dir_for_link;
1698
+ return afs_do_sync_operation(op);
14241699
1425
- afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
1426
- afs_vnode_commit_status(&fc, vnode, fc.cb_break_2);
1427
- ihold(&vnode->vfs_inode);
1428
- d_instantiate(dentry, &vnode->vfs_inode);
1429
-
1430
- mutex_unlock(&vnode->io_lock);
1431
- ret = afs_end_vnode_operation(&fc);
1432
- if (ret < 0)
1433
- goto error_key;
1434
- } else {
1435
- goto error_key;
1436
- }
1437
-
1438
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1439
- afs_edit_dir_add(dvnode, &dentry->d_name, &vnode->fid,
1440
- afs_edit_dir_for_link);
1441
-
1442
- key_put(key);
1443
- _leave(" = 0");
1444
- return 0;
1445
-
1446
-error_key:
1447
- key_put(key);
14481700 error:
14491701 d_drop(dentry);
14501702 _leave(" = %d", ret);
14511703 return ret;
14521704 }
1705
+
1706
+static const struct afs_operation_ops afs_symlink_operation = {
1707
+ .issue_afs_rpc = afs_fs_symlink,
1708
+ .issue_yfs_rpc = yfs_fs_symlink,
1709
+ .success = afs_create_success,
1710
+ .aborted = afs_check_for_remote_deletion,
1711
+ .edit_dir = afs_create_edit_dir,
1712
+ .put = afs_create_put,
1713
+};
14531714
14541715 /*
14551716 * create a symlink in an AFS filesystem
....@@ -1457,15 +1718,11 @@
14571718 static int afs_symlink(struct inode *dir, struct dentry *dentry,
14581719 const char *content)
14591720 {
1460
- struct afs_fs_cursor fc;
1461
- struct afs_file_status newstatus;
1721
+ struct afs_operation *op;
14621722 struct afs_vnode *dvnode = AFS_FS_I(dir);
1463
- struct afs_fid newfid;
1464
- struct key *key;
1465
- u64 data_version = dvnode->status.data_version;
14661723 int ret;
14671724
1468
- _enter("{%x:%u},{%pd},%s",
1725
+ _enter("{%llx:%llu},{%pd},%s",
14691726 dvnode->fid.vid, dvnode->fid.vnode, dentry,
14701727 content);
14711728
....@@ -1477,46 +1734,121 @@
14771734 if (strlen(content) >= AFSPATHMAX)
14781735 goto error;
14791736
1480
- key = afs_request_key(dvnode->volume->cell);
1481
- if (IS_ERR(key)) {
1482
- ret = PTR_ERR(key);
1737
+ op = afs_alloc_operation(NULL, dvnode->volume);
1738
+ if (IS_ERR(op)) {
1739
+ ret = PTR_ERR(op);
14831740 goto error;
14841741 }
14851742
1486
- ret = -ERESTARTSYS;
1487
- if (afs_begin_vnode_operation(&fc, dvnode, key)) {
1488
- while (afs_select_fileserver(&fc)) {
1489
- fc.cb_break = afs_calc_vnode_cb_break(dvnode);
1490
- afs_fs_symlink(&fc, dentry->d_name.name,
1491
- content, data_version,
1492
- &newfid, &newstatus);
1493
- }
1743
+ afs_op_set_vnode(op, 0, dvnode);
1744
+ op->file[0].dv_delta = 1;
14941745
1495
- afs_check_for_remote_deletion(&fc, fc.vnode);
1496
- afs_vnode_commit_status(&fc, dvnode, fc.cb_break);
1497
- afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, NULL);
1498
- ret = afs_end_vnode_operation(&fc);
1499
- if (ret < 0)
1500
- goto error_key;
1501
- } else {
1502
- goto error_key;
1503
- }
1746
+ op->dentry = dentry;
1747
+ op->ops = &afs_symlink_operation;
1748
+ op->create.reason = afs_edit_dir_for_symlink;
1749
+ op->create.symlink = content;
1750
+ op->mtime = current_time(dir);
1751
+ return afs_do_sync_operation(op);
15041752
1505
- if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
1506
- afs_edit_dir_add(dvnode, &dentry->d_name, &newfid,
1507
- afs_edit_dir_for_symlink);
1508
-
1509
- key_put(key);
1510
- _leave(" = 0");
1511
- return 0;
1512
-
1513
-error_key:
1514
- key_put(key);
15151753 error:
15161754 d_drop(dentry);
15171755 _leave(" = %d", ret);
15181756 return ret;
15191757 }
1758
+
1759
+static void afs_rename_success(struct afs_operation *op)
1760
+{
1761
+ _enter("op=%08x", op->debug_id);
1762
+
1763
+ op->ctime = op->file[0].scb.status.mtime_client;
1764
+ afs_check_dir_conflict(op, &op->file[1]);
1765
+ afs_vnode_commit_status(op, &op->file[0]);
1766
+ if (op->file[1].vnode != op->file[0].vnode) {
1767
+ op->ctime = op->file[1].scb.status.mtime_client;
1768
+ afs_vnode_commit_status(op, &op->file[1]);
1769
+ }
1770
+}
1771
+
1772
+static void afs_rename_edit_dir(struct afs_operation *op)
1773
+{
1774
+ struct afs_vnode_param *orig_dvp = &op->file[0];
1775
+ struct afs_vnode_param *new_dvp = &op->file[1];
1776
+ struct afs_vnode *orig_dvnode = orig_dvp->vnode;
1777
+ struct afs_vnode *new_dvnode = new_dvp->vnode;
1778
+ struct afs_vnode *vnode = AFS_FS_I(d_inode(op->dentry));
1779
+ struct dentry *old_dentry = op->dentry;
1780
+ struct dentry *new_dentry = op->dentry_2;
1781
+ struct inode *new_inode;
1782
+
1783
+ _enter("op=%08x", op->debug_id);
1784
+
1785
+ if (op->rename.rehash) {
1786
+ d_rehash(op->rename.rehash);
1787
+ op->rename.rehash = NULL;
1788
+ }
1789
+
1790
+ down_write(&orig_dvnode->validate_lock);
1791
+ if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags) &&
1792
+ orig_dvnode->status.data_version == orig_dvp->dv_before + orig_dvp->dv_delta)
1793
+ afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
1794
+ afs_edit_dir_for_rename_0);
1795
+
1796
+ if (new_dvnode != orig_dvnode) {
1797
+ up_write(&orig_dvnode->validate_lock);
1798
+ down_write(&new_dvnode->validate_lock);
1799
+ }
1800
+
1801
+ if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags) &&
1802
+ new_dvnode->status.data_version == new_dvp->dv_before + new_dvp->dv_delta) {
1803
+ if (!op->rename.new_negative)
1804
+ afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
1805
+ afs_edit_dir_for_rename_1);
1806
+
1807
+ afs_edit_dir_add(new_dvnode, &new_dentry->d_name,
1808
+ &vnode->fid, afs_edit_dir_for_rename_2);
1809
+ }
1810
+
1811
+ new_inode = d_inode(new_dentry);
1812
+ if (new_inode) {
1813
+ spin_lock(&new_inode->i_lock);
1814
+ if (S_ISDIR(new_inode->i_mode))
1815
+ clear_nlink(new_inode);
1816
+ else if (new_inode->i_nlink > 0)
1817
+ drop_nlink(new_inode);
1818
+ spin_unlock(&new_inode->i_lock);
1819
+ }
1820
+
1821
+ /* Now we can update d_fsdata on the dentries to reflect their
1822
+ * new parent's data_version.
1823
+ *
1824
+ * Note that if we ever implement RENAME_EXCHANGE, we'll have
1825
+ * to update both dentries with opposing dir versions.
1826
+ */
1827
+ afs_update_dentry_version(op, new_dvp, op->dentry);
1828
+ afs_update_dentry_version(op, new_dvp, op->dentry_2);
1829
+
1830
+ d_move(old_dentry, new_dentry);
1831
+
1832
+ up_write(&new_dvnode->validate_lock);
1833
+}
1834
+
1835
+static void afs_rename_put(struct afs_operation *op)
1836
+{
1837
+ _enter("op=%08x", op->debug_id);
1838
+ if (op->rename.rehash)
1839
+ d_rehash(op->rename.rehash);
1840
+ dput(op->rename.tmp);
1841
+ if (op->error)
1842
+ d_rehash(op->dentry);
1843
+}
1844
+
1845
+static const struct afs_operation_ops afs_rename_operation = {
1846
+ .issue_afs_rpc = afs_fs_rename,
1847
+ .issue_yfs_rpc = yfs_fs_rename,
1848
+ .success = afs_rename_success,
1849
+ .edit_dir = afs_rename_edit_dir,
1850
+ .put = afs_rename_put,
1851
+};
15201852
15211853 /*
15221854 * rename a file in an AFS filesystem and/or move it between directories
....@@ -1525,79 +1857,94 @@
15251857 struct inode *new_dir, struct dentry *new_dentry,
15261858 unsigned int flags)
15271859 {
1528
- struct afs_fs_cursor fc;
1860
+ struct afs_operation *op;
15291861 struct afs_vnode *orig_dvnode, *new_dvnode, *vnode;
1530
- struct key *key;
1531
- u64 orig_data_version, new_data_version;
1532
- bool new_negative = d_is_negative(new_dentry);
15331862 int ret;
15341863
15351864 if (flags)
15361865 return -EINVAL;
15371866
1867
+ /* Don't allow silly-rename files be moved around. */
1868
+ if (old_dentry->d_flags & DCACHE_NFSFS_RENAMED)
1869
+ return -EINVAL;
1870
+
15381871 vnode = AFS_FS_I(d_inode(old_dentry));
15391872 orig_dvnode = AFS_FS_I(old_dir);
15401873 new_dvnode = AFS_FS_I(new_dir);
1541
- orig_data_version = orig_dvnode->status.data_version;
1542
- new_data_version = new_dvnode->status.data_version;
15431874
1544
- _enter("{%x:%u},{%x:%u},{%x:%u},{%pd}",
1875
+ _enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}",
15451876 orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
15461877 vnode->fid.vid, vnode->fid.vnode,
15471878 new_dvnode->fid.vid, new_dvnode->fid.vnode,
15481879 new_dentry);
15491880
1550
- key = afs_request_key(orig_dvnode->volume->cell);
1551
- if (IS_ERR(key)) {
1552
- ret = PTR_ERR(key);
1553
- goto error;
1554
- }
1881
+ op = afs_alloc_operation(NULL, orig_dvnode->volume);
1882
+ if (IS_ERR(op))
1883
+ return PTR_ERR(op);
15551884
1556
- ret = -ERESTARTSYS;
1557
- if (afs_begin_vnode_operation(&fc, orig_dvnode, key)) {
1558
- if (orig_dvnode != new_dvnode) {
1559
- if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) {
1560
- afs_end_vnode_operation(&fc);
1561
- goto error_key;
1562
- }
1563
- }
1564
- while (afs_select_fileserver(&fc)) {
1565
- fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode);
1566
- fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode);
1567
- afs_fs_rename(&fc, old_dentry->d_name.name,
1568
- new_dvnode, new_dentry->d_name.name,
1569
- orig_data_version, new_data_version);
1885
+ afs_op_set_vnode(op, 0, orig_dvnode);
1886
+ afs_op_set_vnode(op, 1, new_dvnode); /* May be same as orig_dvnode */
1887
+ op->file[0].dv_delta = 1;
1888
+ op->file[1].dv_delta = 1;
1889
+ op->file[0].modification = true;
1890
+ op->file[1].modification = true;
1891
+ op->file[0].update_ctime = true;
1892
+ op->file[1].update_ctime = true;
1893
+
1894
+ op->dentry = old_dentry;
1895
+ op->dentry_2 = new_dentry;
1896
+ op->rename.new_negative = d_is_negative(new_dentry);
1897
+ op->ops = &afs_rename_operation;
1898
+
1899
+ /* For non-directories, check whether the target is busy and if so,
1900
+ * make a copy of the dentry and then do a silly-rename. If the
1901
+ * silly-rename succeeds, the copied dentry is hashed and becomes the
1902
+ * new target.
1903
+ */
1904
+ if (d_is_positive(new_dentry) && !d_is_dir(new_dentry)) {
1905
+ /* To prevent any new references to the target during the
1906
+ * rename, we unhash the dentry in advance.
1907
+ */
1908
+ if (!d_unhashed(new_dentry)) {
1909
+ d_drop(new_dentry);
1910
+ op->rename.rehash = new_dentry;
15701911 }
15711912
1572
- afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break);
1573
- afs_vnode_commit_status(&fc, new_dvnode, fc.cb_break_2);
1574
- if (orig_dvnode != new_dvnode)
1575
- mutex_unlock(&new_dvnode->io_lock);
1576
- ret = afs_end_vnode_operation(&fc);
1577
- if (ret < 0)
1578
- goto error_key;
1913
+ if (d_count(new_dentry) > 2) {
1914
+ /* copy the target dentry's name */
1915
+ ret = -ENOMEM;
1916
+ op->rename.tmp = d_alloc(new_dentry->d_parent,
1917
+ &new_dentry->d_name);
1918
+ if (!op->rename.tmp)
1919
+ goto error;
1920
+
1921
+ ret = afs_sillyrename(new_dvnode,
1922
+ AFS_FS_I(d_inode(new_dentry)),
1923
+ new_dentry, op->key);
1924
+ if (ret)
1925
+ goto error;
1926
+
1927
+ op->dentry_2 = op->rename.tmp;
1928
+ op->rename.rehash = NULL;
1929
+ op->rename.new_negative = true;
1930
+ }
15791931 }
15801932
1581
- if (ret == 0) {
1582
- if (test_bit(AFS_VNODE_DIR_VALID, &orig_dvnode->flags))
1583
- afs_edit_dir_remove(orig_dvnode, &old_dentry->d_name,
1584
- afs_edit_dir_for_rename);
1933
+ /* This bit is potentially nasty as there's a potential race with
1934
+ * afs_d_revalidate{,_rcu}(). We have to change d_fsdata on the dentry
1935
+ * to reflect it's new parent's new data_version after the op, but
1936
+ * d_revalidate may see old_dentry between the op having taken place
1937
+ * and the version being updated.
1938
+ *
1939
+ * So drop the old_dentry for now to make other threads go through
1940
+ * lookup instead - which we hold a lock against.
1941
+ */
1942
+ d_drop(old_dentry);
15851943
1586
- if (!new_negative &&
1587
- test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
1588
- afs_edit_dir_remove(new_dvnode, &new_dentry->d_name,
1589
- afs_edit_dir_for_rename);
1944
+ return afs_do_sync_operation(op);
15901945
1591
- if (test_bit(AFS_VNODE_DIR_VALID, &new_dvnode->flags))
1592
- afs_edit_dir_add(new_dvnode, &new_dentry->d_name,
1593
- &vnode->fid, afs_edit_dir_for_rename);
1594
- }
1595
-
1596
-error_key:
1597
- key_put(key);
15981946 error:
1599
- _leave(" = %d", ret);
1600
- return ret;
1947
+ return afs_put_operation(op);
16011948 }
16021949
16031950 /*
....@@ -1608,10 +1955,9 @@
16081955 {
16091956 struct afs_vnode *dvnode = AFS_FS_I(page->mapping->host);
16101957
1611
- _enter("{{%x:%u}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
1958
+ _enter("{{%llx:%llu}[%lu]}", dvnode->fid.vid, dvnode->fid.vnode, page->index);
16121959
1613
- set_page_private(page, 0);
1614
- ClearPagePrivate(page);
1960
+ detach_page_private(page);
16151961
16161962 /* The directory will need reloading. */
16171963 if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &dvnode->flags))
....@@ -1638,8 +1984,6 @@
16381984 afs_stat_v(dvnode, n_inval);
16391985
16401986 /* we clean up only if the entire page is being invalidated */
1641
- if (offset == 0 && length == PAGE_SIZE) {
1642
- set_page_private(page, 0);
1643
- ClearPagePrivate(page);
1644
- }
1987
+ if (offset == 0 && length == PAGE_SIZE)
1988
+ detach_page_private(page);
16451989 }