diff options
author | David Howells <dhowells@redhat.com> | 2018-05-23 06:32:06 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2018-05-23 06:32:06 -0400 |
commit | c875c76a061df306ca82b69ba80b8da3ee758c87 (patch) | |
tree | 634907a1372ba2872d170af8d36f3303b97de5b1 | |
parent | 564def71765caf65040f926c0783b9c27cc6c087 (diff) |
afs: Fix a Sparse warning in xdr_decode_AFSFetchStatus()
Sparse doesn't appear able to handle the conditionally-taken locks in
xdr_decode_AFSFetchStatus(), even though the lock and unlock are both
contingent on the same unvarying function argument.
Deal with this by interpolating a wrapper function that takes the lock if
needed and calls xdr_decode_AFSFetchStatus() on two separate branches, one
with the lock held and one without.
This allows Sparse to work out the locking.
Signed-off-by: David Howells <dhowells@redhat.com>
-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++; |