Skip to content

Commit c875c76

Browse files
committed
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 <[email protected]>
1 parent 564def7 commit c875c76

File tree

1 file changed

+55
-42
lines changed

1 file changed

+55
-42
lines changed

fs/afs/fsclient.c

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
137137
u64 data_version, size;
138138
u32 type, abort_code;
139139
u8 flags = 0;
140-
int ret;
141-
142-
if (vnode)
143-
write_seqlock(&vnode->cb_lock);
144140

145141
if (xdr->if_version != htonl(AFS_FSTATUS_VERSION)) {
146142
pr_warn("Unknown AFSFetchStatus version %u\n", ntohl(xdr->if_version));
@@ -168,8 +164,7 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
168164
case AFS_FTYPE_INVALID:
169165
if (abort_code != 0) {
170166
status->abort_code = abort_code;
171-
ret = 0;
172-
goto out;
167+
return 0;
173168
}
174169
/* Fall through */
175170
default:
@@ -222,17 +217,35 @@ static int xdr_decode_AFSFetchStatus(struct afs_call *call,
222217
flags);
223218
}
224219

225-
ret = 0;
226-
227-
out:
228-
if (vnode)
229-
write_sequnlock(&vnode->cb_lock);
230-
return ret;
220+
return 0;
231221

232222
bad:
233223
xdr_dump_bad(*_bp);
234-
ret = afs_protocol_error(call, -EBADMSG);
235-
goto out;
224+
return afs_protocol_error(call, -EBADMSG);
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;
236249
}
237250

238251
/*
@@ -374,8 +387,8 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
374387

375388
/* unmarshall the reply once we've received all of it */
376389
bp = call->buffer;
377-
if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
378-
&call->expected_version, NULL) < 0)
390+
if (afs_decode_status(call, &bp, &vnode->status, vnode,
391+
&call->expected_version, NULL) < 0)
379392
return afs_protocol_error(call, -EBADMSG);
380393
xdr_decode_AFSCallBack(call, vnode, &bp);
381394
if (call->reply[1])
@@ -555,8 +568,8 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
555568
return ret;
556569

557570
bp = call->buffer;
558-
if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
559-
&vnode->status.data_version, req) < 0)
571+
if (afs_decode_status(call, &bp, &vnode->status, vnode,
572+
&vnode->status.data_version, req) < 0)
560573
return afs_protocol_error(call, -EBADMSG);
561574
xdr_decode_AFSCallBack(call, vnode, &bp);
562575
if (call->reply[1])
@@ -708,9 +721,9 @@ static int afs_deliver_fs_create_vnode(struct afs_call *call)
708721
/* unmarshall the reply once we've received all of it */
709722
bp = call->buffer;
710723
xdr_decode_AFSFid(&bp, call->reply[1]);
711-
if (xdr_decode_AFSFetchStatus(call, &bp, call->reply[2], NULL, NULL, NULL) < 0 ||
712-
xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
713-
&call->expected_version, NULL) < 0)
724+
if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) < 0 ||
725+
afs_decode_status(call, &bp, &vnode->status, vnode,
726+
&call->expected_version, NULL) < 0)
714727
return afs_protocol_error(call, -EBADMSG);
715728
xdr_decode_AFSCallBack_raw(&bp, call->reply[3]);
716729
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
@@ -814,8 +827,8 @@ static int afs_deliver_fs_remove(struct afs_call *call)
814827

815828
/* unmarshall the reply once we've received all of it */
816829
bp = call->buffer;
817-
if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
818-
&call->expected_version, NULL) < 0)
830+
if (afs_decode_status(call, &bp, &vnode->status, vnode,
831+
&call->expected_version, NULL) < 0)
819832
return afs_protocol_error(call, -EBADMSG);
820833
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
821834

@@ -904,9 +917,9 @@ static int afs_deliver_fs_link(struct afs_call *call)
904917

905918
/* unmarshall the reply once we've received all of it */
906919
bp = call->buffer;
907-
if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode, NULL, NULL) < 0 ||
908-
xdr_decode_AFSFetchStatus(call, &bp, &dvnode->status, dvnode,
909-
&call->expected_version, NULL) < 0)
920+
if (afs_decode_status(call, &bp, &vnode->status, vnode, NULL, NULL) < 0 ||
921+
afs_decode_status(call, &bp, &dvnode->status, dvnode,
922+
&call->expected_version, NULL) < 0)
910923
return afs_protocol_error(call, -EBADMSG);
911924
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
912925

