1 // SPDX-License-Identifier: GPL-2.0-or-later << 2 /* AFS Cache Manager Service 1 /* AFS Cache Manager Service 3 * 2 * 4 * Copyright (C) 2002 Red Hat, Inc. All Rights 3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. 5 * Written by David Howells (dhowells@redhat.c 4 * Written by David Howells (dhowells@redhat.com) >> 5 * >> 6 * This program is free software; you can redistribute it and/or >> 7 * modify it under the terms of the GNU General Public License >> 8 * as published by the Free Software Foundation; either version >> 9 * 2 of the License, or (at your option) any later version. 6 */ 10 */ 7 11 8 #include <linux/module.h> 12 #include <linux/module.h> 9 #include <linux/init.h> 13 #include <linux/init.h> 10 #include <linux/slab.h> 14 #include <linux/slab.h> 11 #include <linux/sched.h> 15 #include <linux/sched.h> 12 #include <linux/ip.h> 16 #include <linux/ip.h> 13 #include "internal.h" 17 #include "internal.h" 14 #include "afs_cm.h" 18 #include "afs_cm.h" 15 #include "protocol_yfs.h" << 16 #define RXRPC_TRACE_ONLY_DEFINE_ENUMS << 17 #include <trace/events/rxrpc.h> << 18 << 19 static int afs_deliver_cb_init_call_back_state << 20 static int afs_deliver_cb_init_call_back_state << 21 static int afs_deliver_cb_probe(struct afs_cal << 22 static int afs_deliver_cb_callback(struct afs_ << 23 static int afs_deliver_cb_probe_uuid(struct af << 24 static int afs_deliver_cb_tell_me_about_yourse << 25 static void afs_cm_destructor(struct afs_call << 26 static void SRXAFSCB_CallBack(struct work_stru << 27 static void SRXAFSCB_InitCallBackState(struct << 28 static void SRXAFSCB_Probe(struct work_struct << 29 static void SRXAFSCB_ProbeUuid(struct work_str << 30 static void SRXAFSCB_TellMeAboutYourself(struc << 31 19 32 static int afs_deliver_yfs_cb_callback(struct !! 20 #if 0 >> 21 struct workqueue_struct *afs_cm_workqueue; >> 22 #endif /* 0 */ >> 23 >> 24 static int afs_deliver_cb_init_call_back_state(struct afs_call *, >> 25 struct sk_buff *, bool); >> 26 static int afs_deliver_cb_init_call_back_state3(struct afs_call *, >> 27 struct sk_buff *, bool); >> 28 static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool); >> 29 static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool); >> 30 static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool); >> 31 static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *, >> 32 struct sk_buff *, bool); >> 33 static void afs_cm_destructor(struct afs_call *); 33 34 34 /* 35 /* 35 * CB.CallBack operation type 36 * CB.CallBack operation type 36 */ 37 */ 37 static const struct afs_call_type afs_SRXCBCal 38 static const struct afs_call_type afs_SRXCBCallBack = { 38 .name = "CB.CallBack", 39 .name = "CB.CallBack", 39 .deliver = afs_deliver_cb_callb 40 .deliver = afs_deliver_cb_callback, >> 41 .abort_to_error = afs_abort_to_error, 40 .destructor = afs_cm_destructor, 42 .destructor = afs_cm_destructor, 41 .work = SRXAFSCB_CallBack, << 42 }; 43 }; 43 44 44 /* 45 /* 45 * CB.InitCallBackState operation type 46 * CB.InitCallBackState operation type 46 */ 47 */ 47 static const struct afs_call_type afs_SRXCBIni 48 static const struct afs_call_type afs_SRXCBInitCallBackState = { 48 .name = "CB.InitCallBackStat 49 .name = "CB.InitCallBackState", 49 .deliver = afs_deliver_cb_init_ 50 .deliver = afs_deliver_cb_init_call_back_state, >> 51 .abort_to_error = afs_abort_to_error, 50 .destructor = afs_cm_destructor, 52 .destructor = afs_cm_destructor, 51 .work = SRXAFSCB_InitCallBac << 52 }; 53 }; 53 54 54 /* 55 /* 55 * CB.InitCallBackState3 operation type 56 * CB.InitCallBackState3 operation type 56 */ 57 */ 57 static const struct afs_call_type afs_SRXCBIni 58 static const struct afs_call_type afs_SRXCBInitCallBackState3 = { 58 .name = "CB.InitCallBackStat 59 .name = "CB.InitCallBackState3", 59 .deliver = afs_deliver_cb_init_ 60 .deliver = afs_deliver_cb_init_call_back_state3, >> 61 .abort_to_error = afs_abort_to_error, 60 .destructor = afs_cm_destructor, 62 .destructor = afs_cm_destructor, 61 .work = SRXAFSCB_InitCallBac << 62 }; 63 }; 63 64 64 /* 65 /* 65 * CB.Probe operation type 66 * CB.Probe operation type 66 */ 67 */ 67 static const struct afs_call_type afs_SRXCBPro 68 static const struct afs_call_type afs_SRXCBProbe = { 68 .name = "CB.Probe", 69 .name = "CB.Probe", 69 .deliver = afs_deliver_cb_probe 70 .deliver = afs_deliver_cb_probe, >> 71 .abort_to_error = afs_abort_to_error, 70 .destructor = afs_cm_destructor, 72 .destructor = afs_cm_destructor, 71 .work = SRXAFSCB_Probe, << 72 }; 73 }; 73 74 74 /* 75 /* 75 * CB.ProbeUuid operation type 76 * CB.ProbeUuid operation type 76 */ 77 */ 77 static const struct afs_call_type afs_SRXCBPro 78 static const struct afs_call_type afs_SRXCBProbeUuid = { 78 .name = "CB.ProbeUuid", 79 .name = "CB.ProbeUuid", 79 .deliver = afs_deliver_cb_probe 80 .deliver = afs_deliver_cb_probe_uuid, >> 81 .abort_to_error = afs_abort_to_error, 80 .destructor = afs_cm_destructor, 82 .destructor = afs_cm_destructor, 81 .work = SRXAFSCB_ProbeUuid, << 82 }; 83 }; 83 84 84 /* 85 /* 85 * CB.TellMeAboutYourself operation type 86 * CB.TellMeAboutYourself operation type 86 */ 87 */ 87 static const struct afs_call_type afs_SRXCBTel 88 static const struct afs_call_type afs_SRXCBTellMeAboutYourself = { 88 .name = "CB.TellMeAboutYours 89 .name = "CB.TellMeAboutYourself", 89 .deliver = afs_deliver_cb_tell_ 90 .deliver = afs_deliver_cb_tell_me_about_yourself, >> 91 .abort_to_error = afs_abort_to_error, 90 .destructor = afs_cm_destructor, 92 .destructor = afs_cm_destructor, 91 .work = SRXAFSCB_TellMeAbout << 92 }; << 93 << 94 /* << 95 * YFS CB.CallBack operation type << 96 */ << 97 static const struct afs_call_type afs_SRXYFSCB << 98 .name = "YFSCB.CallBack", << 99 .deliver = afs_deliver_yfs_cb_c << 100 .destructor = afs_cm_destructor, << 101 .work = SRXAFSCB_CallBack, << 102 }; 93 }; 103 94 104 /* 95 /* 105 * route an incoming cache manager call 96 * route an incoming cache manager call 106 * - return T if supported, F if not 97 * - return T if supported, F if not 107 */ 98 */ 108 bool afs_cm_incoming_call(struct afs_call *cal 99 bool afs_cm_incoming_call(struct afs_call *call) 109 { 100 { 110 _enter("{%u, CB.OP %u}", call->service !! 101 u32 operation_id = ntohl(call->operation_ID); >> 102 >> 103 _enter("{CB.OP %u}", operation_id); 111 104 112 switch (call->operation_ID) { !! 105 switch (operation_id) { 113 case CBCallBack: 106 case CBCallBack: 114 call->type = &afs_SRXCBCallBac 107 call->type = &afs_SRXCBCallBack; 115 return true; 108 return true; 116 case CBInitCallBackState: 109 case CBInitCallBackState: 117 call->type = &afs_SRXCBInitCal 110 call->type = &afs_SRXCBInitCallBackState; 118 return true; 111 return true; 119 case CBInitCallBackState3: 112 case CBInitCallBackState3: 120 call->type = &afs_SRXCBInitCal 113 call->type = &afs_SRXCBInitCallBackState3; 121 return true; 114 return true; 122 case CBProbe: 115 case CBProbe: 123 call->type = &afs_SRXCBProbe; 116 call->type = &afs_SRXCBProbe; 124 return true; 117 return true; 125 case CBProbeUuid: 118 case CBProbeUuid: 126 call->type = &afs_SRXCBProbeUu 119 call->type = &afs_SRXCBProbeUuid; 127 return true; 120 return true; 128 case CBTellMeAboutYourself: 121 case CBTellMeAboutYourself: 129 call->type = &afs_SRXCBTellMeA 122 call->type = &afs_SRXCBTellMeAboutYourself; 130 return true; 123 return true; 131 case YFSCBCallBack: << 132 if (call->service_id != YFS_CM << 133 return false; << 134 call->type = &afs_SRXYFSCB_Cal << 135 return true; << 136 default: 124 default: 137 return false; 125 return false; 138 } 126 } 139 } 127 } 140 128 141 /* 129 /* 142 * Find the server record by peer address and !! 130 * clean up a cache manager call 143 * manager from a server. << 144 */ << 145 static int afs_find_cm_server_by_peer(struct a << 146 { << 147 struct sockaddr_rxrpc srx; << 148 struct afs_server *server; << 149 struct rxrpc_peer *peer; << 150 << 151 peer = rxrpc_kernel_get_call_peer(call << 152 << 153 server = afs_find_server(call->net, pe << 154 if (!server) { << 155 trace_afs_cm_no_server(call, & << 156 return 0; << 157 } << 158 << 159 call->server = server; << 160 return 0; << 161 } << 162 << 163 /* << 164 * Find the server record by server UUID and r << 165 * manager from a server. << 166 */ 131 */ 167 static int afs_find_cm_server_by_uuid(struct a !! 132 static void afs_cm_destructor(struct afs_call *call) 168 struct a << 169 { 133 { 170 struct afs_server *server; !! 134 _enter(""); 171 135 172 rcu_read_lock(); !! 136 /* Break the callbacks here so that we do it after the final ACK is 173 server = afs_find_server_by_uuid(call- !! 137 * received. The step number here must match the final number in 174 rcu_read_unlock(); !! 138 * afs_deliver_cb_callback(). 175 if (!server) { !! 139 */ 176 trace_afs_cm_no_server_u(call, !! 140 if (call->unmarshall == 6) { 177 return 0; !! 141 ASSERT(call->server && call->count && call->request); >> 142 afs_break_callbacks(call->server, call->count, call->request); 178 } 143 } 179 144 180 call->server = server; !! 145 afs_put_server(call->server); 181 return 0; !! 146 call->server = NULL; 182 } << 183 << 184 /* << 185 * Clean up a cache manager call. << 186 */ << 187 static void afs_cm_destructor(struct afs_call << 188 { << 189 kfree(call->buffer); 147 kfree(call->buffer); 190 call->buffer = NULL; 148 call->buffer = NULL; 191 } 149 } 192 150 193 /* 151 /* 194 * Abort a service call from within an action !! 152 * allow the fileserver to see if the cache manager is still alive 195 */ << 196 static void afs_abort_service_call(struct afs_ << 197 enum rxrpc_ << 198 { << 199 rxrpc_kernel_abort_call(call->net->soc << 200 abort_code, er << 201 afs_set_call_complete(call, error, 0); << 202 } << 203 << 204 /* << 205 * The server supplied a list of callbacks tha << 206 */ 153 */ 207 static void SRXAFSCB_CallBack(struct work_stru 154 static void SRXAFSCB_CallBack(struct work_struct *work) 208 { 155 { 209 struct afs_call *call = container_of(w 156 struct afs_call *call = container_of(work, struct afs_call, work); 210 157 211 _enter(""); 158 _enter(""); 212 159 213 /* We need to break the callbacks befo !! 160 /* be sure to send the reply *before* attempting to spam the AFS server 214 * server holds up change visibility t !! 161 * with FSFetchStatus requests on the vnodes with broken callbacks lest 215 * to maintain cache coherency. !! 162 * the AFS server get into a vicious cycle of trying to break further 216 */ !! 163 * callbacks because it hadn't received completion of the CBCallBack op 217 if (call->server) { !! 164 * yet */ 218 trace_afs_server(call->server- << 219 refcount_read << 220 atomic_read(& << 221 afs_server_tr << 222 afs_break_callbacks(call->serv << 223 } << 224 << 225 afs_send_empty_reply(call); 165 afs_send_empty_reply(call); 226 afs_put_call(call); !! 166 >> 167 afs_break_callbacks(call->server, call->count, call->request); 227 _leave(""); 168 _leave(""); 228 } 169 } 229 170 230 /* 171 /* 231 * deliver request data to a CB.CallBack call 172 * deliver request data to a CB.CallBack call 232 */ 173 */ 233 static int afs_deliver_cb_callback(struct afs_ !! 174 static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb, >> 175 bool last) 234 { 176 { 235 struct afs_callback_break *cb; !! 177 struct afs_callback *cb; >> 178 struct afs_server *server; >> 179 struct in_addr addr; 236 __be32 *bp; 180 __be32 *bp; >> 181 u32 tmp; 237 int ret, loop; 182 int ret, loop; 238 183 239 _enter("{%u}", call->unmarshall); !! 184 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 240 185 241 switch (call->unmarshall) { 186 switch (call->unmarshall) { 242 case 0: 187 case 0: 243 afs_extract_to_tmp(call); !! 188 call->offset = 0; 244 call->unmarshall++; 189 call->unmarshall++; 245 190 246 /* extract the FID array and i 191 /* extract the FID array and its count in two steps */ 247 fallthrough; << 248 case 1: 192 case 1: 249 _debug("extract FID count"); 193 _debug("extract FID count"); 250 ret = afs_extract_data(call, t !! 194 ret = afs_extract_data(call, skb, last, &call->tmp, 4); 251 if (ret < 0) !! 195 switch (ret) { 252 return ret; !! 196 case 0: break; >> 197 case -EAGAIN: return 0; >> 198 default: return ret; >> 199 } 253 200 254 call->count = ntohl(call->tmp) 201 call->count = ntohl(call->tmp); 255 _debug("FID count: %u", call-> 202 _debug("FID count: %u", call->count); 256 if (call->count > AFSCBMAX) 203 if (call->count > AFSCBMAX) 257 return afs_protocol_er !! 204 return -EBADMSG; 258 205 259 call->buffer = kmalloc(array3_ !! 206 call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL); 260 GFP_KER << 261 if (!call->buffer) 207 if (!call->buffer) 262 return -ENOMEM; 208 return -ENOMEM; 263 afs_extract_to_buf(call, call- !! 209 call->offset = 0; 264 call->unmarshall++; 210 call->unmarshall++; 265 211 266 fallthrough; << 267 case 2: 212 case 2: 268 _debug("extract FID array"); 213 _debug("extract FID array"); 269 ret = afs_extract_data(call, t !! 214 ret = afs_extract_data(call, skb, last, call->buffer, 270 if (ret < 0) !! 215 call->count * 3 * 4); 271 return ret; !! 216 switch (ret) { >> 217 case 0: break; >> 218 case -EAGAIN: return 0; >> 219 default: return ret; >> 220 } 272 221 273 _debug("unmarshall FID array") 222 _debug("unmarshall FID array"); 274 call->request = kcalloc(call-> 223 call->request = kcalloc(call->count, 275 sizeof !! 224 sizeof(struct afs_callback), 276 GFP_KE 225 GFP_KERNEL); 277 if (!call->request) 226 if (!call->request) 278 return -ENOMEM; 227 return -ENOMEM; 279 228 280 cb = call->request; 229 cb = call->request; 281 bp = call->buffer; 230 bp = call->buffer; 282 for (loop = call->count; loop 231 for (loop = call->count; loop > 0; loop--, cb++) { 283 cb->fid.vid = ntoh 232 cb->fid.vid = ntohl(*bp++); 284 cb->fid.vnode = ntoh 233 cb->fid.vnode = ntohl(*bp++); 285 cb->fid.unique = ntoh 234 cb->fid.unique = ntohl(*bp++); >> 235 cb->type = AFSCM_CB_UNTYPED; 286 } 236 } 287 237 288 afs_extract_to_tmp(call); !! 238 call->offset = 0; 289 call->unmarshall++; 239 call->unmarshall++; 290 240 291 /* extract the callback array 241 /* extract the callback array and its count in two steps */ 292 fallthrough; << 293 case 3: 242 case 3: 294 _debug("extract CB count"); 243 _debug("extract CB count"); 295 ret = afs_extract_data(call, t !! 244 ret = afs_extract_data(call, skb, last, &call->tmp, 4); 296 if (ret < 0) !! 245 switch (ret) { 297 return ret; !! 246 case 0: break; 298 !! 247 case -EAGAIN: return 0; 299 call->count2 = ntohl(call->tmp !! 248 default: return ret; 300 _debug("CB count: %u", call->c !! 249 } 301 if (call->count2 != call->coun !! 250 302 return afs_protocol_er !! 251 tmp = ntohl(call->tmp); 303 call->iter = &call->def_iter; !! 252 _debug("CB count: %u", tmp); 304 iov_iter_discard(&call->def_it !! 253 if (tmp != call->count && tmp != 0) >> 254 return -EBADMSG; >> 255 call->offset = 0; 305 call->unmarshall++; 256 call->unmarshall++; >> 257 if (tmp == 0) >> 258 goto empty_cb_array; 306 259 307 fallthrough; << 308 case 4: 260 case 4: 309 _debug("extract discard %zu/%u !! 261 _debug("extract CB array"); 310 iov_iter_count(call->it !! 262 ret = afs_extract_data(call, skb, last, call->request, >> 263 call->count * 3 * 4); >> 264 switch (ret) { >> 265 case 0: break; >> 266 case -EAGAIN: return 0; >> 267 default: return ret; >> 268 } 311 269 312 ret = afs_extract_data(call, f !! 270 _debug("unmarshall CB array"); 313 if (ret < 0) !! 271 cb = call->request; 314 return ret; !! 272 bp = call->buffer; >> 273 for (loop = call->count; loop > 0; loop--, cb++) { >> 274 cb->version = ntohl(*bp++); >> 275 cb->expiry = ntohl(*bp++); >> 276 cb->type = ntohl(*bp++); >> 277 } 315 278 >> 279 empty_cb_array: >> 280 call->offset = 0; 316 call->unmarshall++; 281 call->unmarshall++; 317 fallthrough; << 318 282 319 case 5: 283 case 5: >> 284 _debug("trailer"); >> 285 if (skb->len != 0) >> 286 return -EBADMSG; >> 287 >> 288 /* Record that the message was unmarshalled successfully so >> 289 * that the call destructor can know do the callback breaking >> 290 * work, even if the final ACK isn't received. >> 291 * >> 292 * If the step number changes, then afs_cm_destructor() must be >> 293 * updated also. >> 294 */ >> 295 call->unmarshall++; >> 296 case 6: 320 break; 297 break; 321 } 298 } 322 299 323 if (!afs_check_call_state(call, AFS_CA !! 300 if (!last) 324 return afs_io_error(call, afs_ !! 301 return 0; >> 302 >> 303 call->state = AFS_CALL_REPLYING; 325 304 326 /* we'll need the file server record a 305 /* we'll need the file server record as that tells us which set of 327 * vnodes to operate upon */ 306 * vnodes to operate upon */ 328 return afs_find_cm_server_by_peer(call !! 307 memcpy(&addr, &ip_hdr(skb)->saddr, 4); >> 308 server = afs_find_server(&addr); >> 309 if (!server) >> 310 return -ENOTCONN; >> 311 call->server = server; >> 312 >> 313 INIT_WORK(&call->work, SRXAFSCB_CallBack); >> 314 queue_work(afs_wq, &call->work); >> 315 return 0; 329 } 316 } 330 317 331 /* 318 /* 332 * allow the fileserver to request callback st 319 * allow the fileserver to request callback state (re-)initialisation 333 */ 320 */ 334 static void SRXAFSCB_InitCallBackState(struct 321 static void SRXAFSCB_InitCallBackState(struct work_struct *work) 335 { 322 { 336 struct afs_call *call = container_of(w 323 struct afs_call *call = container_of(work, struct afs_call, work); 337 324 338 _enter("{%p}", call->server); 325 _enter("{%p}", call->server); 339 326 340 if (call->server) !! 327 afs_init_callback_state(call->server); 341 afs_init_callback_state(call-> << 342 afs_send_empty_reply(call); 328 afs_send_empty_reply(call); 343 afs_put_call(call); << 344 _leave(""); 329 _leave(""); 345 } 330 } 346 331 347 /* 332 /* 348 * deliver request data to a CB.InitCallBackSt 333 * deliver request data to a CB.InitCallBackState call 349 */ 334 */ 350 static int afs_deliver_cb_init_call_back_state !! 335 static int afs_deliver_cb_init_call_back_state(struct afs_call *call, >> 336 struct sk_buff *skb, >> 337 bool last) 351 { 338 { 352 int ret; !! 339 struct afs_server *server; >> 340 struct in_addr addr; 353 341 354 _enter(""); !! 342 _enter(",{%u},%d", skb->len, last); 355 343 356 afs_extract_discard(call, 0); !! 344 if (skb->len > 0) 357 ret = afs_extract_data(call, false); !! 345 return -EBADMSG; 358 if (ret < 0) !! 346 if (!last) 359 return ret; !! 347 return 0; >> 348 >> 349 /* no unmarshalling required */ >> 350 call->state = AFS_CALL_REPLYING; 360 351 361 /* we'll need the file server record a 352 /* we'll need the file server record as that tells us which set of 362 * vnodes to operate upon */ 353 * vnodes to operate upon */ 363 return afs_find_cm_server_by_peer(call !! 354 memcpy(&addr, &ip_hdr(skb)->saddr, 4); >> 355 server = afs_find_server(&addr); >> 356 if (!server) >> 357 return -ENOTCONN; >> 358 call->server = server; >> 359 >> 360 INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); >> 361 queue_work(afs_wq, &call->work); >> 362 return 0; 364 } 363 } 365 364 366 /* 365 /* 367 * deliver request data to a CB.InitCallBackSt 366 * deliver request data to a CB.InitCallBackState3 call 368 */ 367 */ 369 static int afs_deliver_cb_init_call_back_state !! 368 static int afs_deliver_cb_init_call_back_state3(struct afs_call *call, >> 369 struct sk_buff *skb, >> 370 bool last) 370 { 371 { 371 struct afs_uuid *r; !! 372 struct afs_server *server; 372 unsigned loop; !! 373 struct in_addr addr; 373 __be32 *b; << 374 int ret; << 375 << 376 _enter(""); << 377 << 378 _enter("{%u}", call->unmarshall); << 379 << 380 switch (call->unmarshall) { << 381 case 0: << 382 call->buffer = kmalloc_array(1 << 383 if (!call->buffer) << 384 return -ENOMEM; << 385 afs_extract_to_buf(call, 11 * << 386 call->unmarshall++; << 387 << 388 fallthrough; << 389 case 1: << 390 _debug("extract UUID"); << 391 ret = afs_extract_data(call, f << 392 switch (ret) { << 393 case 0: break; << 394 case -EAGAIN: return 0; << 395 default: return ret; << 396 } << 397 << 398 _debug("unmarshall UUID"); << 399 call->request = kmalloc(sizeof << 400 if (!call->request) << 401 return -ENOMEM; << 402 << 403 b = call->buffer; << 404 r = call->request; << 405 r->time_low << 406 r->time_mid << 407 r->time_hi_and_version << 408 r->clock_seq_hi_and_reserved << 409 r->clock_seq_low << 410 << 411 for (loop = 0; loop < 6; loop+ << 412 r->node[loop] = ntohl( << 413 374 414 call->unmarshall++; !! 375 _enter(",{%u},%d", skb->len, last); 415 fallthrough; << 416 376 417 case 2: !! 377 if (!last) 418 break; !! 378 return 0; 419 } << 420 379 421 if (!afs_check_call_state(call, AFS_CA !! 380 /* no unmarshalling required */ 422 return afs_io_error(call, afs_ !! 381 call->state = AFS_CALL_REPLYING; 423 382 424 /* we'll need the file server record a 383 /* we'll need the file server record as that tells us which set of 425 * vnodes to operate upon */ 384 * vnodes to operate upon */ 426 return afs_find_cm_server_by_uuid(call !! 385 memcpy(&addr, &ip_hdr(skb)->saddr, 4); >> 386 server = afs_find_server(&addr); >> 387 if (!server) >> 388 return -ENOTCONN; >> 389 call->server = server; >> 390 >> 391 INIT_WORK(&call->work, SRXAFSCB_InitCallBackState); >> 392 queue_work(afs_wq, &call->work); >> 393 return 0; 427 } 394 } 428 395 429 /* 396 /* 430 * allow the fileserver to see if the cache ma 397 * allow the fileserver to see if the cache manager is still alive 431 */ 398 */ 432 static void SRXAFSCB_Probe(struct work_struct 399 static void SRXAFSCB_Probe(struct work_struct *work) 433 { 400 { 434 struct afs_call *call = container_of(w 401 struct afs_call *call = container_of(work, struct afs_call, work); 435 402 436 _enter(""); 403 _enter(""); 437 afs_send_empty_reply(call); 404 afs_send_empty_reply(call); 438 afs_put_call(call); << 439 _leave(""); 405 _leave(""); 440 } 406 } 441 407 442 /* 408 /* 443 * deliver request data to a CB.Probe call 409 * deliver request data to a CB.Probe call 444 */ 410 */ 445 static int afs_deliver_cb_probe(struct afs_cal !! 411 static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb, >> 412 bool last) 446 { 413 { 447 int ret; !! 414 _enter(",{%u},%d", skb->len, last); 448 415 449 _enter(""); !! 416 if (skb->len > 0) >> 417 return -EBADMSG; >> 418 if (!last) >> 419 return 0; 450 420 451 afs_extract_discard(call, 0); !! 421 /* no unmarshalling required */ 452 ret = afs_extract_data(call, false); !! 422 call->state = AFS_CALL_REPLYING; 453 if (ret < 0) << 454 return ret; << 455 423 456 if (!afs_check_call_state(call, AFS_CA !! 424 INIT_WORK(&call->work, SRXAFSCB_Probe); 457 return afs_io_error(call, afs_ !! 425 queue_work(afs_wq, &call->work); 458 return afs_find_cm_server_by_peer(call !! 426 return 0; 459 } 427 } 460 428 461 /* 429 /* 462 * Allow the fileserver to quickly find out if !! 430 * allow the fileserver to quickly find out if the fileserver has been rebooted 463 * rebooted. << 464 */ 431 */ 465 static void SRXAFSCB_ProbeUuid(struct work_str 432 static void SRXAFSCB_ProbeUuid(struct work_struct *work) 466 { 433 { 467 struct afs_call *call = container_of(w 434 struct afs_call *call = container_of(work, struct afs_call, work); 468 struct afs_uuid *r = call->request; 435 struct afs_uuid *r = call->request; 469 436 >> 437 struct { >> 438 __be32 match; >> 439 } reply; >> 440 470 _enter(""); 441 _enter(""); 471 442 472 if (memcmp(r, &call->net->uuid, sizeof !! 443 473 afs_send_empty_reply(call); !! 444 if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0) >> 445 reply.match = htonl(0); 474 else 446 else 475 afs_abort_service_call(call, 1 !! 447 reply.match = htonl(1); 476 448 477 afs_put_call(call); !! 449 afs_send_simple_reply(call, &reply, sizeof(reply)); 478 _leave(""); 450 _leave(""); 479 } 451 } 480 452 481 /* 453 /* 482 * deliver request data to a CB.ProbeUuid call 454 * deliver request data to a CB.ProbeUuid call 483 */ 455 */ 484 static int afs_deliver_cb_probe_uuid(struct af !! 456 static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb, >> 457 bool last) 485 { 458 { 486 struct afs_uuid *r; 459 struct afs_uuid *r; 487 unsigned loop; 460 unsigned loop; 488 __be32 *b; 461 __be32 *b; 489 int ret; 462 int ret; 490 463 491 _enter("{%u}", call->unmarshall); !! 464 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); >> 465 >> 466 if (skb->len > 0) >> 467 return -EBADMSG; >> 468 if (!last) >> 469 return 0; 492 470 493 switch (call->unmarshall) { 471 switch (call->unmarshall) { 494 case 0: 472 case 0: 495 call->buffer = kmalloc_array(1 !! 473 call->offset = 0; >> 474 call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL); 496 if (!call->buffer) 475 if (!call->buffer) 497 return -ENOMEM; 476 return -ENOMEM; 498 afs_extract_to_buf(call, 11 * << 499 call->unmarshall++; 477 call->unmarshall++; 500 478 501 fallthrough; << 502 case 1: 479 case 1: 503 _debug("extract UUID"); 480 _debug("extract UUID"); 504 ret = afs_extract_data(call, f !! 481 ret = afs_extract_data(call, skb, last, call->buffer, >> 482 11 * sizeof(__be32)); 505 switch (ret) { 483 switch (ret) { 506 case 0: break; 484 case 0: break; 507 case -EAGAIN: return 0; 485 case -EAGAIN: return 0; 508 default: return ret; 486 default: return ret; 509 } 487 } 510 488 511 _debug("unmarshall UUID"); 489 _debug("unmarshall UUID"); 512 call->request = kmalloc(sizeof 490 call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL); 513 if (!call->request) 491 if (!call->request) 514 return -ENOMEM; 492 return -ENOMEM; 515 493 516 b = call->buffer; 494 b = call->buffer; 517 r = call->request; 495 r = call->request; 518 r->time_low !! 496 r->time_low = ntohl(b[0]); 519 r->time_mid !! 497 r->time_mid = ntohl(b[1]); 520 r->time_hi_and_version !! 498 r->time_hi_and_version = ntohl(b[2]); 521 r->clock_seq_hi_and_reserved 499 r->clock_seq_hi_and_reserved = ntohl(b[3]); 522 r->clock_seq_low 500 r->clock_seq_low = ntohl(b[4]); 523 501 524 for (loop = 0; loop < 6; loop+ 502 for (loop = 0; loop < 6; loop++) 525 r->node[loop] = ntohl( 503 r->node[loop] = ntohl(b[loop + 5]); 526 504 >> 505 call->offset = 0; 527 call->unmarshall++; 506 call->unmarshall++; 528 fallthrough; << 529 507 530 case 2: 508 case 2: >> 509 _debug("trailer"); >> 510 if (skb->len != 0) >> 511 return -EBADMSG; 531 break; 512 break; 532 } 513 } 533 514 534 if (!afs_check_call_state(call, AFS_CA !! 515 if (!last) 535 return afs_io_error(call, afs_ !! 516 return 0; 536 return afs_find_cm_server_by_peer(call !! 517 >> 518 call->state = AFS_CALL_REPLYING; >> 519 >> 520 INIT_WORK(&call->work, SRXAFSCB_ProbeUuid); >> 521 queue_work(afs_wq, &call->work); >> 522 return 0; 537 } 523 } 538 524 539 /* 525 /* 540 * allow the fileserver to ask about the cache 526 * allow the fileserver to ask about the cache manager's capabilities 541 */ 527 */ 542 static void SRXAFSCB_TellMeAboutYourself(struc 528 static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work) 543 { 529 { >> 530 struct afs_interface *ifs; 544 struct afs_call *call = container_of(w 531 struct afs_call *call = container_of(work, struct afs_call, work); 545 int loop; !! 532 int loop, nifs; 546 533 547 struct { 534 struct { 548 struct /* InterfaceAddr */ { 535 struct /* InterfaceAddr */ { 549 __be32 nifs; 536 __be32 nifs; 550 __be32 uuid[11]; 537 __be32 uuid[11]; 551 __be32 ifaddr[32]; 538 __be32 ifaddr[32]; 552 __be32 netmask[32]; 539 __be32 netmask[32]; 553 __be32 mtu[32]; 540 __be32 mtu[32]; 554 } ia; 541 } ia; 555 struct /* Capabilities */ { 542 struct /* Capabilities */ { 556 __be32 capcount; 543 __be32 capcount; 557 __be32 caps[1]; 544 __be32 caps[1]; 558 } cap; 545 } cap; 559 } reply; 546 } reply; 560 547 561 _enter(""); 548 _enter(""); 562 549 >> 550 nifs = 0; >> 551 ifs = kcalloc(32, sizeof(*ifs), GFP_KERNEL); >> 552 if (ifs) { >> 553 nifs = afs_get_ipv4_interfaces(ifs, 32, false); >> 554 if (nifs < 0) { >> 555 kfree(ifs); >> 556 ifs = NULL; >> 557 nifs = 0; >> 558 } >> 559 } >> 560 563 memset(&reply, 0, sizeof(reply)); 561 memset(&reply, 0, sizeof(reply)); >> 562 reply.ia.nifs = htonl(nifs); 564 563 565 reply.ia.uuid[0] = call->net->uuid.tim !! 564 reply.ia.uuid[0] = htonl(afs_uuid.time_low); 566 reply.ia.uuid[1] = htonl(ntohs(call->n !! 565 reply.ia.uuid[1] = htonl(afs_uuid.time_mid); 567 reply.ia.uuid[2] = htonl(ntohs(call->n !! 566 reply.ia.uuid[2] = htonl(afs_uuid.time_hi_and_version); 568 reply.ia.uuid[3] = htonl((s8) call->ne !! 567 reply.ia.uuid[3] = htonl((s8) afs_uuid.clock_seq_hi_and_reserved); 569 reply.ia.uuid[4] = htonl((s8) call->ne !! 568 reply.ia.uuid[4] = htonl((s8) afs_uuid.clock_seq_low); 570 for (loop = 0; loop < 6; loop++) 569 for (loop = 0; loop < 6; loop++) 571 reply.ia.uuid[loop + 5] = hton !! 570 reply.ia.uuid[loop + 5] = htonl((s8) afs_uuid.node[loop]); >> 571 >> 572 if (ifs) { >> 573 for (loop = 0; loop < nifs; loop++) { >> 574 reply.ia.ifaddr[loop] = ifs[loop].address.s_addr; >> 575 reply.ia.netmask[loop] = ifs[loop].netmask.s_addr; >> 576 reply.ia.mtu[loop] = htonl(ifs[loop].mtu); >> 577 } >> 578 kfree(ifs); >> 579 } 572 580 573 reply.cap.capcount = htonl(1); 581 reply.cap.capcount = htonl(1); 574 reply.cap.caps[0] = htonl(AFS_CAP_ERRO 582 reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION); 575 afs_send_simple_reply(call, &reply, si 583 afs_send_simple_reply(call, &reply, sizeof(reply)); 576 afs_put_call(call); !! 584 577 _leave(""); 585 _leave(""); 578 } 586 } 579 587 580 /* 588 /* 581 * deliver request data to a CB.TellMeAboutYou 589 * deliver request data to a CB.TellMeAboutYourself call 582 */ 590 */ 583 static int afs_deliver_cb_tell_me_about_yourse !! 591 static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call, >> 592 struct sk_buff *skb, bool last) 584 { 593 { 585 int ret; !! 594 _enter(",{%u},%d", skb->len, last); 586 << 587 _enter(""); << 588 << 589 afs_extract_discard(call, 0); << 590 ret = afs_extract_data(call, false); << 591 if (ret < 0) << 592 return ret; << 593 << 594 if (!afs_check_call_state(call, AFS_CA << 595 return afs_io_error(call, afs_ << 596 return afs_find_cm_server_by_peer(call << 597 } << 598 << 599 /* << 600 * deliver request data to a YFS CB.CallBack c << 601 */ << 602 static int afs_deliver_yfs_cb_callback(struct << 603 { << 604 struct afs_callback_break *cb; << 605 struct yfs_xdr_YFSFid *bp; << 606 size_t size; << 607 int ret, loop; << 608 << 609 _enter("{%u}", call->unmarshall); << 610 << 611 switch (call->unmarshall) { << 612 case 0: << 613 afs_extract_to_tmp(call); << 614 call->unmarshall++; << 615 << 616 /* extract the FID array and i << 617 fallthrough; << 618 case 1: << 619 _debug("extract FID count"); << 620 ret = afs_extract_data(call, t << 621 if (ret < 0) << 622 return ret; << 623 << 624 call->count = ntohl(call->tmp) << 625 _debug("FID count: %u", call-> << 626 if (call->count > YFSCBMAX) << 627 return afs_protocol_er << 628 << 629 size = array_size(call->count, << 630 call->buffer = kmalloc(size, G << 631 if (!call->buffer) << 632 return -ENOMEM; << 633 afs_extract_to_buf(call, size) << 634 call->unmarshall++; << 635 595 636 fallthrough; !! 596 if (skb->len > 0) 637 case 2: !! 597 return -EBADMSG; 638 _debug("extract FID array"); !! 598 if (!last) 639 ret = afs_extract_data(call, f !! 599 return 0; 640 if (ret < 0) << 641 return ret; << 642 << 643 _debug("unmarshall FID array") << 644 call->request = kcalloc(call-> << 645 sizeof << 646 GFP_KE << 647 if (!call->request) << 648 return -ENOMEM; << 649 << 650 cb = call->request; << 651 bp = call->buffer; << 652 for (loop = call->count; loop << 653 cb->fid.vid = xdr_ << 654 cb->fid.vnode = xdr_ << 655 cb->fid.vnode_hi = nto << 656 cb->fid.unique = ntoh << 657 bp++; << 658 } << 659 << 660 afs_extract_to_tmp(call); << 661 call->unmarshall++; << 662 fallthrough; << 663 << 664 case 3: << 665 break; << 666 } << 667 600 668 if (!afs_check_call_state(call, AFS_CA !! 601 /* no unmarshalling required */ 669 return afs_io_error(call, afs_ !! 602 call->state = AFS_CALL_REPLYING; 670 603 671 /* We'll need the file server record a !! 604 INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself); 672 * vnodes to operate upon. !! 605 queue_work(afs_wq, &call->work); 673 */ !! 606 return 0; 674 return afs_find_cm_server_by_peer(call << 675 } 607 } 676 608
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.