diff options
| -rw-r--r-- | fs/afs/fsclient.c | 97 |
1 files changed, 55 insertions, 42 deletions
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index efacdb7c1dee..b695d9e16c65 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
| @@ -137,10 +137,6 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
| 137 | u64 data_version, size; | 137 | u64 data_version, size; |
| 138 | u32 type, abort_code; | 138 | u32 type, abort_code; |
| 139 | u8 flags = 0; | 139 | u8 flags = 0; |
| 140 | int ret; | ||
| 141 | |||
| 142 | if (vnode) | ||
| 143 | write_seqlock(&vnode->cb_lock); | ||
| 144 | 140 | ||
| 145 | if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) { | 141 | if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) { |
| 146 | pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version)); | 142 | pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version)); |
| @@ -168,8 +164,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
| 168 | case AFS_FTYPE_INVALID: | 164 | case AFS_FTYPE_INVALID: |
| 169 | if (abort_code != 0) { | 165 | if (abort_code != 0) { |
| 170 | status->abort_code = abort_code; | 166 | status->abort_code = abort_code; |
| 171 | ret = 0; | 167 | return 0; |
| 172 | goto out; | ||
| 173 | } | 168 | } |
| 174 | /* Fall through */ | 169 | /* Fall through */ |
| 175 | default: | 170 | default: |
| @@ -222,17 +217,35 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call, | |||
| 222 | flags); | 217 | flags); |
| 223 | } | 218 | } |
| 224 | 219 | ||
| 225 | ret = 0; | 220 | return 0; |
| 226 | |||
| 227 | out: | ||
| 228 | if (vnode) | ||
| 229 | write_sequnlock(&vnode->cb_lock); | ||
| 230 | return ret; | ||
| 231 | 221 | ||
| 232 | bad: | 222 | bad: |
| 233 | xdr_dump_bad(*_bp); | 223 | xdr_dump_bad(*_bp); |
| 234 | ret = afs_protocol_error(call, -EBADMSG); | 224 | return afs_protocol_error(call, -EBADMSG); |
| 235 | goto out; | 225 | } |
| 226 | |||
| 227 | /* | ||
| 228 | * Decode the file status. We need to lock the target vnode if we're going to | ||
| 229 | * update its status so that stat() sees the attributes update atomically. | ||
| 230 | */ | ||
| 231 | static int afs_decode_status(struct afs_call *call, | ||
| 232 | const __be32 **_bp, | ||
| 233 | struct afs_file_status *status, | ||
| 234 | struct afs_vnode *vnode, | ||
| 235 | const afs_dataversion_t *expected_version, | ||
| 236 | struct afs_read *read_req) | ||
| 237 | { | ||
| 238 | int ret; | ||
| 239 | |||
| 240 | if (!vnode) | ||
| 241 | return xdr_decode_AFSFetchStatus(call, _bp, status, vnode, | ||
| 242 | expected_version, read_req); | ||
| 243 | |||
| 244 | write_seqlock(&vnode->cb_lock); | ||
| 245 | ret = xdr_decode_AFSFetchStatus(call, _bp, status, vnode, | ||
| 246 | expected_version, read_req); | ||
| 247 | write_sequnlock(&vnode->cb_lock); | ||
| 248 | return ret; | ||
| 236 | } | 249 | } |
| 237 | 250 | ||
| 238 | /* | 251 | /* |
| @@ -374,8 +387,8 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call) | |||
| 374 | 387 | ||
| 375 | /* unmarshall the reply once we've received all of it */ | 388 | /* unmarshall the reply once we've received all of it */ |
| 376 | bp = call->buffer; | 389 | bp = call->buffer; |
| 377 | if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, | 390 | if (afs_decode_status(call, &bp, &vnode->status, vnode, |
| 378 | &call->expected_version, NULL) < 0) | 391 | &call->expected_version, NULL) < 0) |
| 379 | return afs_protocol_error(call, -EBADMSG); | 392 | return afs_protocol_error(call, -EBADMSG); |
| 380 | xdr_decode_AFSCallBack(call, vnode, &bp); | 393 | xdr_decode_AFSCallBack(call, vnode, &bp); |
| 381 | if (call->reply[1]) | 394 | if (call->reply[1]) |
| @@ -555,8 +568,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call) | |||
| 555 | return ret; | 568 | return ret; |
| 556 | 569 | ||
| 557 | bp = call->buffer; | 570 | bp = call->buffer; |
| 558 | if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, | 571 | if (afs_decode_status(call, &bp, &vnode->status, vnode, |
| 559 | &vnode->status.data_version, req) < 0) | 572 | &vnode->status.data_version, req) < 0) |
| 560 | return afs_protocol_error(call, -EBADMSG); | 573 | return afs_protocol_error(call, -EBADMSG); |
| 561 | xdr_decode_AFSCallBack(call, vnode, &bp); | 574 | xdr_decode_AFSCallBack(call, vnode, &bp); |
| 562 | if (call->reply[1]) | 575 | if (call->reply[1]) |
| @@ -708,9 +721,9 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call) | |||
| 708 | /* unmarshall the reply once we've received all of it */ | 721 | /* unmarshall the reply once we've received all of it */ |
| 709 | bp = call->buffer; | 722 | bp = call->buffer; |
| 710 | xdr_decode_AFSFid(&bp, call->reply[1]); | 723 | xdr_decode_AFSFid(&bp, call->reply[1]); |
| 711 | if (xdr_decode_AFSFetchStatus(call, &bp, call->reply[2], NULL, NULL, NULL) < 0 || | 724 | if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) < 0 || |
| 712 | xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, | 725 | afs_decode_status(call, &bp, &vnode->status, vnode, |
| 713 | &call->expected_version, NULL) < 0) | 726 | &call->expected_version, NULL) < 0) |
| 714 | return afs_protocol_error(call, -EBADMSG); | 727 | return afs_protocol_error(call, -EBADMSG); |
| 715 | xdr_decode_AFSCallBack_raw(&bp, call->reply[3]); | 728 | xdr_decode_AFSCallBack_raw(&bp, call->reply[3]); |
| 716 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 729 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
| @@ -814,8 +827,8 @@ static int afs_deliver_fs_remove(struct afs_call *call) | |||
| 814 | 827 | ||
| 815 | /* unmarshall the reply once we've received all of it */ | 828 | /* unmarshall the reply once we've received all of it */ |
| 816 | bp = call->buffer; | 829 | bp = call->buffer; |
| 817 | if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, | 830 | if (afs_decode_status(call, &bp, &vnode->status, vnode, |
| 818 | &call->expected_version, NULL) < 0) | 831 | &call->expected_version, NULL) < 0) |
| 819 | return afs_protocol_error(call, -EBADMSG); | 832 | return afs_protocol_error(call, -EBADMSG); |
| 820 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 833 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
| 821 | 834 | ||
| @@ -904,9 +917,9 @@ static int afs_deliver_fs_link(struct afs_call *call) | |||
| 904 | 917 | ||
| 905 | /* unmarshall the reply once we've received all of it */ | 918 | /* unmarshall the reply once we've received all of it */ |
| 906 | bp = call->buffer; | 919 | bp = call->buffer; |
| 907 | if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, NULL, NULL) < 0 || | 920 | if (afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL) < 0 || |
| 908 | xdr_decode_AFSFetchStatus(call, &bp, &dvnode->status, dvnode, | 921 | afs_decode_status(call, &bp, &dvnode->status, dvnode, |
| 909 | &call->expected_version, NULL) < 0) | 922 | &call->expected_version, NULL) < 0) |
| 910 | return afs_protocol_error(call, -EBADMSG); | 923 | return afs_protocol_error(call, -EBADMSG); |
| 911 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 924 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
| 912 | 925 | ||
| @@ -991,9 +1004,9 @@ static int afs_deliver_fs_symlink(struct afs_call *call) | |||
| 991 | /* unmarshall the reply once we've received all of it */ | 1004 | /* unmarshall the reply once we've received all of it */ |
| 992 | bp = call->buffer; | 1005 | bp = call->buffer; |
| 993 | xdr_decode_AFSFid(&bp, call->reply[1]); | 1006 | xdr_decode_AFSFid(&bp, call->reply[1]); |
| 994 | if (xdr_decode_AFSFetchStatus(call, &bp, call->reply[2], NULL, NULL, NULL) || | 1007 | if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) || |
| 995 | xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, | 1008 | afs_decode_status(call, &bp, &vnode->status, vnode, |
| 996 | &call->expected_version, NULL) < 0) | 1009 | &call->expected_version, NULL) < 0) |
| 997 | return afs_protocol_error(call, -EBADMSG); | 1010 | return afs_protocol_error(call, -EBADMSG); |
| 998 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1011 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
| 999 | 1012 | ||
| @@ -1097,12 +1110,12 @@ static int afs_deliver_fs_rename(struct afs_call *call) | |||
| 1097 | 1110 | ||
| 1098 | /* unmarshall the reply once we've received all of it */ | 1111 | /* unmarshall the reply once we've received all of it */ |
| 1099 | bp = call->buffer; | 1112 | bp = call->buffer; |
| 1100 | if (xdr_decode_AFSFetchStatus(call, &bp, &orig_dvnode->status, orig_dvnode, | 1113 | if (afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode, |
| 1101 | &call->expected_version, NULL) < 0) | 1114 | &call->expected_version, NULL) < 0) |
| 1102 | return afs_protocol_error(call, -EBADMSG); | 1115 | return afs_protocol_error(call, -EBADMSG); |
| 1103 | if (new_dvnode != orig_dvnode && | 1116 | if (new_dvnode != orig_dvnode && |
| 1104 | xdr_decode_AFSFetchStatus(call, &bp, &new_dvnode->status, new_dvnode, | 1117 | afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode, |
| 1105 | &call->expected_version_2, NULL) < 0) | 1118 | &call->expected_version_2, NULL) < 0) |
| 1106 | return afs_protocol_error(call, -EBADMSG); | 1119 | return afs_protocol_error(call, -EBADMSG); |
| 1107 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1120 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
| 1108 | 1121 | ||
| @@ -1206,8 +1219,8 @@ static int afs_deliver_fs_store_data(struct afs_call *call) | |||
| 1206 | 1219 | ||
| 1207 | /* unmarshall the reply once we've received all of it */ | 1220 | /* unmarshall the reply once we've received all of it */ |
| 1208 | bp = call->buffer; | 1221 | bp = call->buffer; |
| 1209 | if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, | 1222 | if (afs_decode_status(call, &bp, &vnode->status, vnode, |
| 1210 | &call->expected_version, NULL) < 0) | 1223 | &call->expected_version, NULL) < 0) |
| 1211 | return afs_protocol_error(call, -EBADMSG); | 1224 | return afs_protocol_error(call, -EBADMSG); |
| 1212 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1225 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
| 1213 | 1226 | ||
| @@ -1382,8 +1395,8 @@ static int afs_deliver_fs_store_status(struct afs_call *call) | |||
| 1382 | 1395 | ||
| 1383 | /* unmarshall the reply once we've received all of it */ | 1396 | /* unmarshall the reply once we've received all of it */ |
| 1384 | bp = call->buffer; | 1397 | bp = call->buffer; |
| 1385 | if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, | 1398 | if (afs_decode_status(call, &bp, &vnode->status, vnode, |
| 1386 | &call->expected_version, NULL) < 0) | 1399 | &call->expected_version, NULL) < 0) |
| 1387 | return afs_protocol_error(call, -EBADMSG); | 1400 | return afs_protocol_error(call, -EBADMSG); |
| 1388 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ | 1401 | /* xdr_decode_AFSVolSync(&bp, call->reply[X]); */ |
| 1389 | 1402 | ||
| @@ -2084,8 +2097,8 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call) | |||
| 2084 | 2097 | ||
| 2085 | /* unmarshall the reply once we've received all of it */ | 2098 | /* unmarshall the reply once we've received all of it */ |
| 2086 | bp = call->buffer; | 2099 | bp = call->buffer; |
| 2087 | xdr_decode_AFSFetchStatus(call, &bp, status, vnode, | 2100 | afs_decode_status(call, &bp, status, vnode, |
| 2088 | &call->expected_version, NULL); | 2101 | &call->expected_version, NULL); |
| 2089 | callback[call->count].version = ntohl(bp[0]); | 2102 | callback[call->count].version = ntohl(bp[0]); |
| 2090 | callback[call->count].expiry = ntohl(bp[1]); | 2103 | callback[call->count].expiry = ntohl(bp[1]); |
| 2091 | callback[call->count].type = ntohl(bp[2]); | 2104 | callback[call->count].type = ntohl(bp[2]); |
| @@ -2196,9 +2209,9 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call) | |||
| 2196 | 2209 | ||
| 2197 | bp = call->buffer; | 2210 | bp = call->buffer; |
| 2198 | statuses = call->reply[1]; | 2211 | statuses = call->reply[1]; |
| 2199 | if (xdr_decode_AFSFetchStatus(call, &bp, &statuses[call->count], | 2212 | if (afs_decode_status(call, &bp, &statuses[call->count], |
| 2200 | call->count == 0 ? vnode : NULL, | 2213 | call->count == 0 ? vnode : NULL, |
| 2201 | NULL, NULL) < 0) | 2214 | NULL, NULL) < 0) |
| 2202 | return afs_protocol_error(call, -EBADMSG); | 2215 | return afs_protocol_error(call, -EBADMSG); |
| 2203 | 2216 | ||
| 2204 | call->count++; | 2217 | call->count++; |