@@ -991,9 +1004,9 @@ static int afs_deliver_fs_symlink(struct afs_call *call)
9911004
/* unmarshall the reply once we've received all of it */
9921005
bp = call->buffer;
9931006
xdr_decode_AFSFid(&bp, call->reply[1]);
994-
if (xdr_decode_AFSFetchStatus(call, &bp, call->reply[2], NULL, NULL, NULL) ||
995-
xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
996-
&call->expected_version, NULL) < 0)
1007+
if (afs_decode_status(call, &bp, call->reply[2], NULL, NULL, NULL) ||
1008+
afs_decode_status(call, &bp, &vnode->status, vnode,
1009+
&call->expected_version, NULL) < 0)
9971010
return afs_protocol_error(call, -EBADMSG);
9981011
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
9991012

@@ -1097,12 +1110,12 @@ static int afs_deliver_fs_rename(struct afs_call *call)
10971110

10981111
/* unmarshall the reply once we've received all of it */
10991112
bp = call->buffer;
1100-
if (xdr_decode_AFSFetchStatus(call, &bp, &orig_dvnode->status, orig_dvnode,
1101-
&call->expected_version, NULL) < 0)
1113+
if (afs_decode_status(call, &bp, &orig_dvnode->status, orig_dvnode,
1114+
&call->expected_version, NULL) < 0)
11021115
return afs_protocol_error(call, -EBADMSG);
11031116
if (new_dvnode != orig_dvnode &&
1104-
xdr_decode_AFSFetchStatus(call, &bp, &new_dvnode->status, new_dvnode,
1105-
&call->expected_version_2, NULL) < 0)
1117+
afs_decode_status(call, &bp, &new_dvnode->status, new_dvnode,
1118+
&call->expected_version_2, NULL) < 0)
11061119
return afs_protocol_error(call, -EBADMSG);
11071120
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
11081121

@@ -1206,8 +1219,8 @@ static int afs_deliver_fs_store_data(struct afs_call *call)
12061219

12071220
/* unmarshall the reply once we've received all of it */
12081221
bp = call->buffer;
1209-
if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
1210-
&call->expected_version, NULL) < 0)
1222+
if (afs_decode_status(call, &bp, &vnode->status, vnode,
1223+
&call->expected_version, NULL) < 0)
12111224
return afs_protocol_error(call, -EBADMSG);
12121225
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
12131226

@@ -1382,8 +1395,8 @@ static int afs_deliver_fs_store_status(struct afs_call *call)
13821395

13831396
/* unmarshall the reply once we've received all of it */
13841397
bp = call->buffer;
1385-
if (xdr_decode_AFSFetchStatus(call, &bp, &vnode->status, vnode,
1386-
&call->expected_version, NULL) < 0)
1398+
if (afs_decode_status(call, &bp, &vnode->status, vnode,
1399+
&call->expected_version, NULL) < 0)
13871400
return afs_protocol_error(call, -EBADMSG);
13881401
/* xdr_decode_AFSVolSync(&bp, call->reply[X]); */
13891402

@@ -2084,8 +2097,8 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call)
20842097

20852098
/* unmarshall the reply once we've received all of it */
20862099
bp = call->buffer;
2087-
xdr_decode_AFSFetchStatus(call, &bp, status, vnode,
2088-
&call->expected_version, NULL);
2100+
afs_decode_status(call, &bp, status, vnode,
2101+
&call->expected_version, NULL);
20892102
callback[call->count].version = ntohl(bp[0]);
20902103
callback[call->count].expiry = ntohl(bp[1]);
20912104
callback[call->count].type = ntohl(bp[2]);
@@ -2196,9 +2209,9 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
21962209

21972210
bp = call->buffer;
21982211
statuses = call->reply[1];
2199-
if (xdr_decode_AFSFetchStatus(call, &bp, &statuses[call->count],
2200-
call->count == 0 ? vnode : NULL,
2201-
NULL, NULL) < 0)
2212+
if (afs_decode_status(call, &bp, &statuses[call->count],
2213+
call->count == 0 ? vnode : NULL,
2214+
NULL, NULL) < 0)
22022215
return afs_protocol_error(call, -EBADMSG);
22032216

22042217
call->count++;

0 commit comments

Comments
 (0)