nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 * 00004 * Copyright CEA/DAM/DIF (2008) 00005 * contributeur : Philippe DENIEL philippe.deniel@cea.fr 00006 * Thomas LEIBOVICI thomas.leibovici@cea.fr 00007 * 00008 * 00009 * This program is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 3 of the License, or (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00017 * Lesser General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU Lesser General Public 00020 * License along with this library; if not, write to the Free Software 00021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00022 * 00023 * --------------------------------------- 00024 */ 00025 00036 #ifdef HAVE_CONFIG_H 00037 #include "config.h" 00038 #endif 00039 00040 #ifdef _SOLARIS 00041 #include "solaris_port.h" 00042 #endif 00043 00044 #include "sal_functions.h" 00045 #include "nfs_tools.h" 00046 00047 typedef struct nfs4_op_desc__ 00048 { 00049 char *name; 00050 unsigned int val; 00051 int (*funct) (struct nfs_argop4 *, compound_data_t *, struct nfs_resop4 *); 00052 } nfs4_op_desc_t; 00053 00054 /* This array maps the operation number to the related position in array optab4 */ 00055 #ifndef _USE_NFS4_1 00056 const int optab4index[] = 00057 { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 00058 21, 22, 23, 00059 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39 00060 }; 00061 00062 #else 00063 const int optab4index[] = 00064 { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 00065 21, 22, 23, 00066 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 00067 46, 00068 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58 00069 }; 00070 00071 #endif 00072 00073 #define POS_ILLEGAL_V40 40 00074 #define POS_ILLEGAL_V41 59 00075 00076 static const nfs4_op_desc_t optab4v0[] = { 00077 {"OP_ACCESS", NFS4_OP_ACCESS, nfs4_op_access}, 00078 {"OP_CLOSE", NFS4_OP_CLOSE, nfs4_op_close}, 00079 {"OP_COMMIT", NFS4_OP_COMMIT, nfs4_op_commit}, 00080 {"OP_CREATE", NFS4_OP_CREATE, nfs4_op_create}, 00081 {"OP_DELEGPURGE", NFS4_OP_DELEGPURGE, nfs4_op_delegpurge}, 00082 {"OP_DELEGRETURN", NFS4_OP_DELEGRETURN, nfs4_op_delegreturn}, 00083 {"OP_GETATTR", NFS4_OP_GETATTR, nfs4_op_getattr}, 00084 {"OP_GETFH", NFS4_OP_GETFH, nfs4_op_getfh}, 00085 {"OP_LINK", NFS4_OP_LINK, nfs4_op_link}, 00086 {"OP_LOCK", NFS4_OP_LOCK, nfs4_op_lock}, 00087 {"OP_LOCKT", NFS4_OP_LOCKT, nfs4_op_lockt}, 00088 {"OP_LOCKU", NFS4_OP_LOCKU, nfs4_op_locku}, 00089 {"OP_LOOKUP", NFS4_OP_LOOKUP, nfs4_op_lookup}, 00090 {"OP_LOOKUPP", NFS4_OP_LOOKUPP, nfs4_op_lookupp}, 00091 {"OP_NVERIFY", NFS4_OP_NVERIFY, nfs4_op_nverify}, 00092 {"OP_OPEN", NFS4_OP_OPEN, nfs4_op_open}, 00093 {"OP_OPENATTR", NFS4_OP_OPENATTR, nfs4_op_openattr}, 00094 {"OP_OPEN_CONFIRM", NFS4_OP_OPEN_CONFIRM, nfs4_op_open_confirm}, 00095 {"OP_OPEN_DOWNGRADE", NFS4_OP_OPEN_DOWNGRADE, nfs4_op_open_downgrade}, 00096 {"OP_PUTFH", NFS4_OP_PUTFH, nfs4_op_putfh}, 00097 {"OP_PUTPUBFH", NFS4_OP_PUTPUBFH, nfs4_op_putpubfh}, 00098 {"OP_PUTROOTFH", NFS4_OP_PUTROOTFH, nfs4_op_putrootfh}, 00099 {"OP_READ", NFS4_OP_READ, nfs4_op_read}, 00100 {"OP_READDIR", NFS4_OP_READDIR, nfs4_op_readdir}, 00101 {"OP_READLINK", NFS4_OP_READLINK, nfs4_op_readlink}, 00102 {"OP_REMOVE", NFS4_OP_REMOVE, nfs4_op_remove}, 00103 {"OP_RENAME", NFS4_OP_RENAME, nfs4_op_rename}, 00104 {"OP_RENEW", NFS4_OP_RENEW, nfs4_op_renew}, 00105 {"OP_RESTOREFH", NFS4_OP_RESTOREFH, nfs4_op_restorefh}, 00106 {"OP_SAVEFH", NFS4_OP_SAVEFH, nfs4_op_savefh}, 00107 {"OP_SECINFO", NFS4_OP_SECINFO, nfs4_op_secinfo}, 00108 {"OP_SETATTR", NFS4_OP_SETATTR, nfs4_op_setattr}, 00109 {"OP_SETCLIENTID", NFS4_OP_SETCLIENTID, nfs4_op_setclientid}, 00110 {"OP_SETCLIENTID_CONFIRM", NFS4_OP_SETCLIENTID_CONFIRM, nfs4_op_setclientid_confirm}, 00111 {"OP_VERIFY", NFS4_OP_VERIFY, nfs4_op_verify}, 00112 {"OP_WRITE", NFS4_OP_WRITE, nfs4_op_write}, 00113 {"OP_RELEASE_LOCKOWNER", NFS4_OP_RELEASE_LOCKOWNER, nfs4_op_release_lockowner}, 00114 {"OP_ILLEGAL", NFS4_OP_ILLEGAL, nfs4_op_illegal} 00115 }; 00116 00117 #ifdef _USE_NFS4_1 00118 static const nfs4_op_desc_t optab4v1[] = { 00119 {"OP_ACCESS", NFS4_OP_ACCESS, nfs4_op_access}, 00120 {"OP_CLOSE", NFS4_OP_CLOSE, nfs41_op_close}, 00121 {"OP_COMMIT", NFS4_OP_COMMIT, nfs4_op_commit}, 00122 {"OP_CREATE", NFS4_OP_CREATE, nfs4_op_create}, 00123 {"OP_DELEGPURGE", NFS4_OP_DELEGPURGE, nfs4_op_delegpurge}, 00124 {"OP_DELEGRETURN", NFS4_OP_DELEGRETURN, nfs4_op_delegreturn}, 00125 {"OP_GETATTR", NFS4_OP_GETATTR, nfs4_op_getattr}, 00126 {"OP_GETFH", NFS4_OP_GETFH, nfs4_op_getfh}, 00127 {"OP_LINK", NFS4_OP_LINK, nfs4_op_link}, 00128 {"OP_LOCK", NFS4_OP_LOCK, nfs41_op_lock}, 00129 {"OP_LOCKT", NFS4_OP_LOCKT, nfs41_op_lockt}, 00130 {"OP_LOCKU", NFS4_OP_LOCKU, nfs41_op_locku}, 00131 {"OP_LOOKUP", NFS4_OP_LOOKUP, nfs4_op_lookup}, 00132 {"OP_LOOKUPP", NFS4_OP_LOOKUPP, nfs4_op_lookupp}, 00133 {"OP_NVERIFY", NFS4_OP_NVERIFY, nfs4_op_nverify}, 00134 {"OP_OPEN", NFS4_OP_OPEN, nfs41_op_open}, 00135 {"OP_OPENATTR", NFS4_OP_OPENATTR, nfs4_op_openattr}, 00136 {"OP_OPEN_CONFIRM", NFS4_OP_OPEN_CONFIRM, nfs4_op_illegal}, /* OP_OPEN_CONFIRM is deprecated in NFSv4.1 */ 00137 {"OP_OPEN_DOWNGRADE", NFS4_OP_OPEN_DOWNGRADE, nfs4_op_open_downgrade}, 00138 {"OP_PUTFH", NFS4_OP_PUTFH, nfs4_op_putfh}, 00139 {"OP_PUTPUBFH", NFS4_OP_PUTPUBFH, nfs4_op_putpubfh}, 00140 {"OP_PUTROOTFH", NFS4_OP_PUTROOTFH, nfs4_op_putrootfh}, 00141 {"OP_READ", NFS4_OP_READ, nfs4_op_read}, 00142 {"OP_READDIR", NFS4_OP_READDIR, nfs4_op_readdir}, 00143 {"OP_READLINK", NFS4_OP_READLINK, nfs4_op_readlink}, 00144 {"OP_REMOVE", NFS4_OP_REMOVE, nfs4_op_remove}, 00145 {"OP_RENAME", NFS4_OP_RENAME, nfs4_op_rename}, 00146 {"OP_RENEW", NFS4_OP_RENEW, nfs4_op_renew}, 00147 {"OP_RESTOREFH", NFS4_OP_RESTOREFH, nfs4_op_restorefh}, 00148 {"OP_SAVEFH", NFS4_OP_SAVEFH, nfs4_op_savefh}, 00149 {"OP_SECINFO", NFS4_OP_SECINFO, nfs4_op_secinfo}, 00150 {"OP_SETATTR", NFS4_OP_SETATTR, nfs4_op_setattr}, 00151 {"OP_SETCLIENTID", NFS4_OP_SETCLIENTID, nfs4_op_setclientid}, 00152 {"OP_SETCLIENTID_CONFIRM", NFS4_OP_SETCLIENTID_CONFIRM, nfs4_op_setclientid_confirm}, 00153 {"OP_VERIFY", NFS4_OP_VERIFY, nfs4_op_verify}, 00154 {"OP_WRITE", NFS4_OP_WRITE, nfs4_op_write}, 00155 {"OP_RELEASE_LOCKOWNER", NFS4_OP_RELEASE_LOCKOWNER, nfs4_op_release_lockowner}, 00156 {"OP_BACKCHANNEL_CTL", NFS4_OP_BACKCHANNEL_CTL, nfs4_op_illegal}, /* tbd */ 00157 {"OP_BIND_CONN_TO_SESSION", NFS4_OP_BIND_CONN_TO_SESSION, nfs4_op_illegal}, /* tbd */ 00158 {"OP_EXCHANGE_ID", NFS4_OP_EXCHANGE_ID, nfs41_op_exchange_id}, 00159 {"OP_CREATE_SESSION", NFS4_OP_CREATE_SESSION, nfs41_op_create_session}, 00160 {"OP_DESTROY_SESSION", NFS4_OP_DESTROY_SESSION, nfs41_op_destroy_session}, 00161 {"OP_FREE_STATEID", NFS4_OP_FREE_STATEID, nfs41_op_free_stateid}, 00162 {"OP_GET_DIR_DELEGATION", NFS4_OP_GET_DIR_DELEGATION, nfs4_op_illegal}, /* tbd */ 00163 {"OP_GETDEVICEINFO", NFS4_OP_GETDEVICEINFO, nfs41_op_getdeviceinfo}, 00164 {"OP_GETDEVICELIST", NFS4_OP_GETDEVICELIST, nfs41_op_getdevicelist}, 00165 {"OP_LAYOUTCOMMIT", NFS4_OP_LAYOUTCOMMIT, nfs41_op_layoutcommit}, 00166 {"OP_LAYOUTGET", NFS4_OP_LAYOUTGET, nfs41_op_layoutget}, 00167 {"OP_LAYOUTRETURN", NFS4_OP_LAYOUTRETURN, nfs41_op_layoutreturn}, 00168 {"OP_SECINFO_NO_NAME", NFS4_OP_SECINFO_NO_NAME, nfs4_op_illegal}, /* tbd */ 00169 {"OP_SEQUENCE", NFS4_OP_SEQUENCE, nfs41_op_sequence}, 00170 {"OP_SET_SSV", NFS4_OP_SET_SSV, nfs41_op_set_ssv}, 00171 {"OP_TEST_STATEID", NFS4_OP_TEST_STATEID, nfs41_op_test_stateid}, 00172 {"OP_WANT_DELEGATION", NFS4_OP_WANT_DELEGATION, nfs4_op_illegal}, /* tbd */ 00173 {"OP_DESTROY_CLIENTID", NFS4_OP_DESTROY_CLIENTID, nfs4_op_illegal}, /* tbd */ 00174 {"OP_RECLAIM_COMPLETE", NFS4_OP_RECLAIM_COMPLETE, nfs41_op_reclaim_complete}, 00175 {"OP_ILLEGAL", NFS4_OP_ILLEGAL, nfs4_op_illegal} 00176 }; 00177 #endif /* _USE_NFS4_1 */ 00178 00179 #ifdef _USE_NFS4_1 00180 nfs4_op_desc_t *optabvers[] = 00181 { (nfs4_op_desc_t *) optab4v0, (nfs4_op_desc_t *) optab4v1 }; 00182 #else 00183 nfs4_op_desc_t *optabvers[] = { (nfs4_op_desc_t *) optab4v0 }; 00184 #endif 00185 00207 int nfs4_Compound(nfs_arg_t *parg, 00208 exportlist_t *pexport, 00209 fsal_op_context_t *pcontext, 00210 nfs_worker_data_t *pworker, 00211 struct svc_req *preq, 00212 nfs_res_t * pres) 00213 { 00214 unsigned int i = 0; 00215 int status = NFS4_OK; 00216 struct nfs_resop4 res; 00217 char __attribute__ ((__unused__)) funcname[] = "nfs4_Compound"; 00218 compound_data_t data; 00219 int opindex; 00220 #define TAGLEN 64 00221 char tagstr[TAGLEN + 1 + 5]; 00222 00223 /* A "local" #define to avoid typo with nfs (too) long structure names */ 00224 #define COMPOUND4_ARRAY parg->arg_compound4.argarray 00225 #define COMPOUND4_MINOR parg->arg_compound4.minorversion 00226 00227 #ifdef _USE_NFS4_1 00228 if(COMPOUND4_MINOR > 1) 00229 #else 00230 if(COMPOUND4_MINOR != 0) 00231 #endif 00232 { 00233 LogCrit(COMPONENT_NFS_V4, 00234 "Bad Minor Version %d", 00235 COMPOUND4_MINOR); 00236 00237 pres->res_compound4.status = NFS4ERR_MINOR_VERS_MISMATCH; 00238 pres->res_compound4.resarray.resarray_len = 0; 00239 return NFS_REQ_OK; 00240 } 00241 00242 /* Check for empty COMPOUND request */ 00243 if(COMPOUND4_ARRAY.argarray_len == 0) 00244 { 00245 LogMajor(COMPONENT_NFS_V4, 00246 "An empty COMPOUND (no operation in it) was received"); 00247 00248 pres->res_compound4.status = NFS4_OK; 00249 pres->res_compound4.resarray.resarray_len = 0; 00250 return NFS_REQ_OK; 00251 } 00252 00253 /* Check if this export supports NFSv4 */ 00254 if( ( pexport->options & EXPORT_OPTION_NFSV4 ) == 0 ) 00255 { 00256 LogMajor( COMPONENT_NFS_V4, 00257 "The export(id=%u) does not support NFSv4... rejecting it", pexport->id ) ; 00258 pres->res_compound4.status = NFS4ERR_PERM ; 00259 pres->res_compound4.resarray.resarray_len = 0; 00260 return NFS_REQ_OK ; 00261 } 00262 00263 /* Check for too long request */ 00264 if(COMPOUND4_ARRAY.argarray_len > 30) 00265 { 00266 LogMajor(COMPONENT_NFS_V4, 00267 "A COMPOUND with too many operations (%d) was received", 00268 COMPOUND4_ARRAY.argarray_len); 00269 00270 pres->res_compound4.status = NFS4ERR_RESOURCE; 00271 pres->res_compound4.resarray.resarray_len = 0; 00272 return NFS_REQ_OK; 00273 } 00274 00275 /* Initialisation of the compound request internal's data */ 00276 memset(&data, 0, sizeof(data)); 00277 00278 /* Minor version related stuff */ 00279 data.minorversion = COMPOUND4_MINOR; 00282 data.pfullexportlist = pexport; /* Full export list is 00283 provided in input */ 00284 data.pcontext = pcontext; /* Get the fsal credentials from the 00285 worker thread */ 00286 data.pworker = pworker; 00287 data.pseudofs = nfs4_GetPseudoFs(); 00288 data.reqp = preq; 00289 00290 strcpy(data.MntPath, "/"); 00291 00292 /* Building the client credential field */ 00293 if(nfs_rpc_req2client_cred(preq, &(data.credential)) == -1) 00294 return NFS_REQ_DROP; /* Malformed credential */ 00295 00296 /* Keeping the same tag as in the arguments */ 00297 memcpy(&(pres->res_compound4.tag), &(parg->arg_compound4.tag), 00298 sizeof(parg->arg_compound4.tag)); 00299 00300 if(utf8dup(&(pres->res_compound4.tag), &(parg->arg_compound4.tag)) == -1) 00301 { 00302 LogCrit(COMPONENT_NFS_V4, "Unable to duplicate tag into response"); 00303 return NFS_REQ_DROP; 00304 } 00305 00306 /* Allocating the reply nfs_resop4 */ 00307 if((pres->res_compound4.resarray.resarray_val = 00308 gsh_calloc((COMPOUND4_ARRAY.argarray_len), 00309 sizeof(struct nfs_resop4))) == NULL) 00310 { 00311 return NFS_REQ_DROP; 00312 } 00313 00314 if(isDebug(COMPONENT_NFS_V4) && pres->res_compound4.tag.utf8string_len > 0) 00315 { 00316 sprintf(tagstr, " TAG="); 00317 utf82str(tagstr+5, TAGLEN, &(pres->res_compound4.tag)); 00318 } 00319 else 00320 { 00321 tagstr[0] = '\0'; 00322 } 00323 00324 /* Managing the operation list */ 00325 LogDebug(COMPONENT_NFS_V4, 00326 "COMPOUND: There are %d operations%s", 00327 COMPOUND4_ARRAY.argarray_len, tagstr); 00328 00329 #ifdef _USE_NFS4_1 00330 /* Manage error NFS4ERR_NOT_ONLY_OP */ 00331 if(COMPOUND4_ARRAY.argarray_len > 1) 00332 { 00333 /* If not prepended ny OP4_SEQUENCE, OP4_EXCHANGE_ID should be the only request in the compound 00334 * see 18.35.3. and test EID8 for details */ 00335 if(optabvers[1][optab4index[COMPOUND4_ARRAY.argarray_val[0].argop]].val == 00336 NFS4_OP_EXCHANGE_ID) 00337 { 00338 status = NFS4ERR_NOT_ONLY_OP; 00339 pres->res_compound4.resarray.resarray_val[0].nfs_resop4_u.opexchange_id. 00340 eir_status = status; 00341 pres->res_compound4.status = status; 00342 00343 return NFS_REQ_OK; 00344 } 00345 } 00346 #endif 00347 00348 pres->res_compound4.resarray.resarray_len = COMPOUND4_ARRAY.argarray_len; 00349 for(i = 0; i < COMPOUND4_ARRAY.argarray_len; i++) 00350 { 00351 /* Use optab4index to reference the operation */ 00352 #ifdef _USE_NFS4_1 00353 data.oppos = i; /* Useful to check if OP_SEQUENCE is used as the first operation */ 00354 00355 if(COMPOUND4_MINOR == 1) 00356 { 00357 if(data.psession != NULL) 00358 { 00359 if(data.psession->fore_channel_attrs.ca_maxoperations == i) 00360 { 00361 status = NFS4ERR_TOO_MANY_OPS; 00362 pres->res_compound4.resarray.resarray_val[i].nfs_resop4_u.opaccess. 00363 status = status; 00364 pres->res_compound4.resarray.resarray_val[i].resop = 00365 COMPOUND4_ARRAY.argarray_val[i].argop; 00366 pres->res_compound4.status = status; 00367 break; /* stop loop */ 00368 } 00369 } 00370 } 00371 00372 /* if( COMPOUND4_MINOR == 1 ) */ 00373 if((COMPOUND4_ARRAY.argarray_val[i].argop <= NFS4_OP_RELEASE_LOCKOWNER 00374 && COMPOUND4_MINOR == 0) 00375 || (COMPOUND4_ARRAY.argarray_val[i].argop <= NFS4_OP_RECLAIM_COMPLETE 00376 && COMPOUND4_MINOR == 1)) 00377 #else 00378 if(COMPOUND4_ARRAY.argarray_val[i].argop <= NFS4_OP_RELEASE_LOCKOWNER) 00379 #endif 00380 opindex = optab4index[COMPOUND4_ARRAY.argarray_val[i].argop]; 00381 else 00382 { 00383 /* Set optindex to op_illegal */ 00384 #ifdef _USE_NFS4_1 00385 opindex = (COMPOUND4_MINOR==0)?optab4index[POS_ILLEGAL_V40]:optab4index[POS_ILLEGAL_V41]; 00386 #else 00387 opindex = optab4index[POS_ILLEGAL_V40]; 00388 #endif 00389 LogMajor( COMPONENT_NFS_V4, "Client is using Illegal operation #%u", COMPOUND4_ARRAY.argarray_val[i].argop ) ; 00390 } 00391 00392 LogDebug(COMPONENT_NFS_V4, 00393 "Request %d is %d = %s, entry %d in the op array%s", 00394 i, 00395 optabvers[COMPOUND4_MINOR][opindex].val, 00396 optabvers[COMPOUND4_MINOR][opindex].name, 00397 opindex, 00398 tagstr); 00399 00400 memset(&res, 0, sizeof(res)); 00401 status = (optabvers[COMPOUND4_MINOR][opindex].funct) (&(COMPOUND4_ARRAY.argarray_val[i]), 00402 &data, 00403 &res); 00404 00405 memcpy(&(pres->res_compound4.resarray.resarray_val[i]), &res, sizeof(res)); 00406 00407 LogCompoundFH(&data); 00408 00409 /* All the operation, like NFS4_OP_ACESS, have a first replyied field called .status */ 00410 pres->res_compound4.resarray.resarray_val[i].nfs_resop4_u.opaccess.status = status; 00411 00412 if(status != NFS4_OK) 00413 { 00414 /* An error occured, we do not manage the other requests in the COMPOUND, this may be a regular behaviour */ 00415 LogDebug(COMPONENT_NFS_V4, 00416 "Status of %s in position %d = %s%s", 00417 optabvers[COMPOUND4_MINOR][opindex].name, 00418 i, 00419 nfsstat4_to_str(status), 00420 tagstr); 00421 00422 pres->res_compound4.resarray.resarray_len = i + 1; 00423 00424 break; 00425 } 00426 #ifdef _USE_NFS4_1 00427 /* Check Req size */ 00428 00429 /* NFS_V4.1 specific stuff */ 00430 if(data.use_drc) 00431 { 00432 /* Replay cache, only true for SEQUENCE or CREATE_SESSION w/o SEQUENCE. 00433 * Since will only be set in those cases, no need to check operation or anything. 00434 */ 00435 LogFullDebug(COMPONENT_SESSIONS, 00436 "Use session replay cache %p", 00437 data.pcached_res); 00438 00439 /* Free the reply allocated above */ 00440 gsh_free(pres->res_compound4.resarray.resarray_val); 00441 00442 /* Copy the reply from the cache */ 00443 pres->res_compound4_extended = *data.pcached_res; 00444 status = ((COMPOUND4res *) data.pcached_res)->status; 00445 break; /* Exit the for loop */ 00446 } 00447 #endif 00448 } /* for */ 00449 00450 /* Complete the reply, in particular, tell where you stopped if unsuccessfull COMPOUD */ 00451 pres->res_compound4.status = status; 00452 00453 #ifdef _USE_NFS4_1 00454 /* Manage session's DRC: keep NFS4.1 replay for later use, but don't save a 00455 * replayed result again. 00456 */ 00457 if(data.pcached_res != NULL && !data.use_drc) 00458 { 00459 /* Pointer has been set by nfs41_op_sequence and points to slot to cache 00460 * result in. 00461 */ 00462 LogFullDebug(COMPONENT_SESSIONS, 00463 "Save result in session replay cache %p sizeof nfs_res_t=%d", 00464 data.pcached_res, 00465 (int) sizeof(nfs_res_t)); 00466 00467 /* Indicate to nfs4_Compound_Free that this reply is cached. */ 00468 pres->res_compound4_extended.res_cached = TRUE; 00469 00470 /* If the cache is already in use, free it. */ 00471 if(data.pcached_res->res_cached) 00472 { 00473 data.pcached_res->res_cached = FALSE; 00474 nfs4_Compound_Free((nfs_res_t *)data.pcached_res); 00475 } 00476 00477 /* Save the result in the cache. */ 00478 *data.pcached_res = pres->res_compound4_extended; 00479 } 00480 00481 /* If we have reserved a lease, update it and release it */ 00482 if(data.preserved_clientid != NULL) 00483 { 00484 /* Update and release lease */ 00485 P(data.preserved_clientid->cid_mutex); 00486 00487 update_lease(data.preserved_clientid); 00488 00489 V(data.preserved_clientid->cid_mutex); 00490 } 00491 #endif 00492 00493 if(status != NFS4_OK) 00494 LogDebug(COMPONENT_NFS_V4, 00495 "End status = %s lastindex = %d%s", 00496 nfsstat4_to_str(status), i, tagstr); 00497 00498 compound_data_Free(&data); 00499 00500 return NFS_REQ_OK; 00501 } /* nfs4_Compound */ 00502 00514 void nfs4_Compound_FreeOne(nfs_resop4 *pres) 00515 { 00516 switch (pres->resop) 00517 { 00518 case NFS4_OP_ACCESS: 00519 nfs4_op_access_Free(&(pres->nfs_resop4_u.opaccess)); 00520 break; 00521 00522 case NFS4_OP_CLOSE: 00523 nfs4_op_close_Free(&(pres->nfs_resop4_u.opclose)); 00524 break; 00525 00526 case NFS4_OP_COMMIT: 00527 nfs4_op_commit_Free(&(pres->nfs_resop4_u.opcommit)); 00528 break; 00529 00530 case NFS4_OP_CREATE: 00531 nfs4_op_create_Free(&(pres->nfs_resop4_u.opcreate)); 00532 break; 00533 00534 case NFS4_OP_DELEGPURGE: 00535 nfs4_op_delegpurge_Free(&(pres->nfs_resop4_u.opdelegpurge)); 00536 break; 00537 00538 case NFS4_OP_DELEGRETURN: 00539 nfs4_op_delegreturn_Free(&(pres->nfs_resop4_u.opdelegreturn)); 00540 break; 00541 00542 case NFS4_OP_GETATTR: 00543 nfs4_op_getattr_Free(&(pres->nfs_resop4_u.opgetattr)); 00544 break; 00545 00546 case NFS4_OP_GETFH: 00547 nfs4_op_getfh_Free(&(pres->nfs_resop4_u.opgetfh)); 00548 break; 00549 00550 case NFS4_OP_LINK: 00551 nfs4_op_link_Free(&(pres->nfs_resop4_u.oplink)); 00552 break; 00553 00554 case NFS4_OP_LOCK: 00555 nfs4_op_lock_Free(&(pres->nfs_resop4_u.oplock)); 00556 break; 00557 00558 case NFS4_OP_LOCKT: 00559 nfs4_op_lockt_Free(&(pres->nfs_resop4_u.oplockt)); 00560 break; 00561 00562 case NFS4_OP_LOCKU: 00563 nfs4_op_locku_Free(&(pres->nfs_resop4_u.oplocku)); 00564 break; 00565 00566 case NFS4_OP_LOOKUP: 00567 nfs4_op_lookup_Free(&(pres->nfs_resop4_u.oplookup)); 00568 break; 00569 00570 case NFS4_OP_LOOKUPP: 00571 nfs4_op_lookupp_Free(&(pres->nfs_resop4_u.oplookupp)); 00572 break; 00573 00574 case NFS4_OP_NVERIFY: 00575 nfs4_op_nverify_Free(&(pres->nfs_resop4_u.opnverify)); 00576 break; 00577 00578 case NFS4_OP_OPEN: 00579 nfs4_op_open_Free(&(pres->nfs_resop4_u.opopen)); 00580 break; 00581 00582 case NFS4_OP_OPENATTR: 00583 nfs4_op_openattr_Free(&(pres->nfs_resop4_u.opopenattr)); 00584 break; 00585 00586 case NFS4_OP_OPEN_CONFIRM: 00587 nfs4_op_open_confirm_Free(&(pres->nfs_resop4_u.opopen_confirm)); 00588 break; 00589 00590 case NFS4_OP_OPEN_DOWNGRADE: 00591 nfs4_op_open_downgrade_Free(&(pres->nfs_resop4_u.opopen_downgrade)); 00592 break; 00593 00594 case NFS4_OP_PUTFH: 00595 nfs4_op_putfh_Free(&(pres->nfs_resop4_u.opputfh)); 00596 break; 00597 00598 case NFS4_OP_PUTPUBFH: 00599 nfs4_op_putpubfh_Free(&(pres->nfs_resop4_u.opputpubfh)); 00600 break; 00601 00602 case NFS4_OP_PUTROOTFH: 00603 nfs4_op_putrootfh_Free(&(pres->nfs_resop4_u.opputrootfh)); 00604 break; 00605 00606 case NFS4_OP_READ: 00607 nfs4_op_read_Free(&(pres->nfs_resop4_u.opread)); 00608 break; 00609 00610 case NFS4_OP_READDIR: 00611 nfs4_op_readdir_Free(&(pres->nfs_resop4_u.opreaddir)); 00612 break; 00613 00614 case NFS4_OP_READLINK: 00615 nfs4_op_readlink_Free(&(pres->nfs_resop4_u.opreadlink)); 00616 break; 00617 00618 case NFS4_OP_REMOVE: 00619 nfs4_op_remove_Free(&(pres->nfs_resop4_u.opremove)); 00620 break; 00621 00622 case NFS4_OP_RENAME: 00623 nfs4_op_rename_Free(&(pres->nfs_resop4_u.oprename)); 00624 break; 00625 00626 case NFS4_OP_RENEW: 00627 nfs4_op_renew_Free(&(pres->nfs_resop4_u.oprenew)); 00628 break; 00629 00630 case NFS4_OP_RESTOREFH: 00631 nfs4_op_restorefh_Free(&(pres->nfs_resop4_u.oprestorefh)); 00632 break; 00633 00634 case NFS4_OP_SAVEFH: 00635 nfs4_op_savefh_Free(&(pres->nfs_resop4_u.opsavefh)); 00636 break; 00637 00638 case NFS4_OP_SECINFO: 00639 nfs4_op_secinfo_Free(&(pres->nfs_resop4_u.opsecinfo)); 00640 break; 00641 00642 case NFS4_OP_SETATTR: 00643 nfs4_op_setattr_Free(&(pres->nfs_resop4_u.opsetattr)); 00644 break; 00645 00646 case NFS4_OP_SETCLIENTID: 00647 nfs4_op_setclientid_Free(&(pres->nfs_resop4_u.opsetclientid)); 00648 break; 00649 00650 case NFS4_OP_SETCLIENTID_CONFIRM: 00651 nfs4_op_setclientid_confirm_Free(&(pres->nfs_resop4_u.opsetclientid_confirm)); 00652 break; 00653 00654 case NFS4_OP_VERIFY: 00655 nfs4_op_verify_Free(&(pres->nfs_resop4_u.opverify)); 00656 break; 00657 00658 case NFS4_OP_WRITE: 00659 nfs4_op_write_Free(&(pres->nfs_resop4_u.opwrite)); 00660 break; 00661 00662 case NFS4_OP_RELEASE_LOCKOWNER: 00663 nfs4_op_release_lockowner_Free(&(pres->nfs_resop4_u.oprelease_lockowner)); 00664 break; 00665 00666 #ifdef _USE_NFS4_1 00667 case NFS4_OP_EXCHANGE_ID: 00668 nfs41_op_exchange_id_Free(&(pres->nfs_resop4_u.opexchange_id)); 00669 break; 00670 00671 case NFS4_OP_CREATE_SESSION: 00672 nfs41_op_create_session_Free(&(pres->nfs_resop4_u.opcreate_session)); 00673 break; 00674 00675 case NFS4_OP_SEQUENCE: 00676 nfs41_op_sequence_Free(&(pres->nfs_resop4_u.opsequence)); 00677 break; 00678 00679 case NFS4_OP_GETDEVICEINFO: 00680 nfs41_op_getdeviceinfo_Free(&(pres->nfs_resop4_u.opgetdeviceinfo)); 00681 break; 00682 00683 case NFS4_OP_GETDEVICELIST: 00684 nfs41_op_getdevicelist_Free(&(pres->nfs_resop4_u.opgetdevicelist)); 00685 break; 00686 00687 case NFS4_OP_TEST_STATEID: 00688 nfs41_op_test_stateid_Free(&(pres->nfs_resop4_u.optest_stateid)); 00689 break; 00690 00691 case NFS4_OP_FREE_STATEID: 00692 nfs41_op_free_stateid_Free(&(pres->nfs_resop4_u.opfree_stateid)); 00693 break; 00694 00695 case NFS4_OP_BACKCHANNEL_CTL: 00696 case NFS4_OP_BIND_CONN_TO_SESSION: 00697 case NFS4_OP_DESTROY_SESSION: 00698 case NFS4_OP_GET_DIR_DELEGATION: 00699 case NFS4_OP_LAYOUTCOMMIT: 00700 case NFS4_OP_LAYOUTGET: 00701 case NFS4_OP_LAYOUTRETURN: 00702 case NFS4_OP_SECINFO_NO_NAME: 00703 case NFS4_OP_SET_SSV: 00704 case NFS4_OP_WANT_DELEGATION: 00705 case NFS4_OP_DESTROY_CLIENTID: 00706 case NFS4_OP_RECLAIM_COMPLETE: 00707 nfs41_op_reclaim_complete_Free(&(pres->nfs_resop4_u.opreclaim_complete)); 00708 break; 00709 #endif 00710 00711 case NFS4_OP_ILLEGAL: 00712 nfs4_op_illegal_Free(&(pres->nfs_resop4_u.opillegal)); 00713 break; 00714 } /* switch */ 00715 } 00716 00730 void nfs4_Compound_Free(nfs_res_t *pres) 00731 { 00732 unsigned int i = 0; 00733 log_components_t component = COMPONENT_NFS_V4; 00734 00735 if(isFullDebug(COMPONENT_SESSIONS)) 00736 component = COMPONENT_SESSIONS; 00737 00738 if(pres->res_compound4_extended.res_cached) 00739 { 00740 LogFullDebug(component, 00741 "Skipping free of NFS4 result %p", 00742 pres); 00743 return; 00744 } 00745 00746 LogFullDebug(component, 00747 "nfs4_Compound_Free %p (resarraylen=%i)", 00748 pres, 00749 pres->res_compound4.resarray.resarray_len); 00750 00751 for(i = 0; i < pres->res_compound4.resarray.resarray_len; i++) { 00752 nfs_resop4 *val = &pres->res_compound4.resarray.resarray_val[i]; 00753 if (val) { 00754 /* !val is an error case, but it can occur, so avoid 00755 * indirect on NULL */ 00756 nfs4_Compound_FreeOne(val); 00757 } 00758 } 00759 00760 gsh_free(pres->res_compound4.resarray.resarray_val); 00761 free_utf8(&pres->res_compound4.tag); 00762 00763 return; 00764 } /* nfs4_Compound_Free */ 00765 00779 void compound_data_Free(compound_data_t * data) 00780 { 00781 /* Release refcounted cache entries */ 00782 if (data->current_entry) 00783 cache_inode_put(data->current_entry); 00784 00785 if (data->saved_entry) 00786 cache_inode_put(data->saved_entry); 00787 00788 if(data->currentFH.nfs_fh4_val != NULL) 00789 gsh_free(data->currentFH.nfs_fh4_val); 00790 00791 if(data->rootFH.nfs_fh4_val != NULL) 00792 gsh_free(data->rootFH.nfs_fh4_val); 00793 00794 if(data->publicFH.nfs_fh4_val != NULL) 00795 gsh_free(data->publicFH.nfs_fh4_val); 00796 00797 if(data->savedFH.nfs_fh4_val != NULL) 00798 gsh_free(data->savedFH.nfs_fh4_val); 00799 00800 if(data->mounted_on_FH.nfs_fh4_val != NULL) 00801 gsh_free(data->mounted_on_FH.nfs_fh4_val); 00802 00803 } /* compound_data_Free */ 00804 00810 void nfs4_Compound_CopyResOne(nfs_resop4 * pres_dst, nfs_resop4 * pres_src) 00811 { 00812 /* Copy base data structure */ 00813 memcpy(pres_dst, pres_src, sizeof(*pres_dst)); 00814 00815 /* Do deep copy where necessary */ 00816 switch (pres_src->resop) 00817 { 00818 case NFS4_OP_ACCESS: 00819 break; 00820 00821 case NFS4_OP_CLOSE: 00822 nfs4_op_close_CopyRes(&(pres_dst->nfs_resop4_u.opclose), 00823 &(pres_src->nfs_resop4_u.opclose)); 00824 return; 00825 00826 case NFS4_OP_COMMIT: 00827 case NFS4_OP_CREATE: 00828 case NFS4_OP_DELEGPURGE: 00829 case NFS4_OP_DELEGRETURN: 00830 case NFS4_OP_GETATTR: 00831 case NFS4_OP_GETFH: 00832 case NFS4_OP_LINK: 00833 break; 00834 00835 case NFS4_OP_LOCK: 00836 nfs4_op_lock_CopyRes(&(pres_dst->nfs_resop4_u.oplock), 00837 &(pres_src->nfs_resop4_u.oplock)); 00838 return; 00839 00840 case NFS4_OP_LOCKT: 00841 break; 00842 00843 case NFS4_OP_LOCKU: 00844 nfs4_op_locku_CopyRes(&(pres_dst->nfs_resop4_u.oplocku), 00845 &(pres_src->nfs_resop4_u.oplocku)); 00846 return; 00847 00848 case NFS4_OP_LOOKUP: 00849 case NFS4_OP_LOOKUPP: 00850 case NFS4_OP_NVERIFY: 00851 break; 00852 00853 case NFS4_OP_OPEN: 00854 nfs4_op_open_CopyRes(&(pres_dst->nfs_resop4_u.opopen), 00855 &(pres_src->nfs_resop4_u.opopen)); 00856 return; 00857 00858 case NFS4_OP_OPENATTR: 00859 break; 00860 00861 case NFS4_OP_OPEN_CONFIRM: 00862 nfs4_op_open_confirm_CopyRes(&(pres_dst->nfs_resop4_u.opopen_confirm), 00863 &(pres_src->nfs_resop4_u.opopen_confirm)); 00864 return; 00865 00866 case NFS4_OP_OPEN_DOWNGRADE: 00867 nfs4_op_open_downgrade_CopyRes(&(pres_dst->nfs_resop4_u.opopen_downgrade), 00868 &(pres_src->nfs_resop4_u.opopen_downgrade)); 00869 return; 00870 00871 case NFS4_OP_PUTFH: 00872 case NFS4_OP_PUTPUBFH: 00873 case NFS4_OP_PUTROOTFH: 00874 case NFS4_OP_READ: 00875 case NFS4_OP_READDIR: 00876 case NFS4_OP_READLINK: 00877 case NFS4_OP_REMOVE: 00878 case NFS4_OP_RENAME: 00879 case NFS4_OP_RENEW: 00880 case NFS4_OP_RESTOREFH: 00881 case NFS4_OP_SAVEFH: 00882 case NFS4_OP_SECINFO: 00883 case NFS4_OP_SETATTR: 00884 case NFS4_OP_SETCLIENTID: 00885 case NFS4_OP_SETCLIENTID_CONFIRM: 00886 case NFS4_OP_VERIFY: 00887 case NFS4_OP_WRITE: 00888 case NFS4_OP_RELEASE_LOCKOWNER: 00889 break; 00890 00891 #ifdef _USE_NFS4_1 00892 case NFS4_OP_EXCHANGE_ID: 00893 case NFS4_OP_CREATE_SESSION: 00894 case NFS4_OP_SEQUENCE: 00895 case NFS4_OP_GETDEVICEINFO: 00896 case NFS4_OP_GETDEVICELIST: 00897 case NFS4_OP_BACKCHANNEL_CTL: 00898 case NFS4_OP_BIND_CONN_TO_SESSION: 00899 case NFS4_OP_DESTROY_SESSION: 00900 case NFS4_OP_FREE_STATEID: 00901 case NFS4_OP_GET_DIR_DELEGATION: 00902 case NFS4_OP_LAYOUTCOMMIT: 00903 case NFS4_OP_LAYOUTGET: 00904 case NFS4_OP_LAYOUTRETURN: 00905 case NFS4_OP_SECINFO_NO_NAME: 00906 case NFS4_OP_SET_SSV: 00907 case NFS4_OP_TEST_STATEID: 00908 case NFS4_OP_WANT_DELEGATION: 00909 case NFS4_OP_DESTROY_CLIENTID: 00910 case NFS4_OP_RECLAIM_COMPLETE: 00911 break; 00912 #endif 00913 00914 case NFS4_OP_ILLEGAL: 00915 break; 00916 } /* switch */ 00917 00918 LogFatal(COMPONENT_NFS_V4, 00919 "nfs4_Compound_CopyResOne not implemented for %d", 00920 pres_src->resop); 00921 } 00922 00936 void nfs4_Compound_CopyRes(nfs_res_t * pres_dst, nfs_res_t * pres_src) 00937 { 00938 unsigned int i = 0; 00939 00940 LogFullDebug(COMPONENT_NFS_V4, 00941 "nfs4_Compound_CopyRes of %p to %p (resarraylen : %i)", 00942 pres_src, pres_dst, 00943 pres_src->res_compound4.resarray.resarray_len); 00944 00945 for(i = 0; i < pres_src->res_compound4.resarray.resarray_len; i++) 00946 nfs4_Compound_CopyResOne(&pres_dst->res_compound4.resarray.resarray_val[i], 00947 &pres_src->res_compound4.resarray.resarray_val[i]); 00948 } 00949 00964 int nfs4_op_stat_update(nfs_arg_t * parg /* IN */ , 00965 nfs_res_t * pres /* IN */ , 00966 nfs_request_stat_t * pstat_req /* OUT */ ) 00967 { 00968 int i = 0; 00969 00970 switch (COMPOUND4_MINOR) 00971 { 00972 case 0: 00973 for(i = 0; i < pres->res_compound4.resarray.resarray_len; i++) 00974 { 00975 pstat_req->nb_nfs40_op += 1; 00976 pstat_req->stat_op_nfs40[pres->res_compound4.resarray.resarray_val[i].resop]. 00977 total += 1; 00978 00979 /* All operations's reply structures start with their status, whatever the name of this field */ 00980 if(pres->res_compound4.resarray.resarray_val[i].nfs_resop4_u.opaccess.status == 00981 NFS4_OK) 00982 pstat_req->stat_op_nfs40[pres->res_compound4.resarray.resarray_val[i].resop]. 00983 success += 1; 00984 else 00985 pstat_req->stat_op_nfs40[pres->res_compound4.resarray.resarray_val[i].resop]. 00986 failed += 1; 00987 } 00988 break; 00989 00990 #ifdef _USE_NFS4_1 00991 case 1: 00992 for(i = 0; i < pres->res_compound4.resarray.resarray_len; i++) 00993 { 00994 pstat_req->nb_nfs41_op += 1; 00995 pstat_req->stat_op_nfs41[pres->res_compound4.resarray.resarray_val[i].resop]. 00996 total += 1; 00997 00998 /* All operations's reply structures start with their status, whatever the name of this field */ 00999 if(pres->res_compound4.resarray.resarray_val[i].nfs_resop4_u.opaccess.status == 01000 NFS4_OK) 01001 pstat_req->stat_op_nfs41[pres->res_compound4.resarray.resarray_val[i].resop]. 01002 success += 1; 01003 else 01004 pstat_req->stat_op_nfs41[pres->res_compound4.resarray.resarray_val[i].resop]. 01005 failed += 1; 01006 } 01007 01008 break; 01009 #endif 01010 01011 default: 01012 /* Bad parameter */ 01013 return -1; 01014 } 01015 return 0; 01016 } /* nfs4_op_stat_update */