diff options
| -rw-r--r-- | fs/afs/afs.h | 13 | ||||
| -rw-r--r-- | fs/afs/callback.c | 21 | ||||
| -rw-r--r-- | fs/afs/cmservice.c | 14 | ||||
| -rw-r--r-- | fs/afs/dir.c | 357 | ||||
| -rw-r--r-- | fs/afs/dir_silly.c | 31 | ||||
| -rw-r--r-- | fs/afs/file.c | 20 | ||||
| -rw-r--r-- | fs/afs/flock.c | 40 | ||||
| -rw-r--r-- | fs/afs/fs_probe.c | 4 | ||||
| -rw-r--r-- | fs/afs/fsclient.c | 673 | ||||
| -rw-r--r-- | fs/afs/inode.c | 445 | ||||
| -rw-r--r-- | fs/afs/internal.h | 179 | ||||
| -rw-r--r-- | fs/afs/rotate.c | 18 | ||||
| -rw-r--r-- | fs/afs/rxrpc.c | 13 | ||||
| -rw-r--r-- | fs/afs/security.c | 15 | ||||
| -rw-r--r-- | fs/afs/super.c | 20 | ||||
| -rw-r--r-- | fs/afs/vl_probe.c | 4 | ||||
| -rw-r--r-- | fs/afs/vlclient.c | 34 | ||||
| -rw-r--r-- | fs/afs/write.c | 98 | ||||
| -rw-r--r-- | fs/afs/xattr.c | 103 | ||||
| -rw-r--r-- | fs/afs/yfsclient.c | 662 |
20 files changed, 1383 insertions, 1381 deletions
diff --git a/fs/afs/afs.h b/fs/afs/afs.h index 74913c707bba..3f4e460c6655 100644 --- a/fs/afs/afs.h +++ b/fs/afs/afs.h | |||
| @@ -72,8 +72,8 @@ typedef enum { | |||
| 72 | 72 | ||
| 73 | struct afs_callback { | 73 | struct afs_callback { |
| 74 | time64_t expires_at; /* Time at which expires */ | 74 | time64_t expires_at; /* Time at which expires */ |
| 75 | unsigned version; /* Callback version */ | 75 | //unsigned version; /* Callback version */ |
| 76 | afs_callback_type_t type; /* Type of callback */ | 76 | //afs_callback_type_t type; /* Type of callback */ |
| 77 | }; | 77 | }; |
| 78 | 78 | ||
| 79 | struct afs_callback_break { | 79 | struct afs_callback_break { |
| @@ -147,6 +147,15 @@ struct afs_file_status { | |||
| 147 | u32 abort_code; /* Abort if bulk-fetching this failed */ | 147 | u32 abort_code; /* Abort if bulk-fetching this failed */ |
| 148 | }; | 148 | }; |
| 149 | 149 | ||
| 150 | struct afs_status_cb { | ||
| 151 | struct afs_file_status status; | ||
| 152 | struct afs_callback callback; | ||
| 153 | unsigned int cb_break; /* Pre-op callback break counter */ | ||
| 154 | bool have_status; /* True if status record was retrieved */ | ||
| 155 | bool have_cb; /* True if cb record was retrieved */ | ||
| 156 | bool have_error; /* True if status.abort_code indicates an error */ | ||
| 157 | }; | ||
| 158 | |||
| 150 | /* | 159 | /* |
| 151 | * AFS file status change request | 160 | * AFS file status change request |
| 152 | */ | 161 | */ |
diff --git a/fs/afs/callback.c b/fs/afs/callback.c index 4876079aa643..d441bef72163 100644 --- a/fs/afs/callback.c +++ b/fs/afs/callback.c | |||
| @@ -94,15 +94,15 @@ int afs_register_server_cb_interest(struct afs_vnode *vnode, | |||
| 94 | struct afs_server *server = entry->server; | 94 | struct afs_server *server = entry->server; |
| 95 | 95 | ||
| 96 | again: | 96 | again: |
| 97 | if (vnode->cb_interest && | 97 | vcbi = rcu_dereference_protected(vnode->cb_interest, |
| 98 | likely(vnode->cb_interest == entry->cb_interest)) | 98 | lockdep_is_held(&vnode->io_lock)); |
| 99 | if (vcbi && likely(vcbi == entry->cb_interest)) | ||
| 99 | return 0; | 100 | return 0; |
| 100 | 101 | ||
| 101 | read_lock(&slist->lock); | 102 | read_lock(&slist->lock); |
| 102 | cbi = afs_get_cb_interest(entry->cb_interest); | 103 | cbi = afs_get_cb_interest(entry->cb_interest); |
| 103 | read_unlock(&slist->lock); | 104 | read_unlock(&slist->lock); |
| 104 | 105 | ||
| 105 | vcbi = vnode->cb_interest; | ||
| 106 | if (vcbi) { | 106 | if (vcbi) { |
| 107 | if (vcbi == cbi) { | 107 | if (vcbi == cbi) { |
| 108 | afs_put_cb_interest(afs_v2net(vnode), cbi); | 108 | afs_put_cb_interest(afs_v2net(vnode), cbi); |
| @@ -114,8 +114,9 @@ again: | |||
| 114 | */ | 114 | */ |
| 115 | if (cbi && vcbi->server == cbi->server) { | 115 | if (cbi && vcbi->server == cbi->server) { |
| 116 | write_seqlock(&vnode->cb_lock); | 116 | write_seqlock(&vnode->cb_lock); |
| 117 | old = vnode->cb_interest; | 117 | old = rcu_dereference_protected(vnode->cb_interest, |
| 118 | vnode->cb_interest = cbi; | 118 | lockdep_is_held(&vnode->cb_lock.lock)); |
| 119 | rcu_assign_pointer(vnode->cb_interest, cbi); | ||
| 119 | write_sequnlock(&vnode->cb_lock); | 120 | write_sequnlock(&vnode->cb_lock); |
| 120 | afs_put_cb_interest(afs_v2net(vnode), old); | 121 | afs_put_cb_interest(afs_v2net(vnode), old); |
| 121 | return 0; | 122 | return 0; |
| @@ -160,8 +161,9 @@ again: | |||
| 160 | */ | 161 | */ |
| 161 | write_seqlock(&vnode->cb_lock); | 162 | write_seqlock(&vnode->cb_lock); |
| 162 | 163 | ||
| 163 | old = vnode->cb_interest; | 164 | old = rcu_dereference_protected(vnode->cb_interest, |
| 164 | vnode->cb_interest = cbi; | 165 | lockdep_is_held(&vnode->cb_lock.lock)); |
| 166 | rcu_assign_pointer(vnode->cb_interest, cbi); | ||
| 165 | vnode->cb_s_break = cbi->server->cb_s_break; | 167 | vnode->cb_s_break = cbi->server->cb_s_break; |
| 166 | vnode->cb_v_break = vnode->volume->cb_v_break; | 168 | vnode->cb_v_break = vnode->volume->cb_v_break; |
| 167 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | 169 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); |
| @@ -191,10 +193,11 @@ void afs_put_cb_interest(struct afs_net *net, struct afs_cb_interest *cbi) | |||
| 191 | vi = NULL; | 193 | vi = NULL; |
| 192 | 194 | ||
| 193 | write_unlock(&cbi->server->cb_break_lock); | 195 | write_unlock(&cbi->server->cb_break_lock); |
| 194 | kfree(vi); | 196 | if (vi) |
| 197 | kfree_rcu(vi, rcu); | ||
| 195 | afs_put_server(net, cbi->server); | 198 | afs_put_server(net, cbi->server); |
| 196 | } | 199 | } |
| 197 | kfree(cbi); | 200 | kfree_rcu(cbi, rcu); |
| 198 | } | 201 | } |
| 199 | } | 202 | } |
| 200 | 203 | ||
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index 748090014519..01437cfe5432 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c | |||
| @@ -213,7 +213,7 @@ static int afs_find_cm_server_by_peer(struct afs_call *call) | |||
| 213 | return 0; | 213 | return 0; |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | call->cm_server = server; | 216 | call->server = server; |
| 217 | return afs_record_cm_probe(call, server); | 217 | return afs_record_cm_probe(call, server); |
| 218 | } | 218 | } |
| 219 | 219 | ||
| @@ -234,7 +234,7 @@ static int afs_find_cm_server_by_uuid(struct afs_call *call, | |||
| 234 | return 0; | 234 | return 0; |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | call->cm_server = server; | 237 | call->server = server; |
| 238 | return afs_record_cm_probe(call, server); | 238 | return afs_record_cm_probe(call, server); |
| 239 | } | 239 | } |
| 240 | 240 | ||
| @@ -260,8 +260,8 @@ static void SRXAFSCB_CallBack(struct work_struct *work) | |||
| 260 | * server holds up change visibility till it receives our reply so as | 260 | * server holds up change visibility till it receives our reply so as |
| 261 | * to maintain cache coherency. | 261 | * to maintain cache coherency. |
| 262 | */ | 262 | */ |
| 263 | if (call->cm_server) | 263 | if (call->server) |
| 264 | afs_break_callbacks(call->cm_server, call->count, call->request); | 264 | afs_break_callbacks(call->server, call->count, call->request); |
| 265 | 265 | ||
| 266 | afs_send_empty_reply(call); | 266 | afs_send_empty_reply(call); |
| 267 | afs_put_call(call); | 267 | afs_put_call(call); |
| @@ -376,10 +376,10 @@ static void SRXAFSCB_InitCallBackState(struct work_struct *work) | |||
| 376 | { | 376 | { |
| 377 | struct afs_call *call = container_of(work, struct afs_call, work); | 377 | struct afs_call *call = container_of(work, struct afs_call, work); |
| 378 | 378 | ||
| 379 | _enter("{%p}", call->cm_server); | 379 | _enter("{%p}", call->server); |
| 380 | 380 | ||
| 381 | if (call->cm_server) | 381 | if (call->server) |
| 382 | afs_init_callback_state(call->cm_server); | 382 | afs_init_callback_state(call->server); |
| 383 | afs_send_empty_reply(call); | 383 | afs_send_empty_reply(call); |
| 384 | afs_put_call(call); | 384 | afs_put_call(call); |
| 385 | _leave(""); | 385 | _leave(""); |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index c15550310f62..79d93a26759a 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
| 19 | #include <linux/task_io_accounting_ops.h> | 19 | #include <linux/task_io_accounting_ops.h> |
| 20 | #include "internal.h" | 20 | #include "internal.h" |
| 21 | #include "afs_fs.h" | ||
| 21 | #include "xdr_fs.h" | 22 | #include "xdr_fs.h" |
| 22 | 23 | ||
| 23 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, | 24 | static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, |
| @@ -102,8 +103,8 @@ struct afs_lookup_cookie { | |||
| 102 | bool found; | 103 | bool found; |
| 103 | bool one_only; | 104 | bool one_only; |
| 104 | unsigned short nr_fids; | 105 | unsigned short nr_fids; |
| 105 | struct afs_file_status *statuses; | 106 | struct inode **inodes; |
| 106 | struct afs_callback *callbacks; | 107 | struct afs_status_cb *statuses; |
| 107 | struct afs_fid fids[50]; | 108 | struct afs_fid fids[50]; |
| 108 | }; | 109 | }; |
| 109 | 110 | ||
| @@ -638,12 +639,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry, | |||
| 638 | struct key *key) | 639 | struct key *key) |
| 639 | { | 640 | { |
| 640 | struct afs_lookup_cookie *cookie; | 641 | struct afs_lookup_cookie *cookie; |
| 641 | struct afs_cb_interest *cbi = NULL; | 642 | struct afs_cb_interest *dcbi, *cbi = NULL; |
| 642 | struct afs_super_info *as = dir->i_sb->s_fs_info; | 643 | struct afs_super_info *as = dir->i_sb->s_fs_info; |
| 643 | struct afs_iget_data data; | 644 | struct afs_status_cb *scb; |
| 645 | struct afs_iget_data iget_data; | ||
| 644 | struct afs_fs_cursor fc; | 646 | struct afs_fs_cursor fc; |
| 645 | struct afs_vnode *dvnode = AFS_FS_I(dir); | 647 | struct afs_server *server; |
| 646 | struct inode *inode = NULL; | 648 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode; |
| 649 | struct inode *inode = NULL, *ti; | ||
| 647 | int ret, i; | 650 | int ret, i; |
| 648 | 651 | ||
| 649 | _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry); | 652 | _enter("{%lu},%p{%pd},", dir->i_ino, dentry, dentry); |
| @@ -657,10 +660,14 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry, | |||
| 657 | cookie->nr_fids = 1; /* slot 0 is saved for the fid we actually want */ | 660 | cookie->nr_fids = 1; /* slot 0 is saved for the fid we actually want */ |
| 658 | 661 | ||
| 659 | read_seqlock_excl(&dvnode->cb_lock); | 662 | read_seqlock_excl(&dvnode->cb_lock); |
| 660 | if (dvnode->cb_interest && | 663 | dcbi = rcu_dereference_protected(dvnode->cb_interest, |
| 661 | dvnode->cb_interest->server && | 664 | lockdep_is_held(&dvnode->cb_lock.lock)); |
| 662 | test_bit(AFS_SERVER_FL_NO_IBULK, &dvnode->cb_interest->server->flags)) | 665 | if (dcbi) { |
| 663 | cookie->one_only = true; | 666 | server = dcbi->server; |
| 667 | if (server && | ||
| 668 | test_bit(AFS_SERVER_FL_NO_IBULK, &server->flags)) | ||
| 669 | cookie->one_only = true; | ||
| 670 | } | ||
| 664 | read_sequnlock_excl(&dvnode->cb_lock); | 671 | read_sequnlock_excl(&dvnode->cb_lock); |
| 665 | 672 | ||
| 666 | for (i = 0; i < 50; i++) | 673 | for (i = 0; i < 50; i++) |
| @@ -678,24 +685,43 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry, | |||
| 678 | goto out; | 685 | goto out; |
| 679 | 686 | ||
| 680 | /* Check to see if we already have an inode for the primary fid. */ | 687 | /* Check to see if we already have an inode for the primary fid. */ |
| 681 | data.volume = dvnode->volume; | 688 | iget_data.fid = cookie->fids[0]; |
| 682 | data.fid = cookie->fids[0]; | 689 | iget_data.volume = dvnode->volume; |
| 683 | inode = ilookup5(dir->i_sb, cookie->fids[0].vnode, afs_iget5_test, &data); | 690 | iget_data.cb_v_break = dvnode->volume->cb_v_break; |
| 691 | iget_data.cb_s_break = 0; | ||
| 692 | inode = ilookup5(dir->i_sb, cookie->fids[0].vnode, | ||
| 693 | afs_iget5_test, &iget_data); | ||
| 684 | if (inode) | 694 | if (inode) |
| 685 | goto out; | 695 | goto out; |
| 686 | 696 | ||
| 687 | /* Need space for examining all the selected files */ | 697 | /* Need space for examining all the selected files */ |
| 688 | inode = ERR_PTR(-ENOMEM); | 698 | inode = ERR_PTR(-ENOMEM); |
| 689 | cookie->statuses = kcalloc(cookie->nr_fids, sizeof(struct afs_file_status), | 699 | cookie->statuses = kvcalloc(cookie->nr_fids, sizeof(struct afs_status_cb), |
| 690 | GFP_KERNEL); | 700 | GFP_KERNEL); |
| 691 | if (!cookie->statuses) | 701 | if (!cookie->statuses) |
| 692 | goto out; | 702 | goto out; |
| 693 | 703 | ||
| 694 | cookie->callbacks = kcalloc(cookie->nr_fids, sizeof(struct afs_callback), | 704 | cookie->inodes = kcalloc(cookie->nr_fids, sizeof(struct inode *), |
| 695 | GFP_KERNEL); | 705 | GFP_KERNEL); |
| 696 | if (!cookie->callbacks) | 706 | if (!cookie->inodes) |
| 697 | goto out_s; | 707 | goto out_s; |
| 698 | 708 | ||
| 709 | for (i = 1; i < cookie->nr_fids; i++) { | ||
| 710 | scb = &cookie->statuses[i]; | ||
| 711 | |||
| 712 | /* Find any inodes that already exist and get their | ||
| 713 | * callback counters. | ||
| 714 | */ | ||
| 715 | iget_data.fid = cookie->fids[i]; | ||
| 716 | ti = ilookup5_nowait(dir->i_sb, iget_data.fid.vnode, | ||
| 717 | afs_iget5_test, &iget_data); | ||
| 718 | if (!IS_ERR_OR_NULL(ti)) { | ||
| 719 | vnode = AFS_FS_I(ti); | ||
| 720 | scb->cb_break = afs_calc_vnode_cb_break(vnode); | ||
| 721 | cookie->inodes[i] = ti; | ||
| 722 | } | ||
| 723 | } | ||
| 724 | |||
| 699 | /* Try FS.InlineBulkStatus first. Abort codes for the individual | 725 | /* Try FS.InlineBulkStatus first. Abort codes for the individual |
| 700 | * lookups contained therein are stored in the reply without aborting | 726 | * lookups contained therein are stored in the reply without aborting |
| 701 | * the whole operation. | 727 | * the whole operation. |
| @@ -712,11 +738,12 @@ static struct inode *afs_do_lookup(struct inode *dir, struct dentry *dentry, | |||
| 712 | fc.ac.error = -ECONNABORTED; | 738 | fc.ac.error = -ECONNABORTED; |
| 713 | break; | 739 | break; |
| 714 | } | 740 | } |
| 741 | iget_data.cb_v_break = dvnode->volume->cb_v_break; | ||
| 742 | iget_data.cb_s_break = fc.cbi->server->cb_s_break; | ||
| 715 | afs_fs_inline_bulk_status(&fc, | 743 | afs_fs_inline_bulk_status(&fc, |
| 716 | afs_v2net(dvnode), | 744 | afs_v2net(dvnode), |
| 717 | cookie->fids, | 745 | cookie->fids, |
| 718 | cookie->statuses, | 746 | cookie->statuses, |
| 719 | cookie->callbacks, | ||
| 720 | cookie->nr_fids, NULL); | 747 | cookie->nr_fids, NULL); |
| 721 | } | 748 | } |
| 722 | 749 | ||
| @@ -737,15 +764,16 @@ no_inline_bulk_status: | |||
| 737 | * any of the lookups fails - so, for the moment, revert to | 764 | * any of the lookups fails - so, for the moment, revert to |
| 738 | * FS.FetchStatus for just the primary fid. | 765 | * FS.FetchStatus for just the primary fid. |
| 739 | */ | 766 | */ |
| 740 | cookie->nr_fids = 1; | ||
| 741 | inode = ERR_PTR(-ERESTARTSYS); | 767 | inode = ERR_PTR(-ERESTARTSYS); |
| 742 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { | 768 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { |
| 743 | while (afs_select_fileserver(&fc)) { | 769 | while (afs_select_fileserver(&fc)) { |
| 770 | iget_data.cb_v_break = dvnode->volume->cb_v_break; | ||
| 771 | iget_data.cb_s_break = fc.cbi->server->cb_s_break; | ||
| 772 | scb = &cookie->statuses[0]; | ||
| 744 | afs_fs_fetch_status(&fc, | 773 | afs_fs_fetch_status(&fc, |
| 745 | afs_v2net(dvnode), | 774 | afs_v2net(dvnode), |
| 746 | cookie->fids, | 775 | cookie->fids, |
| 747 | cookie->statuses, | 776 | scb, |
| 748 | cookie->callbacks, | ||
| 749 | NULL); | 777 | NULL); |
| 750 | } | 778 | } |
| 751 | 779 | ||
| @@ -757,26 +785,36 @@ no_inline_bulk_status: | |||
| 757 | if (IS_ERR(inode)) | 785 | if (IS_ERR(inode)) |
| 758 | goto out_c; | 786 | goto out_c; |
| 759 | 787 | ||
| 760 | for (i = 0; i < cookie->nr_fids; i++) | ||
| 761 | cookie->statuses[i].abort_code = 0; | ||
| 762 | |||
| 763 | success: | 788 | success: |
| 764 | /* Turn all the files into inodes and save the first one - which is the | 789 | /* Turn all the files into inodes and save the first one - which is the |
| 765 | * one we actually want. | 790 | * one we actually want. |
| 766 | */ | 791 | */ |
| 767 | if (cookie->statuses[0].abort_code != 0) | 792 | scb = &cookie->statuses[0]; |
| 768 | inode = ERR_PTR(afs_abort_to_error(cookie->statuses[0].abort_code)); | 793 | if (scb->status.abort_code != 0) |
| 794 | inode = ERR_PTR(afs_abort_to_error(scb->status.abort_code)); | ||
| 769 | 795 | ||
| 770 | for (i = 0; i < cookie->nr_fids; i++) { | 796 | for (i = 0; i < cookie->nr_fids; i++) { |
| 771 | struct inode *ti; | 797 | struct afs_status_cb *scb = &cookie->statuses[i]; |
| 798 | |||
| 799 | if (!scb->have_status && !scb->have_error) | ||
| 800 | continue; | ||
| 801 | |||
| 802 | if (cookie->inodes[i]) { | ||
| 803 | afs_vnode_commit_status(&fc, AFS_FS_I(cookie->inodes[i]), | ||
| 804 | scb->cb_break, NULL, scb); | ||
| 805 | continue; | ||
| 806 | } | ||
| 772 | 807 | ||
| 773 | if (cookie->statuses[i].abort_code != 0) | 808 | if (scb->status.abort_code != 0) |
| 774 | continue; | 809 | continue; |
| 775 | 810 | ||
| 776 | ti = afs_iget(dir->i_sb, key, &cookie->fids[i], | 811 | iget_data.fid = cookie->fids[i]; |
| 777 | &cookie->statuses[i], | 812 | ti = afs_iget(dir->i_sb, key, &iget_data, scb, cbi, dvnode); |
| 778 | &cookie->callbacks[i], | 813 | if (!IS_ERR(ti)) |
| 779 | cbi, dvnode); | 814 | afs_cache_permit(AFS_FS_I(ti), key, |
| 815 | 0 /* Assume vnode->cb_break is 0 */ + | ||
| 816 | iget_data.cb_v_break, | ||
| 817 | scb); | ||
| 780 | if (i == 0) { | 818 | if (i == 0) { |
| 781 | inode = ti; | 819 | inode = ti; |
| 782 | } else { | 820 | } else { |
| @@ -787,9 +825,13 @@ success: | |||
| 787 | 825 | ||
| 788 | out_c: | 826 | out_c: |
| 789 | afs_put_cb_interest(afs_v2net(dvnode), cbi); | 827 | afs_put_cb_interest(afs_v2net(dvnode), cbi); |
| 790 | kfree(cookie->callbacks); | 828 | if (cookie->inodes) { |
| 829 | for (i = 0; i < cookie->nr_fids; i++) | ||
| 830 | iput(cookie->inodes[i]); | ||
| 831 | kfree(cookie->inodes); | ||
| 832 | } | ||
| 791 | out_s: | 833 | out_s: |
| 792 | kfree(cookie->statuses); | 834 | kvfree(cookie->statuses); |
| 793 | out: | 835 | out: |
| 794 | kfree(cookie); | 836 | kfree(cookie); |
| 795 | return inode; | 837 | return inode; |
| @@ -1114,9 +1156,8 @@ void afs_d_release(struct dentry *dentry) | |||
| 1114 | */ | 1156 | */ |
| 1115 | static void afs_vnode_new_inode(struct afs_fs_cursor *fc, | 1157 | static void afs_vnode_new_inode(struct afs_fs_cursor *fc, |
| 1116 | struct dentry *new_dentry, | 1158 | struct dentry *new_dentry, |
| 1117 | struct afs_fid *newfid, | 1159 | struct afs_iget_data *new_data, |
| 1118 | struct afs_file_status *newstatus, | 1160 | struct afs_status_cb *new_scb) |
| 1119 | struct afs_callback *newcb) | ||
| 1120 | { | 1161 | { |
| 1121 | struct afs_vnode *vnode; | 1162 | struct afs_vnode *vnode; |
| 1122 | struct inode *inode; | 1163 | struct inode *inode; |
| @@ -1125,7 +1166,7 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc, | |||
| 1125 | return; | 1166 | return; |
| 1126 | 1167 | ||
| 1127 | inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key, | 1168 | inode = afs_iget(fc->vnode->vfs_inode.i_sb, fc->key, |
| 1128 | newfid, newstatus, newcb, fc->cbi, fc->vnode); | 1169 | new_data, new_scb, fc->cbi, fc->vnode); |
| 1129 | if (IS_ERR(inode)) { | 1170 | if (IS_ERR(inode)) { |
| 1130 | /* ENOMEM or EINTR at a really inconvenient time - just abandon | 1171 | /* ENOMEM or EINTR at a really inconvenient time - just abandon |
| 1131 | * the new directory on the server. | 1172 | * the new directory on the server. |
| @@ -1136,22 +1177,29 @@ static void afs_vnode_new_inode(struct afs_fs_cursor *fc, | |||
| 1136 | 1177 | ||
| 1137 | vnode = AFS_FS_I(inode); | 1178 | vnode = AFS_FS_I(inode); |
| 1138 | set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); | 1179 | set_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags); |
| 1139 | afs_vnode_commit_status(fc, vnode, 0); | 1180 | if (fc->ac.error == 0) |
| 1181 | afs_cache_permit(vnode, fc->key, vnode->cb_break, new_scb); | ||
| 1140 | d_instantiate(new_dentry, inode); | 1182 | d_instantiate(new_dentry, inode); |
| 1141 | } | 1183 | } |
| 1142 | 1184 | ||
| 1185 | static void afs_prep_for_new_inode(struct afs_fs_cursor *fc, | ||
| 1186 | struct afs_iget_data *iget_data) | ||
| 1187 | { | ||
| 1188 | iget_data->volume = fc->vnode->volume; | ||
| 1189 | iget_data->cb_v_break = fc->vnode->volume->cb_v_break; | ||
| 1190 | iget_data->cb_s_break = fc->cbi->server->cb_s_break; | ||
| 1191 | } | ||
| 1192 | |||
| 1143 | /* | 1193 | /* |
| 1144 | * create a directory on an AFS filesystem | 1194 | * create a directory on an AFS filesystem |
| 1145 | */ | 1195 | */ |
| 1146 | static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | 1196 | static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) |
| 1147 | { | 1197 | { |
| 1148 | struct afs_file_status newstatus; | 1198 | struct afs_iget_data iget_data; |
| 1199 | struct afs_status_cb *scb; | ||
| 1149 | struct afs_fs_cursor fc; | 1200 | struct afs_fs_cursor fc; |
| 1150 | struct afs_callback newcb; | ||
| 1151 | struct afs_vnode *dvnode = AFS_FS_I(dir); | 1201 | struct afs_vnode *dvnode = AFS_FS_I(dir); |
| 1152 | struct afs_fid newfid; | ||
| 1153 | struct key *key; | 1202 | struct key *key; |
| 1154 | u64 data_version = dvnode->status.data_version; | ||
| 1155 | int ret; | 1203 | int ret; |
| 1156 | 1204 | ||
| 1157 | mode |= S_IFDIR; | 1205 | mode |= S_IFDIR; |
| @@ -1159,23 +1207,32 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 1159 | _enter("{%llx:%llu},{%pd},%ho", | 1207 | _enter("{%llx:%llu},{%pd},%ho", |
| 1160 | dvnode->fid.vid, dvnode->fid.vnode, dentry, mode); | 1208 | dvnode->fid.vid, dvnode->fid.vnode, dentry, mode); |
| 1161 | 1209 | ||
| 1210 | ret = -ENOMEM; | ||
| 1211 | scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 1212 | if (!scb) | ||
| 1213 | goto error; | ||
| 1214 | |||
| 1162 | key = afs_request_key(dvnode->volume->cell); | 1215 | key = afs_request_key(dvnode->volume->cell); |
| 1163 | if (IS_ERR(key)) { | 1216 | if (IS_ERR(key)) { |
| 1164 | ret = PTR_ERR(key); | 1217 | ret = PTR_ERR(key); |
| 1165 | goto error; | 1218 | goto error_scb; |
| 1166 | } | 1219 | } |
| 1167 | 1220 | ||
| 1168 | ret = -ERESTARTSYS; | 1221 | ret = -ERESTARTSYS; |
| 1169 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { | 1222 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { |
| 1223 | afs_dataversion_t data_version = dvnode->status.data_version + 1; | ||
| 1224 | |||
| 1170 | while (afs_select_fileserver(&fc)) { | 1225 | while (afs_select_fileserver(&fc)) { |
| 1171 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 1226 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1172 | afs_fs_create(&fc, dentry->d_name.name, mode, data_version, | 1227 | afs_prep_for_new_inode(&fc, &iget_data); |
| 1173 | &newfid, &newstatus, &newcb); | 1228 | afs_fs_create(&fc, dentry->d_name.name, mode, |
| 1229 | &scb[0], &iget_data.fid, &scb[1]); | ||
| 1174 | } | 1230 | } |
| 1175 | 1231 | ||
| 1176 | afs_check_for_remote_deletion(&fc, fc.vnode); | 1232 | afs_check_for_remote_deletion(&fc, dvnode); |
| 1177 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); | 1233 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break, |
| 1178 | afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, &newcb); | 1234 | &data_version, &scb[0]); |
| 1235 | afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]); | ||
| 1179 | ret = afs_end_vnode_operation(&fc); | 1236 | ret = afs_end_vnode_operation(&fc); |
| 1180 | if (ret < 0) | 1237 | if (ret < 0) |
| 1181 | goto error_key; | 1238 | goto error_key; |
| @@ -1185,15 +1242,18 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) | |||
| 1185 | 1242 | ||
| 1186 | if (ret == 0 && | 1243 | if (ret == 0 && |
| 1187 | test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) | 1244 | test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) |
| 1188 | afs_edit_dir_add(dvnode, &dentry->d_name, &newfid, | 1245 | afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid, |
| 1189 | afs_edit_dir_for_create); | 1246 | afs_edit_dir_for_create); |
| 1190 | 1247 | ||
| 1191 | key_put(key); | 1248 | key_put(key); |
| 1249 | kfree(scb); | ||
| 1192 | _leave(" = 0"); | 1250 | _leave(" = 0"); |
| 1193 | return 0; | 1251 | return 0; |
| 1194 | 1252 | ||
| 1195 | error_key: | 1253 | error_key: |
| 1196 | key_put(key); | 1254 | key_put(key); |
| 1255 | error_scb: | ||
| 1256 | kfree(scb); | ||
| 1197 | error: | 1257 | error: |
| 1198 | d_drop(dentry); | 1258 | d_drop(dentry); |
| 1199 | _leave(" = %d", ret); | 1259 | _leave(" = %d", ret); |
| @@ -1220,15 +1280,19 @@ static void afs_dir_remove_subdir(struct dentry *dentry) | |||
| 1220 | */ | 1280 | */ |
| 1221 | static int afs_rmdir(struct inode *dir, struct dentry *dentry) | 1281 | static int afs_rmdir(struct inode *dir, struct dentry *dentry) |
| 1222 | { | 1282 | { |
| 1283 | struct afs_status_cb *scb; | ||
| 1223 | struct afs_fs_cursor fc; | 1284 | struct afs_fs_cursor fc; |
| 1224 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL; | 1285 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL; |
| 1225 | struct key *key; | 1286 | struct key *key; |
| 1226 | u64 data_version = dvnode->status.data_version; | ||
| 1227 | int ret; | 1287 | int ret; |
| 1228 | 1288 | ||
| 1229 | _enter("{%llx:%llu},{%pd}", | 1289 | _enter("{%llx:%llu},{%pd}", |
| 1230 | dvnode->fid.vid, dvnode->fid.vnode, dentry); | 1290 | dvnode->fid.vid, dvnode->fid.vnode, dentry); |
| 1231 | 1291 | ||
| 1292 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 1293 | if (!scb) | ||
| 1294 | return -ENOMEM; | ||
| 1295 | |||
| 1232 | key = afs_request_key(dvnode->volume->cell); | 1296 | key = afs_request_key(dvnode->volume->cell); |
| 1233 | if (IS_ERR(key)) { | 1297 | if (IS_ERR(key)) { |
| 1234 | ret = PTR_ERR(key); | 1298 | ret = PTR_ERR(key); |
| @@ -1251,13 +1315,15 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 1251 | 1315 | ||
| 1252 | ret = -ERESTARTSYS; | 1316 | ret = -ERESTARTSYS; |
| 1253 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { | 1317 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { |
| 1318 | afs_dataversion_t data_version = dvnode->status.data_version + 1; | ||
| 1319 | |||
| 1254 | while (afs_select_fileserver(&fc)) { | 1320 | while (afs_select_fileserver(&fc)) { |
| 1255 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 1321 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1256 | afs_fs_remove(&fc, vnode, dentry->d_name.name, true, | 1322 | afs_fs_remove(&fc, vnode, dentry->d_name.name, true, scb); |
| 1257 | data_version); | ||
| 1258 | } | 1323 | } |
| 1259 | 1324 | ||
| 1260 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); | 1325 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break, |
| 1326 | &data_version, scb); | ||
| 1261 | ret = afs_end_vnode_operation(&fc); | 1327 | ret = afs_end_vnode_operation(&fc); |
| 1262 | if (ret == 0) { | 1328 | if (ret == 0) { |
| 1263 | afs_dir_remove_subdir(dentry); | 1329 | afs_dir_remove_subdir(dentry); |
| @@ -1272,6 +1338,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 1272 | error_key: | 1338 | error_key: |
| 1273 | key_put(key); | 1339 | key_put(key); |
| 1274 | error: | 1340 | error: |
| 1341 | kfree(scb); | ||
| 1275 | return ret; | 1342 | return ret; |
| 1276 | } | 1343 | } |
| 1277 | 1344 | ||
| @@ -1285,32 +1352,27 @@ error: | |||
| 1285 | * However, if we didn't have a callback promise outstanding, or it was | 1352 | * However, if we didn't have a callback promise outstanding, or it was |
| 1286 | * outstanding on a different server, then it won't break it either... | 1353 | * outstanding on a different server, then it won't break it either... |
| 1287 | */ | 1354 | */ |
| 1288 | int afs_dir_remove_link(struct dentry *dentry, struct key *key, | 1355 | static int afs_dir_remove_link(struct afs_vnode *dvnode, struct dentry *dentry, |
| 1289 | unsigned long d_version_before, | 1356 | struct key *key) |
| 1290 | unsigned long d_version_after) | ||
| 1291 | { | 1357 | { |
| 1292 | bool dir_valid; | ||
| 1293 | int ret = 0; | 1358 | int ret = 0; |
| 1294 | 1359 | ||
| 1295 | /* There were no intervening changes on the server if the version | ||
| 1296 | * number we got back was incremented by exactly 1. | ||
| 1297 | */ | ||
| 1298 | dir_valid = (d_version_after == d_version_before + 1); | ||
| 1299 | |||
| 1300 | if (d_really_is_positive(dentry)) { | 1360 | if (d_really_is_positive(dentry)) { |
| 1301 | struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); | 1361 | struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); |
| 1302 | 1362 | ||
| 1303 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { | 1363 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { |
| 1304 | /* Already done */ | 1364 | /* Already done */ |
| 1305 | } else if (dir_valid) { | 1365 | } else if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) { |
| 1366 | write_seqlock(&vnode->cb_lock); | ||
| 1306 | drop_nlink(&vnode->vfs_inode); | 1367 | drop_nlink(&vnode->vfs_inode); |
| 1307 | if (vnode->vfs_inode.i_nlink == 0) { | 1368 | if (vnode->vfs_inode.i_nlink == 0) { |
| 1308 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | 1369 | set_bit(AFS_VNODE_DELETED, &vnode->flags); |
| 1309 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | 1370 | __afs_break_callback(vnode); |
| 1310 | } | 1371 | } |
| 1372 | write_sequnlock(&vnode->cb_lock); | ||
| 1311 | ret = 0; | 1373 | ret = 0; |
| 1312 | } else { | 1374 | } else { |
| 1313 | clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | 1375 | afs_break_callback(vnode); |
| 1314 | 1376 | ||
| 1315 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) | 1377 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) |
| 1316 | kdebug("AFS_VNODE_DELETED"); | 1378 | kdebug("AFS_VNODE_DELETED"); |
| @@ -1331,11 +1393,10 @@ int afs_dir_remove_link(struct dentry *dentry, struct key *key, | |||
| 1331 | static int afs_unlink(struct inode *dir, struct dentry *dentry) | 1393 | static int afs_unlink(struct inode *dir, struct dentry *dentry) |
| 1332 | { | 1394 | { |
| 1333 | struct afs_fs_cursor fc; | 1395 | struct afs_fs_cursor fc; |
| 1396 | struct afs_status_cb *scb; | ||
| 1334 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL; | 1397 | struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL; |
| 1335 | struct key *key; | 1398 | struct key *key; |
| 1336 | unsigned long d_version = (unsigned long)dentry->d_fsdata; | ||
| 1337 | bool need_rehash = false; | 1399 | bool need_rehash = false; |
| 1338 | u64 data_version = dvnode->status.data_version; | ||
| 1339 | int ret; | 1400 | int ret; |
| 1340 | 1401 | ||
| 1341 | _enter("{%llx:%llu},{%pd}", | 1402 | _enter("{%llx:%llu},{%pd}", |
| @@ -1344,10 +1405,15 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1344 | if (dentry->d_name.len >= AFSNAMEMAX) | 1405 | if (dentry->d_name.len >= AFSNAMEMAX) |
| 1345 | return -ENAMETOOLONG; | 1406 | return -ENAMETOOLONG; |
| 1346 | 1407 | ||
| 1408 | ret = -ENOMEM; | ||
| 1409 | scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 1410 | if (!scb) | ||
| 1411 | goto error; | ||
| 1412 | |||
| 1347 | key = afs_request_key(dvnode->volume->cell); | 1413 | key = afs_request_key(dvnode->volume->cell); |
| 1348 | if (IS_ERR(key)) { | 1414 | if (IS_ERR(key)) { |
| 1349 | ret = PTR_ERR(key); | 1415 | ret = PTR_ERR(key); |
| 1350 | goto error; | 1416 | goto error_scb; |
| 1351 | } | 1417 | } |
| 1352 | 1418 | ||
| 1353 | /* Try to make sure we have a callback promise on the victim. */ | 1419 | /* Try to make sure we have a callback promise on the victim. */ |
| @@ -1375,29 +1441,33 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1375 | 1441 | ||
| 1376 | ret = -ERESTARTSYS; | 1442 | ret = -ERESTARTSYS; |
| 1377 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { | 1443 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { |
| 1444 | afs_dataversion_t data_version = dvnode->status.data_version + 1; | ||
| 1445 | afs_dataversion_t data_version_2 = vnode->status.data_version; | ||
| 1446 | |||
| 1378 | while (afs_select_fileserver(&fc)) { | 1447 | while (afs_select_fileserver(&fc)) { |
| 1379 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 1448 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1449 | fc.cb_break_2 = afs_calc_vnode_cb_break(vnode); | ||
| 1380 | 1450 | ||
| 1381 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) && | 1451 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) && |
| 1382 | !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) { | 1452 | !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) { |
| 1383 | yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name, | 1453 | yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name, |
| 1384 | data_version); | 1454 | &scb[0], &scb[1]); |
| 1385 | if (fc.ac.error != -ECONNABORTED || | 1455 | if (fc.ac.error != -ECONNABORTED || |
| 1386 | fc.ac.abort_code != RXGEN_OPCODE) | 1456 | fc.ac.abort_code != RXGEN_OPCODE) |
| 1387 | continue; | 1457 | continue; |
| 1388 | set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags); | 1458 | set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags); |
| 1389 | } | 1459 | } |
| 1390 | 1460 | ||
| 1391 | afs_fs_remove(&fc, vnode, dentry->d_name.name, false, | 1461 | afs_fs_remove(&fc, vnode, dentry->d_name.name, false, &scb[0]); |
| 1392 | data_version); | ||
| 1393 | } | 1462 | } |
| 1394 | 1463 | ||
| 1395 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); | 1464 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break, |
| 1465 | &data_version, &scb[0]); | ||
| 1466 | afs_vnode_commit_status(&fc, vnode, fc.cb_break_2, | ||
| 1467 | &data_version_2, &scb[1]); | ||
| 1396 | ret = afs_end_vnode_operation(&fc); | 1468 | ret = afs_end_vnode_operation(&fc); |
| 1397 | if (ret == 0) | 1469 | if (ret == 0 && !(scb[1].have_status || scb[1].have_error)) |
| 1398 | ret = afs_dir_remove_link( | 1470 | ret = afs_dir_remove_link(dvnode, dentry, key); |
| 1399 | dentry, key, d_version, | ||
| 1400 | (unsigned long)dvnode->status.data_version); | ||
| 1401 | if (ret == 0 && | 1471 | if (ret == 0 && |
| 1402 | test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) | 1472 | test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) |
| 1403 | afs_edit_dir_remove(dvnode, &dentry->d_name, | 1473 | afs_edit_dir_remove(dvnode, &dentry->d_name, |
| @@ -1409,6 +1479,8 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry) | |||
| 1409 | 1479 | ||
| 1410 | error_key: | 1480 | error_key: |
| 1411 | key_put(key); | 1481 | key_put(key); |
| 1482 | error_scb: | ||
| 1483 | kfree(scb); | ||
| 1412 | error: | 1484 | error: |
| 1413 | _leave(" = %d", ret); | 1485 | _leave(" = %d", ret); |
| 1414 | return ret; | 1486 | return ret; |
| @@ -1420,13 +1492,11 @@ error: | |||
| 1420 | static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | 1492 | static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, |
| 1421 | bool excl) | 1493 | bool excl) |
| 1422 | { | 1494 | { |
| 1495 | struct afs_iget_data iget_data; | ||
| 1423 | struct afs_fs_cursor fc; | 1496 | struct afs_fs_cursor fc; |
| 1424 | struct afs_file_status newstatus; | 1497 | struct afs_status_cb *scb; |
| 1425 | struct afs_callback newcb; | ||
| 1426 | struct afs_vnode *dvnode = AFS_FS_I(dir); | 1498 | struct afs_vnode *dvnode = AFS_FS_I(dir); |
| 1427 | struct afs_fid newfid; | ||
| 1428 | struct key *key; | 1499 | struct key *key; |
| 1429 | u64 data_version = dvnode->status.data_version; | ||
| 1430 | int ret; | 1500 | int ret; |
| 1431 | 1501 | ||
| 1432 | mode |= S_IFREG; | 1502 | mode |= S_IFREG; |
| @@ -1444,17 +1514,26 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
| 1444 | goto error; | 1514 | goto error; |
| 1445 | } | 1515 | } |
| 1446 | 1516 | ||
| 1517 | ret = -ENOMEM; | ||
| 1518 | scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 1519 | if (!scb) | ||
| 1520 | goto error_scb; | ||
| 1521 | |||
| 1447 | ret = -ERESTARTSYS; | 1522 | ret = -ERESTARTSYS; |
| 1448 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { | 1523 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { |
| 1524 | afs_dataversion_t data_version = dvnode->status.data_version + 1; | ||
| 1525 | |||
| 1449 | while (afs_select_fileserver(&fc)) { | 1526 | while (afs_select_fileserver(&fc)) { |
| 1450 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 1527 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1451 | afs_fs_create(&fc, dentry->d_name.name, mode, data_version, | 1528 | afs_prep_for_new_inode(&fc, &iget_data); |
| 1452 | &newfid, &newstatus, &newcb); | 1529 | afs_fs_create(&fc, dentry->d_name.name, mode, |
| 1530 | &scb[0], &iget_data.fid, &scb[1]); | ||
| 1453 | } | 1531 | } |
| 1454 | 1532 | ||
| 1455 | afs_check_for_remote_deletion(&fc, fc.vnode); | 1533 | afs_check_for_remote_deletion(&fc, dvnode); |
| 1456 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); | 1534 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break, |
| 1457 | afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, &newcb); | 1535 | &data_version, &scb[0]); |
| 1536 | afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]); | ||
| 1458 | ret = afs_end_vnode_operation(&fc); | 1537 | ret = afs_end_vnode_operation(&fc); |
| 1459 | if (ret < 0) | 1538 | if (ret < 0) |
| 1460 | goto error_key; | 1539 | goto error_key; |
| @@ -1463,13 +1542,16 @@ static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode, | |||
| 1463 | } | 1542 | } |
| 1464 | 1543 | ||
| 1465 | if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) | 1544 | if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) |
| 1466 | afs_edit_dir_add(dvnode, &dentry->d_name, &newfid, | 1545 | afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid, |
| 1467 | afs_edit_dir_for_create); | 1546 | afs_edit_dir_for_create); |
| 1468 | 1547 | ||
| 1548 | kfree(scb); | ||
| 1469 | key_put(key); | 1549 | key_put(key); |
| 1470 | _leave(" = 0"); | 1550 | _leave(" = 0"); |
| 1471 | return 0; | 1551 | return 0; |
| 1472 | 1552 | ||
| 1553 | error_scb: | ||
| 1554 | kfree(scb); | ||
| 1473 | error_key: | 1555 | error_key: |
| 1474 | key_put(key); | 1556 | key_put(key); |
| 1475 | error: | 1557 | error: |
| @@ -1485,15 +1567,12 @@ static int afs_link(struct dentry *from, struct inode *dir, | |||
| 1485 | struct dentry *dentry) | 1567 | struct dentry *dentry) |
| 1486 | { | 1568 | { |
| 1487 | struct afs_fs_cursor fc; | 1569 | struct afs_fs_cursor fc; |
| 1488 | struct afs_vnode *dvnode, *vnode; | 1570 | struct afs_status_cb *scb; |
| 1571 | struct afs_vnode *dvnode = AFS_FS_I(dir); | ||
| 1572 | struct afs_vnode *vnode = AFS_FS_I(d_inode(from)); | ||
| 1489 | struct key *key; | 1573 | struct key *key; |
| 1490 | u64 data_version; | ||
| 1491 | int ret; | 1574 | int ret; |
| 1492 | 1575 | ||
| 1493 | vnode = AFS_FS_I(d_inode(from)); | ||
| 1494 | dvnode = AFS_FS_I(dir); | ||
| 1495 | data_version = dvnode->status.data_version; | ||
| 1496 | |||
| 1497 | _enter("{%llx:%llu},{%llx:%llu},{%pd}", | 1576 | _enter("{%llx:%llu},{%llx:%llu},{%pd}", |
| 1498 | vnode->fid.vid, vnode->fid.vnode, | 1577 | vnode->fid.vid, vnode->fid.vnode, |
| 1499 | dvnode->fid.vid, dvnode->fid.vnode, | 1578 | dvnode->fid.vid, dvnode->fid.vnode, |
| @@ -1503,14 +1582,21 @@ static int afs_link(struct dentry *from, struct inode *dir, | |||
| 1503 | if (dentry->d_name.len >= AFSNAMEMAX) | 1582 | if (dentry->d_name.len >= AFSNAMEMAX) |
| 1504 | goto error; | 1583 | goto error; |
| 1505 | 1584 | ||
| 1585 | ret = -ENOMEM; | ||
| 1586 | scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 1587 | if (!scb) | ||
| 1588 | goto error; | ||
| 1589 | |||
| 1506 | key = afs_request_key(dvnode->volume->cell); | 1590 | key = afs_request_key(dvnode->volume->cell); |
| 1507 | if (IS_ERR(key)) { | 1591 | if (IS_ERR(key)) { |
| 1508 | ret = PTR_ERR(key); | 1592 | ret = PTR_ERR(key); |
| 1509 | goto error; | 1593 | goto error_scb; |
| 1510 | } | 1594 | } |
| 1511 | 1595 | ||
| 1512 | ret = -ERESTARTSYS; | 1596 | ret = -ERESTARTSYS; |
| 1513 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { | 1597 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { |
| 1598 | afs_dataversion_t data_version = dvnode->status.data_version + 1; | ||
| 1599 | |||
| 1514 | if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) { | 1600 | if (mutex_lock_interruptible_nested(&vnode->io_lock, 1) < 0) { |
| 1515 | afs_end_vnode_operation(&fc); | 1601 | afs_end_vnode_operation(&fc); |
| 1516 | goto error_key; | 1602 | goto error_key; |
| @@ -1519,11 +1605,14 @@ static int afs_link(struct dentry *from, struct inode *dir, | |||
| 1519 | while (afs_select_fileserver(&fc)) { | 1605 | while (afs_select_fileserver(&fc)) { |
| 1520 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 1606 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1521 | fc.cb_break_2 = afs_calc_vnode_cb_break(vnode); | 1607 | fc.cb_break_2 = afs_calc_vnode_cb_break(vnode); |
| 1522 | afs_fs_link(&fc, vnode, dentry->d_name.name, data_version); | 1608 | afs_fs_link(&fc, vnode, dentry->d_name.name, |
| 1609 | &scb[0], &scb[1]); | ||
| 1523 | } | 1610 | } |
| 1524 | 1611 | ||
| 1525 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); | 1612 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break, |
| 1526 | afs_vnode_commit_status(&fc, vnode, fc.cb_break_2); | 1613 | &data_version, &scb[0]); |
| 1614 | afs_vnode_commit_status(&fc, vnode, fc.cb_break_2, | ||
| 1615 | NULL, &scb[1]); | ||
| 1527 | ihold(&vnode->vfs_inode); | 1616 | ihold(&vnode->vfs_inode); |
| 1528 | d_instantiate(dentry, &vnode->vfs_inode); | 1617 | d_instantiate(dentry, &vnode->vfs_inode); |
| 1529 | 1618 | ||
| @@ -1540,11 +1629,14 @@ static int afs_link(struct dentry *from, struct inode *dir, | |||
| 1540 | afs_edit_dir_for_link); | 1629 | afs_edit_dir_for_link); |
| 1541 | 1630 | ||
| 1542 | key_put(key); | 1631 | key_put(key); |
| 1632 | kfree(scb); | ||
| 1543 | _leave(" = 0"); | 1633 | _leave(" = 0"); |
| 1544 | return 0; | 1634 | return 0; |
| 1545 | 1635 | ||
| 1546 | error_key: | 1636 | error_key: |
| 1547 | key_put(key); | 1637 | key_put(key); |
| 1638 | error_scb: | ||
| 1639 | kfree(scb); | ||
| 1548 | error: | 1640 | error: |
| 1549 | d_drop(dentry); | 1641 | d_drop(dentry); |
| 1550 | _leave(" = %d", ret); | 1642 | _leave(" = %d", ret); |
| @@ -1557,12 +1649,11 @@ error: | |||
| 1557 | static int afs_symlink(struct inode *dir, struct dentry *dentry, | 1649 | static int afs_symlink(struct inode *dir, struct dentry *dentry, |
| 1558 | const char *content) | 1650 | const char *content) |
| 1559 | { | 1651 | { |
| 1652 | struct afs_iget_data iget_data; | ||
| 1560 | struct afs_fs_cursor fc; | 1653 | struct afs_fs_cursor fc; |
| 1561 | struct afs_file_status newstatus; | 1654 | struct afs_status_cb *scb; |
| 1562 | struct afs_vnode *dvnode = AFS_FS_I(dir); | 1655 | struct afs_vnode *dvnode = AFS_FS_I(dir); |
| 1563 | struct afs_fid newfid; | ||
| 1564 | struct key *key; | 1656 | struct key *key; |
| 1565 | u64 data_version = dvnode->status.data_version; | ||
| 1566 | int ret; | 1657 | int ret; |
| 1567 | 1658 | ||
| 1568 | _enter("{%llx:%llu},{%pd},%s", | 1659 | _enter("{%llx:%llu},{%pd},%s", |
| @@ -1577,24 +1668,32 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 1577 | if (strlen(content) >= AFSPATHMAX) | 1668 | if (strlen(content) >= AFSPATHMAX) |
| 1578 | goto error; | 1669 | goto error; |
| 1579 | 1670 | ||
| 1671 | ret = -ENOMEM; | ||
| 1672 | scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 1673 | if (!scb) | ||
| 1674 | goto error; | ||
| 1675 | |||
| 1580 | key = afs_request_key(dvnode->volume->cell); | 1676 | key = afs_request_key(dvnode->volume->cell); |
| 1581 | if (IS_ERR(key)) { | 1677 | if (IS_ERR(key)) { |
| 1582 | ret = PTR_ERR(key); | 1678 | ret = PTR_ERR(key); |
| 1583 | goto error; | 1679 | goto error_scb; |
| 1584 | } | 1680 | } |
| 1585 | 1681 | ||
| 1586 | ret = -ERESTARTSYS; | 1682 | ret = -ERESTARTSYS; |
| 1587 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { | 1683 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { |
| 1684 | afs_dataversion_t data_version = dvnode->status.data_version + 1; | ||
| 1685 | |||
| 1588 | while (afs_select_fileserver(&fc)) { | 1686 | while (afs_select_fileserver(&fc)) { |
| 1589 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 1687 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 1590 | afs_fs_symlink(&fc, dentry->d_name.name, | 1688 | afs_prep_for_new_inode(&fc, &iget_data); |
| 1591 | content, data_version, | 1689 | afs_fs_symlink(&fc, dentry->d_name.name, content, |
| 1592 | &newfid, &newstatus); | 1690 | &scb[0], &iget_data.fid, &scb[1]); |
| 1593 | } | 1691 | } |
| 1594 | 1692 | ||
| 1595 | afs_check_for_remote_deletion(&fc, fc.vnode); | 1693 | afs_check_for_remote_deletion(&fc, dvnode); |
| 1596 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); | 1694 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break, |
| 1597 | afs_vnode_new_inode(&fc, dentry, &newfid, &newstatus, NULL); | 1695 | &data_version, &scb[0]); |
| 1696 | afs_vnode_new_inode(&fc, dentry, &iget_data, &scb[1]); | ||
| 1598 | ret = afs_end_vnode_operation(&fc); | 1697 | ret = afs_end_vnode_operation(&fc); |
| 1599 | if (ret < 0) | 1698 | if (ret < 0) |
| 1600 | goto error_key; | 1699 | goto error_key; |
| @@ -1603,15 +1702,18 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry, | |||
| 1603 | } | 1702 | } |
| 1604 | 1703 | ||
| 1605 | if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) | 1704 | if (test_bit(AFS_VNODE_DIR_VALID, &dvnode->flags)) |
| 1606 | afs_edit_dir_add(dvnode, &dentry->d_name, &newfid, | 1705 | afs_edit_dir_add(dvnode, &dentry->d_name, &iget_data.fid, |
| 1607 | afs_edit_dir_for_symlink); | 1706 | afs_edit_dir_for_symlink); |
| 1608 | 1707 | ||
| 1609 | key_put(key); | 1708 | key_put(key); |
| 1709 | kfree(scb); | ||
| 1610 | _leave(" = 0"); | 1710 | _leave(" = 0"); |
| 1611 | return 0; | 1711 | return 0; |
| 1612 | 1712 | ||
| 1613 | error_key: | 1713 | error_key: |
| 1614 | key_put(key); | 1714 | key_put(key); |
| 1715 | error_scb: | ||
| 1716 | kfree(scb); | ||
| 1615 | error: | 1717 | error: |
| 1616 | d_drop(dentry); | 1718 | d_drop(dentry); |
| 1617 | _leave(" = %d", ret); | 1719 | _leave(" = %d", ret); |
| @@ -1626,11 +1728,11 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 1626 | unsigned int flags) | 1728 | unsigned int flags) |
| 1627 | { | 1729 | { |
| 1628 | struct afs_fs_cursor fc; | 1730 | struct afs_fs_cursor fc; |
| 1731 | struct afs_status_cb *scb; | ||
| 1629 | struct afs_vnode *orig_dvnode, *new_dvnode, *vnode; | 1732 | struct afs_vnode *orig_dvnode, *new_dvnode, *vnode; |
| 1630 | struct dentry *tmp = NULL, *rehash = NULL; | 1733 | struct dentry *tmp = NULL, *rehash = NULL; |
| 1631 | struct inode *new_inode; | 1734 | struct inode *new_inode; |
| 1632 | struct key *key; | 1735 | struct key *key; |
| 1633 | u64 orig_data_version, new_data_version; | ||
| 1634 | bool new_negative = d_is_negative(new_dentry); | 1736 | bool new_negative = d_is_negative(new_dentry); |
| 1635 | int ret; | 1737 | int ret; |
| 1636 | 1738 | ||
| @@ -1644,8 +1746,6 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 1644 | vnode = AFS_FS_I(d_inode(old_dentry)); | 1746 | vnode = AFS_FS_I(d_inode(old_dentry)); |
| 1645 | orig_dvnode = AFS_FS_I(old_dir); | 1747 | orig_dvnode = AFS_FS_I(old_dir); |
| 1646 | new_dvnode = AFS_FS_I(new_dir); | 1748 | new_dvnode = AFS_FS_I(new_dir); |
| 1647 | orig_data_version = orig_dvnode->status.data_version; | ||
| 1648 | new_data_version = new_dvnode->status.data_version; | ||
| 1649 | 1749 | ||
| 1650 | _enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}", | 1750 | _enter("{%llx:%llu},{%llx:%llu},{%llx:%llu},{%pd}", |
| 1651 | orig_dvnode->fid.vid, orig_dvnode->fid.vnode, | 1751 | orig_dvnode->fid.vid, orig_dvnode->fid.vnode, |
| @@ -1653,10 +1753,15 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 1653 | new_dvnode->fid.vid, new_dvnode->fid.vnode, | 1753 | new_dvnode->fid.vid, new_dvnode->fid.vnode, |
| 1654 | new_dentry); | 1754 | new_dentry); |
| 1655 | 1755 | ||
| 1756 | ret = -ENOMEM; | ||
| 1757 | scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 1758 | if (!scb) | ||
| 1759 | goto error; | ||
| 1760 | |||
| 1656 | key = afs_request_key(orig_dvnode->volume->cell); | 1761 | key = afs_request_key(orig_dvnode->volume->cell); |
| 1657 | if (IS_ERR(key)) { | 1762 | if (IS_ERR(key)) { |
| 1658 | ret = PTR_ERR(key); | 1763 | ret = PTR_ERR(key); |
| 1659 | goto error; | 1764 | goto error_scb; |
| 1660 | } | 1765 | } |
| 1661 | 1766 | ||
| 1662 | /* For non-directories, check whether the target is busy and if so, | 1767 | /* For non-directories, check whether the target is busy and if so, |
| @@ -1690,31 +1795,43 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
| 1690 | new_dentry = tmp; | 1795 | new_dentry = tmp; |
| 1691 | rehash = NULL; | 1796 | rehash = NULL; |
| 1692 | new_negative = true; | 1797 | new_negative = true; |
| 1693 | orig_data_version = orig_dvnode->status.data_version; | ||
| 1694 | new_data_version = new_dvnode->status.data_version; | ||
| 1695 | } | 1798 | } |
| 1696 | } | 1799 | } |
| 1697 | 1800 | ||
| 1698 | ret = -ERESTARTSYS; | 1801 | ret = -ERESTARTSYS; |
| 1699 | if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) { | 1802 | if (afs_begin_vnode_operation(&fc, orig_dvnode, key, true)) { |
| 1803 | afs_dataversion_t orig_data_version; | ||
| 1804 | afs_dataversion_t new_data_version; | ||
| 1805 | struct afs_status_cb *new_scb = &scb[1]; | ||
| 1806 | |||
| 1807 | orig_data_version = orig_dvnode->status.data_version + 1; | ||
| 1808 | |||
| 1700 | if (orig_dvnode != new_dvnode) { | 1809 | if (orig_dvnode != new_dvnode) { |
| 1701 | if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) { | 1810 | if (mutex_lock_interruptible_nested(&new_dvnode->io_lock, 1) < 0) { |
| 1702 | afs_end_vnode_operation(&fc); | 1811 | afs_end_vnode_operation(&fc); |
| 1703 | goto error_rehash; | 1812 | goto error_rehash; |
| 1704 | } | 1813 | } |
| 1814 | new_data_version = new_dvnode->status.data_version; | ||
| 1815 | } else { | ||
| 1816 | new_data_version = orig_data_version; | ||
| 1817 | new_scb = &scb[0]; | ||
| 1705 | } | 1818 | } |
| 1819 | |||
| 1706 | while (afs_select_fileserver(&fc)) { | 1820 | while (afs_select_fileserver(&fc)) { |
| 1707 | fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode); | 1821 | fc.cb_break = afs_calc_vnode_cb_break(orig_dvnode); |
| 1708 | fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode); | 1822 | fc.cb_break_2 = afs_calc_vnode_cb_break(new_dvnode); |
| 1709 | afs_fs_rename(&fc, old_dentry->d_name.name, | 1823 | afs_fs_rename(&fc, old_dentry->d_name.name, |
| 1710 | new_dvnode, new_dentry->d_name.name, | 1824 | new_dvnode, new_dentry->d_name.name, |
| 1711 | orig_data_version, new_data_version); | 1825 | &scb[0], new_scb); |
| 1712 | } | 1826 | } |
| 1713 | 1827 | ||
| 1714 | afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break); | 1828 | afs_vnode_commit_status(&fc, orig_dvnode, fc.cb_break, |
| 1715 | afs_vnode_commit_status(&fc, new_dvnode, fc.cb_break_2); | 1829 | &orig_data_version, &scb[0]); |
| 1716 | if (orig_dvnode != new_dvnode) | 1830 | if (new_dvnode != orig_dvnode) { |
| 1831 | afs_vnode_commit_status(&fc, new_dvnode, fc.cb_break_2, | ||
| 1832 | &new_data_version, &scb[1]); | ||
| 1717 | mutex_unlock(&new_dvnode->io_lock); | 1833 | mutex_unlock(&new_dvnode->io_lock); |
| 1834 | } | ||
| 1718 | ret = afs_end_vnode_operation(&fc); | 1835 | ret = afs_end_vnode_operation(&fc); |
| 1719 | if (ret < 0) | 1836 | if (ret < 0) |
| 1720 | goto error_rehash; | 1837 | goto error_rehash; |
| @@ -1754,6 +1871,8 @@ error_tmp: | |||
| 1754 | if (tmp) | 1871 | if (tmp) |
| 1755 | dput(tmp); | 1872 | dput(tmp); |
| 1756 | key_put(key); | 1873 | key_put(key); |
| 1874 | error_scb: | ||
| 1875 | kfree(scb); | ||
| 1757 | error: | 1876 | error: |
| 1758 | _leave(" = %d", ret); | 1877 | _leave(" = %d", ret); |
| 1759 | return ret; | 1878 | return ret; |
diff --git a/fs/afs/dir_silly.c b/fs/afs/dir_silly.c index fbc2d301ffe8..28f4aa015229 100644 --- a/fs/afs/dir_silly.c +++ b/fs/afs/dir_silly.c | |||
| @@ -24,21 +24,28 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode | |||
| 24 | struct key *key) | 24 | struct key *key) |
| 25 | { | 25 | { |
| 26 | struct afs_fs_cursor fc; | 26 | struct afs_fs_cursor fc; |
| 27 | u64 dir_data_version = dvnode->status.data_version; | 27 | struct afs_status_cb *scb; |
| 28 | int ret = -ERESTARTSYS; | 28 | int ret = -ERESTARTSYS; |
| 29 | 29 | ||
| 30 | _enter("%pd,%pd", old, new); | 30 | _enter("%pd,%pd", old, new); |
| 31 | 31 | ||
| 32 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 33 | if (!scb) | ||
| 34 | return -ENOMEM; | ||
| 35 | |||
| 32 | trace_afs_silly_rename(vnode, false); | 36 | trace_afs_silly_rename(vnode, false); |
| 33 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { | 37 | if (afs_begin_vnode_operation(&fc, dvnode, key, true)) { |
| 38 | afs_dataversion_t dir_data_version = dvnode->status.data_version + 1; | ||
| 39 | |||
| 34 | while (afs_select_fileserver(&fc)) { | 40 | while (afs_select_fileserver(&fc)) { |
| 35 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 41 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 36 | afs_fs_rename(&fc, old->d_name.name, | 42 | afs_fs_rename(&fc, old->d_name.name, |
| 37 | dvnode, new->d_name.name, | 43 | dvnode, new->d_name.name, |
| 38 | dir_data_version, dir_data_version); | 44 | scb, scb); |
| 39 | } | 45 | } |
| 40 | 46 | ||
| 41 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); | 47 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break, |
| 48 | &dir_data_version, scb); | ||
| 42 | ret = afs_end_vnode_operation(&fc); | 49 | ret = afs_end_vnode_operation(&fc); |
| 43 | } | 50 | } |
| 44 | 51 | ||
| @@ -64,6 +71,7 @@ static int afs_do_silly_rename(struct afs_vnode *dvnode, struct afs_vnode *vnode | |||
| 64 | fsnotify_nameremove(old, 0); | 71 | fsnotify_nameremove(old, 0); |
| 65 | } | 72 | } |
| 66 | 73 | ||
| 74 | kfree(scb); | ||
| 67 | _leave(" = %d", ret); | 75 | _leave(" = %d", ret); |
| 68 | return ret; | 76 | return ret; |
| 69 | } | 77 | } |
| @@ -143,31 +151,37 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode | |||
| 143 | struct dentry *dentry, struct key *key) | 151 | struct dentry *dentry, struct key *key) |
| 144 | { | 152 | { |
| 145 | struct afs_fs_cursor fc; | 153 | struct afs_fs_cursor fc; |
| 146 | u64 dir_data_version = dvnode->status.data_version; | 154 | struct afs_status_cb *scb; |
| 147 | int ret = -ERESTARTSYS; | 155 | int ret = -ERESTARTSYS; |
| 148 | 156 | ||
| 149 | _enter(""); | 157 | _enter(""); |
| 150 | 158 | ||
| 159 | scb = kcalloc(2, sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 160 | if (!scb) | ||
| 161 | return -ENOMEM; | ||
| 162 | |||
| 151 | trace_afs_silly_rename(vnode, true); | 163 | trace_afs_silly_rename(vnode, true); |
| 152 | if (afs_begin_vnode_operation(&fc, dvnode, key, false)) { | 164 | if (afs_begin_vnode_operation(&fc, dvnode, key, false)) { |
| 165 | afs_dataversion_t dir_data_version = dvnode->status.data_version + 1; | ||
| 166 | |||
| 153 | while (afs_select_fileserver(&fc)) { | 167 | while (afs_select_fileserver(&fc)) { |
| 154 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); | 168 | fc.cb_break = afs_calc_vnode_cb_break(dvnode); |
| 155 | 169 | ||
| 156 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) && | 170 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) && |
| 157 | !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) { | 171 | !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) { |
| 158 | yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name, | 172 | yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name, |
| 159 | dir_data_version); | 173 | &scb[0], &scb[1]); |
| 160 | if (fc.ac.error != -ECONNABORTED || | 174 | if (fc.ac.error != -ECONNABORTED || |
| 161 | fc.ac.abort_code != RXGEN_OPCODE) | 175 | fc.ac.abort_code != RXGEN_OPCODE) |
| 162 | continue; | 176 | continue; |
| 163 | set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags); | 177 | set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags); |
| 164 | } | 178 | } |
| 165 | 179 | ||
| 166 | afs_fs_remove(&fc, vnode, dentry->d_name.name, false, | 180 | afs_fs_remove(&fc, vnode, dentry->d_name.name, false, &scb[0]); |
| 167 | dir_data_version); | ||
| 168 | } | 181 | } |
| 169 | 182 | ||
| 170 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break); | 183 | afs_vnode_commit_status(&fc, dvnode, fc.cb_break, |
| 184 | &dir_data_version, &scb[0]); | ||
| 171 | ret = afs_end_vnode_operation(&fc); | 185 | ret = afs_end_vnode_operation(&fc); |
| 172 | if (ret == 0) { | 186 | if (ret == 0) { |
| 173 | drop_nlink(&vnode->vfs_inode); | 187 | drop_nlink(&vnode->vfs_inode); |
| @@ -182,6 +196,7 @@ static int afs_do_silly_unlink(struct afs_vnode *dvnode, struct afs_vnode *vnode | |||
| 182 | afs_edit_dir_for_unlink); | 196 | afs_edit_dir_for_unlink); |
| 183 | } | 197 | } |
| 184 | 198 | ||
| 199 | kfree(scb); | ||
| 185 | _leave(" = %d", ret); | 200 | _leave(" = %d", ret); |
| 186 | return ret; | 201 | return ret; |
| 187 | } | 202 | } |
diff --git a/fs/afs/file.c b/fs/afs/file.c index f59c6149fa02..11e69c5fb7ab 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
| @@ -228,6 +228,7 @@ static void afs_file_readpage_read_complete(struct page *page, | |||
| 228 | int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *desc) | 228 | int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *desc) |
| 229 | { | 229 | { |
| 230 | struct afs_fs_cursor fc; | 230 | struct afs_fs_cursor fc; |
| 231 | struct afs_status_cb *scb; | ||
| 231 | int ret; | 232 | int ret; |
| 232 | 233 | ||
| 233 | _enter("%s{%llx:%llu.%u},%x,,,", | 234 | _enter("%s{%llx:%llu.%u},%x,,,", |
| @@ -237,15 +238,22 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de | |||
| 237 | vnode->fid.unique, | 238 | vnode->fid.unique, |
| 238 | key_serial(key)); | 239 | key_serial(key)); |
| 239 | 240 | ||
| 241 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 242 | if (!scb) | ||
| 243 | return -ENOMEM; | ||
| 244 | |||
| 240 | ret = -ERESTARTSYS; | 245 | ret = -ERESTARTSYS; |
| 241 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { | 246 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { |
| 247 | afs_dataversion_t data_version = vnode->status.data_version; | ||
| 248 | |||
| 242 | while (afs_select_fileserver(&fc)) { | 249 | while (afs_select_fileserver(&fc)) { |
| 243 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 250 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 244 | afs_fs_fetch_data(&fc, desc); | 251 | afs_fs_fetch_data(&fc, scb, desc); |
| 245 | } | 252 | } |
| 246 | 253 | ||
| 247 | afs_check_for_remote_deletion(&fc, fc.vnode); | 254 | afs_check_for_remote_deletion(&fc, vnode); |
| 248 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 255 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, |
| 256 | &data_version, scb); | ||
| 249 | ret = afs_end_vnode_operation(&fc); | 257 | ret = afs_end_vnode_operation(&fc); |
| 250 | } | 258 | } |
| 251 | 259 | ||
| @@ -255,6 +263,7 @@ int afs_fetch_data(struct afs_vnode *vnode, struct key *key, struct afs_read *de | |||
| 255 | &afs_v2net(vnode)->n_fetch_bytes); | 263 | &afs_v2net(vnode)->n_fetch_bytes); |
| 256 | } | 264 | } |
| 257 | 265 | ||
| 266 | kfree(scb); | ||
| 258 | _leave(" = %d", ret); | 267 | _leave(" = %d", ret); |
| 259 | return ret; | 268 | return ret; |
| 260 | } | 269 | } |
| @@ -405,10 +414,10 @@ static int afs_readpage(struct file *file, struct page *page) | |||
| 405 | /* | 414 | /* |
| 406 | * Make pages available as they're filled. | 415 | * Make pages available as they're filled. |
| 407 | */ | 416 | */ |
| 408 | static void afs_readpages_page_done(struct afs_call *call, struct afs_read *req) | 417 | static void afs_readpages_page_done(struct afs_read *req) |
| 409 | { | 418 | { |
| 410 | #ifdef CONFIG_AFS_FSCACHE | 419 | #ifdef CONFIG_AFS_FSCACHE |
| 411 | struct afs_vnode *vnode = call->reply[0]; | 420 | struct afs_vnode *vnode = req->vnode; |
| 412 | #endif | 421 | #endif |
| 413 | struct page *page = req->pages[req->index]; | 422 | struct page *page = req->pages[req->index]; |
| 414 | 423 | ||
| @@ -462,6 +471,7 @@ static int afs_readpages_one(struct file *file, struct address_space *mapping, | |||
| 462 | return -ENOMEM; | 471 | return -ENOMEM; |
| 463 | 472 | ||
| 464 | refcount_set(&req->usage, 1); | 473 | refcount_set(&req->usage, 1); |
| 474 | req->vnode = vnode; | ||
| 465 | req->page_done = afs_readpages_page_done; | 475 | req->page_done = afs_readpages_page_done; |
| 466 | req->pos = first->index; | 476 | req->pos = first->index; |
| 467 | req->pos <<= PAGE_SHIFT; | 477 | req->pos <<= PAGE_SHIFT; |
diff --git a/fs/afs/flock.c b/fs/afs/flock.c index c91cd201013f..ed3ac03682d7 100644 --- a/fs/afs/flock.c +++ b/fs/afs/flock.c | |||
| @@ -74,7 +74,7 @@ static void afs_schedule_lock_extension(struct afs_vnode *vnode) | |||
| 74 | */ | 74 | */ |
| 75 | void afs_lock_op_done(struct afs_call *call) | 75 | void afs_lock_op_done(struct afs_call *call) |
| 76 | { | 76 | { |
| 77 | struct afs_vnode *vnode = call->reply[0]; | 77 | struct afs_vnode *vnode = call->lvnode; |
| 78 | 78 | ||
| 79 | if (call->error == 0) { | 79 | if (call->error == 0) { |
| 80 | spin_lock(&vnode->lock); | 80 | spin_lock(&vnode->lock); |
| @@ -182,6 +182,7 @@ static void afs_kill_lockers_enoent(struct afs_vnode *vnode) | |||
| 182 | static int afs_set_lock(struct afs_vnode *vnode, struct key *key, | 182 | static int afs_set_lock(struct afs_vnode *vnode, struct key *key, |
| 183 | afs_lock_type_t type) | 183 | afs_lock_type_t type) |
| 184 | { | 184 | { |
| 185 | struct afs_status_cb *scb; | ||
| 185 | struct afs_fs_cursor fc; | 186 | struct afs_fs_cursor fc; |
| 186 | int ret; | 187 | int ret; |
| 187 | 188 | ||
| @@ -192,18 +193,23 @@ static int afs_set_lock(struct afs_vnode *vnode, struct key *key, | |||
| 192 | vnode->fid.unique, | 193 | vnode->fid.unique, |
| 193 | key_serial(key), type); | 194 | key_serial(key), type); |
| 194 | 195 | ||
| 196 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 197 | if (!scb) | ||
| 198 | return -ENOMEM; | ||
| 199 | |||
| 195 | ret = -ERESTARTSYS; | 200 | ret = -ERESTARTSYS; |
| 196 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { | 201 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { |
| 197 | while (afs_select_fileserver(&fc)) { | 202 | while (afs_select_fileserver(&fc)) { |
| 198 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 203 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 199 | afs_fs_set_lock(&fc, type); | 204 | afs_fs_set_lock(&fc, type, scb); |
| 200 | } | 205 | } |
| 201 | 206 | ||
| 202 | afs_check_for_remote_deletion(&fc, fc.vnode); | 207 | afs_check_for_remote_deletion(&fc, vnode); |
| 203 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 208 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, NULL, scb); |
| 204 | ret = afs_end_vnode_operation(&fc); | 209 | ret = afs_end_vnode_operation(&fc); |
| 205 | } | 210 | } |
| 206 | 211 | ||
| 212 | kfree(scb); | ||
| 207 | _leave(" = %d", ret); | 213 | _leave(" = %d", ret); |
| 208 | return ret; | 214 | return ret; |
| 209 | } | 215 | } |
| @@ -213,6 +219,7 @@ static int afs_set_lock(struct afs_vnode *vnode, struct key *key, | |||
| 213 | */ | 219 | */ |
| 214 | static int afs_extend_lock(struct afs_vnode *vnode, struct key *key) | 220 | static int afs_extend_lock(struct afs_vnode *vnode, struct key *key) |
| 215 | { | 221 | { |
| 222 | struct afs_status_cb *scb; | ||
| 216 | struct afs_fs_cursor fc; | 223 | struct afs_fs_cursor fc; |
| 217 | int ret; | 224 | int ret; |
| 218 | 225 | ||
| @@ -223,18 +230,23 @@ static int afs_extend_lock(struct afs_vnode *vnode, struct key *key) | |||
| 223 | vnode->fid.unique, | 230 | vnode->fid.unique, |
| 224 | key_serial(key)); | 231 | key_serial(key)); |
| 225 | 232 | ||
| 233 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 234 | if (!scb) | ||
| 235 | return -ENOMEM; | ||
| 236 | |||
| 226 | ret = -ERESTARTSYS; | 237 | ret = -ERESTARTSYS; |
| 227 | if (afs_begin_vnode_operation(&fc, vnode, key, false)) { | 238 | if (afs_begin_vnode_operation(&fc, vnode, key, false)) { |
| 228 | while (afs_select_current_fileserver(&fc)) { | 239 | while (afs_select_current_fileserver(&fc)) { |
| 229 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 240 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 230 | afs_fs_extend_lock(&fc); | 241 | afs_fs_extend_lock(&fc, scb); |
| 231 | } | 242 | } |
| 232 | 243 | ||
| 233 | afs_check_for_remote_deletion(&fc, fc.vnode); | 244 | afs_check_for_remote_deletion(&fc, vnode); |
| 234 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 245 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, NULL, scb); |
| 235 | ret = afs_end_vnode_operation(&fc); | 246 | ret = afs_end_vnode_operation(&fc); |
| 236 | } | 247 | } |
| 237 | 248 | ||
| 249 | kfree(scb); | ||
| 238 | _leave(" = %d", ret); | 250 | _leave(" = %d", ret); |
| 239 | return ret; | 251 | return ret; |
| 240 | } | 252 | } |
| @@ -244,6 +256,7 @@ static int afs_extend_lock(struct afs_vnode *vnode, struct key *key) | |||
| 244 | */ | 256 | */ |
| 245 | static int afs_release_lock(struct afs_vnode *vnode, struct key *key) | 257 | static int afs_release_lock(struct afs_vnode *vnode, struct key *key) |
| 246 | { | 258 | { |
| 259 | struct afs_status_cb *scb; | ||
| 247 | struct afs_fs_cursor fc; | 260 | struct afs_fs_cursor fc; |
| 248 | int ret; | 261 | int ret; |
| 249 | 262 | ||
| @@ -254,18 +267,23 @@ static int afs_release_lock(struct afs_vnode *vnode, struct key *key) | |||
| 254 | vnode->fid.unique, | 267 | vnode->fid.unique, |
| 255 | key_serial(key)); | 268 | key_serial(key)); |
| 256 | 269 | ||
| 270 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 271 | if (!scb) | ||
| 272 | return -ENOMEM; | ||
| 273 | |||
| 257 | ret = -ERESTARTSYS; | 274 | ret = -ERESTARTSYS; |
| 258 | if (afs_begin_vnode_operation(&fc, vnode, key, false)) { | 275 | if (afs_begin_vnode_operation(&fc, vnode, key, false)) { |
| 259 | while (afs_select_current_fileserver(&fc)) { | 276 | while (afs_select_current_fileserver(&fc)) { |
| 260 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 277 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 261 | afs_fs_release_lock(&fc); | 278 | afs_fs_release_lock(&fc, scb); |
| 262 | } | 279 | } |
| 263 | 280 | ||
| 264 | afs_check_for_remote_deletion(&fc, fc.vnode); | 281 | afs_check_for_remote_deletion(&fc, vnode); |
| 265 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 282 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, NULL, scb); |
| 266 | ret = afs_end_vnode_operation(&fc); | 283 | ret = afs_end_vnode_operation(&fc); |
| 267 | } | 284 | } |
| 268 | 285 | ||
| 286 | kfree(scb); | ||
| 269 | _leave(" = %d", ret); | 287 | _leave(" = %d", ret); |
| 270 | return ret; | 288 | return ret; |
| 271 | } | 289 | } |
| @@ -733,7 +751,7 @@ static int afs_do_getlk(struct file *file, struct file_lock *fl) | |||
| 733 | posix_test_lock(file, fl); | 751 | posix_test_lock(file, fl); |
| 734 | if (fl->fl_type == F_UNLCK) { | 752 | if (fl->fl_type == F_UNLCK) { |
| 735 | /* no local locks; consult the server */ | 753 | /* no local locks; consult the server */ |
| 736 | ret = afs_fetch_status(vnode, key, false); | 754 | ret = afs_fetch_status(vnode, key, false, NULL); |
| 737 | if (ret < 0) | 755 | if (ret < 0) |
| 738 | goto error; | 756 | goto error; |
| 739 | 757 | ||
diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c index 5d3abde52a0f..9b7266209343 100644 --- a/fs/afs/fs_probe.c +++ b/fs/afs/fs_probe.c | |||
| @@ -33,8 +33,8 @@ static bool afs_fs_probe_done(struct afs_server *server) | |||
| 33 | void afs_fileserver_probe_result(struct afs_call *call) | 33 | void afs_fileserver_probe_result(struct afs_call *call) |
| 34 | { | 34 | { |
| 35 | struct afs_addr_list *alist = call->alist; | 35 | struct afs_addr_list *alist = call->alist; |
| 36 | struct afs_server *server = call->reply[0]; | 36 | struct afs_server *server = call->server; |
| 37 | unsigned int server_index = (long)call->reply[1]; | 37 | unsigned int server_index = call->server_index; |
| 38 | unsigned int index = call->addr_ix; | 38 | unsigned int index = call->addr_ix; |
| 39 | unsigned int rtt = UINT_MAX; | 39 | unsigned int rtt = UINT_MAX; |
| 40 | bool have_result = false; | 40 | bool have_result = false; |
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 388750d80cab..48298408d6ac 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
| @@ -60,78 +60,17 @@ static void xdr_dump_bad(const __be32 *bp) | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | /* | 62 | /* |
| 63 | * Update the core inode struct from a returned status record. | ||
| 64 | */ | ||
| 65 | void afs_update_inode_from_status(struct afs_vnode *vnode, | ||
| 66 | struct afs_file_status *status, | ||
| 67 | const afs_dataversion_t *expected_version, | ||
| 68 | u8 flags) | ||
| 69 | { | ||
| 70 | struct timespec64 t; | ||
| 71 | umode_t mode; | ||
| 72 | |||
| 73 | t = status->mtime_client; | ||
| 74 | vnode->vfs_inode.i_ctime = t; | ||
| 75 | vnode->vfs_inode.i_mtime = t; | ||
| 76 | vnode->vfs_inode.i_atime = t; | ||
| 77 | |||
| 78 | if (flags & (AFS_VNODE_META_CHANGED | AFS_VNODE_NOT_YET_SET)) { | ||
| 79 | vnode->vfs_inode.i_uid = make_kuid(&init_user_ns, status->owner); | ||
| 80 | vnode->vfs_inode.i_gid = make_kgid(&init_user_ns, status->group); | ||
| 81 | set_nlink(&vnode->vfs_inode, status->nlink); | ||
| 82 | |||
| 83 | mode = vnode->vfs_inode.i_mode; | ||
| 84 | mode &= ~S_IALLUGO; | ||
| 85 | mode |= status->mode; | ||
| 86 | barrier(); | ||
| 87 | vnode->vfs_inode.i_mode = mode; | ||
| 88 | } | ||
| 89 | |||
| 90 | if (!(flags & AFS_VNODE_NOT_YET_SET)) { | ||
| 91 | if (expected_version && | ||
| 92 | *expected_version != status->data_version) { | ||
| 93 | _debug("vnode modified %llx on {%llx:%llu} [exp %llx]", | ||
| 94 | (unsigned long long) status->data_version, | ||
| 95 | vnode->fid.vid, vnode->fid.vnode, | ||
| 96 | (unsigned long long) *expected_version); | ||
| 97 | vnode->invalid_before = status->data_version; | ||
| 98 | if (vnode->status.type == AFS_FTYPE_DIR) { | ||
| 99 | if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags)) | ||
| 100 | afs_stat_v(vnode, n_inval); | ||
| 101 | } else { | ||
| 102 | set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags); | ||
| 103 | } | ||
| 104 | } else if (vnode->status.type == AFS_FTYPE_DIR) { | ||
| 105 | /* Expected directory change is handled elsewhere so | ||
| 106 | * that we can locally edit the directory and save on a | ||
| 107 | * download. | ||
| 108 | */ | ||
| 109 | if (test_bit(AFS_VNODE_DIR_VALID, &vnode->flags)) | ||
| 110 | flags &= ~AFS_VNODE_DATA_CHANGED; | ||
| 111 | } | ||
| 112 | } | ||
| 113 | |||
| 114 | if (flags & (AFS_VNODE_DATA_CHANGED | AFS_VNODE_NOT_YET_SET)) { | ||
| 115 | inode_set_iversion_raw(&vnode->vfs_inode, status->data_version); | ||
| 116 | i_size_write(&vnode->vfs_inode, status->size); | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | /* | ||
| 121 | * decode an AFSFetchStatus block | 63 | * decode an AFSFetchStatus block |
| 122 | */ | 64 | */ |
| 123 | static int xdr_decode_AFSFetchStatus(struct afs_call *call, | 65 | static int xdr_decode_AFSFetchStatus(const __be32 **_bp, |
| 124 | const __be32 **_bp, | 66 | struct afs_call *call, |
| 125 | struct afs_file_status *status, | 67 | struct afs_status_cb *scb) |
| 126 | struct afs_vnode *vnode, | ||
| 127 | const afs_dataversion_t *expected_version, | ||
| 128 | struct afs_read *read_req) | ||
| 129 | { | 68 | { |
| 130 | const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp; | 69 | const struct afs_xdr_AFSFetchStatus *xdr = (const void *)*_bp; |
| 70 | struct afs_file_status *status = &scb->status; | ||
| 131 | bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus); | 71 | bool inline_error = (call->operation_ID == afs_FS_InlineBulkStatus); |
| 132 | u64 data_version, size; | 72 | u64 data_version, size; |
| 133 | u32 type, abort_code; | 73 | u32 type, abort_code; |
| 134 | u8 flags = 0; | ||
| 135 | 74 | ||
| 136 | abort_code = ntohl(xdr->abort_code); | 75 | abort_code = ntohl(xdr->abort_code); |
| 137 | 76 | ||
| @@ -144,6 +83,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
| 144 | * case. | 83 | * case. |
| 145 | */ | 84 | */ |
| 146 | status->abort_code = abort_code; | 85 | status->abort_code = abort_code; |
| 86 | scb->have_error = true; | ||
| 147 | return 0; | 87 | return 0; |
| 148 | } | 88 | } |
| 149 | 89 | ||
| @@ -161,44 +101,25 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
| 161 | case AFS_FTYPE_FILE: | 101 | case AFS_FTYPE_FILE: |
| 162 | case AFS_FTYPE_DIR: | 102 | case AFS_FTYPE_DIR: |
| 163 | case AFS_FTYPE_SYMLINK: | 103 | case AFS_FTYPE_SYMLINK: |
| 164 | if (type != status->type && | ||
| 165 | vnode && | ||
| 166 | !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { | ||
| 167 | pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n", | ||
| 168 | vnode->fid.vid, | ||
| 169 | vnode->fid.vnode, | ||
| 170 | vnode->fid.unique, | ||
| 171 | status->type, type); | ||
| 172 | goto bad; | ||
| 173 | } | ||
| 174 | status->type = type; | 104 | status->type = type; |
| 175 | break; | 105 | break; |
| 176 | default: | 106 | default: |
| 177 | goto bad; | 107 | goto bad; |
| 178 | } | 108 | } |
| 179 | 109 | ||
| 180 | #define EXTRACT_M(FIELD) \ | 110 | status->nlink = ntohl(xdr->nlink); |
| 181 | do { \ | 111 | status->author = ntohl(xdr->author); |
| 182 | u32 x = ntohl(xdr->FIELD); \ | 112 | status->owner = ntohl(xdr->owner); |
| 183 | if (status->FIELD != x) { \ | 113 | status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */ |
| 184 | flags |= AFS_VNODE_META_CHANGED; \ | 114 | status->anon_access = ntohl(xdr->anon_access); |
| 185 | status->FIELD = x; \ | 115 | status->mode = ntohl(xdr->mode) & S_IALLUGO; |
| 186 | } \ | 116 | status->group = ntohl(xdr->group); |
| 187 | } while (0) | 117 | status->lock_count = ntohl(xdr->lock_count); |
| 188 | |||
| 189 | EXTRACT_M(nlink); | ||
| 190 | EXTRACT_M(author); | ||
| 191 | EXTRACT_M(owner); | ||
| 192 | EXTRACT_M(caller_access); /* call ticket dependent */ | ||
| 193 | EXTRACT_M(anon_access); | ||
| 194 | EXTRACT_M(mode); | ||
| 195 | EXTRACT_M(group); | ||
| 196 | 118 | ||
| 197 | status->mtime_client.tv_sec = ntohl(xdr->mtime_client); | 119 | status->mtime_client.tv_sec = ntohl(xdr->mtime_client); |
| 198 | status->mtime_client.tv_nsec = 0; | 120 | status->mtime_client.tv_nsec = 0; |
| 199 | status->mtime_server.tv_sec = ntohl(xdr->mtime_server); | 121 | status->mtime_server.tv_sec = ntohl(xdr->mtime_server); |
| 200 | status->mtime_server.tv_nsec = 0; | 122 | status->mtime_server.tv_nsec = 0; |
| 201 | status->lock_count = ntohl(xdr->lock_count); | ||
| 202 | 123 | ||
| 203 | size = (u64)ntohl(xdr->size_lo); | 124 | size = (u64)ntohl(xdr->size_lo); |
| 204 | size |= (u64)ntohl(xdr->size_hi) << 32; | 125 | size |= (u64)ntohl(xdr->size_hi) << 32; |
| @@ -206,25 +127,10 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
| 206 | 127 | ||
| 207 | data_version = (u64)ntohl(xdr->data_version_lo); | 128 | data_version = (u64)ntohl(xdr->data_version_lo); |
| 208 | data_version |= (u64)ntohl(xdr->data_version_hi) << 32; | 129 | data_version |= (u64)ntohl(xdr->data_version_hi) << 32; |
| 209 | if (data_version != status->data_version) { | 130 | status->data_version = data_version; |
| 210 | status->data_version = data_version; | 131 | scb->have_status = true; |
| 211 | flags |= AFS_VNODE_DATA_CHANGED; | ||
| 212 | } | ||
| 213 | |||
| 214 | if (read_req) { | ||
| 215 | read_req->data_version = data_version; | ||
| 216 | read_req->file_size = size; | ||
| 217 | } | ||
| 218 | 132 | ||
| 219 | *_bp = (const void *)*_bp + sizeof(*xdr); | 133 | *_bp = (const void *)*_bp + sizeof(*xdr); |
| 220 | |||
| 221 | if (vnode) { | ||
| 222 | if (test_bit(AFS_VNODE_UNSET, &vnode->flags)) | ||
| 223 | flags |= AFS_VNODE_NOT_YET_SET; | ||
| 224 | afs_update_inode_from_status(vnode, status, expected_version, | ||
| 225 | flags); | ||
| 226 | } | ||
| 227 | |||
| 228 | return 0; | 134 | return 0; |
| 229 | 135 | ||
| 230 | bad: | 136 | bad: |
| @@ -232,78 +138,26 @@ bad: | |||
| 232 | return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); | 138 | return afs_protocol_error(call, -EBADMSG, afs_eproto_bad_status); |
| 233 | } | 139 | } |
| 234 | 140 | ||
| 235 | /* | ||
| 236 | * Decode the file status. We need to lock the target vnode if we're going to | ||
| 237 | * update its status so that stat() sees the attributes update atomically. | ||
| 238 | */ | ||
| 239 | static int afs_decode_status(struct afs_call *call, | ||
| 240 | const __be32 **_bp, | ||
| 241 | struct afs_file_status *status, | ||
| 242 | struct afs_vnode *vnode, | ||
| 243 | const afs_dataversion_t *expected_version, | ||
| 244 | struct afs_read *read_req) | ||
| 245 | { | ||
| 246 | int ret; | ||
| 247 | |||
| 248 | if (!vnode) | ||
| 249 | return xdr_decode_AFSFetchStatus(call, _bp, status, vnode, | ||
| 250 | expected_version, read_req); | ||
| 251 | |||
| 252 | write_seqlock(&vnode->cb_lock); | ||
| 253 | ret = xdr_decode_AFSFetchStatus(call, _bp, status, vnode, | ||
| 254 | expected_version, read_req); | ||
| 255 | write_sequnlock(&vnode->cb_lock); | ||
| 256 | return ret; | ||
| 257 | } | ||
| 258 | |||
| 259 | static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry) | 141 | static time64_t xdr_decode_expiry(struct afs_call *call, u32 expiry) |
| 260 | { | 142 | { |
| 261 | return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry; | 143 | return ktime_divns(call->reply_time, NSEC_PER_SEC) + expiry; |
| 262 | } | 144 | } |
| 263 | 145 | ||
| 264 | static void xdr_decode_AFSCallBack_raw(struct afs_call *call, | 146 | static void xdr_decode_AFSCallBack(const __be32 **_bp, |
| 265 | struct afs_callback *cb, | 147 | struct afs_call *call, |
| 266 | const __be32 **_bp) | 148 | struct afs_status_cb *scb) |
| 267 | { | 149 | { |
| 150 | struct afs_callback *cb = &scb->callback; | ||
| 268 | const __be32 *bp = *_bp; | 151 | const __be32 *bp = *_bp; |
| 269 | 152 | ||
| 270 | cb->version = ntohl(*bp++); | 153 | bp++; /* version */ |
| 271 | cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++)); | 154 | cb->expires_at = xdr_decode_expiry(call, ntohl(*bp++)); |
| 272 | cb->type = ntohl(*bp++); | 155 | bp++; /* type */ |
| 156 | scb->have_cb = true; | ||
| 273 | *_bp = bp; | 157 | *_bp = bp; |
| 274 | } | 158 | } |
| 275 | 159 | ||
| 276 | /* | 160 | /* |
| 277 | * decode an AFSCallBack block | ||
| 278 | */ | ||
| 279 | static void xdr_decode_AFSCallBack(struct afs_call *call, | ||
| 280 | struct afs_vnode *vnode, | ||
| 281 | const __be32 **_bp) | ||
| 282 | { | ||
| 283 | struct afs_cb_interest *old, *cbi = call->cbi; | ||
| 284 | struct afs_callback cb; | ||
| 285 | |||
| 286 | xdr_decode_AFSCallBack_raw(call, &cb, _bp); | ||
| 287 | |||
| 288 | write_seqlock(&vnode->cb_lock); | ||
| 289 | |||
| 290 | if (!afs_cb_is_broken(call->cb_break, vnode, cbi)) { | ||
| 291 | vnode->cb_version = cb.version; | ||
| 292 | vnode->cb_type = cb.type; | ||
| 293 | vnode->cb_expires_at = cb.expires_at; | ||
| 294 | old = vnode->cb_interest; | ||
| 295 | if (old != call->cbi) { | ||
| 296 | vnode->cb_interest = cbi; | ||
| 297 | cbi = old; | ||
| 298 | } | ||
| 299 | set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | ||
| 300 | } | ||
| 301 | |||
| 302 | write_sequnlock(&vnode->cb_lock); | ||
| 303 | call->cbi = cbi; | ||
| 304 | } | ||
| 305 | |||
| 306 | /* | ||
| 307 | * decode an AFSVolSync block | 161 | * decode an AFSVolSync block |
| 308 | */ | 162 | */ |
| 309 | static void xdr_decode_AFSVolSync(const __be32 **_bp, | 163 | static void xdr_decode_AFSVolSync(const __be32 **_bp, |
| @@ -392,7 +246,6 @@ static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp, | |||
| 392 | */ | 246 | */ |
| 393 | static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) | 247 | static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) |
| 394 | { | 248 | { |
| 395 | struct afs_vnode *vnode = call->reply[0]; | ||
| 396 | const __be32 *bp; | 249 | const __be32 *bp; |
| 397 | int ret; | 250 | int ret; |
| 398 | 251 | ||
| @@ -400,16 +253,13 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) | |||
| 400 | if (ret < 0) | 253 | if (ret < 0) |
| 401 | return ret; | 254 | return ret; |
| 402 | 255 | ||
| 403 | _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); | ||
| 404 | |||
| 405 | /* unmarshall the reply once we've received all of it */ | 256 | /* unmarshall the reply once we've received all of it */ |
| 406 | bp = call->buffer; | 257 | bp = call->buffer; |
| 407 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, | 258 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 408 | &call->expected_version, NULL); | ||
| 409 | if (ret < 0) | 259 | if (ret < 0) |
| 410 | return ret; | 260 | return ret; |
| 411 | xdr_decode_AFSCallBack(call, vnode, &bp); | 261 | xdr_decode_AFSCallBack(&bp, call, call->out_scb); |
| 412 | xdr_decode_AFSVolSync(&bp, call->reply[1]); | 262 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 413 | 263 | ||
| 414 | _leave(" = 0 [done]"); | 264 | _leave(" = 0 [done]"); |
| 415 | return 0; | 265 | return 0; |
| @@ -428,8 +278,8 @@ static const struct afs_call_type afs_RXFSFetchStatus_vnode = { | |||
| 428 | /* | 278 | /* |
| 429 | * fetch the status information for a file | 279 | * fetch the status information for a file |
| 430 | */ | 280 | */ |
| 431 | int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync, | 281 | int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb, |
| 432 | bool new_inode) | 282 | struct afs_volsync *volsync) |
| 433 | { | 283 | { |
| 434 | struct afs_vnode *vnode = fc->vnode; | 284 | struct afs_vnode *vnode = fc->vnode; |
| 435 | struct afs_call *call; | 285 | struct afs_call *call; |
| @@ -437,7 +287,7 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
| 437 | __be32 *bp; | 287 | __be32 *bp; |
| 438 | 288 | ||
| 439 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 289 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 440 | return yfs_fs_fetch_file_status(fc, volsync, new_inode); | 290 | return yfs_fs_fetch_file_status(fc, scb, volsync); |
| 441 | 291 | ||
| 442 | _enter(",%x,{%llx:%llu},,", | 292 | _enter(",%x,{%llx:%llu},,", |
| 443 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 293 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
| @@ -450,10 +300,8 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
| 450 | } | 300 | } |
| 451 | 301 | ||
| 452 | call->key = fc->key; | 302 | call->key = fc->key; |
| 453 | call->reply[0] = vnode; | 303 | call->out_scb = scb; |
| 454 | call->reply[1] = volsync; | 304 | call->out_volsync = volsync; |
| 455 | call->expected_version = new_inode ? 1 : vnode->status.data_version; | ||
| 456 | call->want_reply_time = true; | ||
| 457 | 305 | ||
| 458 | /* marshall the parameters */ | 306 | /* marshall the parameters */ |
| 459 | bp = call->request; | 307 | bp = call->request; |
| @@ -462,7 +310,6 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
| 462 | bp[2] = htonl(vnode->fid.vnode); | 310 | bp[2] = htonl(vnode->fid.vnode); |
| 463 | bp[3] = htonl(vnode->fid.unique); | 311 | bp[3] = htonl(vnode->fid.unique); |
| 464 | 312 | ||
| 465 | call->cb_break = fc->cb_break; | ||
| 466 | afs_use_fs_server(call, fc->cbi); | 313 | afs_use_fs_server(call, fc->cbi); |
| 467 | trace_afs_make_fs_call(call, &vnode->fid); | 314 | trace_afs_make_fs_call(call, &vnode->fid); |
| 468 | 315 | ||
| @@ -476,8 +323,7 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
| 476 | */ | 323 | */ |
| 477 | static int afs_deliver_fs_fetch_data(struct afs_call *call) | 324 | static int afs_deliver_fs_fetch_data(struct afs_call *call) |
| 478 | { | 325 | { |
| 479 | struct afs_vnode *vnode = call->reply[0]; | 326 | struct afs_read *req = call->read_request; |
| 480 | struct afs_read *req = call->reply[2]; | ||
| 481 | const __be32 *bp; | 327 | const __be32 *bp; |
| 482 | unsigned int size; | 328 | unsigned int size; |
| 483 | int ret; | 329 | int ret; |
| @@ -539,7 +385,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) | |||
| 539 | if (req->offset == PAGE_SIZE) { | 385 | if (req->offset == PAGE_SIZE) { |
| 540 | req->offset = 0; | 386 | req->offset = 0; |
| 541 | if (req->page_done) | 387 | if (req->page_done) |
| 542 | req->page_done(call, req); | 388 | req->page_done(req); |
| 543 | req->index++; | 389 | req->index++; |
| 544 | if (req->remain > 0) | 390 | if (req->remain > 0) |
| 545 | goto begin_page; | 391 | goto begin_page; |
| @@ -573,12 +419,14 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) | |||
| 573 | return ret; | 419 | return ret; |
| 574 | 420 | ||
| 575 | bp = call->buffer; | 421 | bp = call->buffer; |
| 576 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, | 422 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 577 | &vnode->status.data_version, req); | ||
| 578 | if (ret < 0) | 423 | if (ret < 0) |
| 579 | return ret; | 424 | return ret; |
| 580 | xdr_decode_AFSCallBack(call, vnode, &bp); | 425 | xdr_decode_AFSCallBack(&bp, call, call->out_scb); |
| 581 | xdr_decode_AFSVolSync(&bp, call->reply[1]); | 426 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 427 | |||
| 428 | req->data_version = call->out_scb->status.data_version; | ||
| 429 | req->file_size = call->out_scb->status.size; | ||
| 582 | 430 | ||
| 583 | call->unmarshall++; | 431 | call->unmarshall++; |
| 584 | 432 | ||
| @@ -591,7 +439,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) | |||
| 591 | zero_user_segment(req->pages[req->index], | 439 | zero_user_segment(req->pages[req->index], |
| 592 | req->offset, PAGE_SIZE); | 440 | req->offset, PAGE_SIZE); |
| 593 | if (req->page_done) | 441 | if (req->page_done) |
| 594 | req->page_done(call, req); | 442 | req->page_done(req); |
| 595 | req->offset = 0; | 443 | req->offset = 0; |
| 596 | } | 444 | } |
| 597 | 445 | ||
| @@ -601,7 +449,7 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) | |||
| 601 | 449 | ||
| 602 | static void afs_fetch_data_destructor(struct afs_call *call) | 450 | static void afs_fetch_data_destructor(struct afs_call *call) |
| 603 | { | 451 | { |
| 604 | struct afs_read *req = call->reply[2]; | 452 | struct afs_read *req = call->read_request; |
| 605 | 453 | ||
| 606 | afs_put_read(req); | 454 | afs_put_read(req); |
| 607 | afs_flat_call_destructor(call); | 455 | afs_flat_call_destructor(call); |
| @@ -627,7 +475,9 @@ static const struct afs_call_type afs_RXFSFetchData64 = { | |||
| 627 | /* | 475 | /* |
| 628 | * fetch data from a very large file | 476 | * fetch data from a very large file |
| 629 | */ | 477 | */ |
| 630 | static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req) | 478 | static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, |
| 479 | struct afs_status_cb *scb, | ||
| 480 | struct afs_read *req) | ||
| 631 | { | 481 | { |
| 632 | struct afs_vnode *vnode = fc->vnode; | 482 | struct afs_vnode *vnode = fc->vnode; |
| 633 | struct afs_call *call; | 483 | struct afs_call *call; |
| @@ -641,11 +491,9 @@ static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 641 | return -ENOMEM; | 491 | return -ENOMEM; |
| 642 | 492 | ||
| 643 | call->key = fc->key; | 493 | call->key = fc->key; |
| 644 | call->reply[0] = vnode; | 494 | call->out_scb = scb; |
| 645 | call->reply[1] = NULL; /* volsync */ | 495 | call->out_volsync = NULL; |
| 646 | call->reply[2] = req; | 496 | call->read_request = req; |
| 647 | call->expected_version = vnode->status.data_version; | ||
| 648 | call->want_reply_time = true; | ||
| 649 | 497 | ||
| 650 | /* marshall the parameters */ | 498 | /* marshall the parameters */ |
| 651 | bp = call->request; | 499 | bp = call->request; |
| @@ -659,7 +507,6 @@ static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 659 | bp[7] = htonl(lower_32_bits(req->len)); | 507 | bp[7] = htonl(lower_32_bits(req->len)); |
| 660 | 508 | ||
| 661 | refcount_inc(&req->usage); | 509 | refcount_inc(&req->usage); |
| 662 | call->cb_break = fc->cb_break; | ||
| 663 | afs_use_fs_server(call, fc->cbi); | 510 | afs_use_fs_server(call, fc->cbi); |
| 664 | trace_afs_make_fs_call(call, &vnode->fid); | 511 | trace_afs_make_fs_call(call, &vnode->fid); |
| 665 | afs_set_fc_call(call, fc); | 512 | afs_set_fc_call(call, fc); |
| @@ -670,7 +517,9 @@ static int afs_fs_fetch_data64(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 670 | /* | 517 | /* |
| 671 | * fetch data from a file | 518 | * fetch data from a file |
| 672 | */ | 519 | */ |
| 673 | int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | 520 | int afs_fs_fetch_data(struct afs_fs_cursor *fc, |
| 521 | struct afs_status_cb *scb, | ||
| 522 | struct afs_read *req) | ||
| 674 | { | 523 | { |
| 675 | struct afs_vnode *vnode = fc->vnode; | 524 | struct afs_vnode *vnode = fc->vnode; |
| 676 | struct afs_call *call; | 525 | struct afs_call *call; |
| @@ -678,12 +527,12 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 678 | __be32 *bp; | 527 | __be32 *bp; |
| 679 | 528 | ||
| 680 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 529 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 681 | return yfs_fs_fetch_data(fc, req); | 530 | return yfs_fs_fetch_data(fc, scb, req); |
| 682 | 531 | ||
| 683 | if (upper_32_bits(req->pos) || | 532 | if (upper_32_bits(req->pos) || |
| 684 | upper_32_bits(req->len) || | 533 | upper_32_bits(req->len) || |
| 685 | upper_32_bits(req->pos + req->len)) | 534 | upper_32_bits(req->pos + req->len)) |
| 686 | return afs_fs_fetch_data64(fc, req); | 535 | return afs_fs_fetch_data64(fc, scb, req); |
| 687 | 536 | ||
| 688 | _enter(""); | 537 | _enter(""); |
| 689 | 538 | ||
| @@ -692,11 +541,9 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 692 | return -ENOMEM; | 541 | return -ENOMEM; |
| 693 | 542 | ||
| 694 | call->key = fc->key; | 543 | call->key = fc->key; |
| 695 | call->reply[0] = vnode; | 544 | call->out_scb = scb; |
| 696 | call->reply[1] = NULL; /* volsync */ | 545 | call->out_volsync = NULL; |
| 697 | call->reply[2] = req; | 546 | call->read_request = req; |
| 698 | call->expected_version = vnode->status.data_version; | ||
| 699 | call->want_reply_time = true; | ||
| 700 | 547 | ||
| 701 | /* marshall the parameters */ | 548 | /* marshall the parameters */ |
| 702 | bp = call->request; | 549 | bp = call->request; |
| @@ -708,7 +555,6 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 708 | bp[5] = htonl(lower_32_bits(req->len)); | 555 | bp[5] = htonl(lower_32_bits(req->len)); |
| 709 | 556 | ||
| 710 | refcount_inc(&req->usage); | 557 | refcount_inc(&req->usage); |
| 711 | call->cb_break = fc->cb_break; | ||
| 712 | afs_use_fs_server(call, fc->cbi); | 558 | afs_use_fs_server(call, fc->cbi); |
| 713 | trace_afs_make_fs_call(call, &vnode->fid); | 559 | trace_afs_make_fs_call(call, &vnode->fid); |
| 714 | afs_set_fc_call(call, fc); | 560 | afs_set_fc_call(call, fc); |
| @@ -721,28 +567,24 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 721 | */ | 567 | */ |
| 722 | static int afs_deliver_fs_create_vnode(struct afs_call *call) | 568 | static int afs_deliver_fs_create_vnode(struct afs_call *call) |
| 723 | { | 569 | { |
| 724 | struct afs_vnode *vnode = call->reply[0]; | ||
| 725 | const __be32 *bp; | 570 | const __be32 *bp; |
| 726 | int ret; | 571 | int ret; |
| 727 | 572 | ||
| 728 | _enter("{%u}", call->unmarshall); | ||
| 729 | |||
| 730 | ret = afs_transfer_reply(call); | 573 | ret = afs_transfer_reply(call); |
| 731 | if (ret < 0) | 574 | if (ret < 0) |
| 732 | return ret; | 575 | return ret; |
| 733 | 576 | ||
| 734 | /* unmarshall the reply once we've received all of it */ | 577 | /* unmarshall the reply once we've received all of it */ |
| 735 | bp = call->buffer; | 578 | bp = call->buffer; |
| 736 | xdr_decode_AFSFid(&bp, call->reply[1]); | 579 | xdr_decode_AFSFid(&bp, call->out_fid); |
| 737 | ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL); | 580 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 738 | if (ret < 0) | 581 | if (ret < 0) |
| 739 | return ret; | 582 | return ret; |
| 740 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, | 583 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); |
| 741 | &call->expected_version, NULL); | ||
| 742 | if (ret < 0) | 584 | if (ret < 0) |
| 743 | return ret; | 585 | return ret; |
| 744 | xdr_decode_AFSCallBack_raw(call, call->reply[3], &bp); | 586 | xdr_decode_AFSCallBack(&bp, call, call->out_scb); |
| 745 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 587 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 746 | 588 | ||
| 747 | _leave(" = 0 [done]"); | 589 | _leave(" = 0 [done]"); |
| 748 | return 0; | 590 | return 0; |
| @@ -771,24 +613,23 @@ static const struct afs_call_type afs_RXFSMakeDir = { | |||
| 771 | int afs_fs_create(struct afs_fs_cursor *fc, | 613 | int afs_fs_create(struct afs_fs_cursor *fc, |
| 772 | const char *name, | 614 | const char *name, |
| 773 | umode_t mode, | 615 | umode_t mode, |
| 774 | u64 current_data_version, | 616 | struct afs_status_cb *dvnode_scb, |
| 775 | struct afs_fid *newfid, | 617 | struct afs_fid *newfid, |
| 776 | struct afs_file_status *newstatus, | 618 | struct afs_status_cb *new_scb) |
| 777 | struct afs_callback *newcb) | ||
| 778 | { | 619 | { |
| 779 | struct afs_vnode *vnode = fc->vnode; | 620 | struct afs_vnode *dvnode = fc->vnode; |
| 780 | struct afs_call *call; | 621 | struct afs_call *call; |
| 781 | struct afs_net *net = afs_v2net(vnode); | 622 | struct afs_net *net = afs_v2net(dvnode); |
| 782 | size_t namesz, reqsz, padsz; | 623 | size_t namesz, reqsz, padsz; |
| 783 | __be32 *bp; | 624 | __be32 *bp; |
| 784 | 625 | ||
| 785 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){ | 626 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){ |
| 786 | if (S_ISDIR(mode)) | 627 | if (S_ISDIR(mode)) |
| 787 | return yfs_fs_make_dir(fc, name, mode, current_data_version, | 628 | return yfs_fs_make_dir(fc, name, mode, dvnode_scb, |
| 788 | newfid, newstatus, newcb); | 629 | newfid, new_scb); |
| 789 | else | 630 | else |
| 790 | return yfs_fs_create_file(fc, name, mode, current_data_version, | 631 | return yfs_fs_create_file(fc, name, mode, dvnode_scb, |
| 791 | newfid, newstatus, newcb); | 632 | newfid, new_scb); |
| 792 | } | 633 | } |
| 793 | 634 | ||
| 794 | _enter(""); | 635 | _enter(""); |
| @@ -804,19 +645,16 @@ int afs_fs_create(struct afs_fs_cursor *fc, | |||
| 804 | return -ENOMEM; | 645 | return -ENOMEM; |
| 805 | 646 | ||
| 806 | call->key = fc->key; | 647 | call->key = fc->key; |
| 807 | call->reply[0] = vnode; | 648 | call->out_dir_scb = dvnode_scb; |
| 808 | call->reply[1] = newfid; | 649 | call->out_fid = newfid; |
| 809 | call->reply[2] = newstatus; | 650 | call->out_scb = new_scb; |
| 810 | call->reply[3] = newcb; | ||
| 811 | call->expected_version = current_data_version + 1; | ||
| 812 | call->want_reply_time = true; | ||
| 813 | 651 | ||
| 814 | /* marshall the parameters */ | 652 | /* marshall the parameters */ |
| 815 | bp = call->request; | 653 | bp = call->request; |
| 816 | *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE); | 654 | *bp++ = htonl(S_ISDIR(mode) ? FSMAKEDIR : FSCREATEFILE); |
| 817 | *bp++ = htonl(vnode->fid.vid); | 655 | *bp++ = htonl(dvnode->fid.vid); |
| 818 | *bp++ = htonl(vnode->fid.vnode); | 656 | *bp++ = htonl(dvnode->fid.vnode); |
| 819 | *bp++ = htonl(vnode->fid.unique); | 657 | *bp++ = htonl(dvnode->fid.unique); |
| 820 | *bp++ = htonl(namesz); | 658 | *bp++ = htonl(namesz); |
| 821 | memcpy(bp, name, namesz); | 659 | memcpy(bp, name, namesz); |
| 822 | bp = (void *) bp + namesz; | 660 | bp = (void *) bp + namesz; |
| @@ -825,42 +663,38 @@ int afs_fs_create(struct afs_fs_cursor *fc, | |||
| 825 | bp = (void *) bp + padsz; | 663 | bp = (void *) bp + padsz; |
| 826 | } | 664 | } |
| 827 | *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); | 665 | *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); |
| 828 | *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ | 666 | *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ |
| 829 | *bp++ = 0; /* owner */ | 667 | *bp++ = 0; /* owner */ |
| 830 | *bp++ = 0; /* group */ | 668 | *bp++ = 0; /* group */ |
| 831 | *bp++ = htonl(mode & S_IALLUGO); /* unix mode */ | 669 | *bp++ = htonl(mode & S_IALLUGO); /* unix mode */ |
| 832 | *bp++ = 0; /* segment size */ | 670 | *bp++ = 0; /* segment size */ |
| 833 | 671 | ||
| 834 | afs_use_fs_server(call, fc->cbi); | 672 | afs_use_fs_server(call, fc->cbi); |
| 835 | trace_afs_make_fs_call1(call, &vnode->fid, name); | 673 | trace_afs_make_fs_call1(call, &dvnode->fid, name); |
| 836 | afs_set_fc_call(call, fc); | 674 | afs_set_fc_call(call, fc); |
| 837 | afs_make_call(&fc->ac, call, GFP_NOFS); | 675 | afs_make_call(&fc->ac, call, GFP_NOFS); |
| 838 | return afs_wait_for_call_to_complete(call, &fc->ac); | 676 | return afs_wait_for_call_to_complete(call, &fc->ac); |
| 839 | } | 677 | } |
| 840 | 678 | ||
| 841 | /* | 679 | /* |
| 842 | * Deliver reply data to any operation that returns file status and volume | 680 | * Deliver reply data to any operation that returns directory status and volume |
| 843 | * sync. | 681 | * sync. |
| 844 | */ | 682 | */ |
| 845 | static int afs_deliver_fs_status_and_vol(struct afs_call *call) | 683 | static int afs_deliver_fs_dir_status_and_vol(struct afs_call *call) |
| 846 | { | 684 | { |
| 847 | struct afs_vnode *vnode = call->reply[0]; | ||
| 848 | const __be32 *bp; | 685 | const __be32 *bp; |
| 849 | int ret; | 686 | int ret; |
| 850 | 687 | ||
| 851 | _enter("{%u}", call->unmarshall); | ||
| 852 | |||
| 853 | ret = afs_transfer_reply(call); | 688 | ret = afs_transfer_reply(call); |
| 854 | if (ret < 0) | 689 | if (ret < 0) |
| 855 | return ret; | 690 | return ret; |
| 856 | 691 | ||
| 857 | /* unmarshall the reply once we've received all of it */ | 692 | /* unmarshall the reply once we've received all of it */ |
| 858 | bp = call->buffer; | 693 | bp = call->buffer; |
| 859 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, | 694 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); |
| 860 | &call->expected_version, NULL); | ||
| 861 | if (ret < 0) | 695 | if (ret < 0) |
| 862 | return ret; | 696 | return ret; |
| 863 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 697 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 864 | 698 | ||
| 865 | _leave(" = 0 [done]"); | 699 | _leave(" = 0 [done]"); |
| 866 | return 0; | 700 | return 0; |
| @@ -872,14 +706,14 @@ static int afs_deliver_fs_status_and_vol(struct afs_call *call) | |||
| 872 | static const struct afs_call_type afs_RXFSRemoveFile = { | 706 | static const struct afs_call_type afs_RXFSRemoveFile = { |
| 873 | .name = "FS.RemoveFile", | 707 | .name = "FS.RemoveFile", |
| 874 | .op = afs_FS_RemoveFile, | 708 | .op = afs_FS_RemoveFile, |
| 875 | .deliver = afs_deliver_fs_status_and_vol, | 709 | .deliver = afs_deliver_fs_dir_status_and_vol, |
| 876 | .destructor = afs_flat_call_destructor, | 710 | .destructor = afs_flat_call_destructor, |
| 877 | }; | 711 | }; |
| 878 | 712 | ||
| 879 | static const struct afs_call_type afs_RXFSRemoveDir = { | 713 | static const struct afs_call_type afs_RXFSRemoveDir = { |
| 880 | .name = "FS.RemoveDir", | 714 | .name = "FS.RemoveDir", |
| 881 | .op = afs_FS_RemoveDir, | 715 | .op = afs_FS_RemoveDir, |
| 882 | .deliver = afs_deliver_fs_status_and_vol, | 716 | .deliver = afs_deliver_fs_dir_status_and_vol, |
| 883 | .destructor = afs_flat_call_destructor, | 717 | .destructor = afs_flat_call_destructor, |
| 884 | }; | 718 | }; |
| 885 | 719 | ||
| @@ -887,7 +721,7 @@ static const struct afs_call_type afs_RXFSRemoveDir = { | |||
| 887 | * remove a file or directory | 721 | * remove a file or directory |
| 888 | */ | 722 | */ |
| 889 | int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | 723 | int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, |
| 890 | const char *name, bool isdir, u64 current_data_version) | 724 | const char *name, bool isdir, struct afs_status_cb *dvnode_scb) |
| 891 | { | 725 | { |
| 892 | struct afs_vnode *dvnode = fc->vnode; | 726 | struct afs_vnode *dvnode = fc->vnode; |
| 893 | struct afs_call *call; | 727 | struct afs_call *call; |
| @@ -896,7 +730,7 @@ int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 896 | __be32 *bp; | 730 | __be32 *bp; |
| 897 | 731 | ||
| 898 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 732 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 899 | return yfs_fs_remove(fc, vnode, name, isdir, current_data_version); | 733 | return yfs_fs_remove(fc, vnode, name, isdir, dvnode_scb); |
| 900 | 734 | ||
| 901 | _enter(""); | 735 | _enter(""); |
| 902 | 736 | ||
| @@ -911,9 +745,7 @@ int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 911 | return -ENOMEM; | 745 | return -ENOMEM; |
| 912 | 746 | ||
| 913 | call->key = fc->key; | 747 | call->key = fc->key; |
| 914 | call->reply[0] = dvnode; | 748 | call->out_dir_scb = dvnode_scb; |
| 915 | call->reply[1] = vnode; | ||
| 916 | call->expected_version = current_data_version + 1; | ||
| 917 | 749 | ||
| 918 | /* marshall the parameters */ | 750 | /* marshall the parameters */ |
| 919 | bp = call->request; | 751 | bp = call->request; |
| @@ -941,7 +773,6 @@ int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 941 | */ | 773 | */ |
| 942 | static int afs_deliver_fs_link(struct afs_call *call) | 774 | static int afs_deliver_fs_link(struct afs_call *call) |
| 943 | { | 775 | { |
| 944 | struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1]; | ||
| 945 | const __be32 *bp; | 776 | const __be32 *bp; |
| 946 | int ret; | 777 | int ret; |
| 947 | 778 | ||
| @@ -953,14 +784,13 @@ static int afs_deliver_fs_link(struct afs_call *call) | |||
| 953 | 784 | ||
| 954 | /* unmarshall the reply once we've received all of it */ | 785 | /* unmarshall the reply once we've received all of it */ |
| 955 | bp = call->buffer; | 786 | bp = call->buffer; |
| 956 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL); | 787 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 957 | if (ret < 0) | 788 | if (ret < 0) |
| 958 | return ret; | 789 | return ret; |
| 959 | ret = afs_decode_status(call, &bp, &dvnode->status, dvnode, | 790 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); |
| 960 | &call->expected_version, NULL); | ||
| 961 | if (ret < 0) | 791 | if (ret < 0) |
| 962 | return ret; | 792 | return ret; |
| 963 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 793 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 964 | 794 | ||
| 965 | _leave(" = 0 [done]"); | 795 | _leave(" = 0 [done]"); |
| 966 | return 0; | 796 | return 0; |
| @@ -980,7 +810,9 @@ static const struct afs_call_type afs_RXFSLink = { | |||
| 980 | * make a hard link | 810 | * make a hard link |
| 981 | */ | 811 | */ |
| 982 | int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | 812 | int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, |
| 983 | const char *name, u64 current_data_version) | 813 | const char *name, |
| 814 | struct afs_status_cb *dvnode_scb, | ||
| 815 | struct afs_status_cb *vnode_scb) | ||
| 984 | { | 816 | { |
| 985 | struct afs_vnode *dvnode = fc->vnode; | 817 | struct afs_vnode *dvnode = fc->vnode; |
| 986 | struct afs_call *call; | 818 | struct afs_call *call; |
| @@ -989,7 +821,7 @@ int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 989 | __be32 *bp; | 821 | __be32 *bp; |
| 990 | 822 | ||
| 991 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 823 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 992 | return yfs_fs_link(fc, vnode, name, current_data_version); | 824 | return yfs_fs_link(fc, vnode, name, dvnode_scb, vnode_scb); |
| 993 | 825 | ||
| 994 | _enter(""); | 826 | _enter(""); |
| 995 | 827 | ||
| @@ -1002,9 +834,8 @@ int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 1002 | return -ENOMEM; | 834 | return -ENOMEM; |
| 1003 | 835 | ||
| 1004 | call->key = fc->key; | 836 | call->key = fc->key; |
| 1005 | call->reply[0] = dvnode; | 837 | call->out_dir_scb = dvnode_scb; |
| 1006 | call->reply[1] = vnode; | 838 | call->out_scb = vnode_scb; |
| 1007 | call->expected_version = current_data_version + 1; | ||
| 1008 | 839 | ||
| 1009 | /* marshall the parameters */ | 840 | /* marshall the parameters */ |
| 1010 | bp = call->request; | 841 | bp = call->request; |
| @@ -1035,7 +866,6 @@ int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 1035 | */ | 866 | */ |
| 1036 | static int afs_deliver_fs_symlink(struct afs_call *call) | 867 | static int afs_deliver_fs_symlink(struct afs_call *call) |
| 1037 | { | 868 | { |
| 1038 | struct afs_vnode *vnode = call->reply[0]; | ||
| 1039 | const __be32 *bp; | 869 | const __be32 *bp; |
| 1040 | int ret; | 870 | int ret; |
| 1041 | 871 | ||
| @@ -1047,15 +877,14 @@ static int afs_deliver_fs_symlink(struct afs_call *call) | |||
| 1047 | 877 | ||
| 1048 | /* unmarshall the reply once we've received all of it */ | 878 | /* unmarshall the reply once we've received all of it */ |
| 1049 | bp = call->buffer; | 879 | bp = call->buffer; |
| 1050 | xdr_decode_AFSFid(&bp, call->reply[1]); | 880 | xdr_decode_AFSFid(&bp, call->out_fid); |
| 1051 | ret = afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL); | 881 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 1052 | if (ret < 0) | 882 | if (ret < 0) |
| 1053 | return ret; | 883 | return ret; |
| 1054 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, | 884 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); |
| 1055 | &call->expected_version, NULL); | ||
| 1056 | if (ret < 0) | 885 | if (ret < 0) |
| 1057 | return ret; | 886 | return ret; |
| 1058 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 887 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 1059 | 888 | ||
| 1060 | _leave(" = 0 [done]"); | 889 | _leave(" = 0 [done]"); |
| 1061 | return 0; | 890 | return 0; |
| @@ -1077,19 +906,19 @@ static const struct afs_call_type afs_RXFSSymlink = { | |||
| 1077 | int afs_fs_symlink(struct afs_fs_cursor *fc, | 906 | int afs_fs_symlink(struct afs_fs_cursor *fc, |
| 1078 | const char *name, | 907 | const char *name, |
| 1079 | const char *contents, | 908 | const char *contents, |
| 1080 | u64 current_data_version, | 909 | struct afs_status_cb *dvnode_scb, |
| 1081 | struct afs_fid *newfid, | 910 | struct afs_fid *newfid, |
| 1082 | struct afs_file_status *newstatus) | 911 | struct afs_status_cb *new_scb) |
| 1083 | { | 912 | { |
| 1084 | struct afs_vnode *vnode = fc->vnode; | 913 | struct afs_vnode *dvnode = fc->vnode; |
| 1085 | struct afs_call *call; | 914 | struct afs_call *call; |
| 1086 | struct afs_net *net = afs_v2net(vnode); | 915 | struct afs_net *net = afs_v2net(dvnode); |
| 1087 | size_t namesz, reqsz, padsz, c_namesz, c_padsz; | 916 | size_t namesz, reqsz, padsz, c_namesz, c_padsz; |
| 1088 | __be32 *bp; | 917 | __be32 *bp; |
| 1089 | 918 | ||
| 1090 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 919 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 1091 | return yfs_fs_symlink(fc, name, contents, current_data_version, | 920 | return yfs_fs_symlink(fc, name, contents, dvnode_scb, |
| 1092 | newfid, newstatus); | 921 | newfid, new_scb); |
| 1093 | 922 | ||
| 1094 | _enter(""); | 923 | _enter(""); |
| 1095 | 924 | ||
| @@ -1107,17 +936,16 @@ int afs_fs_symlink(struct afs_fs_cursor *fc, | |||
| 1107 | return -ENOMEM; | 936 | return -ENOMEM; |
| 1108 | 937 | ||
| 1109 | call->key = fc->key; | 938 | call->key = fc->key; |
| 1110 | call->reply[0] = vnode; | 939 | call->out_dir_scb = dvnode_scb; |
| 1111 | call->reply[1] = newfid; | 940 | call->out_fid = newfid; |
| 1112 | call->reply[2] = newstatus; | 941 | call->out_scb = new_scb; |
| 1113 | call->expected_version = current_data_version + 1; | ||
| 1114 | 942 | ||
| 1115 | /* marshall the parameters */ | 943 | /* marshall the parameters */ |
| 1116 | bp = call->request; | 944 | bp = call->request; |
| 1117 | *bp++ = htonl(FSSYMLINK); | 945 | *bp++ = htonl(FSSYMLINK); |
| 1118 | *bp++ = htonl(vnode->fid.vid); | 946 | *bp++ = htonl(dvnode->fid.vid); |
| 1119 | *bp++ = htonl(vnode->fid.vnode); | 947 | *bp++ = htonl(dvnode->fid.vnode); |
| 1120 | *bp++ = htonl(vnode->fid.unique); | 948 | *bp++ = htonl(dvnode->fid.unique); |
| 1121 | *bp++ = htonl(namesz); | 949 | *bp++ = htonl(namesz); |
| 1122 | memcpy(bp, name, namesz); | 950 | memcpy(bp, name, namesz); |
| 1123 | bp = (void *) bp + namesz; | 951 | bp = (void *) bp + namesz; |
| @@ -1133,14 +961,14 @@ int afs_fs_symlink(struct afs_fs_cursor *fc, | |||
| 1133 | bp = (void *) bp + c_padsz; | 961 | bp = (void *) bp + c_padsz; |
| 1134 | } | 962 | } |
| 1135 | *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); | 963 | *bp++ = htonl(AFS_SET_MODE | AFS_SET_MTIME); |
| 1136 | *bp++ = htonl(vnode->vfs_inode.i_mtime.tv_sec); /* mtime */ | 964 | *bp++ = htonl(dvnode->vfs_inode.i_mtime.tv_sec); /* mtime */ |
| 1137 | *bp++ = 0; /* owner */ | 965 | *bp++ = 0; /* owner */ |
| 1138 | *bp++ = 0; /* group */ | 966 | *bp++ = 0; /* group */ |
| 1139 | *bp++ = htonl(S_IRWXUGO); /* unix mode */ | 967 | *bp++ = htonl(S_IRWXUGO); /* unix mode */ |
| 1140 | *bp++ = 0; /* segment size */ | 968 | *bp++ = 0; /* segment size */ |
| 1141 | 969 | ||
| 1142 | afs_use_fs_server(call, fc->cbi); | 970 | afs_use_fs_server(call, fc->cbi); |
| 1143 | trace_afs_make_fs_call1(call, &vnode->fid, name); | 971 | trace_afs_make_fs_call1(call, &dvnode->fid, name); |
| 1144 | afs_set_fc_call(call, fc); | 972 | afs_set_fc_call(call, fc); |
| 1145 | afs_make_call(&fc->ac, call, GFP_NOFS); | 973 | afs_make_call(&fc->ac, call, GFP_NOFS); |
| 1146 | return afs_wait_for_call_to_complete(call, &fc->ac); | 974 | return afs_wait_for_call_to_complete(call, &fc->ac); |
| @@ -1151,29 +979,24 @@ int afs_fs_symlink(struct afs_fs_cursor *fc, | |||
| 1151 | */ | 979 | */ |
| 1152 | static int afs_deliver_fs_rename(struct afs_call *call) | 980 | static int afs_deliver_fs_rename(struct afs_call *call) |
| 1153 | { | 981 | { |
| 1154 | struct afs_vnode *orig_dvnode = call->reply[0], *new_dvnode = call->reply[1]; | ||
| 1155 | const __be32 *bp; | 982 | const __be32 *bp; |
| 1156 | int ret; | 983 | int ret; |
| 1157 | 984 | ||
| 1158 | _enter("{%u}", call->unmarshall); | ||
| 1159 | |||
| 1160 | ret = afs_transfer_reply(call); | 985 | ret = afs_transfer_reply(call); |
| 1161 | if (ret < 0) | 986 | if (ret < 0) |
| 1162 | return ret; | 987 | return ret; |
| 1163 | 988 | ||
| 1164 | /* unmarshall the reply once we've received all of it */ | 989 | /* unmarshall the reply once we've received all of it */ |
| 1165 | bp = call->buffer; | 990 | bp = call->buffer; |
| 1166 | ret = afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode, | 991 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_dir_scb); |
| 1167 | &call->expected_version, NULL); | ||
| 1168 | if (ret < 0) | 992 | if (ret < 0) |
| 1169 | return ret; | 993 | return ret; |
| 1170 | if (new_dvnode != orig_dvnode) { | 994 | if (call->out_dir_scb != call->out_scb) { |
| 1171 | ret = afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode, | 995 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 1172 | &call->expected_version_2, NULL); | ||
| 1173 | if (ret < 0) | 996 | if (ret < 0) |
| 1174 | return ret; | 997 | return ret; |
| 1175 | } | 998 | } |
| 1176 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 999 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 1177 | 1000 | ||
| 1178 | _leave(" = 0 [done]"); | 1001 | _leave(" = 0 [done]"); |
| 1179 | return 0; | 1002 | return 0; |
| @@ -1190,14 +1013,14 @@ static const struct afs_call_type afs_RXFSRename = { | |||
| 1190 | }; | 1013 | }; |
| 1191 | 1014 | ||
| 1192 | /* | 1015 | /* |
| 1193 | * create a symbolic link | 1016 | * Rename/move a file or directory. |
| 1194 | */ | 1017 | */ |
| 1195 | int afs_fs_rename(struct afs_fs_cursor *fc, | 1018 | int afs_fs_rename(struct afs_fs_cursor *fc, |
| 1196 | const char *orig_name, | 1019 | const char *orig_name, |
| 1197 | struct afs_vnode *new_dvnode, | 1020 | struct afs_vnode *new_dvnode, |
| 1198 | const char *new_name, | 1021 | const char *new_name, |
| 1199 | u64 current_orig_data_version, | 1022 | struct afs_status_cb *orig_dvnode_scb, |
| 1200 | u64 current_new_data_version) | 1023 | struct afs_status_cb *new_dvnode_scb) |
| 1201 | { | 1024 | { |
| 1202 | struct afs_vnode *orig_dvnode = fc->vnode; | 1025 | struct afs_vnode *orig_dvnode = fc->vnode; |
| 1203 | struct afs_call *call; | 1026 | struct afs_call *call; |
| @@ -1208,8 +1031,8 @@ int afs_fs_rename(struct afs_fs_cursor *fc, | |||
| 1208 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 1031 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 1209 | return yfs_fs_rename(fc, orig_name, | 1032 | return yfs_fs_rename(fc, orig_name, |
| 1210 | new_dvnode, new_name, | 1033 | new_dvnode, new_name, |
| 1211 | current_orig_data_version, | 1034 | orig_dvnode_scb, |
| 1212 | current_new_data_version); | 1035 | new_dvnode_scb); |
| 1213 | 1036 | ||
| 1214 | _enter(""); | 1037 | _enter(""); |
| 1215 | 1038 | ||
| @@ -1229,10 +1052,8 @@ int afs_fs_rename(struct afs_fs_cursor *fc, | |||
| 1229 | return -ENOMEM; | 1052 | return -ENOMEM; |
| 1230 | 1053 | ||
| 1231 | call->key = fc->key; | 1054 | call->key = fc->key; |
| 1232 | call->reply[0] = orig_dvnode; | 1055 | call->out_dir_scb = orig_dvnode_scb; |
| 1233 | call->reply[1] = new_dvnode; | 1056 | call->out_scb = new_dvnode_scb; |
| 1234 | call->expected_version = current_orig_data_version + 1; | ||
| 1235 | call->expected_version_2 = current_new_data_version + 1; | ||
| 1236 | 1057 | ||
| 1237 | /* marshall the parameters */ | 1058 | /* marshall the parameters */ |
| 1238 | bp = call->request; | 1059 | bp = call->request; |
| @@ -1271,7 +1092,6 @@ int afs_fs_rename(struct afs_fs_cursor *fc, | |||
| 1271 | */ | 1092 | */ |
| 1272 | static int afs_deliver_fs_store_data(struct afs_call *call) | 1093 | static int afs_deliver_fs_store_data(struct afs_call *call) |
| 1273 | { | 1094 | { |
| 1274 | struct afs_vnode *vnode = call->reply[0]; | ||
| 1275 | const __be32 *bp; | 1095 | const __be32 *bp; |
| 1276 | int ret; | 1096 | int ret; |
| 1277 | 1097 | ||
| @@ -1283,13 +1103,10 @@ static int afs_deliver_fs_store_data(struct afs_call *call) | |||
| 1283 | 1103 | ||
| 1284 | /* unmarshall the reply once we've received all of it */ | 1104 | /* unmarshall the reply once we've received all of it */ |
| 1285 | bp = call->buffer; | 1105 | bp = call->buffer; |
| 1286 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, | 1106 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 1287 | &call->expected_version, NULL); | ||
| 1288 | if (ret < 0) | 1107 | if (ret < 0) |
| 1289 | return ret; | 1108 | return ret; |
| 1290 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1109 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 1291 | |||
| 1292 | afs_pages_written_back(vnode, call); | ||
| 1293 | 1110 | ||
| 1294 | _leave(" = 0 [done]"); | 1111 | _leave(" = 0 [done]"); |
| 1295 | return 0; | 1112 | return 0; |
| @@ -1319,7 +1136,8 @@ static int afs_fs_store_data64(struct afs_fs_cursor *fc, | |||
| 1319 | struct address_space *mapping, | 1136 | struct address_space *mapping, |
| 1320 | pgoff_t first, pgoff_t last, | 1137 | pgoff_t first, pgoff_t last, |
| 1321 | unsigned offset, unsigned to, | 1138 | unsigned offset, unsigned to, |
| 1322 | loff_t size, loff_t pos, loff_t i_size) | 1139 | loff_t size, loff_t pos, loff_t i_size, |
| 1140 | struct afs_status_cb *scb) | ||
| 1323 | { | 1141 | { |
| 1324 | struct afs_vnode *vnode = fc->vnode; | 1142 | struct afs_vnode *vnode = fc->vnode; |
| 1325 | struct afs_call *call; | 1143 | struct afs_call *call; |
| @@ -1337,13 +1155,12 @@ static int afs_fs_store_data64(struct afs_fs_cursor *fc, | |||
| 1337 | 1155 | ||
| 1338 | call->key = fc->key; | 1156 | call->key = fc->key; |
| 1339 | call->mapping = mapping; | 1157 | call->mapping = mapping; |
| 1340 | call->reply[0] = vnode; | ||
| 1341 | call->first = first; | 1158 | call->first = first; |
| 1342 | call->last = last; | 1159 | call->last = last; |
| 1343 | call->first_offset = offset; | 1160 | call->first_offset = offset; |
| 1344 | call->last_to = to; | 1161 | call->last_to = to; |
| 1345 | call->send_pages = true; | 1162 | call->send_pages = true; |
| 1346 | call->expected_version = vnode->status.data_version + 1; | 1163 | call->out_scb = scb; |
| 1347 | 1164 | ||
| 1348 | /* marshall the parameters */ | 1165 | /* marshall the parameters */ |
| 1349 | bp = call->request; | 1166 | bp = call->request; |
| @@ -1377,7 +1194,8 @@ static int afs_fs_store_data64(struct afs_fs_cursor *fc, | |||
| 1377 | */ | 1194 | */ |
| 1378 | int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | 1195 | int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, |
| 1379 | pgoff_t first, pgoff_t last, | 1196 | pgoff_t first, pgoff_t last, |
| 1380 | unsigned offset, unsigned to) | 1197 | unsigned offset, unsigned to, |
| 1198 | struct afs_status_cb *scb) | ||
| 1381 | { | 1199 | { |
| 1382 | struct afs_vnode *vnode = fc->vnode; | 1200 | struct afs_vnode *vnode = fc->vnode; |
| 1383 | struct afs_call *call; | 1201 | struct afs_call *call; |
| @@ -1386,7 +1204,7 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | |||
| 1386 | __be32 *bp; | 1204 | __be32 *bp; |
| 1387 | 1205 | ||
| 1388 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 1206 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 1389 | return yfs_fs_store_data(fc, mapping, first, last, offset, to); | 1207 | return yfs_fs_store_data(fc, mapping, first, last, offset, to, scb); |
| 1390 | 1208 | ||
| 1391 | _enter(",%x,{%llx:%llu},,", | 1209 | _enter(",%x,{%llx:%llu},,", |
| 1392 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 1210 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
| @@ -1407,7 +1225,7 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | |||
| 1407 | 1225 | ||
| 1408 | if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32) | 1226 | if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32) |
| 1409 | return afs_fs_store_data64(fc, mapping, first, last, offset, to, | 1227 | return afs_fs_store_data64(fc, mapping, first, last, offset, to, |
| 1410 | size, pos, i_size); | 1228 | size, pos, i_size, scb); |
| 1411 | 1229 | ||
| 1412 | call = afs_alloc_flat_call(net, &afs_RXFSStoreData, | 1230 | call = afs_alloc_flat_call(net, &afs_RXFSStoreData, |
| 1413 | (4 + 6 + 3) * 4, | 1231 | (4 + 6 + 3) * 4, |
| @@ -1417,13 +1235,12 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | |||
| 1417 | 1235 | ||
| 1418 | call->key = fc->key; | 1236 | call->key = fc->key; |
| 1419 | call->mapping = mapping; | 1237 | call->mapping = mapping; |
| 1420 | call->reply[0] = vnode; | ||
| 1421 | call->first = first; | 1238 | call->first = first; |
| 1422 | call->last = last; | 1239 | call->last = last; |
| 1423 | call->first_offset = offset; | 1240 | call->first_offset = offset; |
| 1424 | call->last_to = to; | 1241 | call->last_to = to; |
| 1425 | call->send_pages = true; | 1242 | call->send_pages = true; |
| 1426 | call->expected_version = vnode->status.data_version + 1; | 1243 | call->out_scb = scb; |
| 1427 | 1244 | ||
| 1428 | /* marshall the parameters */ | 1245 | /* marshall the parameters */ |
| 1429 | bp = call->request; | 1246 | bp = call->request; |
| @@ -1455,7 +1272,6 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | |||
| 1455 | */ | 1272 | */ |
| 1456 | static int afs_deliver_fs_store_status(struct afs_call *call) | 1273 | static int afs_deliver_fs_store_status(struct afs_call *call) |
| 1457 | { | 1274 | { |
| 1458 | struct afs_vnode *vnode = call->reply[0]; | ||
| 1459 | const __be32 *bp; | 1275 | const __be32 *bp; |
| 1460 | int ret; | 1276 | int ret; |
| 1461 | 1277 | ||
| @@ -1467,11 +1283,10 @@ static int afs_deliver_fs_store_status(struct afs_call *call) | |||
| 1467 | 1283 | ||
| 1468 | /* unmarshall the reply once we've received all of it */ | 1284 | /* unmarshall the reply once we've received all of it */ |
| 1469 | bp = call->buffer; | 1285 | bp = call->buffer; |
| 1470 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, | 1286 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 1471 | &call->expected_version, NULL); | ||
| 1472 | if (ret < 0) | 1287 | if (ret < 0) |
| 1473 | return ret; | 1288 | return ret; |
| 1474 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1289 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 1475 | 1290 | ||
| 1476 | _leave(" = 0 [done]"); | 1291 | _leave(" = 0 [done]"); |
| 1477 | return 0; | 1292 | return 0; |
| @@ -1505,7 +1320,8 @@ static const struct afs_call_type afs_RXFSStoreData64_as_Status = { | |||
| 1505 | * set the attributes on a very large file, using FS.StoreData rather than | 1320 | * set the attributes on a very large file, using FS.StoreData rather than |
| 1506 | * FS.StoreStatus so as to alter the file size also | 1321 | * FS.StoreStatus so as to alter the file size also |
| 1507 | */ | 1322 | */ |
| 1508 | static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr) | 1323 | static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr, |
| 1324 | struct afs_status_cb *scb) | ||
| 1509 | { | 1325 | { |
| 1510 | struct afs_vnode *vnode = fc->vnode; | 1326 | struct afs_vnode *vnode = fc->vnode; |
| 1511 | struct afs_call *call; | 1327 | struct afs_call *call; |
| @@ -1524,8 +1340,7 @@ static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1524 | return -ENOMEM; | 1340 | return -ENOMEM; |
| 1525 | 1341 | ||
| 1526 | call->key = fc->key; | 1342 | call->key = fc->key; |
| 1527 | call->reply[0] = vnode; | 1343 | call->out_scb = scb; |
| 1528 | call->expected_version = vnode->status.data_version + 1; | ||
| 1529 | 1344 | ||
| 1530 | /* marshall the parameters */ | 1345 | /* marshall the parameters */ |
| 1531 | bp = call->request; | 1346 | bp = call->request; |
| @@ -1554,7 +1369,8 @@ static int afs_fs_setattr_size64(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1554 | * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus | 1369 | * set the attributes on a file, using FS.StoreData rather than FS.StoreStatus |
| 1555 | * so as to alter the file size also | 1370 | * so as to alter the file size also |
| 1556 | */ | 1371 | */ |
| 1557 | static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr) | 1372 | static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr, |
| 1373 | struct afs_status_cb *scb) | ||
| 1558 | { | 1374 | { |
| 1559 | struct afs_vnode *vnode = fc->vnode; | 1375 | struct afs_vnode *vnode = fc->vnode; |
| 1560 | struct afs_call *call; | 1376 | struct afs_call *call; |
| @@ -1566,7 +1382,7 @@ static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1566 | 1382 | ||
| 1567 | ASSERT(attr->ia_valid & ATTR_SIZE); | 1383 | ASSERT(attr->ia_valid & ATTR_SIZE); |
| 1568 | if (attr->ia_size >> 32) | 1384 | if (attr->ia_size >> 32) |
| 1569 | return afs_fs_setattr_size64(fc, attr); | 1385 | return afs_fs_setattr_size64(fc, attr, scb); |
| 1570 | 1386 | ||
| 1571 | call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status, | 1387 | call = afs_alloc_flat_call(net, &afs_RXFSStoreData_as_Status, |
| 1572 | (4 + 6 + 3) * 4, | 1388 | (4 + 6 + 3) * 4, |
| @@ -1575,8 +1391,7 @@ static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1575 | return -ENOMEM; | 1391 | return -ENOMEM; |
| 1576 | 1392 | ||
| 1577 | call->key = fc->key; | 1393 | call->key = fc->key; |
| 1578 | call->reply[0] = vnode; | 1394 | call->out_scb = scb; |
| 1579 | call->expected_version = vnode->status.data_version + 1; | ||
| 1580 | 1395 | ||
| 1581 | /* marshall the parameters */ | 1396 | /* marshall the parameters */ |
| 1582 | bp = call->request; | 1397 | bp = call->request; |
| @@ -1602,7 +1417,8 @@ static int afs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1602 | * set the attributes on a file, using FS.StoreData if there's a change in file | 1417 | * set the attributes on a file, using FS.StoreData if there's a change in file |
| 1603 | * size, and FS.StoreStatus otherwise | 1418 | * size, and FS.StoreStatus otherwise |
| 1604 | */ | 1419 | */ |
| 1605 | int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr) | 1420 | int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr, |
| 1421 | struct afs_status_cb *scb) | ||
| 1606 | { | 1422 | { |
| 1607 | struct afs_vnode *vnode = fc->vnode; | 1423 | struct afs_vnode *vnode = fc->vnode; |
| 1608 | struct afs_call *call; | 1424 | struct afs_call *call; |
| @@ -1610,10 +1426,10 @@ int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1610 | __be32 *bp; | 1426 | __be32 *bp; |
| 1611 | 1427 | ||
| 1612 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 1428 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 1613 | return yfs_fs_setattr(fc, attr); | 1429 | return yfs_fs_setattr(fc, attr, scb); |
| 1614 | 1430 | ||
| 1615 | if (attr->ia_valid & ATTR_SIZE) | 1431 | if (attr->ia_valid & ATTR_SIZE) |
| 1616 | return afs_fs_setattr_size(fc, attr); | 1432 | return afs_fs_setattr_size(fc, attr, scb); |
| 1617 | 1433 | ||
| 1618 | _enter(",%x,{%llx:%llu},,", | 1434 | _enter(",%x,{%llx:%llu},,", |
| 1619 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 1435 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
| @@ -1625,8 +1441,7 @@ int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1625 | return -ENOMEM; | 1441 | return -ENOMEM; |
| 1626 | 1442 | ||
| 1627 | call->key = fc->key; | 1443 | call->key = fc->key; |
| 1628 | call->reply[0] = vnode; | 1444 | call->out_scb = scb; |
| 1629 | call->expected_version = vnode->status.data_version; | ||
| 1630 | 1445 | ||
| 1631 | /* marshall the parameters */ | 1446 | /* marshall the parameters */ |
| 1632 | bp = call->request; | 1447 | bp = call->request; |
| @@ -1669,7 +1484,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1669 | return ret; | 1484 | return ret; |
| 1670 | 1485 | ||
| 1671 | bp = call->buffer; | 1486 | bp = call->buffer; |
| 1672 | xdr_decode_AFSFetchVolumeStatus(&bp, call->reply[1]); | 1487 | xdr_decode_AFSFetchVolumeStatus(&bp, call->out_volstatus); |
| 1673 | call->unmarshall++; | 1488 | call->unmarshall++; |
| 1674 | afs_extract_to_tmp(call); | 1489 | afs_extract_to_tmp(call); |
| 1675 | 1490 | ||
| @@ -1685,7 +1500,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1685 | return afs_protocol_error(call, -EBADMSG, | 1500 | return afs_protocol_error(call, -EBADMSG, |
| 1686 | afs_eproto_volname_len); | 1501 | afs_eproto_volname_len); |
| 1687 | size = (call->count + 3) & ~3; /* It's padded */ | 1502 | size = (call->count + 3) & ~3; /* It's padded */ |
| 1688 | afs_extract_begin(call, call->reply[2], size); | 1503 | afs_extract_to_buf(call, size); |
| 1689 | call->unmarshall++; | 1504 | call->unmarshall++; |
| 1690 | 1505 | ||
| 1691 | /* Fall through - and extract the volume name */ | 1506 | /* Fall through - and extract the volume name */ |
| @@ -1695,7 +1510,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1695 | if (ret < 0) | 1510 | if (ret < 0) |
| 1696 | return ret; | 1511 | return ret; |
| 1697 | 1512 | ||
| 1698 | p = call->reply[2]; | 1513 | p = call->buffer; |
| 1699 | p[call->count] = 0; | 1514 | p[call->count] = 0; |
| 1700 | _debug("volname '%s'", p); | 1515 | _debug("volname '%s'", p); |
| 1701 | afs_extract_to_tmp(call); | 1516 | afs_extract_to_tmp(call); |
| @@ -1713,7 +1528,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1713 | return afs_protocol_error(call, -EBADMSG, | 1528 | return afs_protocol_error(call, -EBADMSG, |
| 1714 | afs_eproto_offline_msg_len); | 1529 | afs_eproto_offline_msg_len); |
| 1715 | size = (call->count + 3) & ~3; /* It's padded */ | 1530 | size = (call->count + 3) & ~3; /* It's padded */ |
| 1716 | afs_extract_begin(call, call->reply[2], size); | 1531 | afs_extract_to_buf(call, size); |
| 1717 | call->unmarshall++; | 1532 | call->unmarshall++; |
| 1718 | 1533 | ||
| 1719 | /* Fall through - and extract the offline message */ | 1534 | /* Fall through - and extract the offline message */ |
| @@ -1723,7 +1538,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1723 | if (ret < 0) | 1538 | if (ret < 0) |
| 1724 | return ret; | 1539 | return ret; |
| 1725 | 1540 | ||
| 1726 | p = call->reply[2]; | 1541 | p = call->buffer; |
| 1727 | p[call->count] = 0; | 1542 | p[call->count] = 0; |
| 1728 | _debug("offline '%s'", p); | 1543 | _debug("offline '%s'", p); |
| 1729 | 1544 | ||
| @@ -1742,7 +1557,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1742 | return afs_protocol_error(call, -EBADMSG, | 1557 | return afs_protocol_error(call, -EBADMSG, |
| 1743 | afs_eproto_motd_len); | 1558 | afs_eproto_motd_len); |
| 1744 | size = (call->count + 3) & ~3; /* It's padded */ | 1559 | size = (call->count + 3) & ~3; /* It's padded */ |
| 1745 | afs_extract_begin(call, call->reply[2], size); | 1560 | afs_extract_to_buf(call, size); |
| 1746 | call->unmarshall++; | 1561 | call->unmarshall++; |
| 1747 | 1562 | ||
| 1748 | /* Fall through - and extract the message of the day */ | 1563 | /* Fall through - and extract the message of the day */ |
| @@ -1752,7 +1567,7 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1752 | if (ret < 0) | 1567 | if (ret < 0) |
| 1753 | return ret; | 1568 | return ret; |
| 1754 | 1569 | ||
| 1755 | p = call->reply[2]; | 1570 | p = call->buffer; |
| 1756 | p[call->count] = 0; | 1571 | p[call->count] = 0; |
| 1757 | _debug("motd '%s'", p); | 1572 | _debug("motd '%s'", p); |
| 1758 | 1573 | ||
| @@ -1767,23 +1582,13 @@ static int afs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1767 | } | 1582 | } |
| 1768 | 1583 | ||
| 1769 | /* | 1584 | /* |
| 1770 | * destroy an FS.GetVolumeStatus call | ||
| 1771 | */ | ||
| 1772 | static void afs_get_volume_status_call_destructor(struct afs_call *call) | ||
| 1773 | { | ||
| 1774 | kfree(call->reply[2]); | ||
| 1775 | call->reply[2] = NULL; | ||
| 1776 | afs_flat_call_destructor(call); | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | /* | ||
| 1780 | * FS.GetVolumeStatus operation type | 1585 | * FS.GetVolumeStatus operation type |
| 1781 | */ | 1586 | */ |
| 1782 | static const struct afs_call_type afs_RXFSGetVolumeStatus = { | 1587 | static const struct afs_call_type afs_RXFSGetVolumeStatus = { |
| 1783 | .name = "FS.GetVolumeStatus", | 1588 | .name = "FS.GetVolumeStatus", |
| 1784 | .op = afs_FS_GetVolumeStatus, | 1589 | .op = afs_FS_GetVolumeStatus, |
| 1785 | .deliver = afs_deliver_fs_get_volume_status, | 1590 | .deliver = afs_deliver_fs_get_volume_status, |
| 1786 | .destructor = afs_get_volume_status_call_destructor, | 1591 | .destructor = afs_flat_call_destructor, |
| 1787 | }; | 1592 | }; |
| 1788 | 1593 | ||
| 1789 | /* | 1594 | /* |
| @@ -1796,27 +1601,19 @@ int afs_fs_get_volume_status(struct afs_fs_cursor *fc, | |||
| 1796 | struct afs_call *call; | 1601 | struct afs_call *call; |
| 1797 | struct afs_net *net = afs_v2net(vnode); | 1602 | struct afs_net *net = afs_v2net(vnode); |
| 1798 | __be32 *bp; | 1603 | __be32 *bp; |
| 1799 | void *tmpbuf; | ||
| 1800 | 1604 | ||
| 1801 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 1605 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 1802 | return yfs_fs_get_volume_status(fc, vs); | 1606 | return yfs_fs_get_volume_status(fc, vs); |
| 1803 | 1607 | ||
| 1804 | _enter(""); | 1608 | _enter(""); |
| 1805 | 1609 | ||
| 1806 | tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL); | 1610 | call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, |
| 1807 | if (!tmpbuf) | 1611 | max(12 * 4, AFSOPAQUEMAX + 1)); |
| 1612 | if (!call) | ||
| 1808 | return -ENOMEM; | 1613 | return -ENOMEM; |
| 1809 | 1614 | ||
| 1810 | call = afs_alloc_flat_call(net, &afs_RXFSGetVolumeStatus, 2 * 4, 12 * 4); | ||
| 1811 | if (!call) { | ||
| 1812 | kfree(tmpbuf); | ||
| 1813 | return -ENOMEM; | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | call->key = fc->key; | 1615 | call->key = fc->key; |
| 1817 | call->reply[0] = vnode; | 1616 | call->out_volstatus = vs; |
| 1818 | call->reply[1] = vs; | ||
| 1819 | call->reply[2] = tmpbuf; | ||
| 1820 | 1617 | ||
| 1821 | /* marshall the parameters */ | 1618 | /* marshall the parameters */ |
| 1822 | bp = call->request; | 1619 | bp = call->request; |
| @@ -1846,7 +1643,7 @@ static int afs_deliver_fs_xxxx_lock(struct afs_call *call) | |||
| 1846 | 1643 | ||
| 1847 | /* unmarshall the reply once we've received all of it */ | 1644 | /* unmarshall the reply once we've received all of it */ |
| 1848 | bp = call->buffer; | 1645 | bp = call->buffer; |
| 1849 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1646 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 1850 | 1647 | ||
| 1851 | _leave(" = 0 [done]"); | 1648 | _leave(" = 0 [done]"); |
| 1852 | return 0; | 1649 | return 0; |
| @@ -1887,7 +1684,8 @@ static const struct afs_call_type afs_RXFSReleaseLock = { | |||
| 1887 | /* | 1684 | /* |
| 1888 | * Set a lock on a file | 1685 | * Set a lock on a file |
| 1889 | */ | 1686 | */ |
| 1890 | int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type) | 1687 | int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type, |
| 1688 | struct afs_status_cb *scb) | ||
| 1891 | { | 1689 | { |
| 1892 | struct afs_vnode *vnode = fc->vnode; | 1690 | struct afs_vnode *vnode = fc->vnode; |
| 1893 | struct afs_call *call; | 1691 | struct afs_call *call; |
| @@ -1895,7 +1693,7 @@ int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type) | |||
| 1895 | __be32 *bp; | 1693 | __be32 *bp; |
| 1896 | 1694 | ||
| 1897 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 1695 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 1898 | return yfs_fs_set_lock(fc, type); | 1696 | return yfs_fs_set_lock(fc, type, scb); |
| 1899 | 1697 | ||
| 1900 | _enter(""); | 1698 | _enter(""); |
| 1901 | 1699 | ||
| @@ -1904,8 +1702,8 @@ int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type) | |||
| 1904 | return -ENOMEM; | 1702 | return -ENOMEM; |
| 1905 | 1703 | ||
| 1906 | call->key = fc->key; | 1704 | call->key = fc->key; |
| 1907 | call->reply[0] = vnode; | 1705 | call->lvnode = vnode; |
| 1908 | call->want_reply_time = true; | 1706 | call->out_scb = scb; |
| 1909 | 1707 | ||
| 1910 | /* marshall the parameters */ | 1708 | /* marshall the parameters */ |
| 1911 | bp = call->request; | 1709 | bp = call->request; |
| @@ -1925,7 +1723,7 @@ int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type) | |||
| 1925 | /* | 1723 | /* |
| 1926 | * extend a lock on a file | 1724 | * extend a lock on a file |
| 1927 | */ | 1725 | */ |
| 1928 | int afs_fs_extend_lock(struct afs_fs_cursor *fc) | 1726 | int afs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) |
| 1929 | { | 1727 | { |
| 1930 | struct afs_vnode *vnode = fc->vnode; | 1728 | struct afs_vnode *vnode = fc->vnode; |
| 1931 | struct afs_call *call; | 1729 | struct afs_call *call; |
| @@ -1933,7 +1731,7 @@ int afs_fs_extend_lock(struct afs_fs_cursor *fc) | |||
| 1933 | __be32 *bp; | 1731 | __be32 *bp; |
| 1934 | 1732 | ||
| 1935 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 1733 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 1936 | return yfs_fs_extend_lock(fc); | 1734 | return yfs_fs_extend_lock(fc, scb); |
| 1937 | 1735 | ||
| 1938 | _enter(""); | 1736 | _enter(""); |
| 1939 | 1737 | ||
| @@ -1942,8 +1740,8 @@ int afs_fs_extend_lock(struct afs_fs_cursor *fc) | |||
| 1942 | return -ENOMEM; | 1740 | return -ENOMEM; |
| 1943 | 1741 | ||
| 1944 | call->key = fc->key; | 1742 | call->key = fc->key; |
| 1945 | call->reply[0] = vnode; | 1743 | call->lvnode = vnode; |
| 1946 | call->want_reply_time = true; | 1744 | call->out_scb = scb; |
| 1947 | 1745 | ||
| 1948 | /* marshall the parameters */ | 1746 | /* marshall the parameters */ |
| 1949 | bp = call->request; | 1747 | bp = call->request; |
| @@ -1962,7 +1760,7 @@ int afs_fs_extend_lock(struct afs_fs_cursor *fc) | |||
| 1962 | /* | 1760 | /* |
| 1963 | * release a lock on a file | 1761 | * release a lock on a file |
| 1964 | */ | 1762 | */ |
| 1965 | int afs_fs_release_lock(struct afs_fs_cursor *fc) | 1763 | int afs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) |
| 1966 | { | 1764 | { |
| 1967 | struct afs_vnode *vnode = fc->vnode; | 1765 | struct afs_vnode *vnode = fc->vnode; |
| 1968 | struct afs_call *call; | 1766 | struct afs_call *call; |
| @@ -1970,7 +1768,7 @@ int afs_fs_release_lock(struct afs_fs_cursor *fc) | |||
| 1970 | __be32 *bp; | 1768 | __be32 *bp; |
| 1971 | 1769 | ||
| 1972 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 1770 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 1973 | return yfs_fs_release_lock(fc); | 1771 | return yfs_fs_release_lock(fc, scb); |
| 1974 | 1772 | ||
| 1975 | _enter(""); | 1773 | _enter(""); |
| 1976 | 1774 | ||
| @@ -1979,7 +1777,8 @@ int afs_fs_release_lock(struct afs_fs_cursor *fc) | |||
| 1979 | return -ENOMEM; | 1777 | return -ENOMEM; |
| 1980 | 1778 | ||
| 1981 | call->key = fc->key; | 1779 | call->key = fc->key; |
| 1982 | call->reply[0] = vnode; | 1780 | call->lvnode = vnode; |
| 1781 | call->out_scb = scb; | ||
| 1983 | 1782 | ||
| 1984 | /* marshall the parameters */ | 1783 | /* marshall the parameters */ |
| 1985 | bp = call->request; | 1784 | bp = call->request; |
| @@ -2085,14 +1884,6 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call) | |||
| 2085 | return 0; | 1884 | return 0; |
| 2086 | } | 1885 | } |
| 2087 | 1886 | ||
| 2088 | static void afs_destroy_fs_get_capabilities(struct afs_call *call) | ||
| 2089 | { | ||
| 2090 | struct afs_server *server = call->reply[0]; | ||
| 2091 | |||
| 2092 | afs_put_server(call->net, server); | ||
| 2093 | afs_flat_call_destructor(call); | ||
| 2094 | } | ||
| 2095 | |||
| 2096 | /* | 1887 | /* |
| 2097 | * FS.GetCapabilities operation type | 1888 | * FS.GetCapabilities operation type |
| 2098 | */ | 1889 | */ |
| @@ -2101,7 +1892,7 @@ static const struct afs_call_type afs_RXFSGetCapabilities = { | |||
| 2101 | .op = afs_FS_GetCapabilities, | 1892 | .op = afs_FS_GetCapabilities, |
| 2102 | .deliver = afs_deliver_fs_get_capabilities, | 1893 | .deliver = afs_deliver_fs_get_capabilities, |
| 2103 | .done = afs_fileserver_probe_result, | 1894 | .done = afs_fileserver_probe_result, |
| 2104 | .destructor = afs_destroy_fs_get_capabilities, | 1895 | .destructor = afs_flat_call_destructor, |
| 2105 | }; | 1896 | }; |
| 2106 | 1897 | ||
| 2107 | /* | 1898 | /* |
| @@ -2124,10 +1915,9 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net, | |||
| 2124 | return ERR_PTR(-ENOMEM); | 1915 | return ERR_PTR(-ENOMEM); |
| 2125 | 1916 | ||
| 2126 | call->key = key; | 1917 | call->key = key; |
| 2127 | call->reply[0] = afs_get_server(server); | 1918 | call->server = afs_get_server(server); |
| 2128 | call->reply[1] = (void *)(long)server_index; | 1919 | call->server_index = server_index; |
| 2129 | call->upgrade = true; | 1920 | call->upgrade = true; |
| 2130 | call->want_reply_time = true; | ||
| 2131 | call->async = true; | 1921 | call->async = true; |
| 2132 | call->max_lifespan = AFS_PROBE_MAX_LIFESPAN; | 1922 | call->max_lifespan = AFS_PROBE_MAX_LIFESPAN; |
| 2133 | 1923 | ||
| @@ -2146,10 +1936,6 @@ struct afs_call *afs_fs_get_capabilities(struct afs_net *net, | |||
| 2146 | */ | 1936 | */ |
| 2147 | static int afs_deliver_fs_fetch_status(struct afs_call *call) | 1937 | static int afs_deliver_fs_fetch_status(struct afs_call *call) |
| 2148 | { | 1938 | { |
| 2149 | struct afs_file_status *status = call->reply[1]; | ||
| 2150 | struct afs_callback *callback = call->reply[2]; | ||
| 2151 | struct afs_volsync *volsync = call->reply[3]; | ||
| 2152 | struct afs_fid *fid = call->reply[0]; | ||
| 2153 | const __be32 *bp; | 1939 | const __be32 *bp; |
| 2154 | int ret; | 1940 | int ret; |
| 2155 | 1941 | ||
| @@ -2157,16 +1943,13 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call) | |||
| 2157 | if (ret < 0) | 1943 | if (ret < 0) |
| 2158 | return ret; | 1944 | return ret; |
| 2159 | 1945 | ||
| 2160 | _enter("{%llx:%llu}", fid->vid, fid->vnode); | ||
| 2161 | |||
| 2162 | /* unmarshall the reply once we've received all of it */ | 1946 | /* unmarshall the reply once we've received all of it */ |
| 2163 | bp = call->buffer; | 1947 | bp = call->buffer; |
| 2164 | ret = afs_decode_status(call, &bp, status, NULL, | 1948 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 2165 | &call->expected_version, NULL); | ||
| 2166 | if (ret < 0) | 1949 | if (ret < 0) |
| 2167 | return ret; | 1950 | return ret; |
| 2168 | xdr_decode_AFSCallBack_raw(call, callback, &bp); | 1951 | xdr_decode_AFSCallBack(&bp, call, call->out_scb); |
| 2169 | xdr_decode_AFSVolSync(&bp, volsync); | 1952 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 2170 | 1953 | ||
| 2171 | _leave(" = 0 [done]"); | 1954 | _leave(" = 0 [done]"); |
| 2172 | return 0; | 1955 | return 0; |
| @@ -2188,15 +1971,14 @@ static const struct afs_call_type afs_RXFSFetchStatus = { | |||
| 2188 | int afs_fs_fetch_status(struct afs_fs_cursor *fc, | 1971 | int afs_fs_fetch_status(struct afs_fs_cursor *fc, |
| 2189 | struct afs_net *net, | 1972 | struct afs_net *net, |
| 2190 | struct afs_fid *fid, | 1973 | struct afs_fid *fid, |
| 2191 | struct afs_file_status *status, | 1974 | struct afs_status_cb *scb, |
| 2192 | struct afs_callback *callback, | ||
| 2193 | struct afs_volsync *volsync) | 1975 | struct afs_volsync *volsync) |
| 2194 | { | 1976 | { |
| 2195 | struct afs_call *call; | 1977 | struct afs_call *call; |
| 2196 | __be32 *bp; | 1978 | __be32 *bp; |
| 2197 | 1979 | ||
| 2198 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 1980 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 2199 | return yfs_fs_fetch_status(fc, net, fid, status, callback, volsync); | 1981 | return yfs_fs_fetch_status(fc, net, fid, scb, volsync); |
| 2200 | 1982 | ||
| 2201 | _enter(",%x,{%llx:%llu},,", | 1983 | _enter(",%x,{%llx:%llu},,", |
| 2202 | key_serial(fc->key), fid->vid, fid->vnode); | 1984 | key_serial(fc->key), fid->vid, fid->vnode); |
| @@ -2208,12 +1990,9 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc, | |||
| 2208 | } | 1990 | } |
| 2209 | 1991 | ||
| 2210 | call->key = fc->key; | 1992 | call->key = fc->key; |
| 2211 | call->reply[0] = fid; | 1993 | call->out_fid = fid; |
| 2212 | call->reply[1] = status; | 1994 | call->out_scb = scb; |
| 2213 | call->reply[2] = callback; | 1995 | call->out_volsync = volsync; |
| 2214 | call->reply[3] = volsync; | ||
| 2215 | call->expected_version = 1; /* vnode->status.data_version */ | ||
| 2216 | call->want_reply_time = true; | ||
| 2217 | 1996 | ||
| 2218 | /* marshall the parameters */ | 1997 | /* marshall the parameters */ |
| 2219 | bp = call->request; | 1998 | bp = call->request; |
| @@ -2222,7 +2001,6 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc, | |||
| 2222 | bp[2] = htonl(fid->vnode); | 2001 | bp[2] = htonl(fid->vnode); |
| 2223 | bp[3] = htonl(fid->unique); | 2002 | bp[3] = htonl(fid->unique); |
| 2224 | 2003 | ||
| 2225 | call->cb_break = fc->cb_break; | ||
| 2226 | afs_use_fs_server(call, fc->cbi); | 2004 | afs_use_fs_server(call, fc->cbi); |
| 2227 | trace_afs_make_fs_call(call, fid); | 2005 | trace_afs_make_fs_call(call, fid); |
| 2228 | afs_set_fc_call(call, fc); | 2006 | afs_set_fc_call(call, fc); |
| @@ -2235,9 +2013,7 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc, | |||
| 2235 | */ | 2013 | */ |
| 2236 | static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | 2014 | static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) |
| 2237 | { | 2015 | { |
| 2238 | struct afs_file_status *statuses; | 2016 | struct afs_status_cb *scb; |
| 2239 | struct afs_callback *callbacks; | ||
| 2240 | struct afs_vnode *vnode = call->reply[0]; | ||
| 2241 | const __be32 *bp; | 2017 | const __be32 *bp; |
| 2242 | u32 tmp; | 2018 | u32 tmp; |
| 2243 | int ret; | 2019 | int ret; |
| @@ -2276,10 +2052,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
| 2276 | return ret; | 2052 | return ret; |
| 2277 | 2053 | ||
| 2278 | bp = call->buffer; | 2054 | bp = call->buffer; |
| 2279 | statuses = call->reply[1]; | 2055 | scb = &call->out_scb[call->count]; |
| 2280 | ret = afs_decode_status(call, &bp, &statuses[call->count], | 2056 | ret = xdr_decode_AFSFetchStatus(&bp, call, scb); |
| 2281 | call->count == 0 ? vnode : NULL, | ||
| 2282 | NULL, NULL); | ||
| 2283 | if (ret < 0) | 2057 | if (ret < 0) |
| 2284 | return ret; | 2058 | return ret; |
| 2285 | 2059 | ||
| @@ -2318,11 +2092,8 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
| 2318 | 2092 | ||
| 2319 | _debug("unmarshall CB array"); | 2093 | _debug("unmarshall CB array"); |
| 2320 | bp = call->buffer; | 2094 | bp = call->buffer; |
| 2321 | callbacks = call->reply[2]; | 2095 | scb = &call->out_scb[call->count]; |
| 2322 | xdr_decode_AFSCallBack_raw(call, &callbacks[call->count], &bp); | 2096 | xdr_decode_AFSCallBack(&bp, call, scb); |
| 2323 | statuses = call->reply[1]; | ||
| 2324 | if (call->count == 0 && vnode && statuses[0].abort_code == 0) | ||
| 2325 | xdr_decode_AFSCallBack(call, vnode, &bp); | ||
| 2326 | call->count++; | 2097 | call->count++; |
| 2327 | if (call->count < call->count2) | 2098 | if (call->count < call->count2) |
| 2328 | goto more_cbs; | 2099 | goto more_cbs; |
| @@ -2337,7 +2108,7 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
| 2337 | return ret; | 2108 | return ret; |
| 2338 | 2109 | ||
| 2339 | bp = call->buffer; | 2110 | bp = call->buffer; |
| 2340 | xdr_decode_AFSVolSync(&bp, call->reply[3]); | 2111 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 2341 | 2112 | ||
| 2342 | call->unmarshall++; | 2113 | call->unmarshall++; |
| 2343 | 2114 | ||
| @@ -2365,8 +2136,7 @@ static const struct afs_call_type afs_RXFSInlineBulkStatus = { | |||
| 2365 | int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | 2136 | int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, |
| 2366 | struct afs_net *net, | 2137 | struct afs_net *net, |
| 2367 | struct afs_fid *fids, | 2138 | struct afs_fid *fids, |
| 2368 | struct afs_file_status *statuses, | 2139 | struct afs_status_cb *statuses, |
| 2369 | struct afs_callback *callbacks, | ||
| 2370 | unsigned int nr_fids, | 2140 | unsigned int nr_fids, |
| 2371 | struct afs_volsync *volsync) | 2141 | struct afs_volsync *volsync) |
| 2372 | { | 2142 | { |
| @@ -2375,7 +2145,7 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | |||
| 2375 | int i; | 2145 | int i; |
| 2376 | 2146 | ||
| 2377 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) | 2147 | if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)) |
| 2378 | return yfs_fs_inline_bulk_status(fc, net, fids, statuses, callbacks, | 2148 | return yfs_fs_inline_bulk_status(fc, net, fids, statuses, |
| 2379 | nr_fids, volsync); | 2149 | nr_fids, volsync); |
| 2380 | 2150 | ||
| 2381 | _enter(",%x,{%llx:%llu},%u", | 2151 | _enter(",%x,{%llx:%llu},%u", |
| @@ -2390,12 +2160,9 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | |||
| 2390 | } | 2160 | } |
| 2391 | 2161 | ||
| 2392 | call->key = fc->key; | 2162 | call->key = fc->key; |
| 2393 | call->reply[0] = NULL; /* vnode for fid[0] */ | 2163 | call->out_scb = statuses; |
| 2394 | call->reply[1] = statuses; | 2164 | call->out_volsync = volsync; |
| 2395 | call->reply[2] = callbacks; | ||
| 2396 | call->reply[3] = volsync; | ||
| 2397 | call->count2 = nr_fids; | 2165 | call->count2 = nr_fids; |
| 2398 | call->want_reply_time = true; | ||
| 2399 | 2166 | ||
| 2400 | /* marshall the parameters */ | 2167 | /* marshall the parameters */ |
| 2401 | bp = call->request; | 2168 | bp = call->request; |
| @@ -2407,7 +2174,6 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | |||
| 2407 | *bp++ = htonl(fids[i].unique); | 2174 | *bp++ = htonl(fids[i].unique); |
| 2408 | } | 2175 | } |
| 2409 | 2176 | ||
| 2410 | call->cb_break = fc->cb_break; | ||
| 2411 | afs_use_fs_server(call, fc->cbi); | 2177 | afs_use_fs_server(call, fc->cbi); |
| 2412 | trace_afs_make_fs_call(call, &fids[0]); | 2178 | trace_afs_make_fs_call(call, &fids[0]); |
| 2413 | afs_set_fc_call(call, fc); | 2179 | afs_set_fc_call(call, fc); |
| @@ -2420,7 +2186,6 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | |||
| 2420 | */ | 2186 | */ |
| 2421 | static int afs_deliver_fs_fetch_acl(struct afs_call *call) | 2187 | static int afs_deliver_fs_fetch_acl(struct afs_call *call) |
| 2422 | { | 2188 | { |
| 2423 | struct afs_vnode *vnode = call->reply[1]; | ||
| 2424 | struct afs_acl *acl; | 2189 | struct afs_acl *acl; |
| 2425 | const __be32 *bp; | 2190 | const __be32 *bp; |
| 2426 | unsigned int size; | 2191 | unsigned int size; |
| @@ -2445,7 +2210,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call) | |||
| 2445 | acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL); | 2210 | acl = kmalloc(struct_size(acl, data, size), GFP_KERNEL); |
| 2446 | if (!acl) | 2211 | if (!acl) |
| 2447 | return -ENOMEM; | 2212 | return -ENOMEM; |
| 2448 | call->reply[0] = acl; | 2213 | call->ret_acl = acl; |
| 2449 | acl->size = call->count2; | 2214 | acl->size = call->count2; |
| 2450 | afs_extract_begin(call, acl->data, size); | 2215 | afs_extract_begin(call, acl->data, size); |
| 2451 | call->unmarshall++; | 2216 | call->unmarshall++; |
| @@ -2466,11 +2231,10 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call) | |||
| 2466 | return ret; | 2231 | return ret; |
| 2467 | 2232 | ||
| 2468 | bp = call->buffer; | 2233 | bp = call->buffer; |
| 2469 | ret = afs_decode_status(call, &bp, &vnode->status, vnode, | 2234 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); |
| 2470 | &vnode->status.data_version, NULL); | ||
| 2471 | if (ret < 0) | 2235 | if (ret < 0) |
| 2472 | return ret; | 2236 | return ret; |
| 2473 | xdr_decode_AFSVolSync(&bp, call->reply[2]); | 2237 | xdr_decode_AFSVolSync(&bp, call->out_volsync); |
| 2474 | 2238 | ||
| 2475 | call->unmarshall++; | 2239 | call->unmarshall++; |
| 2476 | 2240 | ||
| @@ -2484,7 +2248,7 @@ static int afs_deliver_fs_fetch_acl(struct afs_call *call) | |||
| 2484 | 2248 | ||
| 2485 | static void afs_destroy_fs_fetch_acl(struct afs_call *call) | 2249 | static void afs_destroy_fs_fetch_acl(struct afs_call *call) |
| 2486 | { | 2250 | { |
| 2487 | kfree(call->reply[0]); | 2251 | kfree(call->ret_acl); |
| 2488 | afs_flat_call_destructor(call); | 2252 | afs_flat_call_destructor(call); |
| 2489 | } | 2253 | } |
| 2490 | 2254 | ||
| @@ -2501,7 +2265,8 @@ static const struct afs_call_type afs_RXFSFetchACL = { | |||
| 2501 | /* | 2265 | /* |
| 2502 | * Fetch the ACL for a file. | 2266 | * Fetch the ACL for a file. |
| 2503 | */ | 2267 | */ |
| 2504 | struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc) | 2268 | struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc, |
| 2269 | struct afs_status_cb *scb) | ||
| 2505 | { | 2270 | { |
| 2506 | struct afs_vnode *vnode = fc->vnode; | 2271 | struct afs_vnode *vnode = fc->vnode; |
| 2507 | struct afs_call *call; | 2272 | struct afs_call *call; |
| @@ -2518,10 +2283,9 @@ struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc) | |||
| 2518 | } | 2283 | } |
| 2519 | 2284 | ||
| 2520 | call->key = fc->key; | 2285 | call->key = fc->key; |
| 2521 | call->reply[0] = NULL; | 2286 | call->ret_acl = NULL; |
| 2522 | call->reply[1] = vnode; | 2287 | call->out_scb = scb; |
| 2523 | call->reply[2] = NULL; /* volsync */ | 2288 | call->out_volsync = NULL; |
| 2524 | call->ret_reply0 = true; | ||
| 2525 | 2289 | ||
| 2526 | /* marshall the parameters */ | 2290 | /* marshall the parameters */ |
| 2527 | bp = call->request; | 2291 | bp = call->request; |
| @@ -2530,7 +2294,6 @@ struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc) | |||
| 2530 | bp[2] = htonl(vnode->fid.vnode); | 2294 | bp[2] = htonl(vnode->fid.vnode); |
| 2531 | bp[3] = htonl(vnode->fid.unique); | 2295 | bp[3] = htonl(vnode->fid.unique); |
| 2532 | 2296 | ||
| 2533 | call->cb_break = fc->cb_break; | ||
| 2534 | afs_use_fs_server(call, fc->cbi); | 2297 | afs_use_fs_server(call, fc->cbi); |
| 2535 | trace_afs_make_fs_call(call, &vnode->fid); | 2298 | trace_afs_make_fs_call(call, &vnode->fid); |
| 2536 | afs_make_call(&fc->ac, call, GFP_KERNEL); | 2299 | afs_make_call(&fc->ac, call, GFP_KERNEL); |
| @@ -2538,19 +2301,43 @@ struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *fc) | |||
| 2538 | } | 2301 | } |
| 2539 | 2302 | ||
| 2540 | /* | 2303 | /* |
| 2304 | * Deliver reply data to any operation that returns file status and volume | ||
| 2305 | * sync. | ||
| 2306 | */ | ||
| 2307 | static int afs_deliver_fs_file_status_and_vol(struct afs_call *call) | ||
| 2308 | { | ||
| 2309 | const __be32 *bp; | ||
| 2310 | int ret; | ||
| 2311 | |||
| 2312 | ret = afs_transfer_reply(call); | ||
| 2313 | if (ret < 0) | ||
| 2314 | return ret; | ||
| 2315 | |||
| 2316 | bp = call->buffer; | ||
| 2317 | ret = xdr_decode_AFSFetchStatus(&bp, call, call->out_scb); | ||
| 2318 | if (ret < 0) | ||
| 2319 | return ret; | ||
| 2320 | xdr_decode_AFSVolSync(&bp, call->out_volsync); | ||
| 2321 | |||
| 2322 | _leave(" = 0 [done]"); | ||
| 2323 | return 0; | ||
| 2324 | } | ||
| 2325 | |||
| 2326 | /* | ||
| 2541 | * FS.StoreACL operation type | 2327 | * FS.StoreACL operation type |
| 2542 | */ | 2328 | */ |
| 2543 | static const struct afs_call_type afs_RXFSStoreACL = { | 2329 | static const struct afs_call_type afs_RXFSStoreACL = { |
| 2544 | .name = "FS.StoreACL", | 2330 | .name = "FS.StoreACL", |
| 2545 | .op = afs_FS_StoreACL, | 2331 | .op = afs_FS_StoreACL, |
| 2546 | .deliver = afs_deliver_fs_status_and_vol, | 2332 | .deliver = afs_deliver_fs_file_status_and_vol, |
| 2547 | .destructor = afs_flat_call_destructor, | 2333 | .destructor = afs_flat_call_destructor, |
| 2548 | }; | 2334 | }; |
| 2549 | 2335 | ||
| 2550 | /* | 2336 | /* |
| 2551 | * Fetch the ACL for a file. | 2337 | * Fetch the ACL for a file. |
| 2552 | */ | 2338 | */ |
| 2553 | int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl) | 2339 | int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl, |
| 2340 | struct afs_status_cb *scb) | ||
| 2554 | { | 2341 | { |
| 2555 | struct afs_vnode *vnode = fc->vnode; | 2342 | struct afs_vnode *vnode = fc->vnode; |
| 2556 | struct afs_call *call; | 2343 | struct afs_call *call; |
| @@ -2570,8 +2357,8 @@ int afs_fs_store_acl(struct afs_fs_cursor *fc, const struct afs_acl *acl) | |||
| 2570 | } | 2357 | } |
| 2571 | 2358 | ||
| 2572 | call->key = fc->key; | 2359 | call->key = fc->key; |
| 2573 | call->reply[0] = vnode; | 2360 | call->out_scb = scb; |
| 2574 | call->reply[2] = NULL; /* volsync */ | 2361 | call->out_volsync = NULL; |
| 2575 | 2362 | ||
| 2576 | /* marshall the parameters */ | 2363 | /* marshall the parameters */ |
| 2577 | bp = call->request; | 2364 | bp = call->request; |
diff --git a/fs/afs/inode.c b/fs/afs/inode.c index bf8f56e851df..b42d9d09669c 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/namei.h> | 23 | #include <linux/namei.h> |
| 24 | #include <linux/iversion.h> | 24 | #include <linux/iversion.h> |
| 25 | #include "internal.h" | 25 | #include "internal.h" |
| 26 | #include "afs_fs.h" | ||
| 26 | 27 | ||
| 27 | static const struct inode_operations afs_symlink_inode_operations = { | 28 | static const struct inode_operations afs_symlink_inode_operations = { |
| 28 | .get_link = page_get_link, | 29 | .get_link = page_get_link, |
| @@ -58,38 +59,50 @@ static noinline void dump_vnode(struct afs_vnode *vnode, struct afs_vnode *paren | |||
| 58 | * Initialise an inode from the vnode status. | 59 | * Initialise an inode from the vnode status. |
| 59 | */ | 60 | */ |
| 60 | static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key, | 61 | static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key, |
| 61 | struct afs_vnode *parent_vnode) | 62 | struct afs_cb_interest *cbi, |
| 63 | struct afs_vnode *parent_vnode, | ||
| 64 | struct afs_status_cb *scb) | ||
| 62 | { | 65 | { |
| 66 | struct afs_cb_interest *old_cbi = NULL; | ||
| 67 | struct afs_file_status *status = &scb->status; | ||
| 63 | struct inode *inode = AFS_VNODE_TO_I(vnode); | 68 | struct inode *inode = AFS_VNODE_TO_I(vnode); |
| 69 | struct timespec64 t; | ||
| 64 | 70 | ||
| 65 | _debug("FS: ft=%d lk=%d sz=%llu ver=%Lu mod=%hu", | 71 | _debug("FS: ft=%d lk=%d sz=%llu ver=%Lu mod=%hu", |
| 66 | vnode->status.type, | 72 | status->type, |
| 67 | vnode->status.nlink, | 73 | status->nlink, |
| 68 | (unsigned long long) vnode->status.size, | 74 | (unsigned long long) status->size, |
| 69 | vnode->status.data_version, | 75 | status->data_version, |
| 70 | vnode->status.mode); | 76 | status->mode); |
| 71 | 77 | ||
| 72 | read_seqlock_excl(&vnode->cb_lock); | 78 | write_seqlock(&vnode->cb_lock); |
| 73 | 79 | ||
| 74 | afs_update_inode_from_status(vnode, &vnode->status, NULL, | 80 | vnode->status = *status; |
| 75 | AFS_VNODE_NOT_YET_SET); | ||
| 76 | 81 | ||
| 77 | switch (vnode->status.type) { | 82 | t = status->mtime_client; |
| 83 | inode->i_ctime = t; | ||
| 84 | inode->i_mtime = t; | ||
| 85 | inode->i_atime = t; | ||
| 86 | inode->i_uid = make_kuid(&init_user_ns, status->owner); | ||
| 87 | inode->i_gid = make_kgid(&init_user_ns, status->group); | ||
| 88 | set_nlink(&vnode->vfs_inode, status->nlink); | ||
| 89 | |||
| 90 | switch (status->type) { | ||
| 78 | case AFS_FTYPE_FILE: | 91 | case AFS_FTYPE_FILE: |
| 79 | inode->i_mode = S_IFREG | vnode->status.mode; | 92 | inode->i_mode = S_IFREG | status->mode; |
| 80 | inode->i_op = &afs_file_inode_operations; | 93 | inode->i_op = &afs_file_inode_operations; |
| 81 | inode->i_fop = &afs_file_operations; | 94 | inode->i_fop = &afs_file_operations; |
| 82 | inode->i_mapping->a_ops = &afs_fs_aops; | 95 | inode->i_mapping->a_ops = &afs_fs_aops; |
| 83 | break; | 96 | break; |
| 84 | case AFS_FTYPE_DIR: | 97 | case AFS_FTYPE_DIR: |
| 85 | inode->i_mode = S_IFDIR | vnode->status.mode; | 98 | inode->i_mode = S_IFDIR | status->mode; |
| 86 | inode->i_op = &afs_dir_inode_operations; | 99 | inode->i_op = &afs_dir_inode_operations; |
| 87 | inode->i_fop = &afs_dir_file_operations; | 100 | inode->i_fop = &afs_dir_file_operations; |
| 88 | inode->i_mapping->a_ops = &afs_dir_aops; | 101 | inode->i_mapping->a_ops = &afs_dir_aops; |
| 89 | break; | 102 | break; |
| 90 | case AFS_FTYPE_SYMLINK: | 103 | case AFS_FTYPE_SYMLINK: |
| 91 | /* Symlinks with a mode of 0644 are actually mountpoints. */ | 104 | /* Symlinks with a mode of 0644 are actually mountpoints. */ |
| 92 | if ((vnode->status.mode & 0777) == 0644) { | 105 | if ((status->mode & 0777) == 0644) { |
| 93 | inode->i_flags |= S_AUTOMOUNT; | 106 | inode->i_flags |= S_AUTOMOUNT; |
| 94 | 107 | ||
| 95 | set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); | 108 | set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); |
| @@ -99,7 +112,7 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key, | |||
| 99 | inode->i_fop = &afs_mntpt_file_operations; | 112 | inode->i_fop = &afs_mntpt_file_operations; |
| 100 | inode->i_mapping->a_ops = &afs_fs_aops; | 113 | inode->i_mapping->a_ops = &afs_fs_aops; |
| 101 | } else { | 114 | } else { |
| 102 | inode->i_mode = S_IFLNK | vnode->status.mode; | 115 | inode->i_mode = S_IFLNK | status->mode; |
| 103 | inode->i_op = &afs_symlink_inode_operations; | 116 | inode->i_op = &afs_symlink_inode_operations; |
| 104 | inode->i_mapping->a_ops = &afs_fs_aops; | 117 | inode->i_mapping->a_ops = &afs_fs_aops; |
| 105 | } | 118 | } |
| @@ -107,7 +120,7 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key, | |||
| 107 | break; | 120 | break; |
| 108 | default: | 121 | default: |
| 109 | dump_vnode(vnode, parent_vnode); | 122 | dump_vnode(vnode, parent_vnode); |
| 110 | read_sequnlock_excl(&vnode->cb_lock); | 123 | write_sequnlock(&vnode->cb_lock); |
| 111 | return afs_protocol_error(NULL, -EBADMSG, afs_eproto_file_type); | 124 | return afs_protocol_error(NULL, -EBADMSG, afs_eproto_file_type); |
| 112 | } | 125 | } |
| 113 | 126 | ||
| @@ -116,17 +129,175 @@ static int afs_inode_init_from_status(struct afs_vnode *vnode, struct key *key, | |||
| 116 | * for consistency with other AFS clients. | 129 | * for consistency with other AFS clients. |
| 117 | */ | 130 | */ |
| 118 | inode->i_blocks = ((i_size_read(inode) + 1023) >> 10) << 1; | 131 | inode->i_blocks = ((i_size_read(inode) + 1023) >> 10) << 1; |
| 119 | vnode->invalid_before = vnode->status.data_version; | 132 | i_size_write(&vnode->vfs_inode, status->size); |
| 133 | |||
| 134 | vnode->invalid_before = status->data_version; | ||
| 135 | inode_set_iversion_raw(&vnode->vfs_inode, status->data_version); | ||
| 136 | |||
| 137 | if (!scb->have_cb) { | ||
| 138 | /* it's a symlink we just created (the fileserver | ||
| 139 | * didn't give us a callback) */ | ||
| 140 | vnode->cb_expires_at = ktime_get_real_seconds(); | ||
| 141 | } else { | ||
| 142 | vnode->cb_expires_at = scb->callback.expires_at; | ||
| 143 | old_cbi = rcu_dereference_protected(vnode->cb_interest, | ||
| 144 | lockdep_is_held(&vnode->cb_lock.lock)); | ||
| 145 | if (cbi != old_cbi) | ||
| 146 | rcu_assign_pointer(vnode->cb_interest, afs_get_cb_interest(cbi)); | ||
| 147 | else | ||
| 148 | old_cbi = NULL; | ||
| 149 | set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | ||
| 150 | } | ||
| 120 | 151 | ||
| 121 | read_sequnlock_excl(&vnode->cb_lock); | 152 | write_sequnlock(&vnode->cb_lock); |
| 153 | afs_put_cb_interest(afs_v2net(vnode), old_cbi); | ||
| 122 | return 0; | 154 | return 0; |
| 123 | } | 155 | } |
| 124 | 156 | ||
| 125 | /* | 157 | /* |
| 158 | * Update the core inode struct from a returned status record. | ||
| 159 | */ | ||
| 160 | static void afs_apply_status(struct afs_fs_cursor *fc, | ||
| 161 | struct afs_vnode *vnode, | ||
| 162 | struct afs_status_cb *scb, | ||
| 163 | const afs_dataversion_t *expected_version) | ||
| 164 | { | ||
| 165 | struct afs_file_status *status = &scb->status; | ||
| 166 | struct timespec64 t; | ||
| 167 | umode_t mode; | ||
| 168 | bool data_changed = false; | ||
| 169 | |||
| 170 | BUG_ON(test_bit(AFS_VNODE_UNSET, &vnode->flags)); | ||
| 171 | |||
| 172 | if (status->type != vnode->status.type) { | ||
| 173 | pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n", | ||
| 174 | vnode->fid.vid, | ||
| 175 | vnode->fid.vnode, | ||
| 176 | vnode->fid.unique, | ||
| 177 | status->type, vnode->status.type); | ||
| 178 | afs_protocol_error(NULL, -EBADMSG, afs_eproto_bad_status); | ||
| 179 | return; | ||
| 180 | } | ||
| 181 | |||
| 182 | if (status->nlink != vnode->status.nlink) | ||
| 183 | set_nlink(&vnode->vfs_inode, status->nlink); | ||
| 184 | |||
| 185 | if (status->owner != vnode->status.owner) | ||
| 186 | vnode->vfs_inode.i_uid = make_kuid(&init_user_ns, status->owner); | ||
| 187 | |||
| 188 | if (status->group != vnode->status.group) | ||
| 189 | vnode->vfs_inode.i_gid = make_kgid(&init_user_ns, status->group); | ||
| 190 | |||
| 191 | if (status->mode != vnode->status.mode) { | ||
| 192 | mode = vnode->vfs_inode.i_mode; | ||
| 193 | mode &= ~S_IALLUGO; | ||
| 194 | mode |= status->mode; | ||
| 195 | WRITE_ONCE(vnode->vfs_inode.i_mode, mode); | ||
| 196 | } | ||
| 197 | |||
| 198 | t = status->mtime_client; | ||
| 199 | vnode->vfs_inode.i_ctime = t; | ||
| 200 | vnode->vfs_inode.i_mtime = t; | ||
| 201 | vnode->vfs_inode.i_atime = t; | ||
| 202 | |||
| 203 | if (vnode->status.data_version != status->data_version) | ||
| 204 | data_changed = true; | ||
| 205 | |||
| 206 | vnode->status = *status; | ||
| 207 | |||
| 208 | if (expected_version && | ||
| 209 | *expected_version != status->data_version) { | ||
| 210 | kdebug("vnode modified %llx on {%llx:%llu} [exp %llx] %s", | ||
| 211 | (unsigned long long) status->data_version, | ||
| 212 | vnode->fid.vid, vnode->fid.vnode, | ||
| 213 | (unsigned long long) *expected_version, | ||
| 214 | fc->type ? fc->type->name : "???"); | ||
| 215 | vnode->invalid_before = status->data_version; | ||
| 216 | if (vnode->status.type == AFS_FTYPE_DIR) { | ||
| 217 | if (test_and_clear_bit(AFS_VNODE_DIR_VALID, &vnode->flags)) | ||
| 218 | afs_stat_v(vnode, n_inval); | ||
| 219 | } else { | ||
| 220 | set_bit(AFS_VNODE_ZAP_DATA, &vnode->flags); | ||
| 221 | } | ||
| 222 | } else if (vnode->status.type == AFS_FTYPE_DIR) { | ||
| 223 | /* Expected directory change is handled elsewhere so | ||
| 224 | * that we can locally edit the directory and save on a | ||
| 225 | * download. | ||
| 226 | */ | ||
| 227 | if (test_bit(AFS_VNODE_DIR_VALID, &vnode->flags)) | ||
| 228 | data_changed = false; | ||
| 229 | } | ||
| 230 | |||
| 231 | if (data_changed) { | ||
| 232 | inode_set_iversion_raw(&vnode->vfs_inode, status->data_version); | ||
| 233 | i_size_write(&vnode->vfs_inode, status->size); | ||
| 234 | } | ||
| 235 | } | ||
| 236 | |||
| 237 | /* | ||
| 238 | * Apply a callback to a vnode. | ||
| 239 | */ | ||
| 240 | static void afs_apply_callback(struct afs_fs_cursor *fc, | ||
| 241 | struct afs_vnode *vnode, | ||
| 242 | struct afs_status_cb *scb, | ||
| 243 | unsigned int cb_break) | ||
| 244 | { | ||
| 245 | struct afs_cb_interest *old; | ||
| 246 | struct afs_callback *cb = &scb->callback; | ||
| 247 | |||
| 248 | if (!afs_cb_is_broken(cb_break, vnode, fc->cbi)) { | ||
| 249 | vnode->cb_expires_at = cb->expires_at; | ||
| 250 | old = rcu_dereference_protected(vnode->cb_interest, | ||
| 251 | lockdep_is_held(&vnode->cb_lock.lock)); | ||
| 252 | if (old != fc->cbi) { | ||
| 253 | rcu_assign_pointer(vnode->cb_interest, afs_get_cb_interest(fc->cbi)); | ||
| 254 | afs_put_cb_interest(afs_v2net(vnode), old); | ||
| 255 | } | ||
| 256 | set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | ||
| 257 | } | ||
| 258 | } | ||
| 259 | |||
| 260 | /* | ||
| 261 | * Apply the received status and callback to an inode all in the same critical | ||
| 262 | * section to avoid races with afs_validate(). | ||
| 263 | */ | ||
| 264 | void afs_vnode_commit_status(struct afs_fs_cursor *fc, | ||
| 265 | struct afs_vnode *vnode, | ||
| 266 | unsigned int cb_break, | ||
| 267 | const afs_dataversion_t *expected_version, | ||
| 268 | struct afs_status_cb *scb) | ||
| 269 | { | ||
| 270 | if (fc->ac.error != 0) | ||
| 271 | return; | ||
| 272 | |||
| 273 | write_seqlock(&vnode->cb_lock); | ||
| 274 | |||
| 275 | if (scb->have_error) { | ||
| 276 | if (scb->status.abort_code == VNOVNODE) { | ||
| 277 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | ||
| 278 | clear_nlink(&vnode->vfs_inode); | ||
| 279 | __afs_break_callback(vnode); | ||
| 280 | } | ||
| 281 | } else { | ||
| 282 | if (scb->have_status) | ||
| 283 | afs_apply_status(fc, vnode, scb, expected_version); | ||
| 284 | if (scb->have_cb) | ||
| 285 | afs_apply_callback(fc, vnode, scb, cb_break); | ||
| 286 | } | ||
| 287 | |||
| 288 | write_sequnlock(&vnode->cb_lock); | ||
| 289 | |||
| 290 | if (fc->ac.error == 0 && scb->have_status) | ||
| 291 | afs_cache_permit(vnode, fc->key, cb_break, scb); | ||
| 292 | } | ||
| 293 | |||
| 294 | /* | ||
| 126 | * Fetch file status from the volume. | 295 | * Fetch file status from the volume. |
| 127 | */ | 296 | */ |
| 128 | int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode) | 297 | int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool is_new, |
| 298 | afs_access_t *_caller_access) | ||
| 129 | { | 299 | { |
| 300 | struct afs_status_cb *scb; | ||
| 130 | struct afs_fs_cursor fc; | 301 | struct afs_fs_cursor fc; |
| 131 | int ret; | 302 | int ret; |
| 132 | 303 | ||
| @@ -135,18 +306,38 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode) | |||
| 135 | vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique, | 306 | vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique, |
| 136 | vnode->flags); | 307 | vnode->flags); |
| 137 | 308 | ||
| 309 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 310 | if (!scb) | ||
| 311 | return -ENOMEM; | ||
| 312 | |||
| 138 | ret = -ERESTARTSYS; | 313 | ret = -ERESTARTSYS; |
| 139 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { | 314 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { |
| 315 | afs_dataversion_t data_version = vnode->status.data_version; | ||
| 316 | |||
| 140 | while (afs_select_fileserver(&fc)) { | 317 | while (afs_select_fileserver(&fc)) { |
| 141 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 318 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 142 | afs_fs_fetch_file_status(&fc, NULL, new_inode); | 319 | afs_fs_fetch_file_status(&fc, scb, NULL); |
| 143 | } | 320 | } |
| 144 | 321 | ||
| 145 | afs_check_for_remote_deletion(&fc, fc.vnode); | 322 | if (fc.error) { |
| 146 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 323 | /* Do nothing. */ |
| 324 | } else if (is_new) { | ||
| 325 | ret = afs_inode_init_from_status(vnode, key, fc.cbi, | ||
| 326 | NULL, scb); | ||
| 327 | fc.error = ret; | ||
| 328 | if (ret == 0) | ||
| 329 | afs_cache_permit(vnode, key, fc.cb_break, scb); | ||
| 330 | } else { | ||
| 331 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, | ||
| 332 | &data_version, scb); | ||
| 333 | } | ||
| 334 | afs_check_for_remote_deletion(&fc, vnode); | ||
| 147 | ret = afs_end_vnode_operation(&fc); | 335 | ret = afs_end_vnode_operation(&fc); |
| 148 | } | 336 | } |
| 149 | 337 | ||
| 338 | if (ret == 0 && _caller_access) | ||
| 339 | *_caller_access = scb->status.caller_access; | ||
| 340 | kfree(scb); | ||
| 150 | _leave(" = %d", ret); | 341 | _leave(" = %d", ret); |
| 151 | return ret; | 342 | return ret; |
| 152 | } | 343 | } |
| @@ -156,10 +347,10 @@ int afs_fetch_status(struct afs_vnode *vnode, struct key *key, bool new_inode) | |||
| 156 | */ | 347 | */ |
| 157 | int afs_iget5_test(struct inode *inode, void *opaque) | 348 | int afs_iget5_test(struct inode *inode, void *opaque) |
| 158 | { | 349 | { |
| 159 | struct afs_iget_data *data = opaque; | 350 | struct afs_iget_data *iget_data = opaque; |
| 160 | struct afs_vnode *vnode = AFS_FS_I(inode); | 351 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 161 | 352 | ||
| 162 | return memcmp(&vnode->fid, &data->fid, sizeof(data->fid)) == 0; | 353 | return memcmp(&vnode->fid, &iget_data->fid, sizeof(iget_data->fid)) == 0; |
| 163 | } | 354 | } |
| 164 | 355 | ||
| 165 | /* | 356 | /* |
| @@ -177,17 +368,19 @@ static int afs_iget5_pseudo_dir_test(struct inode *inode, void *opaque) | |||
| 177 | */ | 368 | */ |
| 178 | static int afs_iget5_set(struct inode *inode, void *opaque) | 369 | static int afs_iget5_set(struct inode *inode, void *opaque) |
| 179 | { | 370 | { |
| 180 | struct afs_iget_data *data = opaque; | 371 | struct afs_iget_data *iget_data = opaque; |
| 181 | struct afs_vnode *vnode = AFS_FS_I(inode); | 372 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 182 | 373 | ||
| 183 | vnode->fid = data->fid; | 374 | vnode->fid = iget_data->fid; |
| 184 | vnode->volume = data->volume; | 375 | vnode->volume = iget_data->volume; |
| 376 | vnode->cb_v_break = iget_data->cb_v_break; | ||
| 377 | vnode->cb_s_break = iget_data->cb_s_break; | ||
| 185 | 378 | ||
| 186 | /* YFS supports 96-bit vnode IDs, but Linux only supports | 379 | /* YFS supports 96-bit vnode IDs, but Linux only supports |
| 187 | * 64-bit inode numbers. | 380 | * 64-bit inode numbers. |
| 188 | */ | 381 | */ |
| 189 | inode->i_ino = data->fid.vnode; | 382 | inode->i_ino = iget_data->fid.vnode; |
| 190 | inode->i_generation = data->fid.unique; | 383 | inode->i_generation = iget_data->fid.unique; |
| 191 | return 0; | 384 | return 0; |
| 192 | } | 385 | } |
| 193 | 386 | ||
| @@ -197,38 +390,42 @@ static int afs_iget5_set(struct inode *inode, void *opaque) | |||
| 197 | */ | 390 | */ |
| 198 | struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root) | 391 | struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root) |
| 199 | { | 392 | { |
| 200 | struct afs_iget_data data; | ||
| 201 | struct afs_super_info *as; | 393 | struct afs_super_info *as; |
| 202 | struct afs_vnode *vnode; | 394 | struct afs_vnode *vnode; |
| 203 | struct inode *inode; | 395 | struct inode *inode; |
| 204 | static atomic_t afs_autocell_ino; | 396 | static atomic_t afs_autocell_ino; |
| 205 | 397 | ||
| 398 | struct afs_iget_data iget_data = { | ||
| 399 | .cb_v_break = 0, | ||
| 400 | .cb_s_break = 0, | ||
| 401 | }; | ||
| 402 | |||
| 206 | _enter(""); | 403 | _enter(""); |
| 207 | 404 | ||
| 208 | as = sb->s_fs_info; | 405 | as = sb->s_fs_info; |
| 209 | if (as->volume) { | 406 | if (as->volume) { |
| 210 | data.volume = as->volume; | 407 | iget_data.volume = as->volume; |
| 211 | data.fid.vid = as->volume->vid; | 408 | iget_data.fid.vid = as->volume->vid; |
| 212 | } | 409 | } |
| 213 | if (root) { | 410 | if (root) { |
| 214 | data.fid.vnode = 1; | 411 | iget_data.fid.vnode = 1; |
| 215 | data.fid.unique = 1; | 412 | iget_data.fid.unique = 1; |
| 216 | } else { | 413 | } else { |
| 217 | data.fid.vnode = atomic_inc_return(&afs_autocell_ino); | 414 | iget_data.fid.vnode = atomic_inc_return(&afs_autocell_ino); |
| 218 | data.fid.unique = 0; | 415 | iget_data.fid.unique = 0; |
| 219 | } | 416 | } |
| 220 | 417 | ||
| 221 | inode = iget5_locked(sb, data.fid.vnode, | 418 | inode = iget5_locked(sb, iget_data.fid.vnode, |
| 222 | afs_iget5_pseudo_dir_test, afs_iget5_set, | 419 | afs_iget5_pseudo_dir_test, afs_iget5_set, |
| 223 | &data); | 420 | &iget_data); |
| 224 | if (!inode) { | 421 | if (!inode) { |
| 225 | _leave(" = -ENOMEM"); | 422 | _leave(" = -ENOMEM"); |
| 226 | return ERR_PTR(-ENOMEM); | 423 | return ERR_PTR(-ENOMEM); |
| 227 | } | 424 | } |
| 228 | 425 | ||
| 229 | _debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }", | 426 | _debug("GOT INODE %p { ino=%lu, vl=%llx, vn=%llx, u=%x }", |
| 230 | inode, inode->i_ino, data.fid.vid, data.fid.vnode, | 427 | inode, inode->i_ino, iget_data.fid.vid, iget_data.fid.vnode, |
| 231 | data.fid.unique); | 428 | iget_data.fid.unique); |
| 232 | 429 | ||
| 233 | vnode = AFS_FS_I(inode); | 430 | vnode = AFS_FS_I(inode); |
| 234 | 431 | ||
| @@ -299,23 +496,24 @@ static void afs_get_inode_cache(struct afs_vnode *vnode) | |||
| 299 | * inode retrieval | 496 | * inode retrieval |
| 300 | */ | 497 | */ |
| 301 | struct inode *afs_iget(struct super_block *sb, struct key *key, | 498 | struct inode *afs_iget(struct super_block *sb, struct key *key, |
| 302 | struct afs_fid *fid, struct afs_file_status *status, | 499 | struct afs_iget_data *iget_data, |
| 303 | struct afs_callback *cb, struct afs_cb_interest *cbi, | 500 | struct afs_status_cb *scb, |
| 501 | struct afs_cb_interest *cbi, | ||
| 304 | struct afs_vnode *parent_vnode) | 502 | struct afs_vnode *parent_vnode) |
| 305 | { | 503 | { |
| 306 | struct afs_iget_data data = { .fid = *fid }; | ||
| 307 | struct afs_super_info *as; | 504 | struct afs_super_info *as; |
| 308 | struct afs_vnode *vnode; | 505 | struct afs_vnode *vnode; |
| 506 | struct afs_fid *fid = &iget_data->fid; | ||
| 309 | struct inode *inode; | 507 | struct inode *inode; |
| 310 | int ret; | 508 | int ret; |
| 311 | 509 | ||
| 312 | _enter(",{%llx:%llu.%u},,", fid->vid, fid->vnode, fid->unique); | 510 | _enter(",{%llx:%llu.%u},,", fid->vid, fid->vnode, fid->unique); |
| 313 | 511 | ||
| 314 | as = sb->s_fs_info; | 512 | as = sb->s_fs_info; |
| 315 | data.volume = as->volume; | 513 | iget_data->volume = as->volume; |
| 316 | 514 | ||
| 317 | inode = iget5_locked(sb, fid->vnode, afs_iget5_test, afs_iget5_set, | 515 | inode = iget5_locked(sb, fid->vnode, afs_iget5_test, afs_iget5_set, |
| 318 | &data); | 516 | iget_data); |
| 319 | if (!inode) { | 517 | if (!inode) { |
| 320 | _leave(" = -ENOMEM"); | 518 | _leave(" = -ENOMEM"); |
| 321 | return ERR_PTR(-ENOMEM); | 519 | return ERR_PTR(-ENOMEM); |
| @@ -332,43 +530,25 @@ struct inode *afs_iget(struct super_block *sb, struct key *key, | |||
| 332 | return inode; | 530 | return inode; |
| 333 | } | 531 | } |
| 334 | 532 | ||
| 335 | if (!status) { | 533 | if (!scb) { |
| 336 | /* it's a remotely extant inode */ | 534 | /* it's a remotely extant inode */ |
| 337 | ret = afs_fetch_status(vnode, key, true); | 535 | ret = afs_fetch_status(vnode, key, true, NULL); |
| 338 | if (ret < 0) | 536 | if (ret < 0) |
| 339 | goto bad_inode; | 537 | goto bad_inode; |
| 340 | } else { | 538 | } else { |
| 341 | /* it's an inode we just created */ | 539 | ret = afs_inode_init_from_status(vnode, key, cbi, parent_vnode, |
| 342 | memcpy(&vnode->status, status, sizeof(vnode->status)); | 540 | scb); |
| 343 | 541 | if (ret < 0) | |
| 344 | if (!cb) { | 542 | goto bad_inode; |
| 345 | /* it's a symlink we just created (the fileserver | ||
| 346 | * didn't give us a callback) */ | ||
| 347 | vnode->cb_version = 0; | ||
| 348 | vnode->cb_type = 0; | ||
| 349 | vnode->cb_expires_at = ktime_get(); | ||
| 350 | } else { | ||
| 351 | vnode->cb_version = cb->version; | ||
| 352 | vnode->cb_type = cb->type; | ||
| 353 | vnode->cb_expires_at = cb->expires_at; | ||
| 354 | vnode->cb_interest = afs_get_cb_interest(cbi); | ||
| 355 | set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | ||
| 356 | } | ||
| 357 | |||
| 358 | vnode->cb_expires_at += ktime_get_real_seconds(); | ||
| 359 | } | 543 | } |
| 360 | 544 | ||
| 361 | ret = afs_inode_init_from_status(vnode, key, parent_vnode); | ||
| 362 | if (ret < 0) | ||
| 363 | goto bad_inode; | ||
| 364 | |||
| 365 | afs_get_inode_cache(vnode); | 545 | afs_get_inode_cache(vnode); |
| 366 | 546 | ||
| 367 | /* success */ | 547 | /* success */ |
| 368 | clear_bit(AFS_VNODE_UNSET, &vnode->flags); | 548 | clear_bit(AFS_VNODE_UNSET, &vnode->flags); |
| 369 | inode->i_flags |= S_NOATIME; | 549 | inode->i_flags |= S_NOATIME; |
| 370 | unlock_new_inode(inode); | 550 | unlock_new_inode(inode); |
| 371 | _leave(" = %p [CB { v=%u t=%u }]", inode, vnode->cb_version, vnode->cb_type); | 551 | _leave(" = %p", inode); |
| 372 | return inode; | 552 | return inode; |
| 373 | 553 | ||
| 374 | /* failure */ | 554 | /* failure */ |
| @@ -400,6 +580,66 @@ void afs_zap_data(struct afs_vnode *vnode) | |||
| 400 | } | 580 | } |
| 401 | 581 | ||
| 402 | /* | 582 | /* |
| 583 | * Check the validity of a vnode/inode. | ||
| 584 | */ | ||
| 585 | bool afs_check_validity(struct afs_vnode *vnode) | ||
| 586 | { | ||
| 587 | struct afs_cb_interest *cbi; | ||
| 588 | struct afs_server *server; | ||
| 589 | struct afs_volume *volume = vnode->volume; | ||
| 590 | time64_t now = ktime_get_real_seconds(); | ||
| 591 | bool valid, need_clear = false; | ||
| 592 | unsigned int cb_break, cb_s_break, cb_v_break; | ||
| 593 | int seq = 0; | ||
| 594 | |||
| 595 | do { | ||
| 596 | read_seqbegin_or_lock(&vnode->cb_lock, &seq); | ||
| 597 | cb_v_break = READ_ONCE(volume->cb_v_break); | ||
| 598 | cb_break = vnode->cb_break; | ||
| 599 | |||
| 600 | if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { | ||
| 601 | cbi = rcu_dereference(vnode->cb_interest); | ||
| 602 | server = rcu_dereference(cbi->server); | ||
| 603 | cb_s_break = READ_ONCE(server->cb_s_break); | ||
| 604 | |||
| 605 | if (vnode->cb_s_break != cb_s_break || | ||
| 606 | vnode->cb_v_break != cb_v_break) { | ||
| 607 | vnode->cb_s_break = cb_s_break; | ||
| 608 | vnode->cb_v_break = cb_v_break; | ||
| 609 | need_clear = true; | ||
| 610 | valid = false; | ||
| 611 | } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) { | ||
| 612 | need_clear = true; | ||
| 613 | valid = false; | ||
| 614 | } else if (vnode->cb_expires_at - 10 <= now) { | ||
| 615 | need_clear = true; | ||
| 616 | valid = false; | ||
| 617 | } else { | ||
| 618 | valid = true; | ||
| 619 | } | ||
| 620 | } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { | ||
| 621 | valid = true; | ||
| 622 | } else { | ||
| 623 | vnode->cb_v_break = cb_v_break; | ||
| 624 | valid = false; | ||
| 625 | } | ||
| 626 | |||
| 627 | } while (need_seqretry(&vnode->cb_lock, seq)); | ||
| 628 | |||
| 629 | done_seqretry(&vnode->cb_lock, seq); | ||
| 630 | |||
| 631 | if (need_clear) { | ||
| 632 | write_seqlock(&vnode->cb_lock); | ||
| 633 | if (cb_break == vnode->cb_break) | ||
| 634 | __afs_break_callback(vnode); | ||
| 635 | write_sequnlock(&vnode->cb_lock); | ||
| 636 | valid = false; | ||
| 637 | } | ||
| 638 | |||
| 639 | return valid; | ||
| 640 | } | ||
| 641 | |||
| 642 | /* | ||
| 403 | * validate a vnode/inode | 643 | * validate a vnode/inode |
| 404 | * - there are several things we need to check | 644 | * - there are several things we need to check |
| 405 | * - parent dir data changes (rm, rmdir, rename, mkdir, create, link, | 645 | * - parent dir data changes (rm, rmdir, rename, mkdir, create, link, |
| @@ -410,7 +650,6 @@ void afs_zap_data(struct afs_vnode *vnode) | |||
| 410 | */ | 650 | */ |
| 411 | int afs_validate(struct afs_vnode *vnode, struct key *key) | 651 | int afs_validate(struct afs_vnode *vnode, struct key *key) |
| 412 | { | 652 | { |
| 413 | time64_t now = ktime_get_real_seconds(); | ||
| 414 | bool valid; | 653 | bool valid; |
| 415 | int ret; | 654 | int ret; |
| 416 | 655 | ||
| @@ -418,33 +657,9 @@ int afs_validate(struct afs_vnode *vnode, struct key *key) | |||
| 418 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, | 657 | vnode->fid.vid, vnode->fid.vnode, vnode->flags, |
| 419 | key_serial(key)); | 658 | key_serial(key)); |
| 420 | 659 | ||
| 421 | /* Quickly check the callback state. Ideally, we'd use read_seqbegin | 660 | rcu_read_lock(); |
| 422 | * here, but we have no way to pass the net namespace to the RCU | 661 | valid = afs_check_validity(vnode); |
| 423 | * cleanup for the server record. | 662 | rcu_read_unlock(); |
| 424 | */ | ||
| 425 | read_seqlock_excl(&vnode->cb_lock); | ||
| 426 | |||
| 427 | if (test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { | ||
| 428 | if (vnode->cb_s_break != vnode->cb_interest->server->cb_s_break || | ||
| 429 | vnode->cb_v_break != vnode->volume->cb_v_break) { | ||
| 430 | vnode->cb_s_break = vnode->cb_interest->server->cb_s_break; | ||
| 431 | vnode->cb_v_break = vnode->volume->cb_v_break; | ||
| 432 | valid = false; | ||
| 433 | } else if (test_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) { | ||
| 434 | valid = false; | ||
| 435 | } else if (vnode->cb_expires_at - 10 <= now) { | ||
| 436 | valid = false; | ||
| 437 | } else { | ||
| 438 | valid = true; | ||
| 439 | } | ||
| 440 | } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) { | ||
| 441 | valid = true; | ||
| 442 | } else { | ||
| 443 | vnode->cb_v_break = vnode->volume->cb_v_break; | ||
| 444 | valid = false; | ||
| 445 | } | ||
| 446 | |||
| 447 | read_sequnlock_excl(&vnode->cb_lock); | ||
| 448 | 663 | ||
| 449 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) | 664 | if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) |
| 450 | clear_nlink(&vnode->vfs_inode); | 665 | clear_nlink(&vnode->vfs_inode); |
| @@ -460,7 +675,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key) | |||
| 460 | * access */ | 675 | * access */ |
| 461 | if (!test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { | 676 | if (!test_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) { |
| 462 | _debug("not promised"); | 677 | _debug("not promised"); |
| 463 | ret = afs_fetch_status(vnode, key, false); | 678 | ret = afs_fetch_status(vnode, key, false, NULL); |
| 464 | if (ret < 0) { | 679 | if (ret < 0) { |
| 465 | if (ret == -ENOENT) { | 680 | if (ret == -ENOENT) { |
| 466 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | 681 | set_bit(AFS_VNODE_DELETED, &vnode->flags); |
| @@ -531,6 +746,7 @@ int afs_drop_inode(struct inode *inode) | |||
| 531 | */ | 746 | */ |
| 532 | void afs_evict_inode(struct inode *inode) | 747 | void afs_evict_inode(struct inode *inode) |
| 533 | { | 748 | { |
| 749 | struct afs_cb_interest *cbi; | ||
| 534 | struct afs_vnode *vnode; | 750 | struct afs_vnode *vnode; |
| 535 | 751 | ||
| 536 | vnode = AFS_FS_I(inode); | 752 | vnode = AFS_FS_I(inode); |
| @@ -547,10 +763,14 @@ void afs_evict_inode(struct inode *inode) | |||
| 547 | truncate_inode_pages_final(&inode->i_data); | 763 | truncate_inode_pages_final(&inode->i_data); |
| 548 | clear_inode(inode); | 764 | clear_inode(inode); |
| 549 | 765 | ||
| 550 | if (vnode->cb_interest) { | 766 | write_seqlock(&vnode->cb_lock); |
| 551 | afs_put_cb_interest(afs_i2net(inode), vnode->cb_interest); | 767 | cbi = rcu_dereference_protected(vnode->cb_interest, |
| 552 | vnode->cb_interest = NULL; | 768 | lockdep_is_held(&vnode->cb_lock.lock)); |
| 769 | if (cbi) { | ||
| 770 | afs_put_cb_interest(afs_i2net(inode), cbi); | ||
| 771 | rcu_assign_pointer(vnode->cb_interest, NULL); | ||
| 553 | } | 772 | } |
| 773 | write_sequnlock(&vnode->cb_lock); | ||
| 554 | 774 | ||
| 555 | while (!list_empty(&vnode->wb_keys)) { | 775 | while (!list_empty(&vnode->wb_keys)) { |
| 556 | struct afs_wb_key *wbk = list_entry(vnode->wb_keys.next, | 776 | struct afs_wb_key *wbk = list_entry(vnode->wb_keys.next, |
| @@ -585,9 +805,10 @@ void afs_evict_inode(struct inode *inode) | |||
| 585 | int afs_setattr(struct dentry *dentry, struct iattr *attr) | 805 | int afs_setattr(struct dentry *dentry, struct iattr *attr) |
| 586 | { | 806 | { |
| 587 | struct afs_fs_cursor fc; | 807 | struct afs_fs_cursor fc; |
| 808 | struct afs_status_cb *scb; | ||
| 588 | struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); | 809 | struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); |
| 589 | struct key *key; | 810 | struct key *key; |
| 590 | int ret; | 811 | int ret = -ENOMEM; |
| 591 | 812 | ||
| 592 | _enter("{%llx:%llu},{n=%pd},%x", | 813 | _enter("{%llx:%llu},{n=%pd},%x", |
| 593 | vnode->fid.vid, vnode->fid.vnode, dentry, | 814 | vnode->fid.vid, vnode->fid.vnode, dentry, |
| @@ -599,6 +820,10 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 599 | return 0; | 820 | return 0; |
| 600 | } | 821 | } |
| 601 | 822 | ||
| 823 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_KERNEL); | ||
| 824 | if (!scb) | ||
| 825 | goto error; | ||
| 826 | |||
| 602 | /* flush any dirty data outstanding on a regular file */ | 827 | /* flush any dirty data outstanding on a regular file */ |
| 603 | if (S_ISREG(vnode->vfs_inode.i_mode)) | 828 | if (S_ISREG(vnode->vfs_inode.i_mode)) |
| 604 | filemap_write_and_wait(vnode->vfs_inode.i_mapping); | 829 | filemap_write_and_wait(vnode->vfs_inode.i_mapping); |
| @@ -609,25 +834,33 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr) | |||
| 609 | key = afs_request_key(vnode->volume->cell); | 834 | key = afs_request_key(vnode->volume->cell); |
| 610 | if (IS_ERR(key)) { | 835 | if (IS_ERR(key)) { |
| 611 | ret = PTR_ERR(key); | 836 | ret = PTR_ERR(key); |
| 612 | goto error; | 837 | goto error_scb; |
| 613 | } | 838 | } |
| 614 | } | 839 | } |
| 615 | 840 | ||
| 616 | ret = -ERESTARTSYS; | 841 | ret = -ERESTARTSYS; |
| 617 | if (afs_begin_vnode_operation(&fc, vnode, key, false)) { | 842 | if (afs_begin_vnode_operation(&fc, vnode, key, false)) { |
| 843 | afs_dataversion_t data_version = vnode->status.data_version; | ||
| 844 | |||
| 845 | if (attr->ia_valid & ATTR_SIZE) | ||
| 846 | data_version++; | ||
| 847 | |||
| 618 | while (afs_select_fileserver(&fc)) { | 848 | while (afs_select_fileserver(&fc)) { |
| 619 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 849 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 620 | afs_fs_setattr(&fc, attr); | 850 | afs_fs_setattr(&fc, attr, scb); |
| 621 | } | 851 | } |
| 622 | 852 | ||
| 623 | afs_check_for_remote_deletion(&fc, fc.vnode); | 853 | afs_check_for_remote_deletion(&fc, vnode); |
| 624 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 854 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, |
| 855 | &data_version, scb); | ||
| 625 | ret = afs_end_vnode_operation(&fc); | 856 | ret = afs_end_vnode_operation(&fc); |
| 626 | } | 857 | } |
| 627 | 858 | ||
| 628 | if (!(attr->ia_valid & ATTR_FILE)) | 859 | if (!(attr->ia_valid & ATTR_FILE)) |
| 629 | key_put(key); | 860 | key_put(key); |
| 630 | 861 | ||
| 862 | error_scb: | ||
| 863 | kfree(scb); | ||
| 631 | error: | 864 | error: |
| 632 | _leave(" = %d", ret); | 865 | _leave(" = %d", ret); |
| 633 | return ret; | 866 | return ret; |
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 833fa39ee337..2073c1a3ab4b 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
| @@ -66,6 +66,8 @@ struct afs_fs_context { | |||
| 66 | struct afs_iget_data { | 66 | struct afs_iget_data { |
| 67 | struct afs_fid fid; | 67 | struct afs_fid fid; |
| 68 | struct afs_volume *volume; /* volume on which resides */ | 68 | struct afs_volume *volume; /* volume on which resides */ |
| 69 | unsigned int cb_v_break; /* Pre-fetch volume break count */ | ||
| 70 | unsigned int cb_s_break; /* Pre-fetch server break count */ | ||
| 69 | }; | 71 | }; |
| 70 | 72 | ||
| 71 | enum afs_call_state { | 73 | enum afs_call_state { |
| @@ -111,8 +113,12 @@ struct afs_call { | |||
| 111 | struct rxrpc_call *rxcall; /* RxRPC call handle */ | 113 | struct rxrpc_call *rxcall; /* RxRPC call handle */ |
| 112 | struct key *key; /* security for this call */ | 114 | struct key *key; /* security for this call */ |
| 113 | struct afs_net *net; /* The network namespace */ | 115 | struct afs_net *net; /* The network namespace */ |
| 114 | struct afs_server *cm_server; /* Server affected by incoming CM call */ | 116 | union { |
| 117 | struct afs_server *server; | ||
| 118 | struct afs_vlserver *vlserver; | ||
| 119 | }; | ||
| 115 | struct afs_cb_interest *cbi; /* Callback interest for server used */ | 120 | struct afs_cb_interest *cbi; /* Callback interest for server used */ |
| 121 | struct afs_vnode *lvnode; /* vnode being locked */ | ||
| 116 | void *request; /* request data (first part) */ | 122 | void *request; /* request data (first part) */ |
| 117 | struct address_space *mapping; /* Pages being written from */ | 123 | struct address_space *mapping; /* Pages being written from */ |
| 118 | struct iov_iter iter; /* Buffer iterator */ | 124 | struct iov_iter iter; /* Buffer iterator */ |
| @@ -122,7 +128,20 @@ struct afs_call { | |||
| 122 | struct bio_vec bvec[1]; | 128 | struct bio_vec bvec[1]; |
| 123 | }; | 129 | }; |
| 124 | void *buffer; /* reply receive buffer */ | 130 | void *buffer; /* reply receive buffer */ |
| 125 | void *reply[4]; /* Where to put the reply */ | 131 | union { |
| 132 | long ret0; /* Value to reply with instead of 0 */ | ||
| 133 | struct afs_addr_list *ret_alist; | ||
| 134 | struct afs_vldb_entry *ret_vldb; | ||
| 135 | struct afs_acl *ret_acl; | ||
| 136 | }; | ||
| 137 | struct afs_fid *out_fid; | ||
| 138 | struct afs_status_cb *out_dir_scb; | ||
| 139 | struct afs_status_cb *out_scb; | ||
| 140 | struct yfs_acl *out_yacl; | ||
| 141 | struct afs_volsync *out_volsync; | ||
| 142 | struct afs_volume_status *out_volstatus; | ||
| 143 | struct afs_read *read_request; | ||
| 144 | unsigned int server_index; | ||
| 126 | pgoff_t first; /* first page in mapping to deal with */ | 145 | pgoff_t first; /* first page in mapping to deal with */ |
| 127 | pgoff_t last; /* last page in mapping to deal with */ | 146 | pgoff_t last; /* last page in mapping to deal with */ |
| 128 | atomic_t usage; | 147 | atomic_t usage; |
| @@ -135,7 +154,6 @@ struct afs_call { | |||
| 135 | unsigned request_size; /* size of request data */ | 154 | unsigned request_size; /* size of request data */ |
| 136 | unsigned reply_max; /* maximum size of reply */ | 155 | unsigned reply_max; /* maximum size of reply */ |
| 137 | unsigned first_offset; /* offset into mapping[first] */ | 156 | unsigned first_offset; /* offset into mapping[first] */ |
| 138 | unsigned int cb_break; /* cb_break + cb_s_break before the call */ | ||
| 139 | union { | 157 | union { |
| 140 | unsigned last_to; /* amount of mapping[last] */ | 158 | unsigned last_to; /* amount of mapping[last] */ |
| 141 | unsigned count2; /* count used in unmarshalling */ | 159 | unsigned count2; /* count used in unmarshalling */ |
| @@ -146,9 +164,8 @@ struct afs_call { | |||
| 146 | bool send_pages; /* T if data from mapping should be sent */ | 164 | bool send_pages; /* T if data from mapping should be sent */ |
| 147 | bool need_attention; /* T if RxRPC poked us */ | 165 | bool need_attention; /* T if RxRPC poked us */ |
| 148 | bool async; /* T if asynchronous */ | 166 | bool async; /* T if asynchronous */ |
| 149 | bool ret_reply0; /* T if should return reply[0] on success */ | ||
| 150 | bool upgrade; /* T to request service upgrade */ | 167 | bool upgrade; /* T to request service upgrade */ |
| 151 | bool want_reply_time; /* T if want reply_time */ | 168 | bool have_reply_time; /* T if have got reply_time */ |
| 152 | bool intr; /* T if interruptible */ | 169 | bool intr; /* T if interruptible */ |
| 153 | u16 service_id; /* Actual service ID (after upgrade) */ | 170 | u16 service_id; /* Actual service ID (after upgrade) */ |
| 154 | unsigned int debug_id; /* Trace ID */ | 171 | unsigned int debug_id; /* Trace ID */ |
| @@ -161,8 +178,6 @@ struct afs_call { | |||
| 161 | } __attribute__((packed)); | 178 | } __attribute__((packed)); |
| 162 | __be64 tmp64; | 179 | __be64 tmp64; |
| 163 | }; | 180 | }; |
| 164 | afs_dataversion_t expected_version; /* Updated version expected from store */ | ||
| 165 | afs_dataversion_t expected_version_2; /* 2nd updated version expected from store */ | ||
| 166 | ktime_t reply_time; /* Time of first reply packet */ | 181 | ktime_t reply_time; /* Time of first reply packet */ |
| 167 | }; | 182 | }; |
| 168 | 183 | ||
| @@ -223,7 +238,8 @@ struct afs_read { | |||
| 223 | unsigned int index; /* Which page we're reading into */ | 238 | unsigned int index; /* Which page we're reading into */ |
| 224 | unsigned int nr_pages; | 239 | unsigned int nr_pages; |
| 225 | unsigned int offset; /* offset into current page */ | 240 | unsigned int offset; /* offset into current page */ |
| 226 | void (*page_done)(struct afs_call *, struct afs_read *); | 241 | struct afs_vnode *vnode; |
| 242 | void (*page_done)(struct afs_read *); | ||
| 227 | struct page **pages; | 243 | struct page **pages; |
| 228 | struct page *array[]; | 244 | struct page *array[]; |
| 229 | }; | 245 | }; |
| @@ -540,7 +556,10 @@ struct afs_server { | |||
| 540 | struct afs_vol_interest { | 556 | struct afs_vol_interest { |
| 541 | struct hlist_node srv_link; /* Link in server->cb_volumes */ | 557 | struct hlist_node srv_link; /* Link in server->cb_volumes */ |
| 542 | struct hlist_head cb_interests; /* List of callback interests on the server */ | 558 | struct hlist_head cb_interests; /* List of callback interests on the server */ |
| 543 | afs_volid_t vid; /* Volume ID to match */ | 559 | union { |
| 560 | struct rcu_head rcu; | ||
| 561 | afs_volid_t vid; /* Volume ID to match */ | ||
| 562 | }; | ||
| 544 | unsigned int usage; | 563 | unsigned int usage; |
| 545 | }; | 564 | }; |
| 546 | 565 | ||
| @@ -552,7 +571,10 @@ struct afs_cb_interest { | |||
| 552 | struct afs_vol_interest *vol_interest; | 571 | struct afs_vol_interest *vol_interest; |
| 553 | struct afs_server *server; /* Server on which this interest resides */ | 572 | struct afs_server *server; /* Server on which this interest resides */ |
| 554 | struct super_block *sb; /* Superblock on which inodes reside */ | 573 | struct super_block *sb; /* Superblock on which inodes reside */ |
| 555 | afs_volid_t vid; /* Volume ID to match */ | 574 | union { |
| 575 | struct rcu_head rcu; | ||
| 576 | afs_volid_t vid; /* Volume ID to match */ | ||
| 577 | }; | ||
| 556 | refcount_t usage; | 578 | refcount_t usage; |
| 557 | }; | 579 | }; |
| 558 | 580 | ||
| @@ -662,15 +684,13 @@ struct afs_vnode { | |||
| 662 | afs_lock_type_t lock_type : 8; | 684 | afs_lock_type_t lock_type : 8; |
| 663 | 685 | ||
| 664 | /* outstanding callback notification on this file */ | 686 | /* outstanding callback notification on this file */ |
| 665 | struct afs_cb_interest *cb_interest; /* Server on which this resides */ | 687 | struct afs_cb_interest __rcu *cb_interest; /* Server on which this resides */ |
| 666 | unsigned int cb_s_break; /* Mass break counter on ->server */ | 688 | unsigned int cb_s_break; /* Mass break counter on ->server */ |
| 667 | unsigned int cb_v_break; /* Mass break counter on ->volume */ | 689 | unsigned int cb_v_break; /* Mass break counter on ->volume */ |
| 668 | unsigned int cb_break; /* Break counter on vnode */ | 690 | unsigned int cb_break; /* Break counter on vnode */ |
| 669 | seqlock_t cb_lock; /* Lock for ->cb_interest, ->status, ->cb_*break */ | 691 | seqlock_t cb_lock; /* Lock for ->cb_interest, ->status, ->cb_*break */ |
| 670 | 692 | ||
| 671 | time64_t cb_expires_at; /* time at which callback expires */ | 693 | time64_t cb_expires_at; /* time at which callback expires */ |
| 672 | unsigned cb_version; /* callback version */ | ||
| 673 | afs_callback_type_t cb_type; /* type of callback */ | ||
| 674 | }; | 694 | }; |
| 675 | 695 | ||
| 676 | static inline struct fscache_cookie *afs_vnode_cache(struct afs_vnode *vnode) | 696 | static inline struct fscache_cookie *afs_vnode_cache(struct afs_vnode *vnode) |
| @@ -757,6 +777,7 @@ struct afs_vl_cursor { | |||
| 757 | * Cursor for iterating over a set of fileservers. | 777 | * Cursor for iterating over a set of fileservers. |
| 758 | */ | 778 | */ |
| 759 | struct afs_fs_cursor { | 779 | struct afs_fs_cursor { |
| 780 | const struct afs_call_type *type; /* Type of call done */ | ||
| 760 | struct afs_addr_cursor ac; | 781 | struct afs_addr_cursor ac; |
| 761 | struct afs_vnode *vnode; | 782 | struct afs_vnode *vnode; |
| 762 | struct afs_server_list *server_list; /* Current server list (pins ref) */ | 783 | struct afs_server_list *server_list; /* Current server list (pins ref) */ |
| @@ -885,7 +906,6 @@ extern const struct address_space_operations afs_dir_aops; | |||
| 885 | extern const struct dentry_operations afs_fs_dentry_operations; | 906 | extern const struct dentry_operations afs_fs_dentry_operations; |
| 886 | 907 | ||
| 887 | extern void afs_d_release(struct dentry *); | 908 | extern void afs_d_release(struct dentry *); |
| 888 | extern int afs_dir_remove_link(struct dentry *, struct key *, unsigned long, unsigned long); | ||
| 889 | 909 | ||
| 890 | /* | 910 | /* |
| 891 | * dir_edit.c | 911 | * dir_edit.c |
| @@ -943,50 +963,48 @@ extern int afs_flock(struct file *, int, struct file_lock *); | |||
| 943 | /* | 963 | /* |
| 944 | * fsclient.c | 964 | * fsclient.c |
| 945 | */ | 965 | */ |
| 946 | #define AFS_VNODE_NOT_YET_SET 0x01 | 966 | extern int afs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_status_cb *, |
| 947 | #define AFS_VNODE_META_CHANGED 0x02 | 967 | struct afs_volsync *); |
| 948 | #define AFS_VNODE_DATA_CHANGED 0x04 | ||
| 949 | extern void afs_update_inode_from_status(struct afs_vnode *, struct afs_file_status *, | ||
| 950 | const afs_dataversion_t *, u8); | ||
| 951 | |||
| 952 | extern int afs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_volsync *, bool); | ||
| 953 | extern int afs_fs_give_up_callbacks(struct afs_net *, struct afs_server *); | 968 | extern int afs_fs_give_up_callbacks(struct afs_net *, struct afs_server *); |
| 954 | extern int afs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *); | 969 | extern int afs_fs_fetch_data(struct afs_fs_cursor *, struct afs_status_cb *, struct afs_read *); |
| 955 | extern int afs_fs_create(struct afs_fs_cursor *, const char *, umode_t, u64, | 970 | extern int afs_fs_create(struct afs_fs_cursor *, const char *, umode_t, |
| 956 | struct afs_fid *, struct afs_file_status *, struct afs_callback *); | 971 | struct afs_status_cb *, struct afs_fid *, struct afs_status_cb *); |
| 957 | extern int afs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, u64); | 972 | extern int afs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, |
| 958 | extern int afs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64); | 973 | struct afs_status_cb *); |
| 959 | extern int afs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, u64, | 974 | extern int afs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, |
| 960 | struct afs_fid *, struct afs_file_status *); | 975 | struct afs_status_cb *, struct afs_status_cb *); |
| 976 | extern int afs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, | ||
| 977 | struct afs_status_cb *, struct afs_fid *, struct afs_status_cb *); | ||
| 961 | extern int afs_fs_rename(struct afs_fs_cursor *, const char *, | 978 | extern int afs_fs_rename(struct afs_fs_cursor *, const char *, |
| 962 | struct afs_vnode *, const char *, u64, u64); | 979 | struct afs_vnode *, const char *, |
| 980 | struct afs_status_cb *, struct afs_status_cb *); | ||
| 963 | extern int afs_fs_store_data(struct afs_fs_cursor *, struct address_space *, | 981 | extern int afs_fs_store_data(struct afs_fs_cursor *, struct address_space *, |
| 964 | pgoff_t, pgoff_t, unsigned, unsigned); | 982 | pgoff_t, pgoff_t, unsigned, unsigned, struct afs_status_cb *); |
| 965 | extern int afs_fs_setattr(struct afs_fs_cursor *, struct iattr *); | 983 | extern int afs_fs_setattr(struct afs_fs_cursor *, struct iattr *, struct afs_status_cb *); |
| 966 | extern int afs_fs_get_volume_status(struct afs_fs_cursor *, struct afs_volume_status *); | 984 | extern int afs_fs_get_volume_status(struct afs_fs_cursor *, struct afs_volume_status *); |
| 967 | extern int afs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t); | 985 | extern int afs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t, struct afs_status_cb *); |
| 968 | extern int afs_fs_extend_lock(struct afs_fs_cursor *); | 986 | extern int afs_fs_extend_lock(struct afs_fs_cursor *, struct afs_status_cb *); |
| 969 | extern int afs_fs_release_lock(struct afs_fs_cursor *); | 987 | extern int afs_fs_release_lock(struct afs_fs_cursor *, struct afs_status_cb *); |
| 970 | extern int afs_fs_give_up_all_callbacks(struct afs_net *, struct afs_server *, | 988 | extern int afs_fs_give_up_all_callbacks(struct afs_net *, struct afs_server *, |
| 971 | struct afs_addr_cursor *, struct key *); | 989 | struct afs_addr_cursor *, struct key *); |
| 972 | extern struct afs_call *afs_fs_get_capabilities(struct afs_net *, struct afs_server *, | 990 | extern struct afs_call *afs_fs_get_capabilities(struct afs_net *, struct afs_server *, |
| 973 | struct afs_addr_cursor *, struct key *, | 991 | struct afs_addr_cursor *, struct key *, |
| 974 | unsigned int); | 992 | unsigned int); |
| 975 | extern int afs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *, | 993 | extern int afs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *, |
| 976 | struct afs_fid *, struct afs_file_status *, | 994 | struct afs_fid *, struct afs_status_cb *, |
| 977 | struct afs_callback *, unsigned int, | 995 | unsigned int, struct afs_volsync *); |
| 978 | struct afs_volsync *); | ||
| 979 | extern int afs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *, | 996 | extern int afs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *, |
| 980 | struct afs_fid *, struct afs_file_status *, | 997 | struct afs_fid *, struct afs_status_cb *, |
| 981 | struct afs_callback *, struct afs_volsync *); | 998 | struct afs_volsync *); |
| 982 | 999 | ||
| 983 | struct afs_acl { | 1000 | struct afs_acl { |
| 984 | u32 size; | 1001 | u32 size; |
| 985 | u8 data[]; | 1002 | u8 data[]; |
| 986 | }; | 1003 | }; |
| 987 | 1004 | ||
| 988 | extern struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *); | 1005 | extern struct afs_acl *afs_fs_fetch_acl(struct afs_fs_cursor *, struct afs_status_cb *); |
| 989 | extern int afs_fs_store_acl(struct afs_fs_cursor *, const struct afs_acl *); | 1006 | extern int afs_fs_store_acl(struct afs_fs_cursor *, const struct afs_acl *, |
| 1007 | struct afs_status_cb *); | ||
| 990 | 1008 | ||
| 991 | /* | 1009 | /* |
| 992 | * fs_probe.c | 1010 | * fs_probe.c |
| @@ -998,15 +1016,20 @@ extern int afs_wait_for_fs_probes(struct afs_server_list *, unsigned long); | |||
| 998 | /* | 1016 | /* |
| 999 | * inode.c | 1017 | * inode.c |
| 1000 | */ | 1018 | */ |
| 1001 | extern int afs_fetch_status(struct afs_vnode *, struct key *, bool); | 1019 | extern void afs_vnode_commit_status(struct afs_fs_cursor *, |
| 1020 | struct afs_vnode *, | ||
| 1021 | unsigned int, | ||
| 1022 | const afs_dataversion_t *, | ||
| 1023 | struct afs_status_cb *); | ||
| 1024 | extern int afs_fetch_status(struct afs_vnode *, struct key *, bool, afs_access_t *); | ||
| 1002 | extern int afs_iget5_test(struct inode *, void *); | 1025 | extern int afs_iget5_test(struct inode *, void *); |
| 1003 | extern struct inode *afs_iget_pseudo_dir(struct super_block *, bool); | 1026 | extern struct inode *afs_iget_pseudo_dir(struct super_block *, bool); |
| 1004 | extern struct inode *afs_iget(struct super_block *, struct key *, | 1027 | extern struct inode *afs_iget(struct super_block *, struct key *, |
| 1005 | struct afs_fid *, struct afs_file_status *, | 1028 | struct afs_iget_data *, struct afs_status_cb *, |
| 1006 | struct afs_callback *, | ||
| 1007 | struct afs_cb_interest *, | 1029 | struct afs_cb_interest *, |
| 1008 | struct afs_vnode *); | 1030 | struct afs_vnode *); |
| 1009 | extern void afs_zap_data(struct afs_vnode *); | 1031 | extern void afs_zap_data(struct afs_vnode *); |
| 1032 | extern bool afs_check_validity(struct afs_vnode *); | ||
| 1010 | extern int afs_validate(struct afs_vnode *, struct key *); | 1033 | extern int afs_validate(struct afs_vnode *, struct key *); |
| 1011 | extern int afs_getattr(const struct path *, struct kstat *, u32, unsigned int); | 1034 | extern int afs_getattr(const struct path *, struct kstat *, u32, unsigned int); |
| 1012 | extern int afs_setattr(struct dentry *, struct iattr *); | 1035 | extern int afs_setattr(struct dentry *, struct iattr *); |
| @@ -1127,6 +1150,7 @@ extern int afs_protocol_error(struct afs_call *, int, enum afs_eproto_cause); | |||
| 1127 | static inline void afs_set_fc_call(struct afs_call *call, struct afs_fs_cursor *fc) | 1150 | static inline void afs_set_fc_call(struct afs_call *call, struct afs_fs_cursor *fc) |
| 1128 | { | 1151 | { |
| 1129 | call->intr = fc->flags & AFS_FS_CURSOR_INTR; | 1152 | call->intr = fc->flags & AFS_FS_CURSOR_INTR; |
| 1153 | fc->type = call->type; | ||
| 1130 | } | 1154 | } |
| 1131 | 1155 | ||
| 1132 | static inline void afs_extract_begin(struct afs_call *call, void *buf, size_t size) | 1156 | static inline void afs_extract_begin(struct afs_call *call, void *buf, size_t size) |
| @@ -1209,7 +1233,8 @@ static inline void afs_set_call_complete(struct afs_call *call, | |||
| 1209 | */ | 1233 | */ |
| 1210 | extern void afs_put_permits(struct afs_permits *); | 1234 | extern void afs_put_permits(struct afs_permits *); |
| 1211 | extern void afs_clear_permits(struct afs_vnode *); | 1235 | extern void afs_clear_permits(struct afs_vnode *); |
| 1212 | extern void afs_cache_permit(struct afs_vnode *, struct key *, unsigned int); | 1236 | extern void afs_cache_permit(struct afs_vnode *, struct key *, unsigned int, |
| 1237 | struct afs_status_cb *); | ||
| 1213 | extern void afs_zap_permits(struct rcu_head *); | 1238 | extern void afs_zap_permits(struct rcu_head *); |
| 1214 | extern struct key *afs_request_key(struct afs_cell *); | 1239 | extern struct key *afs_request_key(struct afs_cell *); |
| 1215 | extern int afs_check_permit(struct afs_vnode *, struct key *, afs_access_t *); | 1240 | extern int afs_check_permit(struct afs_vnode *, struct key *, afs_access_t *); |
| @@ -1335,7 +1360,6 @@ extern int afs_write_end(struct file *file, struct address_space *mapping, | |||
| 1335 | struct page *page, void *fsdata); | 1360 | struct page *page, void *fsdata); |
| 1336 | extern int afs_writepage(struct page *, struct writeback_control *); | 1361 | extern int afs_writepage(struct page *, struct writeback_control *); |
| 1337 | extern int afs_writepages(struct address_space *, struct writeback_control *); | 1362 | extern int afs_writepages(struct address_space *, struct writeback_control *); |
| 1338 | extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *); | ||
| 1339 | extern ssize_t afs_file_write(struct kiocb *, struct iov_iter *); | 1363 | extern ssize_t afs_file_write(struct kiocb *, struct iov_iter *); |
| 1340 | extern int afs_fsync(struct file *, loff_t, loff_t, int); | 1364 | extern int afs_fsync(struct file *, loff_t, loff_t, int); |
| 1341 | extern vm_fault_t afs_page_mkwrite(struct vm_fault *vmf); | 1365 | extern vm_fault_t afs_page_mkwrite(struct vm_fault *vmf); |
| @@ -1351,33 +1375,36 @@ extern ssize_t afs_listxattr(struct dentry *, char *, size_t); | |||
| 1351 | /* | 1375 | /* |
| 1352 | * yfsclient.c | 1376 | * yfsclient.c |
| 1353 | */ | 1377 | */ |
| 1354 | extern int yfs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_volsync *, bool); | 1378 | extern int yfs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_status_cb *, |
| 1355 | extern int yfs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *); | 1379 | struct afs_volsync *); |
| 1356 | extern int yfs_fs_create_file(struct afs_fs_cursor *, const char *, umode_t, u64, | 1380 | extern int yfs_fs_fetch_data(struct afs_fs_cursor *, struct afs_status_cb *, struct afs_read *); |
| 1357 | struct afs_fid *, struct afs_file_status *, struct afs_callback *); | 1381 | extern int yfs_fs_create_file(struct afs_fs_cursor *, const char *, umode_t, struct afs_status_cb *, |
| 1358 | extern int yfs_fs_make_dir(struct afs_fs_cursor *, const char *, umode_t, u64, | 1382 | struct afs_fid *, struct afs_status_cb *); |
| 1359 | struct afs_fid *, struct afs_file_status *, struct afs_callback *); | 1383 | extern int yfs_fs_make_dir(struct afs_fs_cursor *, const char *, umode_t, struct afs_status_cb *, |
| 1360 | extern int yfs_fs_remove_file2(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64); | 1384 | struct afs_fid *, struct afs_status_cb *); |
| 1361 | extern int yfs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, u64); | 1385 | extern int yfs_fs_remove_file2(struct afs_fs_cursor *, struct afs_vnode *, const char *, |
| 1362 | extern int yfs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64); | 1386 | struct afs_status_cb *, struct afs_status_cb *); |
| 1363 | extern int yfs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, u64, | 1387 | extern int yfs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, |
| 1364 | struct afs_fid *, struct afs_file_status *); | 1388 | struct afs_status_cb *); |
| 1365 | extern int yfs_fs_rename(struct afs_fs_cursor *, const char *, | 1389 | extern int yfs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, |
| 1366 | struct afs_vnode *, const char *, u64, u64); | 1390 | struct afs_status_cb *, struct afs_status_cb *); |
| 1391 | extern int yfs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, | ||
| 1392 | struct afs_status_cb *, struct afs_fid *, struct afs_status_cb *); | ||
| 1393 | extern int yfs_fs_rename(struct afs_fs_cursor *, const char *, struct afs_vnode *, const char *, | ||
| 1394 | struct afs_status_cb *, struct afs_status_cb *); | ||
| 1367 | extern int yfs_fs_store_data(struct afs_fs_cursor *, struct address_space *, | 1395 | extern int yfs_fs_store_data(struct afs_fs_cursor *, struct address_space *, |
| 1368 | pgoff_t, pgoff_t, unsigned, unsigned); | 1396 | pgoff_t, pgoff_t, unsigned, unsigned, struct afs_status_cb *); |
| 1369 | extern int yfs_fs_setattr(struct afs_fs_cursor *, struct iattr *); | 1397 | extern int yfs_fs_setattr(struct afs_fs_cursor *, struct iattr *, struct afs_status_cb *); |
| 1370 | extern int yfs_fs_get_volume_status(struct afs_fs_cursor *, struct afs_volume_status *); | 1398 | extern int yfs_fs_get_volume_status(struct afs_fs_cursor *, struct afs_volume_status *); |
| 1371 | extern int yfs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t); | 1399 | extern int yfs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t, struct afs_status_cb *); |
| 1372 | extern int yfs_fs_extend_lock(struct afs_fs_cursor *); | 1400 | extern int yfs_fs_extend_lock(struct afs_fs_cursor *, struct afs_status_cb *); |
| 1373 | extern int yfs_fs_release_lock(struct afs_fs_cursor *); | 1401 | extern int yfs_fs_release_lock(struct afs_fs_cursor *, struct afs_status_cb *); |
| 1374 | extern int yfs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *, | 1402 | extern int yfs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *, |
| 1375 | struct afs_fid *, struct afs_file_status *, | 1403 | struct afs_fid *, struct afs_status_cb *, |
| 1376 | struct afs_callback *, struct afs_volsync *); | 1404 | struct afs_volsync *); |
| 1377 | extern int yfs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *, | 1405 | extern int yfs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *, |
| 1378 | struct afs_fid *, struct afs_file_status *, | 1406 | struct afs_fid *, struct afs_status_cb *, |
| 1379 | struct afs_callback *, unsigned int, | 1407 | unsigned int, struct afs_volsync *); |
| 1380 | struct afs_volsync *); | ||
| 1381 | 1408 | ||
| 1382 | struct yfs_acl { | 1409 | struct yfs_acl { |
| 1383 | struct afs_acl *acl; /* Dir/file/symlink ACL */ | 1410 | struct afs_acl *acl; /* Dir/file/symlink ACL */ |
| @@ -1390,8 +1417,10 @@ struct yfs_acl { | |||
| 1390 | }; | 1417 | }; |
| 1391 | 1418 | ||
| 1392 | extern void yfs_free_opaque_acl(struct yfs_acl *); | 1419 | extern void yfs_free_opaque_acl(struct yfs_acl *); |
| 1393 | extern struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *, struct yfs_acl *); | 1420 | extern struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *, struct yfs_acl *, |
| 1394 | extern int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *, const struct afs_acl *); | 1421 | struct afs_status_cb *); |
| 1422 | extern int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *, const struct afs_acl *, | ||
| 1423 | struct afs_status_cb *); | ||
| 1395 | 1424 | ||
| 1396 | /* | 1425 | /* |
| 1397 | * Miscellaneous inline functions. | 1426 | * Miscellaneous inline functions. |
| @@ -1406,14 +1435,6 @@ static inline struct inode *AFS_VNODE_TO_I(struct afs_vnode *vnode) | |||
| 1406 | return &vnode->vfs_inode; | 1435 | return &vnode->vfs_inode; |
| 1407 | } | 1436 | } |
| 1408 | 1437 | ||
| 1409 | static inline void afs_vnode_commit_status(struct afs_fs_cursor *fc, | ||
| 1410 | struct afs_vnode *vnode, | ||
| 1411 | unsigned int cb_break) | ||
| 1412 | { | ||
| 1413 | if (fc->ac.error == 0) | ||
| 1414 | afs_cache_permit(vnode, fc->key, cb_break); | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | static inline void afs_check_for_remote_deletion(struct afs_fs_cursor *fc, | 1438 | static inline void afs_check_for_remote_deletion(struct afs_fs_cursor *fc, |
| 1418 | struct afs_vnode *vnode) | 1439 | struct afs_vnode *vnode) |
| 1419 | { | 1440 | { |
diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index 52f3a9910f0d..b00c739e0e63 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c | |||
| @@ -66,7 +66,8 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc, | |||
| 66 | fc->untried = (1UL << fc->server_list->nr_servers) - 1; | 66 | fc->untried = (1UL << fc->server_list->nr_servers) - 1; |
| 67 | fc->index = READ_ONCE(fc->server_list->preferred); | 67 | fc->index = READ_ONCE(fc->server_list->preferred); |
| 68 | 68 | ||
| 69 | cbi = vnode->cb_interest; | 69 | cbi = rcu_dereference_protected(vnode->cb_interest, |
| 70 | lockdep_is_held(&vnode->io_lock)); | ||
| 70 | if (cbi) { | 71 | if (cbi) { |
| 71 | /* See if the vnode's preferred record is still available */ | 72 | /* See if the vnode's preferred record is still available */ |
| 72 | for (i = 0; i < fc->server_list->nr_servers; i++) { | 73 | for (i = 0; i < fc->server_list->nr_servers; i++) { |
| @@ -87,8 +88,8 @@ static bool afs_start_fs_iteration(struct afs_fs_cursor *fc, | |||
| 87 | 88 | ||
| 88 | /* Note that the callback promise is effectively broken */ | 89 | /* Note that the callback promise is effectively broken */ |
| 89 | write_seqlock(&vnode->cb_lock); | 90 | write_seqlock(&vnode->cb_lock); |
| 90 | ASSERTCMP(cbi, ==, vnode->cb_interest); | 91 | ASSERTCMP(cbi, ==, rcu_access_pointer(vnode->cb_interest)); |
| 91 | vnode->cb_interest = NULL; | 92 | rcu_assign_pointer(vnode->cb_interest, NULL); |
| 92 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) | 93 | if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) |
| 93 | vnode->cb_break++; | 94 | vnode->cb_break++; |
| 94 | write_sequnlock(&vnode->cb_lock); | 95 | write_sequnlock(&vnode->cb_lock); |
| @@ -417,7 +418,9 @@ selected_server: | |||
| 417 | if (error < 0) | 418 | if (error < 0) |
| 418 | goto failed_set_error; | 419 | goto failed_set_error; |
| 419 | 420 | ||
| 420 | fc->cbi = afs_get_cb_interest(vnode->cb_interest); | 421 | fc->cbi = afs_get_cb_interest( |
| 422 | rcu_dereference_protected(vnode->cb_interest, | ||
| 423 | lockdep_is_held(&vnode->io_lock))); | ||
| 421 | 424 | ||
| 422 | read_lock(&server->fs_lock); | 425 | read_lock(&server->fs_lock); |
| 423 | alist = rcu_dereference_protected(server->addresses, | 426 | alist = rcu_dereference_protected(server->addresses, |
| @@ -487,12 +490,15 @@ failed: | |||
| 487 | bool afs_select_current_fileserver(struct afs_fs_cursor *fc) | 490 | bool afs_select_current_fileserver(struct afs_fs_cursor *fc) |
| 488 | { | 491 | { |
| 489 | struct afs_vnode *vnode = fc->vnode; | 492 | struct afs_vnode *vnode = fc->vnode; |
| 490 | struct afs_cb_interest *cbi = vnode->cb_interest; | 493 | struct afs_cb_interest *cbi; |
| 491 | struct afs_addr_list *alist; | 494 | struct afs_addr_list *alist; |
| 492 | int error = fc->ac.error; | 495 | int error = fc->ac.error; |
| 493 | 496 | ||
| 494 | _enter(""); | 497 | _enter(""); |
| 495 | 498 | ||
| 499 | cbi = rcu_dereference_protected(vnode->cb_interest, | ||
| 500 | lockdep_is_held(&vnode->io_lock)); | ||
| 501 | |||
| 496 | switch (error) { | 502 | switch (error) { |
| 497 | case SHRT_MAX: | 503 | case SHRT_MAX: |
| 498 | if (!cbi) { | 504 | if (!cbi) { |
| @@ -501,7 +507,7 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc) | |||
| 501 | return false; | 507 | return false; |
| 502 | } | 508 | } |
| 503 | 509 | ||
| 504 | fc->cbi = afs_get_cb_interest(vnode->cb_interest); | 510 | fc->cbi = afs_get_cb_interest(cbi); |
| 505 | 511 | ||
| 506 | read_lock(&cbi->server->fs_lock); | 512 | read_lock(&cbi->server->fs_lock); |
| 507 | alist = rcu_dereference_protected(cbi->server->addresses, | 513 | alist = rcu_dereference_protected(cbi->server->addresses, |
diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 02a39e6adf63..4fa5ce92b9b9 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c | |||
| @@ -188,7 +188,7 @@ void afs_put_call(struct afs_call *call) | |||
| 188 | if (call->type->destructor) | 188 | if (call->type->destructor) |
| 189 | call->type->destructor(call); | 189 | call->type->destructor(call); |
| 190 | 190 | ||
| 191 | afs_put_server(call->net, call->cm_server); | 191 | afs_put_server(call->net, call->server); |
| 192 | afs_put_cb_interest(call->net, call->cbi); | 192 | afs_put_cb_interest(call->net, call->cbi); |
| 193 | afs_put_addrlist(call->alist); | 193 | afs_put_addrlist(call->alist); |
| 194 | kfree(call->request); | 194 | kfree(call->request); |
| @@ -534,11 +534,11 @@ static void afs_deliver_to_call(struct afs_call *call) | |||
| 534 | return; | 534 | return; |
| 535 | } | 535 | } |
| 536 | 536 | ||
| 537 | if (call->want_reply_time && | 537 | if (!call->have_reply_time && |
| 538 | rxrpc_kernel_get_reply_time(call->net->socket, | 538 | rxrpc_kernel_get_reply_time(call->net->socket, |
| 539 | call->rxcall, | 539 | call->rxcall, |
| 540 | &call->reply_time)) | 540 | &call->reply_time)) |
| 541 | call->want_reply_time = false; | 541 | call->have_reply_time = true; |
| 542 | 542 | ||
| 543 | ret = call->type->deliver(call); | 543 | ret = call->type->deliver(call); |
| 544 | state = READ_ONCE(call->state); | 544 | state = READ_ONCE(call->state); |
| @@ -696,10 +696,9 @@ long afs_wait_for_call_to_complete(struct afs_call *call, | |||
| 696 | ret = ac->error; | 696 | ret = ac->error; |
| 697 | switch (ret) { | 697 | switch (ret) { |
| 698 | case 0: | 698 | case 0: |
| 699 | if (call->ret_reply0) { | 699 | ret = call->ret0; |
| 700 | ret = (long)call->reply[0]; | 700 | call->ret0 = 0; |
| 701 | call->reply[0] = NULL; | 701 | |
| 702 | } | ||
| 703 | /* Fall through */ | 702 | /* Fall through */ |
| 704 | case -ECONNABORTED: | 703 | case -ECONNABORTED: |
| 705 | ac->responded = true; | 704 | ac->responded = true; |
diff --git a/fs/afs/security.c b/fs/afs/security.c index db5529e47eb8..5d8ece98561e 100644 --- a/fs/afs/security.c +++ b/fs/afs/security.c | |||
| @@ -116,10 +116,10 @@ static void afs_hash_permits(struct afs_permits *permits) | |||
| 116 | * as the ACL *may* have changed. | 116 | * as the ACL *may* have changed. |
| 117 | */ | 117 | */ |
| 118 | void afs_cache_permit(struct afs_vnode *vnode, struct key *key, | 118 | void afs_cache_permit(struct afs_vnode *vnode, struct key *key, |
| 119 | unsigned int cb_break) | 119 | unsigned int cb_break, struct afs_status_cb *scb) |
| 120 | { | 120 | { |
| 121 | struct afs_permits *permits, *xpermits, *replacement, *zap, *new = NULL; | 121 | struct afs_permits *permits, *xpermits, *replacement, *zap, *new = NULL; |
| 122 | afs_access_t caller_access = READ_ONCE(vnode->status.caller_access); | 122 | afs_access_t caller_access = scb->status.caller_access; |
| 123 | size_t size = 0; | 123 | size_t size = 0; |
| 124 | bool changed = false; | 124 | bool changed = false; |
| 125 | int i, j; | 125 | int i, j; |
| @@ -146,7 +146,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key, | |||
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | if (afs_cb_is_broken(cb_break, vnode, | 148 | if (afs_cb_is_broken(cb_break, vnode, |
| 149 | vnode->cb_interest)) { | 149 | rcu_dereference(vnode->cb_interest))) { |
| 150 | changed = true; | 150 | changed = true; |
| 151 | break; | 151 | break; |
| 152 | } | 152 | } |
| @@ -176,7 +176,7 @@ void afs_cache_permit(struct afs_vnode *vnode, struct key *key, | |||
| 176 | } | 176 | } |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | if (afs_cb_is_broken(cb_break, vnode, vnode->cb_interest)) | 179 | if (afs_cb_is_broken(cb_break, vnode, rcu_dereference(vnode->cb_interest))) |
| 180 | goto someone_else_changed_it; | 180 | goto someone_else_changed_it; |
| 181 | 181 | ||
| 182 | /* We need a ref on any permits list we want to copy as we'll have to | 182 | /* We need a ref on any permits list we want to copy as we'll have to |
| @@ -253,14 +253,16 @@ found: | |||
| 253 | 253 | ||
| 254 | kfree(new); | 254 | kfree(new); |
| 255 | 255 | ||
| 256 | rcu_read_lock(); | ||
| 256 | spin_lock(&vnode->lock); | 257 | spin_lock(&vnode->lock); |
| 257 | zap = rcu_access_pointer(vnode->permit_cache); | 258 | zap = rcu_access_pointer(vnode->permit_cache); |
| 258 | if (!afs_cb_is_broken(cb_break, vnode, vnode->cb_interest) && | 259 | if (!afs_cb_is_broken(cb_break, vnode, rcu_dereference(vnode->cb_interest)) && |
| 259 | zap == permits) | 260 | zap == permits) |
| 260 | rcu_assign_pointer(vnode->permit_cache, replacement); | 261 | rcu_assign_pointer(vnode->permit_cache, replacement); |
| 261 | else | 262 | else |
| 262 | zap = replacement; | 263 | zap = replacement; |
| 263 | spin_unlock(&vnode->lock); | 264 | spin_unlock(&vnode->lock); |
| 265 | rcu_read_unlock(); | ||
| 264 | afs_put_permits(zap); | 266 | afs_put_permits(zap); |
| 265 | out_put: | 267 | out_put: |
| 266 | afs_put_permits(permits); | 268 | afs_put_permits(permits); |
| @@ -320,13 +322,12 @@ int afs_check_permit(struct afs_vnode *vnode, struct key *key, | |||
| 320 | */ | 322 | */ |
| 321 | _debug("no valid permit"); | 323 | _debug("no valid permit"); |
| 322 | 324 | ||
| 323 | ret = afs_fetch_status(vnode, key, false); | 325 | ret = afs_fetch_status(vnode, key, false, _access); |
| 324 | if (ret < 0) { | 326 | if (ret < 0) { |
| 325 | *_access = 0; | 327 | *_access = 0; |
| 326 | _leave(" = %d", ret); | 328 | _leave(" = %d", ret); |
| 327 | return ret; | 329 | return ret; |
| 328 | } | 330 | } |
| 329 | *_access = vnode->status.caller_access; | ||
| 330 | } | 331 | } |
| 331 | 332 | ||
| 332 | _leave(" = 0 [access %x]", *_access); | 333 | _leave(" = 0 [access %x]", *_access); |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 3df11eede7f4..f18911e8d770 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
| @@ -426,7 +426,7 @@ static int afs_set_super(struct super_block *sb, struct fs_context *fc) | |||
| 426 | static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx) | 426 | static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx) |
| 427 | { | 427 | { |
| 428 | struct afs_super_info *as = AFS_FS_S(sb); | 428 | struct afs_super_info *as = AFS_FS_S(sb); |
| 429 | struct afs_fid fid; | 429 | struct afs_iget_data iget_data; |
| 430 | struct inode *inode = NULL; | 430 | struct inode *inode = NULL; |
| 431 | int ret; | 431 | int ret; |
| 432 | 432 | ||
| @@ -451,11 +451,13 @@ static int afs_fill_super(struct super_block *sb, struct afs_fs_context *ctx) | |||
| 451 | } else { | 451 | } else { |
| 452 | sprintf(sb->s_id, "%llu", as->volume->vid); | 452 | sprintf(sb->s_id, "%llu", as->volume->vid); |
| 453 | afs_activate_volume(as->volume); | 453 | afs_activate_volume(as->volume); |
| 454 | fid.vid = as->volume->vid; | 454 | iget_data.fid.vid = as->volume->vid; |
| 455 | fid.vnode = 1; | 455 | iget_data.fid.vnode = 1; |
| 456 | fid.vnode_hi = 0; | 456 | iget_data.fid.vnode_hi = 0; |
| 457 | fid.unique = 1; | 457 | iget_data.fid.unique = 1; |
| 458 | inode = afs_iget(sb, ctx->key, &fid, NULL, NULL, NULL, NULL); | 458 | iget_data.cb_v_break = as->volume->cb_v_break; |
| 459 | iget_data.cb_s_break = 0; | ||
| 460 | inode = afs_iget(sb, ctx->key, &iget_data, NULL, NULL, NULL); | ||
| 459 | } | 461 | } |
| 460 | 462 | ||
| 461 | if (IS_ERR(inode)) | 463 | if (IS_ERR(inode)) |
| @@ -677,13 +679,12 @@ static struct inode *afs_alloc_inode(struct super_block *sb) | |||
| 677 | vnode->volume = NULL; | 679 | vnode->volume = NULL; |
| 678 | vnode->lock_key = NULL; | 680 | vnode->lock_key = NULL; |
| 679 | vnode->permit_cache = NULL; | 681 | vnode->permit_cache = NULL; |
| 680 | vnode->cb_interest = NULL; | 682 | RCU_INIT_POINTER(vnode->cb_interest, NULL); |
| 681 | #ifdef CONFIG_AFS_FSCACHE | 683 | #ifdef CONFIG_AFS_FSCACHE |
| 682 | vnode->cache = NULL; | 684 | vnode->cache = NULL; |
| 683 | #endif | 685 | #endif |
| 684 | 686 | ||
| 685 | vnode->flags = 1 << AFS_VNODE_UNSET; | 687 | vnode->flags = 1 << AFS_VNODE_UNSET; |
| 686 | vnode->cb_type = 0; | ||
| 687 | vnode->lock_state = AFS_VNODE_LOCK_NONE; | 688 | vnode->lock_state = AFS_VNODE_LOCK_NONE; |
| 688 | 689 | ||
| 689 | init_rwsem(&vnode->rmdir_lock); | 690 | init_rwsem(&vnode->rmdir_lock); |
| @@ -708,7 +709,7 @@ static void afs_destroy_inode(struct inode *inode) | |||
| 708 | 709 | ||
| 709 | _debug("DESTROY INODE %p", inode); | 710 | _debug("DESTROY INODE %p", inode); |
| 710 | 711 | ||
| 711 | ASSERTCMP(vnode->cb_interest, ==, NULL); | 712 | ASSERTCMP(rcu_access_pointer(vnode->cb_interest), ==, NULL); |
| 712 | 713 | ||
| 713 | atomic_dec(&afs_count_active_inodes); | 714 | atomic_dec(&afs_count_active_inodes); |
| 714 | } | 715 | } |
| @@ -749,7 +750,6 @@ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
| 749 | } | 750 | } |
| 750 | 751 | ||
| 751 | afs_check_for_remote_deletion(&fc, fc.vnode); | 752 | afs_check_for_remote_deletion(&fc, fc.vnode); |
| 752 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | ||
| 753 | ret = afs_end_vnode_operation(&fc); | 753 | ret = afs_end_vnode_operation(&fc); |
| 754 | } | 754 | } |
| 755 | 755 | ||
diff --git a/fs/afs/vl_probe.c b/fs/afs/vl_probe.c index b05e0de04f42..beb991563939 100644 --- a/fs/afs/vl_probe.c +++ b/fs/afs/vl_probe.c | |||
| @@ -33,8 +33,8 @@ static bool afs_vl_probe_done(struct afs_vlserver *server) | |||
| 33 | void afs_vlserver_probe_result(struct afs_call *call) | 33 | void afs_vlserver_probe_result(struct afs_call *call) |
| 34 | { | 34 | { |
| 35 | struct afs_addr_list *alist = call->alist; | 35 | struct afs_addr_list *alist = call->alist; |
| 36 | struct afs_vlserver *server = call->reply[0]; | 36 | struct afs_vlserver *server = call->vlserver; |
| 37 | unsigned int server_index = (long)call->reply[1]; | 37 | unsigned int server_index = call->server_index; |
| 38 | unsigned int index = call->addr_ix; | 38 | unsigned int index = call->addr_ix; |
| 39 | unsigned int rtt = UINT_MAX; | 39 | unsigned int rtt = UINT_MAX; |
| 40 | bool have_result = false; | 40 | bool have_result = false; |
diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c index 7c53768a360b..3d4b9836a2e2 100644 --- a/fs/afs/vlclient.c +++ b/fs/afs/vlclient.c | |||
| @@ -34,7 +34,7 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) | |||
| 34 | 34 | ||
| 35 | /* unmarshall the reply once we've received all of it */ | 35 | /* unmarshall the reply once we've received all of it */ |
| 36 | uvldb = call->buffer; | 36 | uvldb = call->buffer; |
| 37 | entry = call->reply[0]; | 37 | entry = call->ret_vldb; |
| 38 | 38 | ||
| 39 | nr_servers = ntohl(uvldb->nServers); | 39 | nr_servers = ntohl(uvldb->nServers); |
| 40 | if (nr_servers > AFS_NMAXNSERVERS) | 40 | if (nr_servers > AFS_NMAXNSERVERS) |
| @@ -110,7 +110,7 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) | |||
| 110 | 110 | ||
| 111 | static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call) | 111 | static void afs_destroy_vl_get_entry_by_name_u(struct afs_call *call) |
| 112 | { | 112 | { |
| 113 | kfree(call->reply[0]); | 113 | kfree(call->ret_vldb); |
| 114 | afs_flat_call_destructor(call); | 114 | afs_flat_call_destructor(call); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| @@ -155,8 +155,7 @@ struct afs_vldb_entry *afs_vl_get_entry_by_name_u(struct afs_vl_cursor *vc, | |||
| 155 | } | 155 | } |
| 156 | 156 | ||
| 157 | call->key = vc->key; | 157 | call->key = vc->key; |
| 158 | call->reply[0] = entry; | 158 | call->ret_vldb = entry; |
| 159 | call->ret_reply0 = true; | ||
| 160 | call->max_lifespan = AFS_VL_MAX_LIFESPAN; | 159 | call->max_lifespan = AFS_VL_MAX_LIFESPAN; |
| 161 | 160 | ||
| 162 | /* Marshall the parameters */ | 161 | /* Marshall the parameters */ |
| @@ -215,7 +214,7 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call) | |||
| 215 | if (!alist) | 214 | if (!alist) |
| 216 | return -ENOMEM; | 215 | return -ENOMEM; |
| 217 | alist->version = uniquifier; | 216 | alist->version = uniquifier; |
| 218 | call->reply[0] = alist; | 217 | call->ret_alist = alist; |
| 219 | call->count = count; | 218 | call->count = count; |
| 220 | call->count2 = nentries; | 219 | call->count2 = nentries; |
| 221 | call->unmarshall++; | 220 | call->unmarshall++; |
| @@ -230,7 +229,7 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call) | |||
| 230 | if (ret < 0) | 229 | if (ret < 0) |
| 231 | return ret; | 230 | return ret; |
| 232 | 231 | ||
| 233 | alist = call->reply[0]; | 232 | alist = call->ret_alist; |
| 234 | bp = call->buffer; | 233 | bp = call->buffer; |
| 235 | count = min(call->count, 4U); | 234 | count = min(call->count, 4U); |
| 236 | for (i = 0; i < count; i++) | 235 | for (i = 0; i < count; i++) |
| @@ -250,8 +249,7 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *call) | |||
| 250 | 249 | ||
| 251 | static void afs_vl_get_addrs_u_destructor(struct afs_call *call) | 250 | static void afs_vl_get_addrs_u_destructor(struct afs_call *call) |
| 252 | { | 251 | { |
| 253 | afs_put_server(call->net, (struct afs_server *)call->reply[0]); | 252 | afs_put_addrlist(call->ret_alist); |
| 254 | kfree(call->reply[1]); | ||
| 255 | return afs_flat_call_destructor(call); | 253 | return afs_flat_call_destructor(call); |
| 256 | } | 254 | } |
| 257 | 255 | ||
| @@ -288,8 +286,7 @@ struct afs_addr_list *afs_vl_get_addrs_u(struct afs_vl_cursor *vc, | |||
| 288 | return ERR_PTR(-ENOMEM); | 286 | return ERR_PTR(-ENOMEM); |
| 289 | 287 | ||
| 290 | call->key = vc->key; | 288 | call->key = vc->key; |
| 291 | call->reply[0] = NULL; | 289 | call->ret_alist = NULL; |
| 292 | call->ret_reply0 = true; | ||
| 293 | call->max_lifespan = AFS_VL_MAX_LIFESPAN; | 290 | call->max_lifespan = AFS_VL_MAX_LIFESPAN; |
| 294 | 291 | ||
| 295 | /* Marshall the parameters */ | 292 | /* Marshall the parameters */ |
| @@ -360,9 +357,7 @@ static int afs_deliver_vl_get_capabilities(struct afs_call *call) | |||
| 360 | 357 | ||
| 361 | static void afs_destroy_vl_get_capabilities(struct afs_call *call) | 358 | static void afs_destroy_vl_get_capabilities(struct afs_call *call) |
| 362 | { | 359 | { |
| 363 | struct afs_vlserver *server = call->reply[0]; | 360 | afs_put_vlserver(call->net, call->vlserver); |
| 364 | |||
| 365 | afs_put_vlserver(call->net, server); | ||
| 366 | afs_flat_call_destructor(call); | 361 | afs_flat_call_destructor(call); |
| 367 | } | 362 | } |
| 368 | 363 | ||
| @@ -400,10 +395,9 @@ struct afs_call *afs_vl_get_capabilities(struct afs_net *net, | |||
| 400 | return ERR_PTR(-ENOMEM); | 395 | return ERR_PTR(-ENOMEM); |
| 401 | 396 | ||
| 402 | call->key = key; | 397 | call->key = key; |
| 403 | call->reply[0] = afs_get_vlserver(server); | 398 | call->vlserver = afs_get_vlserver(server); |
| 404 | call->reply[1] = (void *)(long)server_index; | 399 | call->server_index = server_index; |
| 405 | call->upgrade = true; | 400 | call->upgrade = true; |
| 406 | call->want_reply_time = true; | ||
| 407 | call->async = true; | 401 | call->async = true; |
| 408 | call->max_lifespan = AFS_PROBE_MAX_LIFESPAN; | 402 | call->max_lifespan = AFS_PROBE_MAX_LIFESPAN; |
| 409 | 403 | ||
| @@ -463,7 +457,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) | |||
| 463 | if (!alist) | 457 | if (!alist) |
| 464 | return -ENOMEM; | 458 | return -ENOMEM; |
| 465 | alist->version = uniquifier; | 459 | alist->version = uniquifier; |
| 466 | call->reply[0] = alist; | 460 | call->ret_alist = alist; |
| 467 | 461 | ||
| 468 | if (call->count == 0) | 462 | if (call->count == 0) |
| 469 | goto extract_volendpoints; | 463 | goto extract_volendpoints; |
| @@ -491,7 +485,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) | |||
| 491 | if (ret < 0) | 485 | if (ret < 0) |
| 492 | return ret; | 486 | return ret; |
| 493 | 487 | ||
| 494 | alist = call->reply[0]; | 488 | alist = call->ret_alist; |
| 495 | bp = call->buffer; | 489 | bp = call->buffer; |
| 496 | switch (call->count2) { | 490 | switch (call->count2) { |
| 497 | case YFS_ENDPOINT_IPV4: | 491 | case YFS_ENDPOINT_IPV4: |
| @@ -612,7 +606,6 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_call *call) | |||
| 612 | break; | 606 | break; |
| 613 | } | 607 | } |
| 614 | 608 | ||
| 615 | alist = call->reply[0]; | ||
| 616 | _leave(" = 0 [done]"); | 609 | _leave(" = 0 [done]"); |
| 617 | return 0; | 610 | return 0; |
| 618 | } | 611 | } |
| @@ -647,8 +640,7 @@ struct afs_addr_list *afs_yfsvl_get_endpoints(struct afs_vl_cursor *vc, | |||
| 647 | return ERR_PTR(-ENOMEM); | 640 | return ERR_PTR(-ENOMEM); |
| 648 | 641 | ||
| 649 | call->key = vc->key; | 642 | call->key = vc->key; |
| 650 | call->reply[0] = NULL; | 643 | call->ret_alist = NULL; |
| 651 | call->ret_reply0 = true; | ||
| 652 | call->max_lifespan = AFS_VL_MAX_LIFESPAN; | 644 | call->max_lifespan = AFS_VL_MAX_LIFESPAN; |
| 653 | 645 | ||
| 654 | /* Marshall the parameters */ | 646 | /* Marshall the parameters */ |
diff --git a/fs/afs/write.c b/fs/afs/write.c index e669f2fae873..8bcab95f1127 100644 --- a/fs/afs/write.c +++ b/fs/afs/write.c | |||
| @@ -314,6 +314,46 @@ static void afs_redirty_pages(struct writeback_control *wbc, | |||
| 314 | } | 314 | } |
| 315 | 315 | ||
| 316 | /* | 316 | /* |
| 317 | * completion of write to server | ||
| 318 | */ | ||
| 319 | static void afs_pages_written_back(struct afs_vnode *vnode, | ||
| 320 | pgoff_t first, pgoff_t last) | ||
| 321 | { | ||
| 322 | struct pagevec pv; | ||
| 323 | unsigned long priv; | ||
| 324 | unsigned count, loop; | ||
| 325 | |||
| 326 | _enter("{%llx:%llu},{%lx-%lx}", | ||
| 327 | vnode->fid.vid, vnode->fid.vnode, first, last); | ||
| 328 | |||
| 329 | pagevec_init(&pv); | ||
| 330 | |||
| 331 | do { | ||
| 332 | _debug("done %lx-%lx", first, last); | ||
| 333 | |||
| 334 | count = last - first + 1; | ||
| 335 | if (count > PAGEVEC_SIZE) | ||
| 336 | count = PAGEVEC_SIZE; | ||
| 337 | pv.nr = find_get_pages_contig(vnode->vfs_inode.i_mapping, | ||
| 338 | first, count, pv.pages); | ||
| 339 | ASSERTCMP(pv.nr, ==, count); | ||
| 340 | |||
| 341 | for (loop = 0; loop < count; loop++) { | ||
| 342 | priv = page_private(pv.pages[loop]); | ||
| 343 | trace_afs_page_dirty(vnode, tracepoint_string("clear"), | ||
| 344 | pv.pages[loop]->index, priv); | ||
| 345 | set_page_private(pv.pages[loop], 0); | ||
| 346 | end_page_writeback(pv.pages[loop]); | ||
| 347 | } | ||
| 348 | first += count; | ||
| 349 | __pagevec_release(&pv); | ||
| 350 | } while (first <= last); | ||
| 351 | |||
| 352 | afs_prune_wb_keys(vnode); | ||
| 353 | _leave(""); | ||
| 354 | } | ||
| 355 | |||
| 356 | /* | ||
| 317 | * write to a file | 357 | * write to a file |
| 318 | */ | 358 | */ |
| 319 | static int afs_store_data(struct address_space *mapping, | 359 | static int afs_store_data(struct address_space *mapping, |
| @@ -322,6 +362,7 @@ static int afs_store_data(struct address_space *mapping, | |||
| 322 | { | 362 | { |
| 323 | struct afs_vnode *vnode = AFS_FS_I(mapping->host); | 363 | struct afs_vnode *vnode = AFS_FS_I(mapping->host); |
| 324 | struct afs_fs_cursor fc; | 364 | struct afs_fs_cursor fc; |
| 365 | struct afs_status_cb *scb; | ||
| 325 | struct afs_wb_key *wbk = NULL; | 366 | struct afs_wb_key *wbk = NULL; |
| 326 | struct list_head *p; | 367 | struct list_head *p; |
| 327 | int ret = -ENOKEY, ret2; | 368 | int ret = -ENOKEY, ret2; |
| @@ -333,6 +374,10 @@ static int afs_store_data(struct address_space *mapping, | |||
| 333 | vnode->fid.unique, | 374 | vnode->fid.unique, |
| 334 | first, last, offset, to); | 375 | first, last, offset, to); |
| 335 | 376 | ||
| 377 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS); | ||
| 378 | if (!scb) | ||
| 379 | return -ENOMEM; | ||
| 380 | |||
| 336 | spin_lock(&vnode->wb_lock); | 381 | spin_lock(&vnode->wb_lock); |
| 337 | p = vnode->wb_keys.next; | 382 | p = vnode->wb_keys.next; |
| 338 | 383 | ||
| @@ -351,6 +396,7 @@ try_next_key: | |||
| 351 | 396 | ||
| 352 | spin_unlock(&vnode->wb_lock); | 397 | spin_unlock(&vnode->wb_lock); |
| 353 | afs_put_wb_key(wbk); | 398 | afs_put_wb_key(wbk); |
| 399 | kfree(scb); | ||
| 354 | _leave(" = %d [no keys]", ret); | 400 | _leave(" = %d [no keys]", ret); |
| 355 | return ret; | 401 | return ret; |
| 356 | 402 | ||
| @@ -362,13 +408,18 @@ found_key: | |||
| 362 | 408 | ||
| 363 | ret = -ERESTARTSYS; | 409 | ret = -ERESTARTSYS; |
| 364 | if (afs_begin_vnode_operation(&fc, vnode, wbk->key, false)) { | 410 | if (afs_begin_vnode_operation(&fc, vnode, wbk->key, false)) { |
| 411 | afs_dataversion_t data_version = vnode->status.data_version + 1; | ||
| 412 | |||
| 365 | while (afs_select_fileserver(&fc)) { | 413 | while (afs_select_fileserver(&fc)) { |
| 366 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 414 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 367 | afs_fs_store_data(&fc, mapping, first, last, offset, to); | 415 | afs_fs_store_data(&fc, mapping, first, last, offset, to, scb); |
| 368 | } | 416 | } |
| 369 | 417 | ||
| 370 | afs_check_for_remote_deletion(&fc, fc.vnode); | 418 | afs_check_for_remote_deletion(&fc, vnode); |
| 371 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 419 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, |
| 420 | &data_version, scb); | ||
| 421 | if (fc.ac.error == 0) | ||
| 422 | afs_pages_written_back(vnode, first, last); | ||
| 372 | ret = afs_end_vnode_operation(&fc); | 423 | ret = afs_end_vnode_operation(&fc); |
| 373 | } | 424 | } |
| 374 | 425 | ||
| @@ -393,6 +444,7 @@ found_key: | |||
| 393 | } | 444 | } |
| 394 | 445 | ||
| 395 | afs_put_wb_key(wbk); | 446 | afs_put_wb_key(wbk); |
| 447 | kfree(scb); | ||
| 396 | _leave(" = %d", ret); | 448 | _leave(" = %d", ret); |
| 397 | return ret; | 449 | return ret; |
| 398 | } | 450 | } |
| @@ -679,46 +731,6 @@ int afs_writepages(struct address_space *mapping, | |||
| 679 | } | 731 | } |
| 680 | 732 | ||
| 681 | /* | 733 | /* |
| 682 | * completion of write to server | ||
| 683 | */ | ||
| 684 | void afs_pages_written_back(struct afs_vnode *vnode, struct afs_call *call) | ||
| 685 | { | ||
| 686 | struct pagevec pv; | ||
| 687 | unsigned long priv; | ||
| 688 | unsigned count, loop; | ||
| 689 | pgoff_t first = call->first, last = call->last; | ||
| 690 | |||
| 691 | _enter("{%llx:%llu},{%lx-%lx}", | ||
| 692 | vnode->fid.vid, vnode->fid.vnode, first, last); | ||
| 693 | |||
| 694 | pagevec_init(&pv); | ||
| 695 | |||
| 696 | do { | ||
| 697 | _debug("done %lx-%lx", first, last); | ||
| 698 | |||
| 699 | count = last - first + 1; | ||
| 700 | if (count > PAGEVEC_SIZE) | ||
| 701 | count = PAGEVEC_SIZE; | ||
| 702 | pv.nr = find_get_pages_contig(vnode->vfs_inode.i_mapping, | ||
| 703 | first, count, pv.pages); | ||
| 704 | ASSERTCMP(pv.nr, ==, count); | ||
| 705 | |||
| 706 | for (loop = 0; loop < count; loop++) { | ||
| 707 | priv = page_private(pv.pages[loop]); | ||
| 708 | trace_afs_page_dirty(vnode, tracepoint_string("clear"), | ||
| 709 | pv.pages[loop]->index, priv); | ||
| 710 | set_page_private(pv.pages[loop], 0); | ||
| 711 | end_page_writeback(pv.pages[loop]); | ||
| 712 | } | ||
| 713 | first += count; | ||
| 714 | __pagevec_release(&pv); | ||
| 715 | } while (first <= last); | ||
| 716 | |||
| 717 | afs_prune_wb_keys(vnode); | ||
| 718 | _leave(""); | ||
| 719 | } | ||
| 720 | |||
| 721 | /* | ||
| 722 | * write to an AFS file | 734 | * write to an AFS file |
| 723 | */ | 735 | */ |
| 724 | ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) | 736 | ssize_t afs_file_write(struct kiocb *iocb, struct iov_iter *from) |
diff --git a/fs/afs/xattr.c b/fs/afs/xattr.c index e13b005fac42..17f58fea7ec1 100644 --- a/fs/afs/xattr.c +++ b/fs/afs/xattr.c | |||
| @@ -47,24 +47,34 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler, | |||
| 47 | void *buffer, size_t size) | 47 | void *buffer, size_t size) |
| 48 | { | 48 | { |
| 49 | struct afs_fs_cursor fc; | 49 | struct afs_fs_cursor fc; |
| 50 | struct afs_status_cb *scb; | ||
| 50 | struct afs_vnode *vnode = AFS_FS_I(inode); | 51 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 51 | struct afs_acl *acl = NULL; | 52 | struct afs_acl *acl = NULL; |
| 52 | struct key *key; | 53 | struct key *key; |
| 53 | int ret; | 54 | int ret = -ENOMEM; |
| 55 | |||
| 56 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS); | ||
| 57 | if (!scb) | ||
| 58 | goto error; | ||
| 54 | 59 | ||
| 55 | key = afs_request_key(vnode->volume->cell); | 60 | key = afs_request_key(vnode->volume->cell); |
| 56 | if (IS_ERR(key)) | 61 | if (IS_ERR(key)) { |
| 57 | return PTR_ERR(key); | 62 | ret = PTR_ERR(key); |
| 63 | goto error_scb; | ||
| 64 | } | ||
| 58 | 65 | ||
| 59 | ret = -ERESTARTSYS; | 66 | ret = -ERESTARTSYS; |
| 60 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { | 67 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { |
| 68 | afs_dataversion_t data_version = vnode->status.data_version; | ||
| 69 | |||
| 61 | while (afs_select_fileserver(&fc)) { | 70 | while (afs_select_fileserver(&fc)) { |
| 62 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 71 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 63 | acl = afs_fs_fetch_acl(&fc); | 72 | acl = afs_fs_fetch_acl(&fc, scb); |
| 64 | } | 73 | } |
| 65 | 74 | ||
| 66 | afs_check_for_remote_deletion(&fc, fc.vnode); | 75 | afs_check_for_remote_deletion(&fc, fc.vnode); |
| 67 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 76 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, |
| 77 | &data_version, scb); | ||
| 68 | ret = afs_end_vnode_operation(&fc); | 78 | ret = afs_end_vnode_operation(&fc); |
| 69 | } | 79 | } |
| 70 | 80 | ||
| @@ -80,6 +90,9 @@ static int afs_xattr_get_acl(const struct xattr_handler *handler, | |||
| 80 | } | 90 | } |
| 81 | 91 | ||
| 82 | key_put(key); | 92 | key_put(key); |
| 93 | error_scb: | ||
| 94 | kfree(scb); | ||
| 95 | error: | ||
| 83 | return ret; | 96 | return ret; |
| 84 | } | 97 | } |
| 85 | 98 | ||
| @@ -92,22 +105,27 @@ static int afs_xattr_set_acl(const struct xattr_handler *handler, | |||
| 92 | const void *buffer, size_t size, int flags) | 105 | const void *buffer, size_t size, int flags) |
| 93 | { | 106 | { |
| 94 | struct afs_fs_cursor fc; | 107 | struct afs_fs_cursor fc; |
| 108 | struct afs_status_cb *scb; | ||
| 95 | struct afs_vnode *vnode = AFS_FS_I(inode); | 109 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 96 | struct afs_acl *acl = NULL; | 110 | struct afs_acl *acl = NULL; |
| 97 | struct key *key; | 111 | struct key *key; |
| 98 | int ret; | 112 | int ret = -ENOMEM; |
| 99 | 113 | ||
| 100 | if (flags == XATTR_CREATE) | 114 | if (flags == XATTR_CREATE) |
| 101 | return -EINVAL; | 115 | return -EINVAL; |
| 102 | 116 | ||
| 103 | key = afs_request_key(vnode->volume->cell); | 117 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS); |
| 104 | if (IS_ERR(key)) | 118 | if (!scb) |
| 105 | return PTR_ERR(key); | 119 | goto error; |
| 106 | 120 | ||
| 107 | acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL); | 121 | acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL); |
| 108 | if (!acl) { | 122 | if (!acl) |
| 109 | key_put(key); | 123 | goto error_scb; |
| 110 | return -ENOMEM; | 124 | |
| 125 | key = afs_request_key(vnode->volume->cell); | ||
| 126 | if (IS_ERR(key)) { | ||
| 127 | ret = PTR_ERR(key); | ||
| 128 | goto error_acl; | ||
| 111 | } | 129 | } |
| 112 | 130 | ||
| 113 | acl->size = size; | 131 | acl->size = size; |
| @@ -115,18 +133,25 @@ static int afs_xattr_set_acl(const struct xattr_handler *handler, | |||
| 115 | 133 | ||
| 116 | ret = -ERESTARTSYS; | 134 | ret = -ERESTARTSYS; |
| 117 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { | 135 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { |
| 136 | afs_dataversion_t data_version = vnode->status.data_version; | ||
| 137 | |||
| 118 | while (afs_select_fileserver(&fc)) { | 138 | while (afs_select_fileserver(&fc)) { |
| 119 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 139 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 120 | afs_fs_store_acl(&fc, acl); | 140 | afs_fs_store_acl(&fc, acl, scb); |
| 121 | } | 141 | } |
| 122 | 142 | ||
| 123 | afs_check_for_remote_deletion(&fc, fc.vnode); | 143 | afs_check_for_remote_deletion(&fc, fc.vnode); |
| 124 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 144 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, |
| 145 | &data_version, scb); | ||
| 125 | ret = afs_end_vnode_operation(&fc); | 146 | ret = afs_end_vnode_operation(&fc); |
| 126 | } | 147 | } |
| 127 | 148 | ||
| 128 | kfree(acl); | ||
| 129 | key_put(key); | 149 | key_put(key); |
| 150 | error_acl: | ||
| 151 | kfree(acl); | ||
| 152 | error_scb: | ||
| 153 | kfree(scb); | ||
| 154 | error: | ||
| 130 | return ret; | 155 | return ret; |
| 131 | } | 156 | } |
| 132 | 157 | ||
| @@ -145,6 +170,7 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler, | |||
| 145 | void *buffer, size_t size) | 170 | void *buffer, size_t size) |
| 146 | { | 171 | { |
| 147 | struct afs_fs_cursor fc; | 172 | struct afs_fs_cursor fc; |
| 173 | struct afs_status_cb *scb; | ||
| 148 | struct afs_vnode *vnode = AFS_FS_I(inode); | 174 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 149 | struct yfs_acl *yacl = NULL; | 175 | struct yfs_acl *yacl = NULL; |
| 150 | struct key *key; | 176 | struct key *key; |
| @@ -171,21 +197,28 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler, | |||
| 171 | else if (which == 3) | 197 | else if (which == 3) |
| 172 | yacl->flags |= YFS_ACL_WANT_VOL_ACL; | 198 | yacl->flags |= YFS_ACL_WANT_VOL_ACL; |
| 173 | 199 | ||
| 200 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS); | ||
| 201 | if (!scb) | ||
| 202 | goto error_yacl; | ||
| 203 | |||
| 174 | key = afs_request_key(vnode->volume->cell); | 204 | key = afs_request_key(vnode->volume->cell); |
| 175 | if (IS_ERR(key)) { | 205 | if (IS_ERR(key)) { |
| 176 | ret = PTR_ERR(key); | 206 | ret = PTR_ERR(key); |
| 177 | goto error_yacl; | 207 | goto error_scb; |
| 178 | } | 208 | } |
| 179 | 209 | ||
| 180 | ret = -ERESTARTSYS; | 210 | ret = -ERESTARTSYS; |
| 181 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { | 211 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { |
| 212 | afs_dataversion_t data_version = vnode->status.data_version; | ||
| 213 | |||
| 182 | while (afs_select_fileserver(&fc)) { | 214 | while (afs_select_fileserver(&fc)) { |
| 183 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 215 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 184 | yfs_fs_fetch_opaque_acl(&fc, yacl); | 216 | yfs_fs_fetch_opaque_acl(&fc, yacl, scb); |
| 185 | } | 217 | } |
| 186 | 218 | ||
| 187 | afs_check_for_remote_deletion(&fc, fc.vnode); | 219 | afs_check_for_remote_deletion(&fc, fc.vnode); |
| 188 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 220 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, |
| 221 | &data_version, scb); | ||
| 189 | ret = afs_end_vnode_operation(&fc); | 222 | ret = afs_end_vnode_operation(&fc); |
| 190 | } | 223 | } |
| 191 | 224 | ||
| @@ -225,6 +258,8 @@ static int afs_xattr_get_yfs(const struct xattr_handler *handler, | |||
| 225 | 258 | ||
| 226 | error_key: | 259 | error_key: |
| 227 | key_put(key); | 260 | key_put(key); |
| 261 | error_scb: | ||
| 262 | kfree(scb); | ||
| 228 | error_yacl: | 263 | error_yacl: |
| 229 | yfs_free_opaque_acl(yacl); | 264 | yfs_free_opaque_acl(yacl); |
| 230 | error: | 265 | error: |
| @@ -240,42 +275,54 @@ static int afs_xattr_set_yfs(const struct xattr_handler *handler, | |||
| 240 | const void *buffer, size_t size, int flags) | 275 | const void *buffer, size_t size, int flags) |
| 241 | { | 276 | { |
| 242 | struct afs_fs_cursor fc; | 277 | struct afs_fs_cursor fc; |
| 278 | struct afs_status_cb *scb; | ||
| 243 | struct afs_vnode *vnode = AFS_FS_I(inode); | 279 | struct afs_vnode *vnode = AFS_FS_I(inode); |
| 244 | struct afs_acl *acl = NULL; | 280 | struct afs_acl *acl = NULL; |
| 245 | struct key *key; | 281 | struct key *key; |
| 246 | int ret; | 282 | int ret = -ENOMEM; |
| 247 | 283 | ||
| 248 | if (flags == XATTR_CREATE || | 284 | if (flags == XATTR_CREATE || |
| 249 | strcmp(name, "acl") != 0) | 285 | strcmp(name, "acl") != 0) |
| 250 | return -EINVAL; | 286 | return -EINVAL; |
| 251 | 287 | ||
| 252 | key = afs_request_key(vnode->volume->cell); | 288 | scb = kzalloc(sizeof(struct afs_status_cb), GFP_NOFS); |
| 253 | if (IS_ERR(key)) | 289 | if (!scb) |
| 254 | return PTR_ERR(key); | 290 | goto error; |
| 255 | 291 | ||
| 256 | acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL); | 292 | acl = kmalloc(sizeof(*acl) + size, GFP_KERNEL); |
| 257 | if (!acl) { | 293 | if (!acl) |
| 258 | key_put(key); | 294 | goto error_scb; |
| 259 | return -ENOMEM; | ||
| 260 | } | ||
| 261 | 295 | ||
| 262 | acl->size = size; | 296 | acl->size = size; |
| 263 | memcpy(acl->data, buffer, size); | 297 | memcpy(acl->data, buffer, size); |
| 264 | 298 | ||
| 299 | key = afs_request_key(vnode->volume->cell); | ||
| 300 | if (IS_ERR(key)) { | ||
| 301 | ret = PTR_ERR(key); | ||
| 302 | goto error_acl; | ||
| 303 | } | ||
| 304 | |||
| 265 | ret = -ERESTARTSYS; | 305 | ret = -ERESTARTSYS; |
| 266 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { | 306 | if (afs_begin_vnode_operation(&fc, vnode, key, true)) { |
| 307 | afs_dataversion_t data_version = vnode->status.data_version; | ||
| 308 | |||
| 267 | while (afs_select_fileserver(&fc)) { | 309 | while (afs_select_fileserver(&fc)) { |
| 268 | fc.cb_break = afs_calc_vnode_cb_break(vnode); | 310 | fc.cb_break = afs_calc_vnode_cb_break(vnode); |
| 269 | yfs_fs_store_opaque_acl2(&fc, acl); | 311 | yfs_fs_store_opaque_acl2(&fc, acl, scb); |
| 270 | } | 312 | } |
| 271 | 313 | ||
| 272 | afs_check_for_remote_deletion(&fc, fc.vnode); | 314 | afs_check_for_remote_deletion(&fc, fc.vnode); |
| 273 | afs_vnode_commit_status(&fc, vnode, fc.cb_break); | 315 | afs_vnode_commit_status(&fc, vnode, fc.cb_break, |
| 316 | &data_version, scb); | ||
| 274 | ret = afs_end_vnode_operation(&fc); | 317 | ret = afs_end_vnode_operation(&fc); |
| 275 | } | 318 | } |
| 276 | 319 | ||
| 320 | error_acl: | ||
| 277 | kfree(acl); | 321 | kfree(acl); |
| 278 | key_put(key); | 322 | key_put(key); |
| 323 | error_scb: | ||
| 324 | kfree(scb); | ||
| 325 | error: | ||
| 279 | return ret; | 326 | return ret; |
| 280 | } | 327 | } |
| 281 | 328 | ||
diff --git a/fs/afs/yfsclient.c b/fs/afs/yfsclient.c index b42bd412dba1..10de675dc6fc 100644 --- a/fs/afs/yfsclient.c +++ b/fs/afs/yfsclient.c | |||
| @@ -183,24 +183,19 @@ static void xdr_dump_bad(const __be32 *bp) | |||
| 183 | /* | 183 | /* |
| 184 | * Decode a YFSFetchStatus block | 184 | * Decode a YFSFetchStatus block |
| 185 | */ | 185 | */ |
| 186 | static int xdr_decode_YFSFetchStatus(struct afs_call *call, | 186 | static int xdr_decode_YFSFetchStatus(const __be32 **_bp, |
| 187 | const __be32 **_bp, | 187 | struct afs_call *call, |
| 188 | struct afs_file_status *status, | 188 | struct afs_status_cb *scb) |
| 189 | struct afs_vnode *vnode, | ||
| 190 | const afs_dataversion_t *expected_version, | ||
| 191 | struct afs_read *read_req) | ||
| 192 | { | 189 | { |
| 193 | const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp; | 190 | const struct yfs_xdr_YFSFetchStatus *xdr = (const void *)*_bp; |
| 191 | struct afs_file_status *status = &scb->status; | ||
| 194 | u32 type; | 192 | u32 type; |
| 195 | u8 flags = 0; | ||
| 196 | 193 | ||
| 197 | status->abort_code = ntohl(xdr->abort_code); | 194 | status->abort_code = ntohl(xdr->abort_code); |
| 198 | if (status->abort_code != 0) { | 195 | if (status->abort_code != 0) { |
| 199 | if (vnode && status->abort_code == VNOVNODE) { | 196 | if (status->abort_code == VNOVNODE) |
| 200 | set_bit(AFS_VNODE_DELETED, &vnode->flags); | ||
| 201 | status->nlink = 0; | 197 | status->nlink = 0; |
| 202 | __afs_break_callback(vnode); | 198 | scb->have_error = true; |
| 203 | } | ||
| 204 | return 0; | 199 | return 0; |
| 205 | } | 200 | } |
| 206 | 201 | ||
| @@ -209,77 +204,28 @@ static int xdr_decode_YFSFetchStatus(struct afs_call *call, | |||
| 209 | case AFS_FTYPE_FILE: | 204 | case AFS_FTYPE_FILE: |
| 210 | case AFS_FTYPE_DIR: | 205 | case AFS_FTYPE_DIR: |
| 211 | case AFS_FTYPE_SYMLINK: | 206 | case AFS_FTYPE_SYMLINK: |
| 212 | if (type != status->type && | ||
| 213 | vnode && | ||
| 214 | !test_bit(AFS_VNODE_UNSET, &vnode->flags)) { | ||
| 215 | pr_warning("Vnode %llx:%llx:%x changed type %u to %u\n", | ||
| 216 | vnode->fid.vid, | ||
| 217 | vnode->fid.vnode, | ||
| 218 | vnode->fid.unique, | ||
| 219 | status->type, type); | ||
| 220 | goto bad; | ||
| 221 | } | ||
| 222 | status->type = type; | 207 | status->type = type; |
| 223 | break; | 208 | break; |
| 224 | default: | 209 | default: |
| 225 | goto bad; | 210 | goto bad; |
| 226 | } | 211 | } |
| 227 | 212 | ||
| 228 | #define EXTRACT_M4(FIELD) \ | 213 | status->nlink = ntohl(xdr->nlink); |
| 229 | do { \ | 214 | status->author = xdr_to_u64(xdr->author); |
| 230 | u32 x = ntohl(xdr->FIELD); \ | 215 | status->owner = xdr_to_u64(xdr->owner); |
| 231 | if (status->FIELD != x) { \ | 216 | status->caller_access = ntohl(xdr->caller_access); /* Ticket dependent */ |
| 232 | flags |= AFS_VNODE_META_CHANGED; \ | 217 | status->anon_access = ntohl(xdr->anon_access); |
| 233 | status->FIELD = x; \ | 218 | status->mode = ntohl(xdr->mode) & S_IALLUGO; |
| 234 | } \ | 219 | status->group = xdr_to_u64(xdr->group); |
| 235 | } while (0) | 220 | status->lock_count = ntohl(xdr->lock_count); |
| 236 | 221 | ||
| 237 | #define EXTRACT_M8(FIELD) \ | 222 | status->mtime_client = xdr_to_time(xdr->mtime_client); |
| 238 | do { \ | 223 | status->mtime_server = xdr_to_time(xdr->mtime_server); |
| 239 | u64 x = xdr_to_u64(xdr->FIELD); \ | 224 | status->size = xdr_to_u64(xdr->size); |
| 240 | if (status->FIELD != x) { \ | 225 | status->data_version = xdr_to_u64(xdr->data_version); |
| 241 | flags |= AFS_VNODE_META_CHANGED; \ | 226 | scb->have_status = true; |
| 242 | status->FIELD = x; \ | ||
| 243 | } \ | ||
| 244 | } while (0) | ||
| 245 | |||
| 246 | #define EXTRACT_D8(FIELD) \ | ||
| 247 | do { \ | ||
| 248 | u64 x = xdr_to_u64(xdr->FIELD); \ | ||
| 249 | if (status->FIELD != x) { \ | ||
| 250 | flags |= AFS_VNODE_DATA_CHANGED; \ | ||
| 251 | status->FIELD = x; \ | ||
| 252 | } \ | ||
| 253 | } while (0) | ||
| 254 | |||
| 255 | EXTRACT_M4(nlink); | ||
| 256 | EXTRACT_D8(size); | ||
| 257 | EXTRACT_D8(data_version); | ||
| 258 | EXTRACT_M8(author); | ||
| 259 | EXTRACT_M8(owner); | ||
| 260 | EXTRACT_M8(group); | ||
| 261 | EXTRACT_M4(mode); | ||
| 262 | EXTRACT_M4(caller_access); /* call ticket dependent */ | ||
| 263 | EXTRACT_M4(anon_access); | ||
| 264 | |||
| 265 | status->mtime_client = xdr_to_time(xdr->mtime_client); | ||
| 266 | status->mtime_server = xdr_to_time(xdr->mtime_server); | ||
| 267 | status->lock_count = ntohl(xdr->lock_count); | ||
| 268 | |||
| 269 | if (read_req) { | ||
| 270 | read_req->data_version = status->data_version; | ||
| 271 | read_req->file_size = status->size; | ||
| 272 | } | ||
| 273 | 227 | ||
| 274 | *_bp += xdr_size(xdr); | 228 | *_bp += xdr_size(xdr); |
| 275 | |||
| 276 | if (vnode) { | ||
| 277 | if (test_bit(AFS_VNODE_UNSET, &vnode->flags)) | ||
| 278 | flags |= AFS_VNODE_NOT_YET_SET; | ||
| 279 | afs_update_inode_from_status(vnode, status, expected_version, | ||
| 280 | flags); | ||
| 281 | } | ||
| 282 | |||
| 283 | return 0; | 229 | return 0; |
| 284 | 230 | ||
| 285 | bad: | 231 | bad: |
| @@ -288,76 +234,24 @@ bad: | |||
| 288 | } | 234 | } |
| 289 | 235 | ||
| 290 | /* | 236 | /* |
| 291 | * Decode the file status. We need to lock the target vnode if we're going to | 237 | * Decode a YFSCallBack block |
| 292 | * update its status so that stat() sees the attributes update atomically. | ||
| 293 | */ | 238 | */ |
| 294 | static int yfs_decode_status(struct afs_call *call, | 239 | static void xdr_decode_YFSCallBack(const __be32 **_bp, |
| 295 | const __be32 **_bp, | 240 | struct afs_call *call, |
| 296 | struct afs_file_status *status, | 241 | struct afs_status_cb *scb) |
| 297 | struct afs_vnode *vnode, | ||
| 298 | const afs_dataversion_t *expected_version, | ||
| 299 | struct afs_read *read_req) | ||
| 300 | { | ||
| 301 | int ret; | ||
| 302 | |||
| 303 | if (!vnode) | ||
| 304 | return xdr_decode_YFSFetchStatus(call, _bp, status, vnode, | ||
| 305 | expected_version, read_req); | ||
| 306 | |||
| 307 | write_seqlock(&vnode->cb_lock); | ||
| 308 | ret = xdr_decode_YFSFetchStatus(call, _bp, status, vnode, | ||
| 309 | expected_version, read_req); | ||
| 310 | write_sequnlock(&vnode->cb_lock); | ||
| 311 | return ret; | ||
| 312 | } | ||
| 313 | |||
| 314 | static void xdr_decode_YFSCallBack_raw(struct afs_call *call, | ||
| 315 | struct afs_callback *cb, | ||
| 316 | const __be32 **_bp) | ||
| 317 | { | 242 | { |
| 318 | struct yfs_xdr_YFSCallBack *x = (void *)*_bp; | 243 | struct yfs_xdr_YFSCallBack *x = (void *)*_bp; |
| 244 | struct afs_callback *cb = &scb->callback; | ||
| 319 | ktime_t cb_expiry; | 245 | ktime_t cb_expiry; |
| 320 | 246 | ||
| 321 | cb_expiry = call->reply_time; | 247 | cb_expiry = call->reply_time; |
| 322 | cb_expiry = ktime_add(cb_expiry, xdr_to_u64(x->expiration_time) * 100); | 248 | cb_expiry = ktime_add(cb_expiry, xdr_to_u64(x->expiration_time) * 100); |
| 323 | cb->expires_at = ktime_divns(cb_expiry, NSEC_PER_SEC); | 249 | cb->expires_at = ktime_divns(cb_expiry, NSEC_PER_SEC); |
| 324 | cb->version = ntohl(x->version); | 250 | scb->have_cb = true; |
| 325 | cb->type = ntohl(x->type); | ||
| 326 | |||
| 327 | *_bp += xdr_size(x); | 251 | *_bp += xdr_size(x); |
| 328 | } | 252 | } |
| 329 | 253 | ||
| 330 | /* | 254 | /* |
| 331 | * Decode a YFSCallBack block | ||
| 332 | */ | ||
| 333 | static void xdr_decode_YFSCallBack(struct afs_call *call, | ||
| 334 | struct afs_vnode *vnode, | ||
| 335 | const __be32 **_bp) | ||
| 336 | { | ||
| 337 | struct afs_cb_interest *old, *cbi = call->cbi; | ||
| 338 | struct afs_callback cb; | ||
| 339 | |||
| 340 | xdr_decode_YFSCallBack_raw(call, &cb, _bp); | ||
| 341 | |||
| 342 | write_seqlock(&vnode->cb_lock); | ||
| 343 | |||
| 344 | if (!afs_cb_is_broken(call->cb_break, vnode, cbi)) { | ||
| 345 | vnode->cb_version = cb.version; | ||
| 346 | vnode->cb_type = cb.type; | ||
| 347 | vnode->cb_expires_at = cb.expires_at; | ||
| 348 | old = vnode->cb_interest; | ||
| 349 | if (old != call->cbi) { | ||
| 350 | vnode->cb_interest = cbi; | ||
| 351 | cbi = old; | ||
| 352 | } | ||
| 353 | set_bit(AFS_VNODE_CB_PROMISED, &vnode->flags); | ||
| 354 | } | ||
| 355 | |||
| 356 | write_sequnlock(&vnode->cb_lock); | ||
| 357 | call->cbi = cbi; | ||
| 358 | } | ||
| 359 | |||
| 360 | /* | ||
| 361 | * Decode a YFSVolSync block | 255 | * Decode a YFSVolSync block |
| 362 | */ | 256 | */ |
| 363 | static void xdr_decode_YFSVolSync(const __be32 **_bp, | 257 | static void xdr_decode_YFSVolSync(const __be32 **_bp, |
| @@ -441,11 +335,10 @@ static void xdr_decode_YFSFetchVolumeStatus(const __be32 **_bp, | |||
| 441 | } | 335 | } |
| 442 | 336 | ||
| 443 | /* | 337 | /* |
| 444 | * deliver reply data to an FS.FetchStatus | 338 | * Deliver a reply that's a status, callback and volsync. |
| 445 | */ | 339 | */ |
| 446 | static int yfs_deliver_fs_fetch_status_vnode(struct afs_call *call) | 340 | static int yfs_deliver_fs_status_cb_and_volsync(struct afs_call *call) |
| 447 | { | 341 | { |
| 448 | struct afs_vnode *vnode = call->reply[0]; | ||
| 449 | const __be32 *bp; | 342 | const __be32 *bp; |
| 450 | int ret; | 343 | int ret; |
| 451 | 344 | ||
| @@ -453,16 +346,36 @@ static int yfs_deliver_fs_fetch_status_vnode(struct afs_call *call) | |||
| 453 | if (ret < 0) | 346 | if (ret < 0) |
| 454 | return ret; | 347 | return ret; |
| 455 | 348 | ||
| 456 | _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); | ||
| 457 | |||
| 458 | /* unmarshall the reply once we've received all of it */ | 349 | /* unmarshall the reply once we've received all of it */ |
| 459 | bp = call->buffer; | 350 | bp = call->buffer; |
| 460 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | 351 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); |
| 461 | &call->expected_version, NULL); | ||
| 462 | if (ret < 0) | 352 | if (ret < 0) |
| 463 | return ret; | 353 | return ret; |
| 464 | xdr_decode_YFSCallBack(call, vnode, &bp); | 354 | xdr_decode_YFSCallBack(&bp, call, call->out_scb); |
| 465 | xdr_decode_YFSVolSync(&bp, call->reply[1]); | 355 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 356 | |||
| 357 | _leave(" = 0 [done]"); | ||
| 358 | return 0; | ||
| 359 | } | ||
| 360 | |||
| 361 | /* | ||
| 362 | * Deliver reply data to operations that just return a file status and a volume | ||
| 363 | * sync record. | ||
| 364 | */ | ||
| 365 | static int yfs_deliver_status_and_volsync(struct afs_call *call) | ||
| 366 | { | ||
| 367 | const __be32 *bp; | ||
| 368 | int ret; | ||
| 369 | |||
| 370 | ret = afs_transfer_reply(call); | ||
| 371 | if (ret < 0) | ||
| 372 | return ret; | ||
| 373 | |||
| 374 | bp = call->buffer; | ||
| 375 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); | ||
| 376 | if (ret < 0) | ||
| 377 | return ret; | ||
| 378 | xdr_decode_YFSVolSync(&bp, call->out_volsync); | ||
| 466 | 379 | ||
| 467 | _leave(" = 0 [done]"); | 380 | _leave(" = 0 [done]"); |
| 468 | return 0; | 381 | return 0; |
| @@ -474,15 +387,15 @@ static int yfs_deliver_fs_fetch_status_vnode(struct afs_call *call) | |||
| 474 | static const struct afs_call_type yfs_RXYFSFetchStatus_vnode = { | 387 | static const struct afs_call_type yfs_RXYFSFetchStatus_vnode = { |
| 475 | .name = "YFS.FetchStatus(vnode)", | 388 | .name = "YFS.FetchStatus(vnode)", |
| 476 | .op = yfs_FS_FetchStatus, | 389 | .op = yfs_FS_FetchStatus, |
| 477 | .deliver = yfs_deliver_fs_fetch_status_vnode, | 390 | .deliver = yfs_deliver_fs_status_cb_and_volsync, |
| 478 | .destructor = afs_flat_call_destructor, | 391 | .destructor = afs_flat_call_destructor, |
| 479 | }; | 392 | }; |
| 480 | 393 | ||
| 481 | /* | 394 | /* |
| 482 | * Fetch the status information for a file. | 395 | * Fetch the status information for a file. |
| 483 | */ | 396 | */ |
| 484 | int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsync, | 397 | int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_status_cb *scb, |
| 485 | bool new_inode) | 398 | struct afs_volsync *volsync) |
| 486 | { | 399 | { |
| 487 | struct afs_vnode *vnode = fc->vnode; | 400 | struct afs_vnode *vnode = fc->vnode; |
| 488 | struct afs_call *call; | 401 | struct afs_call *call; |
| @@ -504,9 +417,8 @@ int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
| 504 | } | 417 | } |
| 505 | 418 | ||
| 506 | call->key = fc->key; | 419 | call->key = fc->key; |
| 507 | call->reply[0] = vnode; | 420 | call->out_scb = scb; |
| 508 | call->reply[1] = volsync; | 421 | call->out_volsync = volsync; |
| 509 | call->expected_version = new_inode ? 1 : vnode->status.data_version; | ||
| 510 | 422 | ||
| 511 | /* marshall the parameters */ | 423 | /* marshall the parameters */ |
| 512 | bp = call->request; | 424 | bp = call->request; |
| @@ -515,7 +427,6 @@ int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
| 515 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | 427 | bp = xdr_encode_YFSFid(bp, &vnode->fid); |
| 516 | yfs_check_req(call, bp); | 428 | yfs_check_req(call, bp); |
| 517 | 429 | ||
| 518 | call->cb_break = fc->cb_break; | ||
| 519 | afs_use_fs_server(call, fc->cbi); | 430 | afs_use_fs_server(call, fc->cbi); |
| 520 | trace_afs_make_fs_call(call, &vnode->fid); | 431 | trace_afs_make_fs_call(call, &vnode->fid); |
| 521 | afs_set_fc_call(call, fc); | 432 | afs_set_fc_call(call, fc); |
| @@ -528,8 +439,7 @@ int yfs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy | |||
| 528 | */ | 439 | */ |
| 529 | static int yfs_deliver_fs_fetch_data64(struct afs_call *call) | 440 | static int yfs_deliver_fs_fetch_data64(struct afs_call *call) |
| 530 | { | 441 | { |
| 531 | struct afs_vnode *vnode = call->reply[0]; | 442 | struct afs_read *req = call->read_request; |
| 532 | struct afs_read *req = call->reply[2]; | ||
| 533 | const __be32 *bp; | 443 | const __be32 *bp; |
| 534 | unsigned int size; | 444 | unsigned int size; |
| 535 | int ret; | 445 | int ret; |
| @@ -586,7 +496,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) | |||
| 586 | if (req->offset == PAGE_SIZE) { | 496 | if (req->offset == PAGE_SIZE) { |
| 587 | req->offset = 0; | 497 | req->offset = 0; |
| 588 | if (req->page_done) | 498 | if (req->page_done) |
| 589 | req->page_done(call, req); | 499 | req->page_done(req); |
| 590 | req->index++; | 500 | req->index++; |
| 591 | if (req->remain > 0) | 501 | if (req->remain > 0) |
| 592 | goto begin_page; | 502 | goto begin_page; |
| @@ -623,12 +533,14 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) | |||
| 623 | return ret; | 533 | return ret; |
| 624 | 534 | ||
| 625 | bp = call->buffer; | 535 | bp = call->buffer; |
| 626 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | 536 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); |
| 627 | &vnode->status.data_version, req); | ||
| 628 | if (ret < 0) | 537 | if (ret < 0) |
| 629 | return ret; | 538 | return ret; |
| 630 | xdr_decode_YFSCallBack(call, vnode, &bp); | 539 | xdr_decode_YFSCallBack(&bp, call, call->out_scb); |
| 631 | xdr_decode_YFSVolSync(&bp, call->reply[1]); | 540 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 541 | |||
| 542 | req->data_version = call->out_scb->status.data_version; | ||
| 543 | req->file_size = call->out_scb->status.size; | ||
| 632 | 544 | ||
| 633 | call->unmarshall++; | 545 | call->unmarshall++; |
| 634 | 546 | ||
| @@ -642,7 +554,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) | |||
| 642 | zero_user_segment(req->pages[req->index], | 554 | zero_user_segment(req->pages[req->index], |
| 643 | req->offset, PAGE_SIZE); | 555 | req->offset, PAGE_SIZE); |
| 644 | if (req->page_done) | 556 | if (req->page_done) |
| 645 | req->page_done(call, req); | 557 | req->page_done(req); |
| 646 | req->offset = 0; | 558 | req->offset = 0; |
| 647 | } | 559 | } |
| 648 | 560 | ||
| @@ -652,9 +564,7 @@ static int yfs_deliver_fs_fetch_data64(struct afs_call *call) | |||
| 652 | 564 | ||
| 653 | static void yfs_fetch_data_destructor(struct afs_call *call) | 565 | static void yfs_fetch_data_destructor(struct afs_call *call) |
| 654 | { | 566 | { |
| 655 | struct afs_read *req = call->reply[2]; | 567 | afs_put_read(call->read_request); |
| 656 | |||
| 657 | afs_put_read(req); | ||
| 658 | afs_flat_call_destructor(call); | 568 | afs_flat_call_destructor(call); |
| 659 | } | 569 | } |
| 660 | 570 | ||
| @@ -671,7 +581,8 @@ static const struct afs_call_type yfs_RXYFSFetchData64 = { | |||
| 671 | /* | 581 | /* |
| 672 | * Fetch data from a file. | 582 | * Fetch data from a file. |
| 673 | */ | 583 | */ |
| 674 | int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | 584 | int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_status_cb *scb, |
| 585 | struct afs_read *req) | ||
| 675 | { | 586 | { |
| 676 | struct afs_vnode *vnode = fc->vnode; | 587 | struct afs_vnode *vnode = fc->vnode; |
| 677 | struct afs_call *call; | 588 | struct afs_call *call; |
| @@ -693,11 +604,9 @@ int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 693 | return -ENOMEM; | 604 | return -ENOMEM; |
| 694 | 605 | ||
| 695 | call->key = fc->key; | 606 | call->key = fc->key; |
| 696 | call->reply[0] = vnode; | 607 | call->out_scb = scb; |
| 697 | call->reply[1] = NULL; /* volsync */ | 608 | call->out_volsync = NULL; |
| 698 | call->reply[2] = req; | 609 | call->read_request = req; |
| 699 | call->expected_version = vnode->status.data_version; | ||
| 700 | call->want_reply_time = true; | ||
| 701 | 610 | ||
| 702 | /* marshall the parameters */ | 611 | /* marshall the parameters */ |
| 703 | bp = call->request; | 612 | bp = call->request; |
| @@ -709,7 +618,6 @@ int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 709 | yfs_check_req(call, bp); | 618 | yfs_check_req(call, bp); |
| 710 | 619 | ||
| 711 | refcount_inc(&req->usage); | 620 | refcount_inc(&req->usage); |
| 712 | call->cb_break = fc->cb_break; | ||
| 713 | afs_use_fs_server(call, fc->cbi); | 621 | afs_use_fs_server(call, fc->cbi); |
| 714 | trace_afs_make_fs_call(call, &vnode->fid); | 622 | trace_afs_make_fs_call(call, &vnode->fid); |
| 715 | afs_set_fc_call(call, fc); | 623 | afs_set_fc_call(call, fc); |
| @@ -722,7 +630,6 @@ int yfs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req) | |||
| 722 | */ | 630 | */ |
| 723 | static int yfs_deliver_fs_create_vnode(struct afs_call *call) | 631 | static int yfs_deliver_fs_create_vnode(struct afs_call *call) |
| 724 | { | 632 | { |
| 725 | struct afs_vnode *vnode = call->reply[0]; | ||
| 726 | const __be32 *bp; | 633 | const __be32 *bp; |
| 727 | int ret; | 634 | int ret; |
| 728 | 635 | ||
| @@ -734,16 +641,15 @@ static int yfs_deliver_fs_create_vnode(struct afs_call *call) | |||
| 734 | 641 | ||
| 735 | /* unmarshall the reply once we've received all of it */ | 642 | /* unmarshall the reply once we've received all of it */ |
| 736 | bp = call->buffer; | 643 | bp = call->buffer; |
| 737 | xdr_decode_YFSFid(&bp, call->reply[1]); | 644 | xdr_decode_YFSFid(&bp, call->out_fid); |
| 738 | ret = yfs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL); | 645 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); |
| 739 | if (ret < 0) | 646 | if (ret < 0) |
| 740 | return ret; | 647 | return ret; |
| 741 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | 648 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb); |
| 742 | &call->expected_version, NULL); | ||
| 743 | if (ret < 0) | 649 | if (ret < 0) |
| 744 | return ret; | 650 | return ret; |
| 745 | xdr_decode_YFSCallBack_raw(call, call->reply[3], &bp); | 651 | xdr_decode_YFSCallBack(&bp, call, call->out_scb); |
| 746 | xdr_decode_YFSVolSync(&bp, NULL); | 652 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 747 | 653 | ||
| 748 | _leave(" = 0 [done]"); | 654 | _leave(" = 0 [done]"); |
| 749 | return 0; | 655 | return 0; |
| @@ -765,14 +671,13 @@ static const struct afs_call_type afs_RXFSCreateFile = { | |||
| 765 | int yfs_fs_create_file(struct afs_fs_cursor *fc, | 671 | int yfs_fs_create_file(struct afs_fs_cursor *fc, |
| 766 | const char *name, | 672 | const char *name, |
| 767 | umode_t mode, | 673 | umode_t mode, |
| 768 | u64 current_data_version, | 674 | struct afs_status_cb *dvnode_scb, |
| 769 | struct afs_fid *newfid, | 675 | struct afs_fid *newfid, |
| 770 | struct afs_file_status *newstatus, | 676 | struct afs_status_cb *new_scb) |
| 771 | struct afs_callback *newcb) | ||
| 772 | { | 677 | { |
| 773 | struct afs_vnode *vnode = fc->vnode; | 678 | struct afs_vnode *dvnode = fc->vnode; |
| 774 | struct afs_call *call; | 679 | struct afs_call *call; |
| 775 | struct afs_net *net = afs_v2net(vnode); | 680 | struct afs_net *net = afs_v2net(dvnode); |
| 776 | size_t namesz, reqsz, rplsz; | 681 | size_t namesz, reqsz, rplsz; |
| 777 | __be32 *bp; | 682 | __be32 *bp; |
| 778 | 683 | ||
| @@ -796,24 +701,22 @@ int yfs_fs_create_file(struct afs_fs_cursor *fc, | |||
| 796 | return -ENOMEM; | 701 | return -ENOMEM; |
| 797 | 702 | ||
| 798 | call->key = fc->key; | 703 | call->key = fc->key; |
| 799 | call->reply[0] = vnode; | 704 | call->out_dir_scb = dvnode_scb; |
| 800 | call->reply[1] = newfid; | 705 | call->out_fid = newfid; |
| 801 | call->reply[2] = newstatus; | 706 | call->out_scb = new_scb; |
| 802 | call->reply[3] = newcb; | ||
| 803 | call->expected_version = current_data_version + 1; | ||
| 804 | 707 | ||
| 805 | /* marshall the parameters */ | 708 | /* marshall the parameters */ |
| 806 | bp = call->request; | 709 | bp = call->request; |
| 807 | bp = xdr_encode_u32(bp, YFSCREATEFILE); | 710 | bp = xdr_encode_u32(bp, YFSCREATEFILE); |
| 808 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | 711 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ |
| 809 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | 712 | bp = xdr_encode_YFSFid(bp, &dvnode->fid); |
| 810 | bp = xdr_encode_string(bp, name, namesz); | 713 | bp = xdr_encode_string(bp, name, namesz); |
| 811 | bp = xdr_encode_YFSStoreStatus_mode(bp, mode); | 714 | bp = xdr_encode_YFSStoreStatus_mode(bp, mode); |
| 812 | bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */ | 715 | bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */ |
| 813 | yfs_check_req(call, bp); | 716 | yfs_check_req(call, bp); |
| 814 | 717 | ||
| 815 | afs_use_fs_server(call, fc->cbi); | 718 | afs_use_fs_server(call, fc->cbi); |
| 816 | trace_afs_make_fs_call1(call, &vnode->fid, name); | 719 | trace_afs_make_fs_call1(call, &dvnode->fid, name); |
| 817 | afs_set_fc_call(call, fc); | 720 | afs_set_fc_call(call, fc); |
| 818 | afs_make_call(&fc->ac, call, GFP_NOFS); | 721 | afs_make_call(&fc->ac, call, GFP_NOFS); |
| 819 | return afs_wait_for_call_to_complete(call, &fc->ac); | 722 | return afs_wait_for_call_to_complete(call, &fc->ac); |
| @@ -832,14 +735,13 @@ static const struct afs_call_type yfs_RXFSMakeDir = { | |||
| 832 | int yfs_fs_make_dir(struct afs_fs_cursor *fc, | 735 | int yfs_fs_make_dir(struct afs_fs_cursor *fc, |
| 833 | const char *name, | 736 | const char *name, |
| 834 | umode_t mode, | 737 | umode_t mode, |
| 835 | u64 current_data_version, | 738 | struct afs_status_cb *dvnode_scb, |
| 836 | struct afs_fid *newfid, | 739 | struct afs_fid *newfid, |
| 837 | struct afs_file_status *newstatus, | 740 | struct afs_status_cb *new_scb) |
| 838 | struct afs_callback *newcb) | ||
| 839 | { | 741 | { |
| 840 | struct afs_vnode *vnode = fc->vnode; | 742 | struct afs_vnode *dvnode = fc->vnode; |
| 841 | struct afs_call *call; | 743 | struct afs_call *call; |
| 842 | struct afs_net *net = afs_v2net(vnode); | 744 | struct afs_net *net = afs_v2net(dvnode); |
| 843 | size_t namesz, reqsz, rplsz; | 745 | size_t namesz, reqsz, rplsz; |
| 844 | __be32 *bp; | 746 | __be32 *bp; |
| 845 | 747 | ||
| @@ -862,23 +764,21 @@ int yfs_fs_make_dir(struct afs_fs_cursor *fc, | |||
| 862 | return -ENOMEM; | 764 | return -ENOMEM; |
| 863 | 765 | ||
| 864 | call->key = fc->key; | 766 | call->key = fc->key; |
| 865 | call->reply[0] = vnode; | 767 | call->out_dir_scb = dvnode_scb; |
| 866 | call->reply[1] = newfid; | 768 | call->out_fid = newfid; |
| 867 | call->reply[2] = newstatus; | 769 | call->out_scb = new_scb; |
| 868 | call->reply[3] = newcb; | ||
| 869 | call->expected_version = current_data_version + 1; | ||
| 870 | 770 | ||
| 871 | /* marshall the parameters */ | 771 | /* marshall the parameters */ |
| 872 | bp = call->request; | 772 | bp = call->request; |
| 873 | bp = xdr_encode_u32(bp, YFSMAKEDIR); | 773 | bp = xdr_encode_u32(bp, YFSMAKEDIR); |
| 874 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ | 774 | bp = xdr_encode_u32(bp, 0); /* RPC flags */ |
| 875 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | 775 | bp = xdr_encode_YFSFid(bp, &dvnode->fid); |
| 876 | bp = xdr_encode_string(bp, name, namesz); | 776 | bp = xdr_encode_string(bp, name, namesz); |
| 877 | bp = xdr_encode_YFSStoreStatus_mode(bp, mode); | 777 | bp = xdr_encode_YFSStoreStatus_mode(bp, mode); |
| 878 | yfs_check_req(call, bp); | 778 | yfs_check_req(call, bp); |
| 879 | 779 | ||
| 880 | afs_use_fs_server(call, fc->cbi); | 780 | afs_use_fs_server(call, fc->cbi); |
| 881 | trace_afs_make_fs_call1(call, &vnode->fid, name); | 781 | trace_afs_make_fs_call1(call, &dvnode->fid, name); |
| 882 | afs_set_fc_call(call, fc); | 782 | afs_set_fc_call(call, fc); |
| 883 | afs_make_call(&fc->ac, call, GFP_NOFS); | 783 | afs_make_call(&fc->ac, call, GFP_NOFS); |
| 884 | return afs_wait_for_call_to_complete(call, &fc->ac); | 784 | return afs_wait_for_call_to_complete(call, &fc->ac); |
| @@ -889,8 +789,6 @@ int yfs_fs_make_dir(struct afs_fs_cursor *fc, | |||
| 889 | */ | 789 | */ |
| 890 | static int yfs_deliver_fs_remove_file2(struct afs_call *call) | 790 | static int yfs_deliver_fs_remove_file2(struct afs_call *call) |
| 891 | { | 791 | { |
| 892 | struct afs_vnode *dvnode = call->reply[0]; | ||
| 893 | struct afs_vnode *vnode = call->reply[1]; | ||
| 894 | struct afs_fid fid; | 792 | struct afs_fid fid; |
| 895 | const __be32 *bp; | 793 | const __be32 *bp; |
| 896 | int ret; | 794 | int ret; |
| @@ -901,20 +799,18 @@ static int yfs_deliver_fs_remove_file2(struct afs_call *call) | |||
| 901 | if (ret < 0) | 799 | if (ret < 0) |
| 902 | return ret; | 800 | return ret; |
| 903 | 801 | ||
| 904 | /* unmarshall the reply once we've received all of it */ | ||
| 905 | bp = call->buffer; | 802 | bp = call->buffer; |
| 906 | ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode, | 803 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb); |
| 907 | &call->expected_version, NULL); | ||
| 908 | if (ret < 0) | 804 | if (ret < 0) |
| 909 | return ret; | 805 | return ret; |
| 910 | 806 | ||
| 911 | xdr_decode_YFSFid(&bp, &fid); | 807 | xdr_decode_YFSFid(&bp, &fid); |
| 912 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL); | 808 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); |
| 913 | if (ret < 0) | 809 | if (ret < 0) |
| 914 | return ret; | 810 | return ret; |
| 915 | /* Was deleted if vnode->status.abort_code == VNOVNODE. */ | 811 | /* Was deleted if vnode->status.abort_code == VNOVNODE. */ |
| 916 | 812 | ||
| 917 | xdr_decode_YFSVolSync(&bp, NULL); | 813 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 918 | return 0; | 814 | return 0; |
| 919 | } | 815 | } |
| 920 | 816 | ||
| @@ -932,7 +828,8 @@ static const struct afs_call_type yfs_RXYFSRemoveFile2 = { | |||
| 932 | * Remove a file and retrieve new file status. | 828 | * Remove a file and retrieve new file status. |
| 933 | */ | 829 | */ |
| 934 | int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | 830 | int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode, |
| 935 | const char *name, u64 current_data_version) | 831 | const char *name, struct afs_status_cb *dvnode_scb, |
| 832 | struct afs_status_cb *vnode_scb) | ||
| 936 | { | 833 | { |
| 937 | struct afs_vnode *dvnode = fc->vnode; | 834 | struct afs_vnode *dvnode = fc->vnode; |
| 938 | struct afs_call *call; | 835 | struct afs_call *call; |
| @@ -957,9 +854,8 @@ int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 957 | return -ENOMEM; | 854 | return -ENOMEM; |
| 958 | 855 | ||
| 959 | call->key = fc->key; | 856 | call->key = fc->key; |
| 960 | call->reply[0] = dvnode; | 857 | call->out_dir_scb = dvnode_scb; |
| 961 | call->reply[1] = vnode; | 858 | call->out_scb = vnode_scb; |
| 962 | call->expected_version = current_data_version + 1; | ||
| 963 | 859 | ||
| 964 | /* marshall the parameters */ | 860 | /* marshall the parameters */ |
| 965 | bp = call->request; | 861 | bp = call->request; |
| @@ -981,7 +877,6 @@ int yfs_fs_remove_file2(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 981 | */ | 877 | */ |
| 982 | static int yfs_deliver_fs_remove(struct afs_call *call) | 878 | static int yfs_deliver_fs_remove(struct afs_call *call) |
| 983 | { | 879 | { |
| 984 | struct afs_vnode *dvnode = call->reply[0]; | ||
| 985 | const __be32 *bp; | 880 | const __be32 *bp; |
| 986 | int ret; | 881 | int ret; |
| 987 | 882 | ||
| @@ -991,14 +886,12 @@ static int yfs_deliver_fs_remove(struct afs_call *call) | |||
| 991 | if (ret < 0) | 886 | if (ret < 0) |
| 992 | return ret; | 887 | return ret; |
| 993 | 888 | ||
| 994 | /* unmarshall the reply once we've received all of it */ | ||
| 995 | bp = call->buffer; | 889 | bp = call->buffer; |
| 996 | ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode, | 890 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb); |
| 997 | &call->expected_version, NULL); | ||
| 998 | if (ret < 0) | 891 | if (ret < 0) |
| 999 | return ret; | 892 | return ret; |
| 1000 | 893 | ||
| 1001 | xdr_decode_YFSVolSync(&bp, NULL); | 894 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 1002 | return 0; | 895 | return 0; |
| 1003 | } | 896 | } |
| 1004 | 897 | ||
| @@ -1023,7 +916,8 @@ static const struct afs_call_type yfs_RXYFSRemoveDir = { | |||
| 1023 | * remove a file or directory | 916 | * remove a file or directory |
| 1024 | */ | 917 | */ |
| 1025 | int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | 918 | int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, |
| 1026 | const char *name, bool isdir, u64 current_data_version) | 919 | const char *name, bool isdir, |
| 920 | struct afs_status_cb *dvnode_scb) | ||
| 1027 | { | 921 | { |
| 1028 | struct afs_vnode *dvnode = fc->vnode; | 922 | struct afs_vnode *dvnode = fc->vnode; |
| 1029 | struct afs_call *call; | 923 | struct afs_call *call; |
| @@ -1046,9 +940,7 @@ int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 1046 | return -ENOMEM; | 940 | return -ENOMEM; |
| 1047 | 941 | ||
| 1048 | call->key = fc->key; | 942 | call->key = fc->key; |
| 1049 | call->reply[0] = dvnode; | 943 | call->out_dir_scb = dvnode_scb; |
| 1050 | call->reply[1] = vnode; | ||
| 1051 | call->expected_version = current_data_version + 1; | ||
| 1052 | 944 | ||
| 1053 | /* marshall the parameters */ | 945 | /* marshall the parameters */ |
| 1054 | bp = call->request; | 946 | bp = call->request; |
| @@ -1070,7 +962,6 @@ int yfs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 1070 | */ | 962 | */ |
| 1071 | static int yfs_deliver_fs_link(struct afs_call *call) | 963 | static int yfs_deliver_fs_link(struct afs_call *call) |
| 1072 | { | 964 | { |
| 1073 | struct afs_vnode *dvnode = call->reply[0], *vnode = call->reply[1]; | ||
| 1074 | const __be32 *bp; | 965 | const __be32 *bp; |
| 1075 | int ret; | 966 | int ret; |
| 1076 | 967 | ||
| @@ -1080,16 +971,14 @@ static int yfs_deliver_fs_link(struct afs_call *call) | |||
| 1080 | if (ret < 0) | 971 | if (ret < 0) |
| 1081 | return ret; | 972 | return ret; |
| 1082 | 973 | ||
| 1083 | /* unmarshall the reply once we've received all of it */ | ||
| 1084 | bp = call->buffer; | 974 | bp = call->buffer; |
| 1085 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL); | 975 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); |
| 1086 | if (ret < 0) | 976 | if (ret < 0) |
| 1087 | return ret; | 977 | return ret; |
| 1088 | ret = yfs_decode_status(call, &bp, &dvnode->status, dvnode, | 978 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb); |
| 1089 | &call->expected_version, NULL); | ||
| 1090 | if (ret < 0) | 979 | if (ret < 0) |
| 1091 | return ret; | 980 | return ret; |
| 1092 | xdr_decode_YFSVolSync(&bp, NULL); | 981 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 1093 | _leave(" = 0 [done]"); | 982 | _leave(" = 0 [done]"); |
| 1094 | return 0; | 983 | return 0; |
| 1095 | } | 984 | } |
| @@ -1108,7 +997,9 @@ static const struct afs_call_type yfs_RXYFSLink = { | |||
| 1108 | * Make a hard link. | 997 | * Make a hard link. |
| 1109 | */ | 998 | */ |
| 1110 | int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | 999 | int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, |
| 1111 | const char *name, u64 current_data_version) | 1000 | const char *name, |
| 1001 | struct afs_status_cb *dvnode_scb, | ||
| 1002 | struct afs_status_cb *vnode_scb) | ||
| 1112 | { | 1003 | { |
| 1113 | struct afs_vnode *dvnode = fc->vnode; | 1004 | struct afs_vnode *dvnode = fc->vnode; |
| 1114 | struct afs_call *call; | 1005 | struct afs_call *call; |
| @@ -1132,9 +1023,8 @@ int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 1132 | return -ENOMEM; | 1023 | return -ENOMEM; |
| 1133 | 1024 | ||
| 1134 | call->key = fc->key; | 1025 | call->key = fc->key; |
| 1135 | call->reply[0] = dvnode; | 1026 | call->out_dir_scb = dvnode_scb; |
| 1136 | call->reply[1] = vnode; | 1027 | call->out_scb = vnode_scb; |
| 1137 | call->expected_version = current_data_version + 1; | ||
| 1138 | 1028 | ||
| 1139 | /* marshall the parameters */ | 1029 | /* marshall the parameters */ |
| 1140 | bp = call->request; | 1030 | bp = call->request; |
| @@ -1157,7 +1047,6 @@ int yfs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode, | |||
| 1157 | */ | 1047 | */ |
| 1158 | static int yfs_deliver_fs_symlink(struct afs_call *call) | 1048 | static int yfs_deliver_fs_symlink(struct afs_call *call) |
| 1159 | { | 1049 | { |
| 1160 | struct afs_vnode *vnode = call->reply[0]; | ||
| 1161 | const __be32 *bp; | 1050 | const __be32 *bp; |
| 1162 | int ret; | 1051 | int ret; |
| 1163 | 1052 | ||
| @@ -1169,15 +1058,14 @@ static int yfs_deliver_fs_symlink(struct afs_call *call) | |||
| 1169 | 1058 | ||
| 1170 | /* unmarshall the reply once we've received all of it */ | 1059 | /* unmarshall the reply once we've received all of it */ |
| 1171 | bp = call->buffer; | 1060 | bp = call->buffer; |
| 1172 | xdr_decode_YFSFid(&bp, call->reply[1]); | 1061 | xdr_decode_YFSFid(&bp, call->out_fid); |
| 1173 | ret = yfs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL); | 1062 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); |
| 1174 | if (ret < 0) | 1063 | if (ret < 0) |
| 1175 | return ret; | 1064 | return ret; |
| 1176 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | 1065 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb); |
| 1177 | &call->expected_version, NULL); | ||
| 1178 | if (ret < 0) | 1066 | if (ret < 0) |
| 1179 | return ret; | 1067 | return ret; |
| 1180 | xdr_decode_YFSVolSync(&bp, NULL); | 1068 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 1181 | 1069 | ||
| 1182 | _leave(" = 0 [done]"); | 1070 | _leave(" = 0 [done]"); |
| 1183 | return 0; | 1071 | return 0; |
| @@ -1199,9 +1087,9 @@ static const struct afs_call_type yfs_RXYFSSymlink = { | |||
| 1199 | int yfs_fs_symlink(struct afs_fs_cursor *fc, | 1087 | int yfs_fs_symlink(struct afs_fs_cursor *fc, |
| 1200 | const char *name, | 1088 | const char *name, |
| 1201 | const char *contents, | 1089 | const char *contents, |
| 1202 | u64 current_data_version, | 1090 | struct afs_status_cb *dvnode_scb, |
| 1203 | struct afs_fid *newfid, | 1091 | struct afs_fid *newfid, |
| 1204 | struct afs_file_status *newstatus) | 1092 | struct afs_status_cb *vnode_scb) |
| 1205 | { | 1093 | { |
| 1206 | struct afs_vnode *dvnode = fc->vnode; | 1094 | struct afs_vnode *dvnode = fc->vnode; |
| 1207 | struct afs_call *call; | 1095 | struct afs_call *call; |
| @@ -1228,10 +1116,9 @@ int yfs_fs_symlink(struct afs_fs_cursor *fc, | |||
| 1228 | return -ENOMEM; | 1116 | return -ENOMEM; |
| 1229 | 1117 | ||
| 1230 | call->key = fc->key; | 1118 | call->key = fc->key; |
| 1231 | call->reply[0] = dvnode; | 1119 | call->out_dir_scb = dvnode_scb; |
| 1232 | call->reply[1] = newfid; | 1120 | call->out_fid = newfid; |
| 1233 | call->reply[2] = newstatus; | 1121 | call->out_scb = vnode_scb; |
| 1234 | call->expected_version = current_data_version + 1; | ||
| 1235 | 1122 | ||
| 1236 | /* marshall the parameters */ | 1123 | /* marshall the parameters */ |
| 1237 | bp = call->request; | 1124 | bp = call->request; |
| @@ -1255,8 +1142,6 @@ int yfs_fs_symlink(struct afs_fs_cursor *fc, | |||
| 1255 | */ | 1142 | */ |
| 1256 | static int yfs_deliver_fs_rename(struct afs_call *call) | 1143 | static int yfs_deliver_fs_rename(struct afs_call *call) |
| 1257 | { | 1144 | { |
| 1258 | struct afs_vnode *orig_dvnode = call->reply[0]; | ||
| 1259 | struct afs_vnode *new_dvnode = call->reply[1]; | ||
| 1260 | const __be32 *bp; | 1145 | const __be32 *bp; |
| 1261 | int ret; | 1146 | int ret; |
| 1262 | 1147 | ||
| @@ -1266,20 +1151,17 @@ static int yfs_deliver_fs_rename(struct afs_call *call) | |||
| 1266 | if (ret < 0) | 1151 | if (ret < 0) |
| 1267 | return ret; | 1152 | return ret; |
| 1268 | 1153 | ||
| 1269 | /* unmarshall the reply once we've received all of it */ | ||
| 1270 | bp = call->buffer; | 1154 | bp = call->buffer; |
| 1271 | ret = yfs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode, | 1155 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_dir_scb); |
| 1272 | &call->expected_version, NULL); | ||
| 1273 | if (ret < 0) | 1156 | if (ret < 0) |
| 1274 | return ret; | 1157 | return ret; |
| 1275 | if (new_dvnode != orig_dvnode) { | 1158 | if (call->out_dir_scb != call->out_scb) { |
| 1276 | ret = yfs_decode_status(call, &bp, &new_dvnode->status, new_dvnode, | 1159 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); |
| 1277 | &call->expected_version_2, NULL); | ||
| 1278 | if (ret < 0) | 1160 | if (ret < 0) |
| 1279 | return ret; | 1161 | return ret; |
| 1280 | } | 1162 | } |
| 1281 | 1163 | ||
| 1282 | xdr_decode_YFSVolSync(&bp, NULL); | 1164 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 1283 | _leave(" = 0 [done]"); | 1165 | _leave(" = 0 [done]"); |
| 1284 | return 0; | 1166 | return 0; |
| 1285 | } | 1167 | } |
| @@ -1301,8 +1183,8 @@ int yfs_fs_rename(struct afs_fs_cursor *fc, | |||
| 1301 | const char *orig_name, | 1183 | const char *orig_name, |
| 1302 | struct afs_vnode *new_dvnode, | 1184 | struct afs_vnode *new_dvnode, |
| 1303 | const char *new_name, | 1185 | const char *new_name, |
| 1304 | u64 current_orig_data_version, | 1186 | struct afs_status_cb *orig_dvnode_scb, |
| 1305 | u64 current_new_data_version) | 1187 | struct afs_status_cb *new_dvnode_scb) |
| 1306 | { | 1188 | { |
| 1307 | struct afs_vnode *orig_dvnode = fc->vnode; | 1189 | struct afs_vnode *orig_dvnode = fc->vnode; |
| 1308 | struct afs_call *call; | 1190 | struct afs_call *call; |
| @@ -1328,10 +1210,8 @@ int yfs_fs_rename(struct afs_fs_cursor *fc, | |||
| 1328 | return -ENOMEM; | 1210 | return -ENOMEM; |
| 1329 | 1211 | ||
| 1330 | call->key = fc->key; | 1212 | call->key = fc->key; |
| 1331 | call->reply[0] = orig_dvnode; | 1213 | call->out_dir_scb = orig_dvnode_scb; |
| 1332 | call->reply[1] = new_dvnode; | 1214 | call->out_scb = new_dvnode_scb; |
| 1333 | call->expected_version = current_orig_data_version + 1; | ||
| 1334 | call->expected_version_2 = current_new_data_version + 1; | ||
| 1335 | 1215 | ||
| 1336 | /* marshall the parameters */ | 1216 | /* marshall the parameters */ |
| 1337 | bp = call->request; | 1217 | bp = call->request; |
| @@ -1351,41 +1231,12 @@ int yfs_fs_rename(struct afs_fs_cursor *fc, | |||
| 1351 | } | 1231 | } |
| 1352 | 1232 | ||
| 1353 | /* | 1233 | /* |
| 1354 | * Deliver reply data to a YFS.StoreData64 operation. | ||
| 1355 | */ | ||
| 1356 | static int yfs_deliver_fs_store_data(struct afs_call *call) | ||
| 1357 | { | ||
| 1358 | struct afs_vnode *vnode = call->reply[0]; | ||
| 1359 | const __be32 *bp; | ||
| 1360 | int ret; | ||
| 1361 | |||
| 1362 | _enter(""); | ||
| 1363 | |||
| 1364 | ret = afs_transfer_reply(call); | ||
| 1365 | if (ret < 0) | ||
| 1366 | return ret; | ||
| 1367 | |||
| 1368 | /* unmarshall the reply once we've received all of it */ | ||
| 1369 | bp = call->buffer; | ||
| 1370 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
| 1371 | &call->expected_version, NULL); | ||
| 1372 | if (ret < 0) | ||
| 1373 | return ret; | ||
| 1374 | xdr_decode_YFSVolSync(&bp, NULL); | ||
| 1375 | |||
| 1376 | afs_pages_written_back(vnode, call); | ||
| 1377 | |||
| 1378 | _leave(" = 0 [done]"); | ||
| 1379 | return 0; | ||
| 1380 | } | ||
| 1381 | |||
| 1382 | /* | ||
| 1383 | * YFS.StoreData64 operation type. | 1234 | * YFS.StoreData64 operation type. |
| 1384 | */ | 1235 | */ |
| 1385 | static const struct afs_call_type yfs_RXYFSStoreData64 = { | 1236 | static const struct afs_call_type yfs_RXYFSStoreData64 = { |
| 1386 | .name = "YFS.StoreData64", | 1237 | .name = "YFS.StoreData64", |
| 1387 | .op = yfs_FS_StoreData64, | 1238 | .op = yfs_FS_StoreData64, |
| 1388 | .deliver = yfs_deliver_fs_store_data, | 1239 | .deliver = yfs_deliver_status_and_volsync, |
| 1389 | .destructor = afs_flat_call_destructor, | 1240 | .destructor = afs_flat_call_destructor, |
| 1390 | }; | 1241 | }; |
| 1391 | 1242 | ||
| @@ -1394,7 +1245,8 @@ static const struct afs_call_type yfs_RXYFSStoreData64 = { | |||
| 1394 | */ | 1245 | */ |
| 1395 | int yfs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | 1246 | int yfs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, |
| 1396 | pgoff_t first, pgoff_t last, | 1247 | pgoff_t first, pgoff_t last, |
| 1397 | unsigned offset, unsigned to) | 1248 | unsigned offset, unsigned to, |
| 1249 | struct afs_status_cb *scb) | ||
| 1398 | { | 1250 | { |
| 1399 | struct afs_vnode *vnode = fc->vnode; | 1251 | struct afs_vnode *vnode = fc->vnode; |
| 1400 | struct afs_call *call; | 1252 | struct afs_call *call; |
| @@ -1432,13 +1284,12 @@ int yfs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | |||
| 1432 | 1284 | ||
| 1433 | call->key = fc->key; | 1285 | call->key = fc->key; |
| 1434 | call->mapping = mapping; | 1286 | call->mapping = mapping; |
| 1435 | call->reply[0] = vnode; | ||
| 1436 | call->first = first; | 1287 | call->first = first; |
| 1437 | call->last = last; | 1288 | call->last = last; |
| 1438 | call->first_offset = offset; | 1289 | call->first_offset = offset; |
| 1439 | call->last_to = to; | 1290 | call->last_to = to; |
| 1440 | call->send_pages = true; | 1291 | call->send_pages = true; |
| 1441 | call->expected_version = vnode->status.data_version + 1; | 1292 | call->out_scb = scb; |
| 1442 | 1293 | ||
| 1443 | /* marshall the parameters */ | 1294 | /* marshall the parameters */ |
| 1444 | bp = call->request; | 1295 | bp = call->request; |
| @@ -1459,46 +1310,19 @@ int yfs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping, | |||
| 1459 | } | 1310 | } |
| 1460 | 1311 | ||
| 1461 | /* | 1312 | /* |
| 1462 | * deliver reply data to an FS.StoreStatus | ||
| 1463 | */ | ||
| 1464 | static int yfs_deliver_fs_store_status(struct afs_call *call) | ||
| 1465 | { | ||
| 1466 | struct afs_vnode *vnode = call->reply[0]; | ||
| 1467 | const __be32 *bp; | ||
| 1468 | int ret; | ||
| 1469 | |||
| 1470 | _enter(""); | ||
| 1471 | |||
| 1472 | ret = afs_transfer_reply(call); | ||
| 1473 | if (ret < 0) | ||
| 1474 | return ret; | ||
| 1475 | |||
| 1476 | /* unmarshall the reply once we've received all of it */ | ||
| 1477 | bp = call->buffer; | ||
| 1478 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
| 1479 | &call->expected_version, NULL); | ||
| 1480 | if (ret < 0) | ||
| 1481 | return ret; | ||
| 1482 | xdr_decode_YFSVolSync(&bp, NULL); | ||
| 1483 | |||
| 1484 | _leave(" = 0 [done]"); | ||
| 1485 | return 0; | ||
| 1486 | } | ||
| 1487 | |||
| 1488 | /* | ||
| 1489 | * YFS.StoreStatus operation type | 1313 | * YFS.StoreStatus operation type |
| 1490 | */ | 1314 | */ |
| 1491 | static const struct afs_call_type yfs_RXYFSStoreStatus = { | 1315 | static const struct afs_call_type yfs_RXYFSStoreStatus = { |
| 1492 | .name = "YFS.StoreStatus", | 1316 | .name = "YFS.StoreStatus", |
| 1493 | .op = yfs_FS_StoreStatus, | 1317 | .op = yfs_FS_StoreStatus, |
| 1494 | .deliver = yfs_deliver_fs_store_status, | 1318 | .deliver = yfs_deliver_status_and_volsync, |
| 1495 | .destructor = afs_flat_call_destructor, | 1319 | .destructor = afs_flat_call_destructor, |
| 1496 | }; | 1320 | }; |
| 1497 | 1321 | ||
| 1498 | static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = { | 1322 | static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = { |
| 1499 | .name = "YFS.StoreData64", | 1323 | .name = "YFS.StoreData64", |
| 1500 | .op = yfs_FS_StoreData64, | 1324 | .op = yfs_FS_StoreData64, |
| 1501 | .deliver = yfs_deliver_fs_store_status, | 1325 | .deliver = yfs_deliver_status_and_volsync, |
| 1502 | .destructor = afs_flat_call_destructor, | 1326 | .destructor = afs_flat_call_destructor, |
| 1503 | }; | 1327 | }; |
| 1504 | 1328 | ||
| @@ -1506,7 +1330,8 @@ static const struct afs_call_type yfs_RXYFSStoreData64_as_Status = { | |||
| 1506 | * Set the attributes on a file, using YFS.StoreData64 rather than | 1330 | * Set the attributes on a file, using YFS.StoreData64 rather than |
| 1507 | * YFS.StoreStatus so as to alter the file size also. | 1331 | * YFS.StoreStatus so as to alter the file size also. |
| 1508 | */ | 1332 | */ |
| 1509 | static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr) | 1333 | static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr, |
| 1334 | struct afs_status_cb *scb) | ||
| 1510 | { | 1335 | { |
| 1511 | struct afs_vnode *vnode = fc->vnode; | 1336 | struct afs_vnode *vnode = fc->vnode; |
| 1512 | struct afs_call *call; | 1337 | struct afs_call *call; |
| @@ -1527,8 +1352,7 @@ static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1527 | return -ENOMEM; | 1352 | return -ENOMEM; |
| 1528 | 1353 | ||
| 1529 | call->key = fc->key; | 1354 | call->key = fc->key; |
| 1530 | call->reply[0] = vnode; | 1355 | call->out_scb = scb; |
| 1531 | call->expected_version = vnode->status.data_version + 1; | ||
| 1532 | 1356 | ||
| 1533 | /* marshall the parameters */ | 1357 | /* marshall the parameters */ |
| 1534 | bp = call->request; | 1358 | bp = call->request; |
| @@ -1552,7 +1376,8 @@ static int yfs_fs_setattr_size(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1552 | * Set the attributes on a file, using YFS.StoreData64 if there's a change in | 1376 | * Set the attributes on a file, using YFS.StoreData64 if there's a change in |
| 1553 | * file size, and YFS.StoreStatus otherwise. | 1377 | * file size, and YFS.StoreStatus otherwise. |
| 1554 | */ | 1378 | */ |
| 1555 | int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr) | 1379 | int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr, |
| 1380 | struct afs_status_cb *scb) | ||
| 1556 | { | 1381 | { |
| 1557 | struct afs_vnode *vnode = fc->vnode; | 1382 | struct afs_vnode *vnode = fc->vnode; |
| 1558 | struct afs_call *call; | 1383 | struct afs_call *call; |
| @@ -1560,7 +1385,7 @@ int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1560 | __be32 *bp; | 1385 | __be32 *bp; |
| 1561 | 1386 | ||
| 1562 | if (attr->ia_valid & ATTR_SIZE) | 1387 | if (attr->ia_valid & ATTR_SIZE) |
| 1563 | return yfs_fs_setattr_size(fc, attr); | 1388 | return yfs_fs_setattr_size(fc, attr, scb); |
| 1564 | 1389 | ||
| 1565 | _enter(",%x,{%llx:%llu},,", | 1390 | _enter(",%x,{%llx:%llu},,", |
| 1566 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); | 1391 | key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode); |
| @@ -1575,8 +1400,7 @@ int yfs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr) | |||
| 1575 | return -ENOMEM; | 1400 | return -ENOMEM; |
| 1576 | 1401 | ||
| 1577 | call->key = fc->key; | 1402 | call->key = fc->key; |
| 1578 | call->reply[0] = vnode; | 1403 | call->out_scb = scb; |
| 1579 | call->expected_version = vnode->status.data_version; | ||
| 1580 | 1404 | ||
| 1581 | /* marshall the parameters */ | 1405 | /* marshall the parameters */ |
| 1582 | bp = call->request; | 1406 | bp = call->request; |
| @@ -1618,7 +1442,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1618 | return ret; | 1442 | return ret; |
| 1619 | 1443 | ||
| 1620 | bp = call->buffer; | 1444 | bp = call->buffer; |
| 1621 | xdr_decode_YFSFetchVolumeStatus(&bp, call->reply[1]); | 1445 | xdr_decode_YFSFetchVolumeStatus(&bp, call->out_volstatus); |
| 1622 | call->unmarshall++; | 1446 | call->unmarshall++; |
| 1623 | afs_extract_to_tmp(call); | 1447 | afs_extract_to_tmp(call); |
| 1624 | 1448 | ||
| @@ -1634,7 +1458,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1634 | return afs_protocol_error(call, -EBADMSG, | 1458 | return afs_protocol_error(call, -EBADMSG, |
| 1635 | afs_eproto_volname_len); | 1459 | afs_eproto_volname_len); |
| 1636 | size = (call->count + 3) & ~3; /* It's padded */ | 1460 | size = (call->count + 3) & ~3; /* It's padded */ |
| 1637 | afs_extract_begin(call, call->reply[2], size); | 1461 | afs_extract_to_buf(call, size); |
| 1638 | call->unmarshall++; | 1462 | call->unmarshall++; |
| 1639 | 1463 | ||
| 1640 | /* Fall through - and extract the volume name */ | 1464 | /* Fall through - and extract the volume name */ |
| @@ -1644,7 +1468,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1644 | if (ret < 0) | 1468 | if (ret < 0) |
| 1645 | return ret; | 1469 | return ret; |
| 1646 | 1470 | ||
| 1647 | p = call->reply[2]; | 1471 | p = call->buffer; |
| 1648 | p[call->count] = 0; | 1472 | p[call->count] = 0; |
| 1649 | _debug("volname '%s'", p); | 1473 | _debug("volname '%s'", p); |
| 1650 | afs_extract_to_tmp(call); | 1474 | afs_extract_to_tmp(call); |
| @@ -1662,7 +1486,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1662 | return afs_protocol_error(call, -EBADMSG, | 1486 | return afs_protocol_error(call, -EBADMSG, |
| 1663 | afs_eproto_offline_msg_len); | 1487 | afs_eproto_offline_msg_len); |
| 1664 | size = (call->count + 3) & ~3; /* It's padded */ | 1488 | size = (call->count + 3) & ~3; /* It's padded */ |
| 1665 | afs_extract_begin(call, call->reply[2], size); | 1489 | afs_extract_to_buf(call, size); |
| 1666 | call->unmarshall++; | 1490 | call->unmarshall++; |
| 1667 | 1491 | ||
| 1668 | /* Fall through - and extract the offline message */ | 1492 | /* Fall through - and extract the offline message */ |
| @@ -1672,7 +1496,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1672 | if (ret < 0) | 1496 | if (ret < 0) |
| 1673 | return ret; | 1497 | return ret; |
| 1674 | 1498 | ||
| 1675 | p = call->reply[2]; | 1499 | p = call->buffer; |
| 1676 | p[call->count] = 0; | 1500 | p[call->count] = 0; |
| 1677 | _debug("offline '%s'", p); | 1501 | _debug("offline '%s'", p); |
| 1678 | 1502 | ||
| @@ -1691,7 +1515,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1691 | return afs_protocol_error(call, -EBADMSG, | 1515 | return afs_protocol_error(call, -EBADMSG, |
| 1692 | afs_eproto_motd_len); | 1516 | afs_eproto_motd_len); |
| 1693 | size = (call->count + 3) & ~3; /* It's padded */ | 1517 | size = (call->count + 3) & ~3; /* It's padded */ |
| 1694 | afs_extract_begin(call, call->reply[2], size); | 1518 | afs_extract_to_buf(call, size); |
| 1695 | call->unmarshall++; | 1519 | call->unmarshall++; |
| 1696 | 1520 | ||
| 1697 | /* Fall through - and extract the message of the day */ | 1521 | /* Fall through - and extract the message of the day */ |
| @@ -1701,7 +1525,7 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1701 | if (ret < 0) | 1525 | if (ret < 0) |
| 1702 | return ret; | 1526 | return ret; |
| 1703 | 1527 | ||
| 1704 | p = call->reply[2]; | 1528 | p = call->buffer; |
| 1705 | p[call->count] = 0; | 1529 | p[call->count] = 0; |
| 1706 | _debug("motd '%s'", p); | 1530 | _debug("motd '%s'", p); |
| 1707 | 1531 | ||
| @@ -1717,23 +1541,13 @@ static int yfs_deliver_fs_get_volume_status(struct afs_call *call) | |||
| 1717 | } | 1541 | } |
| 1718 | 1542 | ||
| 1719 | /* | 1543 | /* |
| 1720 | * Destroy a YFS.GetVolumeStatus call. | ||
| 1721 | */ | ||
| 1722 | static void yfs_get_volume_status_call_destructor(struct afs_call *call) | ||
| 1723 | { | ||
| 1724 | kfree(call->reply[2]); | ||
| 1725 | call->reply[2] = NULL; | ||
| 1726 | afs_flat_call_destructor(call); | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | /* | ||
| 1730 | * YFS.GetVolumeStatus operation type | 1544 | * YFS.GetVolumeStatus operation type |
| 1731 | */ | 1545 | */ |
| 1732 | static const struct afs_call_type yfs_RXYFSGetVolumeStatus = { | 1546 | static const struct afs_call_type yfs_RXYFSGetVolumeStatus = { |
| 1733 | .name = "YFS.GetVolumeStatus", | 1547 | .name = "YFS.GetVolumeStatus", |
| 1734 | .op = yfs_FS_GetVolumeStatus, | 1548 | .op = yfs_FS_GetVolumeStatus, |
| 1735 | .deliver = yfs_deliver_fs_get_volume_status, | 1549 | .deliver = yfs_deliver_fs_get_volume_status, |
| 1736 | .destructor = yfs_get_volume_status_call_destructor, | 1550 | .destructor = afs_flat_call_destructor, |
| 1737 | }; | 1551 | }; |
| 1738 | 1552 | ||
| 1739 | /* | 1553 | /* |
| @@ -1746,28 +1560,21 @@ int yfs_fs_get_volume_status(struct afs_fs_cursor *fc, | |||
| 1746 | struct afs_call *call; | 1560 | struct afs_call *call; |
| 1747 | struct afs_net *net = afs_v2net(vnode); | 1561 | struct afs_net *net = afs_v2net(vnode); |
| 1748 | __be32 *bp; | 1562 | __be32 *bp; |
| 1749 | void *tmpbuf; | ||
| 1750 | 1563 | ||
| 1751 | _enter(""); | 1564 | _enter(""); |
| 1752 | 1565 | ||
| 1753 | tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL); | ||
| 1754 | if (!tmpbuf) | ||
| 1755 | return -ENOMEM; | ||
| 1756 | |||
| 1757 | call = afs_alloc_flat_call(net, &yfs_RXYFSGetVolumeStatus, | 1566 | call = afs_alloc_flat_call(net, &yfs_RXYFSGetVolumeStatus, |
| 1758 | sizeof(__be32) * 2 + | 1567 | sizeof(__be32) * 2 + |
| 1759 | sizeof(struct yfs_xdr_u64), | 1568 | sizeof(struct yfs_xdr_u64), |
| 1760 | sizeof(struct yfs_xdr_YFSFetchVolumeStatus) + | 1569 | max_t(size_t, |
| 1761 | sizeof(__be32)); | 1570 | sizeof(struct yfs_xdr_YFSFetchVolumeStatus) + |
| 1762 | if (!call) { | 1571 | sizeof(__be32), |
| 1763 | kfree(tmpbuf); | 1572 | AFSOPAQUEMAX + 1)); |
| 1573 | if (!call) | ||
| 1764 | return -ENOMEM; | 1574 | return -ENOMEM; |
| 1765 | } | ||
| 1766 | 1575 | ||
| 1767 | call->key = fc->key; | 1576 | call->key = fc->key; |
| 1768 | call->reply[0] = vnode; | 1577 | call->out_volstatus = vs; |
| 1769 | call->reply[1] = vs; | ||
| 1770 | call->reply[2] = tmpbuf; | ||
| 1771 | 1578 | ||
| 1772 | /* marshall the parameters */ | 1579 | /* marshall the parameters */ |
| 1773 | bp = call->request; | 1580 | bp = call->request; |
| @@ -1784,34 +1591,6 @@ int yfs_fs_get_volume_status(struct afs_fs_cursor *fc, | |||
| 1784 | } | 1591 | } |
| 1785 | 1592 | ||
| 1786 | /* | 1593 | /* |
| 1787 | * Deliver reply data to operations that just return a file status and a volume | ||
| 1788 | * sync record. | ||
| 1789 | */ | ||
| 1790 | static int yfs_deliver_status_and_volsync(struct afs_call *call) | ||
| 1791 | { | ||
| 1792 | struct afs_vnode *vnode = call->reply[0]; | ||
| 1793 | const __be32 *bp; | ||
| 1794 | int ret; | ||
| 1795 | |||
| 1796 | _enter("{%u}", call->unmarshall); | ||
| 1797 | |||
| 1798 | ret = afs_transfer_reply(call); | ||
| 1799 | if (ret < 0) | ||
| 1800 | return ret; | ||
| 1801 | |||
| 1802 | /* unmarshall the reply once we've received all of it */ | ||
| 1803 | bp = call->buffer; | ||
| 1804 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | ||
| 1805 | &call->expected_version, NULL); | ||
| 1806 | if (ret < 0) | ||
| 1807 | return ret; | ||
| 1808 | xdr_decode_YFSVolSync(&bp, NULL); | ||
| 1809 | |||
| 1810 | _leave(" = 0 [done]"); | ||
| 1811 | return 0; | ||
| 1812 | } | ||
| 1813 | |||
| 1814 | /* | ||
| 1815 | * YFS.SetLock operation type | 1594 | * YFS.SetLock operation type |
| 1816 | */ | 1595 | */ |
| 1817 | static const struct afs_call_type yfs_RXYFSSetLock = { | 1596 | static const struct afs_call_type yfs_RXYFSSetLock = { |
| @@ -1846,7 +1625,8 @@ static const struct afs_call_type yfs_RXYFSReleaseLock = { | |||
| 1846 | /* | 1625 | /* |
| 1847 | * Set a lock on a file | 1626 | * Set a lock on a file |
| 1848 | */ | 1627 | */ |
| 1849 | int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type) | 1628 | int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type, |
| 1629 | struct afs_status_cb *scb) | ||
| 1850 | { | 1630 | { |
| 1851 | struct afs_vnode *vnode = fc->vnode; | 1631 | struct afs_vnode *vnode = fc->vnode; |
| 1852 | struct afs_call *call; | 1632 | struct afs_call *call; |
| @@ -1865,8 +1645,8 @@ int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type) | |||
| 1865 | return -ENOMEM; | 1645 | return -ENOMEM; |
| 1866 | 1646 | ||
| 1867 | call->key = fc->key; | 1647 | call->key = fc->key; |
| 1868 | call->reply[0] = vnode; | 1648 | call->lvnode = vnode; |
| 1869 | call->want_reply_time = true; | 1649 | call->out_scb = scb; |
| 1870 | 1650 | ||
| 1871 | /* marshall the parameters */ | 1651 | /* marshall the parameters */ |
| 1872 | bp = call->request; | 1652 | bp = call->request; |
| @@ -1886,7 +1666,7 @@ int yfs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type) | |||
| 1886 | /* | 1666 | /* |
| 1887 | * extend a lock on a file | 1667 | * extend a lock on a file |
| 1888 | */ | 1668 | */ |
| 1889 | int yfs_fs_extend_lock(struct afs_fs_cursor *fc) | 1669 | int yfs_fs_extend_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) |
| 1890 | { | 1670 | { |
| 1891 | struct afs_vnode *vnode = fc->vnode; | 1671 | struct afs_vnode *vnode = fc->vnode; |
| 1892 | struct afs_call *call; | 1672 | struct afs_call *call; |
| @@ -1904,8 +1684,8 @@ int yfs_fs_extend_lock(struct afs_fs_cursor *fc) | |||
| 1904 | return -ENOMEM; | 1684 | return -ENOMEM; |
| 1905 | 1685 | ||
| 1906 | call->key = fc->key; | 1686 | call->key = fc->key; |
| 1907 | call->reply[0] = vnode; | 1687 | call->lvnode = vnode; |
| 1908 | call->want_reply_time = true; | 1688 | call->out_scb = scb; |
| 1909 | 1689 | ||
| 1910 | /* marshall the parameters */ | 1690 | /* marshall the parameters */ |
| 1911 | bp = call->request; | 1691 | bp = call->request; |
| @@ -1924,7 +1704,7 @@ int yfs_fs_extend_lock(struct afs_fs_cursor *fc) | |||
| 1924 | /* | 1704 | /* |
| 1925 | * release a lock on a file | 1705 | * release a lock on a file |
| 1926 | */ | 1706 | */ |
| 1927 | int yfs_fs_release_lock(struct afs_fs_cursor *fc) | 1707 | int yfs_fs_release_lock(struct afs_fs_cursor *fc, struct afs_status_cb *scb) |
| 1928 | { | 1708 | { |
| 1929 | struct afs_vnode *vnode = fc->vnode; | 1709 | struct afs_vnode *vnode = fc->vnode; |
| 1930 | struct afs_call *call; | 1710 | struct afs_call *call; |
| @@ -1942,7 +1722,8 @@ int yfs_fs_release_lock(struct afs_fs_cursor *fc) | |||
| 1942 | return -ENOMEM; | 1722 | return -ENOMEM; |
| 1943 | 1723 | ||
| 1944 | call->key = fc->key; | 1724 | call->key = fc->key; |
| 1945 | call->reply[0] = vnode; | 1725 | call->lvnode = vnode; |
| 1726 | call->out_scb = scb; | ||
| 1946 | 1727 | ||
| 1947 | /* marshall the parameters */ | 1728 | /* marshall the parameters */ |
| 1948 | bp = call->request; | 1729 | bp = call->request; |
| @@ -1959,43 +1740,12 @@ int yfs_fs_release_lock(struct afs_fs_cursor *fc) | |||
| 1959 | } | 1740 | } |
| 1960 | 1741 | ||
| 1961 | /* | 1742 | /* |
| 1962 | * Deliver reply data to an FS.FetchStatus with no vnode. | ||
| 1963 | */ | ||
| 1964 | static int yfs_deliver_fs_fetch_status(struct afs_call *call) | ||
| 1965 | { | ||
| 1966 | struct afs_file_status *status = call->reply[1]; | ||
| 1967 | struct afs_callback *callback = call->reply[2]; | ||
| 1968 | struct afs_volsync *volsync = call->reply[3]; | ||
| 1969 | struct afs_vnode *vnode = call->reply[0]; | ||
| 1970 | const __be32 *bp; | ||
| 1971 | int ret; | ||
| 1972 | |||
| 1973 | ret = afs_transfer_reply(call); | ||
| 1974 | if (ret < 0) | ||
| 1975 | return ret; | ||
| 1976 | |||
| 1977 | _enter("{%llx:%llu}", vnode->fid.vid, vnode->fid.vnode); | ||
| 1978 | |||
| 1979 | /* unmarshall the reply once we've received all of it */ | ||
| 1980 | bp = call->buffer; | ||
| 1981 | ret = yfs_decode_status(call, &bp, status, vnode, | ||
| 1982 | &call->expected_version, NULL); | ||
| 1983 | if (ret < 0) | ||
| 1984 | return ret; | ||
| 1985 | xdr_decode_YFSCallBack_raw(call, callback, &bp); | ||
| 1986 | xdr_decode_YFSVolSync(&bp, volsync); | ||
| 1987 | |||
| 1988 | _leave(" = 0 [done]"); | ||
| 1989 | return 0; | ||
| 1990 | } | ||
| 1991 | |||
| 1992 | /* | ||
| 1993 | * YFS.FetchStatus operation type | 1743 | * YFS.FetchStatus operation type |
| 1994 | */ | 1744 | */ |
| 1995 | static const struct afs_call_type yfs_RXYFSFetchStatus = { | 1745 | static const struct afs_call_type yfs_RXYFSFetchStatus = { |
| 1996 | .name = "YFS.FetchStatus", | 1746 | .name = "YFS.FetchStatus", |
| 1997 | .op = yfs_FS_FetchStatus, | 1747 | .op = yfs_FS_FetchStatus, |
| 1998 | .deliver = yfs_deliver_fs_fetch_status, | 1748 | .deliver = yfs_deliver_fs_status_cb_and_volsync, |
| 1999 | .destructor = afs_flat_call_destructor, | 1749 | .destructor = afs_flat_call_destructor, |
| 2000 | }; | 1750 | }; |
| 2001 | 1751 | ||
| @@ -2005,8 +1755,7 @@ static const struct afs_call_type yfs_RXYFSFetchStatus = { | |||
| 2005 | int yfs_fs_fetch_status(struct afs_fs_cursor *fc, | 1755 | int yfs_fs_fetch_status(struct afs_fs_cursor *fc, |
| 2006 | struct afs_net *net, | 1756 | struct afs_net *net, |
| 2007 | struct afs_fid *fid, | 1757 | struct afs_fid *fid, |
| 2008 | struct afs_file_status *status, | 1758 | struct afs_status_cb *scb, |
| 2009 | struct afs_callback *callback, | ||
| 2010 | struct afs_volsync *volsync) | 1759 | struct afs_volsync *volsync) |
| 2011 | { | 1760 | { |
| 2012 | struct afs_call *call; | 1761 | struct afs_call *call; |
| @@ -2027,11 +1776,8 @@ int yfs_fs_fetch_status(struct afs_fs_cursor *fc, | |||
| 2027 | } | 1776 | } |
| 2028 | 1777 | ||
| 2029 | call->key = fc->key; | 1778 | call->key = fc->key; |
| 2030 | call->reply[0] = NULL; /* vnode for fid[0] */ | 1779 | call->out_scb = scb; |
| 2031 | call->reply[1] = status; | 1780 | call->out_volsync = volsync; |
| 2032 | call->reply[2] = callback; | ||
| 2033 | call->reply[3] = volsync; | ||
| 2034 | call->expected_version = 1; /* vnode->status.data_version */ | ||
| 2035 | 1781 | ||
| 2036 | /* marshall the parameters */ | 1782 | /* marshall the parameters */ |
| 2037 | bp = call->request; | 1783 | bp = call->request; |
| @@ -2040,7 +1786,6 @@ int yfs_fs_fetch_status(struct afs_fs_cursor *fc, | |||
| 2040 | bp = xdr_encode_YFSFid(bp, fid); | 1786 | bp = xdr_encode_YFSFid(bp, fid); |
| 2041 | yfs_check_req(call, bp); | 1787 | yfs_check_req(call, bp); |
| 2042 | 1788 | ||
| 2043 | call->cb_break = fc->cb_break; | ||
| 2044 | afs_use_fs_server(call, fc->cbi); | 1789 | afs_use_fs_server(call, fc->cbi); |
| 2045 | trace_afs_make_fs_call(call, fid); | 1790 | trace_afs_make_fs_call(call, fid); |
| 2046 | afs_set_fc_call(call, fc); | 1791 | afs_set_fc_call(call, fc); |
| @@ -2053,9 +1798,7 @@ int yfs_fs_fetch_status(struct afs_fs_cursor *fc, | |||
| 2053 | */ | 1798 | */ |
| 2054 | static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) | 1799 | static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) |
| 2055 | { | 1800 | { |
| 2056 | struct afs_file_status *statuses; | 1801 | struct afs_status_cb *scb; |
| 2057 | struct afs_callback *callbacks; | ||
| 2058 | struct afs_vnode *vnode = call->reply[0]; | ||
| 2059 | const __be32 *bp; | 1802 | const __be32 *bp; |
| 2060 | u32 tmp; | 1803 | u32 tmp; |
| 2061 | int ret; | 1804 | int ret; |
| @@ -2094,10 +1837,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
| 2094 | return ret; | 1837 | return ret; |
| 2095 | 1838 | ||
| 2096 | bp = call->buffer; | 1839 | bp = call->buffer; |
| 2097 | statuses = call->reply[1]; | 1840 | scb = &call->out_scb[call->count]; |
| 2098 | ret = yfs_decode_status(call, &bp, &statuses[call->count], | 1841 | ret = xdr_decode_YFSFetchStatus(&bp, call, scb); |
| 2099 | call->count == 0 ? vnode : NULL, | ||
| 2100 | NULL, NULL); | ||
| 2101 | if (ret < 0) | 1842 | if (ret < 0) |
| 2102 | return ret; | 1843 | return ret; |
| 2103 | 1844 | ||
| @@ -2136,13 +1877,8 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
| 2136 | 1877 | ||
| 2137 | _debug("unmarshall CB array"); | 1878 | _debug("unmarshall CB array"); |
| 2138 | bp = call->buffer; | 1879 | bp = call->buffer; |
| 2139 | callbacks = call->reply[2]; | 1880 | scb = &call->out_scb[call->count]; |
| 2140 | xdr_decode_YFSCallBack_raw(call, &callbacks[call->count], &bp); | 1881 | xdr_decode_YFSCallBack(&bp, call, scb); |
| 2141 | statuses = call->reply[1]; | ||
| 2142 | if (call->count == 0 && vnode && statuses[0].abort_code == 0) { | ||
| 2143 | bp = call->buffer; | ||
| 2144 | xdr_decode_YFSCallBack(call, vnode, &bp); | ||
| 2145 | } | ||
| 2146 | call->count++; | 1882 | call->count++; |
| 2147 | if (call->count < call->count2) | 1883 | if (call->count < call->count2) |
| 2148 | goto more_cbs; | 1884 | goto more_cbs; |
| @@ -2157,7 +1893,7 @@ static int yfs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
| 2157 | return ret; | 1893 | return ret; |
| 2158 | 1894 | ||
| 2159 | bp = call->buffer; | 1895 | bp = call->buffer; |
| 2160 | xdr_decode_YFSVolSync(&bp, call->reply[3]); | 1896 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 2161 | 1897 | ||
| 2162 | call->unmarshall++; | 1898 | call->unmarshall++; |
| 2163 | 1899 | ||
| @@ -2186,8 +1922,7 @@ static const struct afs_call_type yfs_RXYFSInlineBulkStatus = { | |||
| 2186 | int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | 1922 | int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc, |
| 2187 | struct afs_net *net, | 1923 | struct afs_net *net, |
| 2188 | struct afs_fid *fids, | 1924 | struct afs_fid *fids, |
| 2189 | struct afs_file_status *statuses, | 1925 | struct afs_status_cb *statuses, |
| 2190 | struct afs_callback *callbacks, | ||
| 2191 | unsigned int nr_fids, | 1926 | unsigned int nr_fids, |
| 2192 | struct afs_volsync *volsync) | 1927 | struct afs_volsync *volsync) |
| 2193 | { | 1928 | { |
| @@ -2210,10 +1945,8 @@ int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | |||
| 2210 | } | 1945 | } |
| 2211 | 1946 | ||
| 2212 | call->key = fc->key; | 1947 | call->key = fc->key; |
| 2213 | call->reply[0] = NULL; /* vnode for fid[0] */ | 1948 | call->out_scb = statuses; |
| 2214 | call->reply[1] = statuses; | 1949 | call->out_volsync = volsync; |
| 2215 | call->reply[2] = callbacks; | ||
| 2216 | call->reply[3] = volsync; | ||
| 2217 | call->count2 = nr_fids; | 1950 | call->count2 = nr_fids; |
| 2218 | 1951 | ||
| 2219 | /* marshall the parameters */ | 1952 | /* marshall the parameters */ |
| @@ -2225,7 +1958,6 @@ int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | |||
| 2225 | bp = xdr_encode_YFSFid(bp, &fids[i]); | 1958 | bp = xdr_encode_YFSFid(bp, &fids[i]); |
| 2226 | yfs_check_req(call, bp); | 1959 | yfs_check_req(call, bp); |
| 2227 | 1960 | ||
| 2228 | call->cb_break = fc->cb_break; | ||
| 2229 | afs_use_fs_server(call, fc->cbi); | 1961 | afs_use_fs_server(call, fc->cbi); |
| 2230 | trace_afs_make_fs_call(call, &fids[0]); | 1962 | trace_afs_make_fs_call(call, &fids[0]); |
| 2231 | afs_set_fc_call(call, fc); | 1963 | afs_set_fc_call(call, fc); |
| @@ -2238,9 +1970,7 @@ int yfs_fs_inline_bulk_status(struct afs_fs_cursor *fc, | |||
| 2238 | */ | 1970 | */ |
| 2239 | static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) | 1971 | static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) |
| 2240 | { | 1972 | { |
| 2241 | struct afs_volsync *volsync = call->reply[2]; | 1973 | struct yfs_acl *yacl = call->out_yacl; |
| 2242 | struct afs_vnode *vnode = call->reply[1]; | ||
| 2243 | struct yfs_acl *yacl = call->reply[0]; | ||
| 2244 | struct afs_acl *acl; | 1974 | struct afs_acl *acl; |
| 2245 | const __be32 *bp; | 1975 | const __be32 *bp; |
| 2246 | unsigned int size; | 1976 | unsigned int size; |
| @@ -2325,11 +2055,10 @@ static int yfs_deliver_fs_fetch_opaque_acl(struct afs_call *call) | |||
| 2325 | bp = call->buffer; | 2055 | bp = call->buffer; |
| 2326 | yacl->inherit_flag = ntohl(*bp++); | 2056 | yacl->inherit_flag = ntohl(*bp++); |
| 2327 | yacl->num_cleaned = ntohl(*bp++); | 2057 | yacl->num_cleaned = ntohl(*bp++); |
| 2328 | ret = yfs_decode_status(call, &bp, &vnode->status, vnode, | 2058 | ret = xdr_decode_YFSFetchStatus(&bp, call, call->out_scb); |
| 2329 | &call->expected_version, NULL); | ||
| 2330 | if (ret < 0) | 2059 | if (ret < 0) |
| 2331 | return ret; | 2060 | return ret; |
| 2332 | xdr_decode_YFSVolSync(&bp, volsync); | 2061 | xdr_decode_YFSVolSync(&bp, call->out_volsync); |
| 2333 | 2062 | ||
| 2334 | call->unmarshall++; | 2063 | call->unmarshall++; |
| 2335 | 2064 | ||
| @@ -2364,7 +2093,8 @@ static const struct afs_call_type yfs_RXYFSFetchOpaqueACL = { | |||
| 2364 | * Fetch the YFS advanced ACLs for a file. | 2093 | * Fetch the YFS advanced ACLs for a file. |
| 2365 | */ | 2094 | */ |
| 2366 | struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc, | 2095 | struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc, |
| 2367 | struct yfs_acl *yacl) | 2096 | struct yfs_acl *yacl, |
| 2097 | struct afs_status_cb *scb) | ||
| 2368 | { | 2098 | { |
| 2369 | struct afs_vnode *vnode = fc->vnode; | 2099 | struct afs_vnode *vnode = fc->vnode; |
| 2370 | struct afs_call *call; | 2100 | struct afs_call *call; |
| @@ -2386,9 +2116,9 @@ struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc, | |||
| 2386 | } | 2116 | } |
| 2387 | 2117 | ||
| 2388 | call->key = fc->key; | 2118 | call->key = fc->key; |
| 2389 | call->reply[0] = yacl; | 2119 | call->out_yacl = yacl; |
| 2390 | call->reply[1] = vnode; | 2120 | call->out_scb = scb; |
| 2391 | call->reply[2] = NULL; /* volsync */ | 2121 | call->out_volsync = NULL; |
| 2392 | 2122 | ||
| 2393 | /* marshall the parameters */ | 2123 | /* marshall the parameters */ |
| 2394 | bp = call->request; | 2124 | bp = call->request; |
| @@ -2397,7 +2127,6 @@ struct yfs_acl *yfs_fs_fetch_opaque_acl(struct afs_fs_cursor *fc, | |||
| 2397 | bp = xdr_encode_YFSFid(bp, &vnode->fid); | 2127 | bp = xdr_encode_YFSFid(bp, &vnode->fid); |
| 2398 | yfs_check_req(call, bp); | 2128 | yfs_check_req(call, bp); |
| 2399 | 2129 | ||
| 2400 | call->cb_break = fc->cb_break; | ||
| 2401 | afs_use_fs_server(call, fc->cbi); | 2130 | afs_use_fs_server(call, fc->cbi); |
| 2402 | trace_afs_make_fs_call(call, &vnode->fid); | 2131 | trace_afs_make_fs_call(call, &vnode->fid); |
| 2403 | afs_make_call(&fc->ac, call, GFP_KERNEL); | 2132 | afs_make_call(&fc->ac, call, GFP_KERNEL); |
| @@ -2417,7 +2146,8 @@ static const struct afs_call_type yfs_RXYFSStoreOpaqueACL2 = { | |||
| 2417 | /* | 2146 | /* |
| 2418 | * Fetch the YFS ACL for a file. | 2147 | * Fetch the YFS ACL for a file. |
| 2419 | */ | 2148 | */ |
| 2420 | int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *fc, const struct afs_acl *acl) | 2149 | int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *fc, const struct afs_acl *acl, |
| 2150 | struct afs_status_cb *scb) | ||
| 2421 | { | 2151 | { |
| 2422 | struct afs_vnode *vnode = fc->vnode; | 2152 | struct afs_vnode *vnode = fc->vnode; |
| 2423 | struct afs_call *call; | 2153 | struct afs_call *call; |
| @@ -2441,8 +2171,8 @@ int yfs_fs_store_opaque_acl2(struct afs_fs_cursor *fc, const struct afs_acl *acl | |||
| 2441 | } | 2171 | } |
| 2442 | 2172 | ||
| 2443 | call->key = fc->key; | 2173 | call->key = fc->key; |
| 2444 | call->reply[0] = vnode; | 2174 | call->out_scb = scb; |
| 2445 | call->reply[2] = NULL; /* volsync */ | 2175 | call->out_volsync = NULL; |
| 2446 | 2176 | ||
| 2447 | /* marshall the parameters */ | 2177 | /* marshall the parameters */ |
| 2448 | bp = call->request; | 2178 | bp = call->request; |
