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 00037 #ifdef HAVE_CONFIG_H 00038 #include "config.h" 00039 #endif 00040 00041 #ifdef _SOLARIS 00042 #include "solaris_port.h" 00043 #endif 00044 00045 #include <stdio.h> 00046 #include <string.h> 00047 #include <pthread.h> 00048 #include "HashData.h" 00049 #include "HashTable.h" 00050 #include "log.h" 00051 #include "ganesha_rpc.h" 00052 #include "nfs4.h" 00053 #include "nfs_core.h" 00054 #include "sal_functions.h" 00055 #include "nfs_proto_functions.h" 00056 #include "nfs_proto_tools.h" 00057 00058 static nfsstat4 nfs4_chk_shrdny(struct nfs_argop4 *, compound_data_t *, 00059 cache_entry_t *, fsal_accessflags_t, fsal_accessflags_t, fsal_openflags_t *, 00060 bool_t , fsal_attrib_list_t *, struct nfs_resop4 *); 00061 00062 static nfsstat4 nfs4_do_open(struct nfs_argop4 * op, 00063 compound_data_t * data, 00064 cache_entry_t * pentry_newfile, 00065 cache_entry_t * pentry_parent, 00066 state_owner_t * powner, 00067 state_t ** statep, 00068 fsal_name_t * filename, 00069 fsal_openflags_t openflags, 00070 char ** cause2); 00071 00072 static nfsstat4 nfs4_create_fh(compound_data_t *, cache_entry_t *, char **); 00086 #define STATE_ADD " (state_add failed)" 00087 #define STATE_SHARE_ADD " (state_share_add failed)" 00088 #define STATE_SHARE_UP " (state_share_upgrade failed)" 00089 #define CACHE_INODE_OPEN " cache_inode_open" 00090 #define arg_OPEN4 op->nfs_argop4_u.opopen 00091 #define res_OPEN4 resp->nfs_resop4_u.opopen 00092 00093 int nfs4_op_open(struct nfs_argop4 *op, compound_data_t *data, 00094 struct nfs_resop4 *resp) 00095 { 00096 char __attribute__ ((__unused__)) funcname[] = "nfs4_op_open"; 00097 00098 cache_entry_t * pentry_parent = NULL; 00099 cache_entry_t * pentry_lookup = NULL; 00100 cache_entry_t * pentry_newfile = NULL; 00101 fsal_attrib_list_t attr_parent; 00102 fsal_attrib_list_t attr; 00103 fsal_attrib_list_t attr_newfile; 00104 fsal_attrib_list_t sattr; 00105 fsal_openflags_t openflags = 0; 00106 cache_inode_status_t cache_status = CACHE_INODE_SUCCESS; 00107 state_status_t state_status; 00108 int retval; 00109 fsal_name_t filename; 00110 bool_t AttrProvided = FALSE; 00111 bool_t ReuseState = FALSE; 00112 fsal_accessmode_t mode = 0600; 00113 nfs_client_id_t * pclientid; 00114 state_t * pfile_state = NULL; 00115 state_t * pstate_iterate; 00116 state_nfs4_owner_name_t owner_name; 00117 state_owner_t * powner = NULL; 00118 const char * tag = "OPEN"; 00119 const char * cause = "OOPS"; 00120 const char * cause2 = ""; 00121 struct glist_head * glist; 00122 open_claim_type4 claim = arg_OPEN4.claim.claim; 00123 nfsstat4 status4; 00124 uint32_t tmp_attr[2]; 00125 #ifdef _USE_QUOTA 00126 fsal_status_t fsal_status; 00127 #endif 00128 char * text = ""; 00129 00130 LogDebug(COMPONENT_STATE, 00131 "Entering NFS v4 OPEN handler -----------------------------------------------------"); 00132 00133 /* What kind of open is it ? */ 00134 LogFullDebug(COMPONENT_STATE, 00135 "OPEN: Claim type = %d Open Type = %d Share Deny = %d Share Access = %d ", 00136 arg_OPEN4.claim.claim, 00137 arg_OPEN4.openhow.opentype, 00138 arg_OPEN4.share_deny, 00139 arg_OPEN4.share_access); 00140 00141 fsal_accessflags_t write_access = FSAL_WRITE_ACCESS; 00142 fsal_accessflags_t read_access = FSAL_READ_ACCESS; 00143 00144 resp->resop = NFS4_OP_OPEN; 00145 res_OPEN4.status = NFS4_OK; 00146 res_OPEN4.OPEN4res_u.resok4.rflags = 0 ; 00147 00148 /* Do basic checks on a filehandle */ 00149 res_OPEN4.status = nfs4_sanity_check_FH(data, 0LL); 00150 if(res_OPEN4.status != NFS4_OK) 00151 return res_OPEN4.status; 00152 00153 /* This can't be done on the pseudofs */ 00154 if(nfs4_Is_Fh_Pseudo(&(data->currentFH))) 00155 { 00156 res_OPEN4.status = NFS4ERR_ROFS; 00157 LogDebug(COMPONENT_STATE, 00158 "NFS4 OPEN returning NFS4ERR_ROFS"); 00159 return res_OPEN4.status; 00160 } 00161 00162 if (nfs_export_check_security(data->reqp, data->pexport) == FALSE) 00163 { 00164 res_OPEN4.status = NFS4ERR_PERM; 00165 return res_OPEN4.status; 00166 } 00167 00168 /* 00169 * If Filehandle points to a xattr object, manage it via the xattrs 00170 * specific functions 00171 */ 00172 if(nfs4_Is_Fh_Xattr(&(data->currentFH))) 00173 return nfs4_op_open_xattr(op, data, resp); 00174 00175 /* If data->current_entry is empty, repopulate it */ 00176 if(data->current_entry == NULL) 00177 { 00178 /* refcount +1 */ 00179 if((data->current_entry = nfs_FhandleToCache(NFS_V4, 00180 NULL, 00181 NULL, 00182 &(data->currentFH), 00183 NULL, 00184 NULL, 00185 &(res_OPEN4.status), 00186 &attr, 00187 data->pcontext, 00188 &retval)) == NULL) 00189 { 00190 res_OPEN4.status = NFS4ERR_RESOURCE; 00191 LogDebug(COMPONENT_STATE, 00192 "NFS4 OPEN returning NFS4ERR_RESOURCE after " 00193 "trying to repopulate cache"); 00194 return res_OPEN4.status; 00195 } 00196 } 00197 00198 if (claim == CLAIM_PREVIOUS) 00199 cause = "CLAIM_PREVIOUS"; 00200 else 00201 cause = "CLAIM_NULL"; 00202 00203 /* Set parent */ 00204 /* for CLAIM_PREVIOUS, currentFH is the file being reclaimed, not a dir */ 00205 pentry_parent = data->current_entry; 00206 00207 /* It this a known client id ? */ 00208 LogDebug(COMPONENT_STATE, 00209 "OPEN Client id = %llx", 00210 (unsigned long long)arg_OPEN4.owner.clientid); 00211 00212 if(nfs_client_id_get_confirmed(arg_OPEN4.owner.clientid, &pclientid) != 00213 CLIENT_ID_SUCCESS) 00214 { 00215 res_OPEN4.status = NFS4ERR_STALE_CLIENTID; 00216 cause2 = " (failed to find confirmed clientid)"; 00217 goto out3; 00218 } 00219 00220 /* Check if lease is expired and reserve it */ 00221 P(pclientid->cid_mutex); 00222 00223 if(!reserve_lease(pclientid)) 00224 { 00225 V(pclientid->cid_mutex); 00226 00227 dec_client_id_ref(pclientid); 00228 00229 res_OPEN4.status = NFS4ERR_EXPIRED; 00230 cause2 = " (clientid expired)"; 00231 goto out3; 00232 } 00233 00234 V(pclientid->cid_mutex); 00235 00236 if (arg_OPEN4.openhow.opentype == OPEN4_CREATE && claim != CLAIM_NULL) { 00237 res_OPEN4.status = NFS4ERR_INVAL; 00238 cause2 = " (create without claim type null)"; 00239 goto out2; 00240 } 00241 00242 /* Is this open_owner known? If so, get it so we can use replay cache */ 00243 convert_nfs4_open_owner(&arg_OPEN4.owner, &owner_name, 0LL); 00244 00245 if(!nfs4_owner_Get_Pointer(&owner_name, &powner)) 00246 { 00247 LogFullDebug(COMPONENT_STATE, "OPEN new owner"); 00248 } 00249 else 00250 { 00251 if(isFullDebug(COMPONENT_STATE)) 00252 { 00253 char str[HASHTABLE_DISPLAY_STRLEN]; 00254 00255 display_nfs4_owner(powner, str); 00256 00257 LogFullDebug(COMPONENT_STATE, 00258 "A previously known open_owner is used:%p %s arg_OPEN4.seqid=%u", 00259 powner, str, arg_OPEN4.seqid); 00260 } 00261 00262 if(arg_OPEN4.seqid == 0) 00263 { 00264 LogDebug(COMPONENT_STATE, 00265 "Previously known open_owner is used with seqid=0, ask the client to confirm it again"); 00266 powner->so_owner.so_nfs4_owner.so_confirmed = FALSE; 00267 } 00268 else 00269 { 00270 /* Check for replay */ 00271 if(!Check_nfs4_seqid(powner, arg_OPEN4.seqid, op, data, resp, tag)) 00272 { 00273 /* Response is setup for us and LogDebug told what was wrong */ 00274 goto out2; 00275 } 00276 } 00277 } 00278 /* Is this open_owner known ? */ 00279 if(powner == NULL) 00280 { 00281 /* This open owner is not known yet, allocated and set up a new one */ 00282 powner = create_nfs4_owner(&owner_name, 00283 pclientid, 00284 STATE_OPEN_OWNER_NFSV4, 00285 NULL, 00286 0); 00287 00288 if(powner == NULL) 00289 { 00290 res_OPEN4.status = NFS4ERR_RESOURCE; 00291 LogDebug(COMPONENT_STATE, 00292 "NFS4 OPEN returning NFS4ERR_RESOURCE for CLAIM_NULL (could not create NFS4 Owner"); 00293 dec_client_id_ref(pclientid); 00294 return res_OPEN4.status; 00295 } 00296 } 00297 00298 if (nfs_in_grace() && claim != CLAIM_PREVIOUS) 00299 { 00300 cause2 = " (in grace period)"; 00301 res_OPEN4.status = NFS4ERR_GRACE; 00302 goto out; 00303 } 00304 if (nfs_in_grace() && claim == CLAIM_PREVIOUS && 00305 pclientid->cid_allow_reclaim != 1) 00306 { 00307 cause2 = " (client cannot reclaim)"; 00308 res_OPEN4.status = NFS4ERR_NO_GRACE; 00309 goto out; 00310 } 00311 if (!nfs_in_grace() && claim == CLAIM_PREVIOUS) 00312 { 00313 cause2 = " (not in grace period)"; 00314 res_OPEN4.status = NFS4ERR_NO_GRACE; 00315 goto out; 00316 } 00317 00318 /* 00319 * check if share_access does not have any access set, or has invalid bits 00320 * that are set. check that share_deny doesn't have any invalid bits set. 00321 */ 00322 if (!(arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_BOTH) || 00323 (arg_OPEN4.share_access & ~OPEN4_SHARE_ACCESS_BOTH) || 00324 (arg_OPEN4.share_deny & ~OPEN4_SHARE_DENY_BOTH)) 00325 { 00326 res_OPEN4.status = NFS4ERR_INVAL; 00327 cause2 = " (invalid share_access or share_deny)"; 00328 goto out; 00329 } 00330 00331 /* Set openflags. */ 00332 if(arg_OPEN4.share_access == OPEN4_SHARE_ACCESS_BOTH) 00333 openflags = FSAL_O_RDWR; 00334 else if(arg_OPEN4.share_access == OPEN4_SHARE_ACCESS_READ) 00335 openflags = FSAL_O_RDONLY; 00336 else if(arg_OPEN4.share_access == OPEN4_SHARE_ACCESS_WRITE) 00337 openflags = FSAL_O_WRONLY; 00338 00339 /* First switch is based upon claim type */ 00340 switch (claim) 00341 { 00342 case CLAIM_NULL: 00343 /* Check for name length */ 00344 if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN) 00345 { 00346 res_OPEN4.status = NFS4ERR_NAMETOOLONG; 00347 goto out; 00348 } 00349 00350 /* get the filename from the argument, it should not be empty */ 00351 if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0) 00352 { 00353 res_OPEN4.status = NFS4ERR_INVAL; 00354 cause2 = " (empty filename)"; 00355 goto out; 00356 } 00357 00358 /* Check if asked attributes are correct */ 00359 if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 || 00360 arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4) 00361 { 00362 if(!nfs4_Fattr_Supported 00363 (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs)) 00364 { 00365 res_OPEN4.status = NFS4ERR_ATTRNOTSUPP; 00366 goto out; 00367 } 00368 00369 /* Do not use READ attr, use WRITE attr */ 00370 if(!nfs4_Fattr_Check_Access 00371 (&arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs, 00372 FATTR4_ATTR_WRITE)) 00373 { 00374 res_OPEN4.status = NFS4ERR_INVAL; 00375 cause2 = " (bad attr)"; 00376 goto out; 00377 } 00378 } 00379 00380 /* Check if filename is correct */ 00381 if((cache_status = 00382 cache_inode_error_convert(FSAL_buffdesc2name 00383 ((fsal_buffdesc_t *) & arg_OPEN4.claim.open_claim4_u. 00384 file, &filename))) != CACHE_INODE_SUCCESS) 00385 { 00386 res_OPEN4.status = nfs4_Errno(cache_status); 00387 cause2 = " FSAL_buffdesc2name"; 00388 goto out; 00389 } 00390 00391 /* Check parent */ 00392 pentry_parent = data->current_entry; 00393 00394 /* Parent must be a directory */ 00395 if((pentry_parent->type != DIRECTORY)) 00396 { 00397 /* Parent object is not a directory... */ 00398 if(pentry_parent->type == SYMBOLIC_LINK) 00399 res_OPEN4.status = NFS4ERR_SYMLINK; 00400 else 00401 res_OPEN4.status = NFS4ERR_NOTDIR; 00402 00403 cause2 = " (parent not directory)"; 00404 goto out; 00405 } 00406 00407 /* Status of parent directory before the operation */ 00408 if(cache_inode_getattr(pentry_parent, 00409 &attr_parent, 00410 data->pcontext, 00411 &cache_status) != CACHE_INODE_SUCCESS) 00412 { 00413 res_OPEN4.status = nfs4_Errno(cache_status); 00414 cause2 = " cache_inode_getattr"; 00415 goto out; 00416 } 00417 00418 res_OPEN4.OPEN4res_u.resok4.cinfo.before 00419 = cache_inode_get_changeid4(pentry_parent); 00420 00421 /* CLient may have provided fattr4 to set attributes at creation time */ 00422 if(arg_OPEN4.openhow.openflag4_u.how.mode == GUARDED4 || 00423 arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4) 00424 { 00425 if(arg_OPEN4.openhow.openflag4_u.how.createhow4_u.createattrs.attrmask. 00426 bitmap4_len != 0) 00427 { 00428 /* Convert fattr4 so nfs4_sattr */ 00429 res_OPEN4.status = 00430 nfs4_Fattr_To_FSAL_attr(&sattr, 00431 &(arg_OPEN4.openhow.openflag4_u.how. 00432 createhow4_u.createattrs)); 00433 00434 if(res_OPEN4.status != NFS4_OK) 00435 { 00436 cause2 = " (nfs4_Fattr_To_FSAL_attr failed)"; 00437 goto out; 00438 } 00439 00440 AttrProvided = TRUE; 00441 } 00442 } 00443 00444 /* Second switch is based upon "openhow" */ 00445 switch (arg_OPEN4.openhow.opentype) 00446 { 00447 case OPEN4_CREATE: 00448 /* a new file is to be created */ 00449 #ifdef _USE_QUOTA 00450 /* if quota support is active, then we should check is the FSAL allows inode creation or not */ 00451 fsal_status = FSAL_check_quota( data->pexport->fullpath, 00452 FSAL_QUOTA_INODES, 00453 FSAL_OP_CONTEXT_TO_UID( data->pcontext ) ) ; 00454 if( FSAL_IS_ERROR( fsal_status ) ) 00455 { 00456 res_OPEN4.status = NFS4ERR_DQUOT ; 00457 dec_client_id_ref(pclientid); 00458 return res_OPEN4.status; 00459 } 00460 #endif /* _USE_QUOTA */ 00461 00462 if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4) 00463 cause = "OPEN4_CREATE EXCLUSIVE"; 00464 else 00465 cause = "OPEN4_CREATE"; 00466 00467 /* Does a file with this name already exist ? */ 00468 pentry_lookup = cache_inode_lookup(pentry_parent, 00469 &filename, 00470 &attr_newfile, 00471 data->pcontext, 00472 &cache_status); 00473 if(cache_status != CACHE_INODE_NOT_FOUND) 00474 { 00475 /* if open is UNCHECKED, return NFS4_OK (RFC3530 page 172) */ 00476 if(arg_OPEN4.openhow.openflag4_u.how.mode == UNCHECKED4 00477 && (cache_status == CACHE_INODE_SUCCESS)) 00478 { 00479 00480 /* 00481 * we are not creating the file, attributes on recreate 00482 * should be ignored except for size = 0. 00483 */ 00484 if (AttrProvided && (sattr.asked_attributes & FSAL_ATTR_SIZE) 00485 && (sattr.filesize == 0)) 00486 { 00487 sattr.asked_attributes = FSAL_ATTR_SIZE; 00488 } 00489 else 00490 { 00491 AttrProvided = FALSE; 00492 } 00493 pthread_rwlock_wrlock(&pentry_lookup->state_lock); 00494 status4 = nfs4_chk_shrdny(op, data, pentry_lookup, 00495 read_access, write_access, &openflags, AttrProvided, 00496 &sattr, resp); 00497 if (status4 != NFS4_OK) 00498 { 00499 pthread_rwlock_unlock(&pentry_lookup->state_lock); 00500 cause2 = " cache_inode_access"; 00501 res_OPEN4.status = status4; 00502 cache_inode_put(pentry_lookup); 00503 goto out; 00504 } 00505 00506 status4 = nfs4_do_open(op, data, pentry_lookup, pentry_parent, 00507 powner, &pfile_state, &filename, openflags, &text); 00508 pthread_rwlock_unlock(&pentry_lookup->state_lock); 00509 if (status4 != NFS4_OK) 00510 { 00511 cause2 = (const char *)text; 00512 res_OPEN4.status = status4; 00513 cache_inode_put(pentry_lookup); 00514 goto out; 00515 } 00516 00517 res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 3; 00518 if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val = 00519 gsh_calloc(res_OPEN4.OPEN4res_u.resok4.attrset. 00520 bitmap4_len, sizeof(uint32_t))) == NULL) 00521 { 00522 res_OPEN4.status = NFS4ERR_RESOURCE; 00523 res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 0; 00524 cause2 = " (allocation of bitmap failed)"; 00525 cache_inode_put(pentry_lookup); 00526 goto out; 00527 } 00528 00529 res_OPEN4.OPEN4res_u.resok4.cinfo.after 00530 = cache_inode_get_changeid4(pentry_parent); 00531 res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = FALSE; 00532 00533 /* No delegation */ 00534 res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type = 00535 OPEN_DELEGATE_NONE; 00536 00537 /* If server use OPEN_CONFIRM4, set the correct flag */ 00538 P(powner->so_mutex); 00539 if(powner->so_owner.so_nfs4_owner.so_confirmed == FALSE) 00540 { 00541 res_OPEN4.OPEN4res_u.resok4.rflags |= 00542 OPEN4_RESULT_CONFIRM | OPEN4_RESULT_LOCKTYPE_POSIX; 00543 } 00544 else 00545 { 00546 res_OPEN4.OPEN4res_u.resok4.rflags |= OPEN4_RESULT_LOCKTYPE_POSIX ; 00547 } 00548 V(powner->so_mutex); 00549 00550 if (data->current_entry) { 00551 cache_inode_put(data->current_entry); 00552 data->current_entry = NULL; 00553 } 00554 00555 status4 = nfs4_create_fh(data, pentry_lookup, &text); 00556 if(status4 != NFS4_OK) 00557 { 00558 cause2 = text; 00559 res_OPEN4.status = status4; 00560 goto out; 00561 } 00562 00563 data->current_entry = pentry_lookup; 00564 data->current_filetype = REGULAR_FILE; 00565 00566 /* regular exit */ 00567 goto out_success; 00568 } 00569 00570 /* if open is EXCLUSIVE, but verifier is the same, 00571 return NFS4_OK (RFC3530 page 173) */ 00572 if(arg_OPEN4.openhow.openflag4_u.how.mode == EXCLUSIVE4) 00573 { 00574 if((pentry_lookup != NULL) 00575 && (pentry_lookup->type == REGULAR_FILE)) 00576 { 00577 /* Acquire lock to enter critical section on 00578 this entry */ 00579 pthread_rwlock_rdlock(&pentry_lookup->state_lock); 00580 glist_for_each(glist, 00581 &pentry_lookup->state_list) 00582 { 00583 pstate_iterate = glist_entry(glist, state_t, 00584 state_list); 00585 00586 /* Check if open_owner is the same */ 00587 if((pstate_iterate->state_type == STATE_TYPE_SHARE) 00588 && !memcmp(arg_OPEN4.owner.owner.owner_val, 00589 pstate_iterate->state_powner 00590 ->so_owner_val, 00591 pstate_iterate->state_powner 00592 ->so_owner_len) 00593 && !memcmp(pstate_iterate->state_data.share. 00594 share_oexcl_verifier, 00595 arg_OPEN4.openhow.openflag4_u.how. 00596 createhow4_u.createverf, 00597 NFS4_VERIFIER_SIZE)) 00598 { 00599 00600 /* A former open EXCLUSIVE with same 00601 owner and verifier was found, resend 00602 it */ 00603 00604 memset(&(res_OPEN4.OPEN4res_u.resok4 00605 .cinfo.after), 0, sizeof(changeid4)); 00606 res_OPEN4.OPEN4res_u.resok4.cinfo.after = 00607 cache_inode_get_changeid4(pentry_parent); 00608 res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = FALSE; 00609 00610 /* No delegation */ 00611 res_OPEN4.OPEN4res_u.resok4.delegation 00612 .delegation_type = OPEN_DELEGATE_NONE; 00613 00614 /* If server use OPEN_CONFIRM4, set the 00615 correct flag */ 00616 P(powner->so_mutex); 00617 if(powner->so_owner.so_nfs4_owner.so_confirmed 00618 == FALSE) 00619 { 00620 res_OPEN4.OPEN4res_u.resok4.rflags |= 00621 OPEN4_RESULT_CONFIRM | 00622 OPEN4_RESULT_LOCKTYPE_POSIX; 00623 } 00624 else 00625 { 00626 res_OPEN4.OPEN4res_u.resok4.rflags |= 00627 OPEN4_RESULT_LOCKTYPE_POSIX; 00628 } 00629 V(powner->so_mutex); 00630 00631 if (data->current_entry) { 00632 cache_inode_put(data->current_entry); 00633 data->current_entry = NULL; 00634 } 00635 00636 status4 = nfs4_create_fh(data, 00637 pentry_lookup, 00638 &text); 00639 if(status4 != NFS4_OK) 00640 { 00641 cause2 = text; 00642 res_OPEN4.status = status4; 00643 pthread_rwlock_unlock(&pentry_lookup 00644 ->state_lock); 00645 goto out; 00646 } 00647 00648 data->current_entry = pentry_lookup; 00649 data->current_filetype = REGULAR_FILE; 00650 00651 /* Avoid segfault during test OPEN4 00652 (pstate would be NULL) */ 00653 pfile_state = pstate_iterate; 00654 00655 /* regular exit */ 00656 pthread_rwlock_unlock(&pentry_lookup 00657 ->state_lock); 00658 goto out_success; 00659 } 00660 } 00661 pthread_rwlock_unlock(&pentry_lookup->state_lock); 00662 } 00663 } 00664 00665 /* Managing GUARDED4 mode */ 00666 if(cache_status != CACHE_INODE_SUCCESS) 00667 res_OPEN4.status = nfs4_Errno(cache_status); 00668 else 00669 res_OPEN4.status = NFS4ERR_EXIST; /* File already exists */ 00670 00671 cause2 = "GUARDED4"; 00672 cache_inode_put(pentry_lookup); 00673 goto out; 00674 } 00675 00676 LogFullDebug(COMPONENT_STATE, 00677 " OPEN open.how = %d", 00678 arg_OPEN4.openhow.openflag4_u.how.mode); 00679 00680 /* Create the file, if we reach this point, it does not 00681 exist, we can create it */ 00682 if((pentry_newfile 00683 = cache_inode_create(pentry_parent, 00684 &filename, 00685 REGULAR_FILE, 00686 mode, 00687 NULL, 00688 &attr_newfile, 00689 data->pcontext, 00690 &cache_status)) == NULL) 00691 { 00692 /* If the file already exists, this is not an error if 00693 open mode is UNCHECKED */ 00694 if(cache_status != CACHE_INODE_ENTRY_EXISTS) 00695 { 00696 res_OPEN4.status = nfs4_Errno(cache_status); 00697 cause2 = " UNCHECKED cache_inode_create"; 00698 goto out; 00699 } 00700 else 00701 { 00702 /* If this point is reached, then something has 00703 gone wrong. The only way cache_inode_create() 00704 returns NULL with CACHE_INODE_ENTRY_EXISTS 00705 is if the entry->type != REGULAR_FILE. */ 00706 res_OPEN4.status = NFS4ERR_EXIST; 00707 cause2 = " not a REGULAR file"; 00708 goto out; 00709 } 00710 } 00711 cache_status = CACHE_INODE_SUCCESS; 00712 00713 if(AttrProvided == TRUE) /* Set the attribute if provided */ 00714 { 00715 if((cache_status 00716 = cache_inode_setattr(pentry_newfile, 00717 &sattr, 00718 data->pcontext, 00719 &cache_status)) != 00720 CACHE_INODE_SUCCESS) 00721 { 00722 res_OPEN4.status = nfs4_Errno(cache_status); 00723 cause2 = " cache_inode_setattr"; 00724 cache_inode_put(pentry_newfile); 00725 goto out; 00726 } 00727 } 00728 00729 pthread_rwlock_wrlock(&pentry_newfile->state_lock); 00730 status4 = nfs4_do_open(op, data, pentry_newfile, pentry_parent, 00731 powner, &pfile_state, &filename, openflags, &text); 00732 pthread_rwlock_unlock(&pentry_newfile->state_lock); 00733 if (status4 != NFS4_OK) 00734 { 00735 cause2 = text; 00736 res_OPEN4.status = status4; 00737 cache_inode_put(pentry_newfile); 00738 goto out; 00739 } 00740 00741 break; 00742 00743 case OPEN4_NOCREATE: 00744 /* It was not a creation, but a regular open */ 00745 cause = "OPEN4_NOCREATE"; 00746 00747 /* Does a file with this name already exist ? */ 00748 if((pentry_newfile 00749 = cache_inode_lookup(pentry_parent, 00750 &filename, 00751 &attr_newfile, 00752 data->pcontext, 00753 &cache_status)) == NULL) 00754 { 00755 res_OPEN4.status = nfs4_Errno(cache_status); 00756 cause2 = " cache_inode_lookup"; 00757 goto out; 00758 } 00759 00760 /* OPEN4 is to be done on a file */ 00761 if(pentry_newfile->type != REGULAR_FILE) 00762 { 00763 cache_inode_put(pentry_newfile); 00764 if(pentry_newfile->type == DIRECTORY) 00765 { 00766 res_OPEN4.status = NFS4ERR_ISDIR; 00767 goto out; 00768 } 00769 else 00770 { 00771 res_OPEN4.status = NFS4ERR_SYMLINK; 00772 goto out; 00773 } 00774 } 00775 00776 status4 = nfs4_chk_shrdny(op, data, pentry_newfile, read_access, 00777 write_access, &openflags, FALSE, NULL, resp); 00778 if (status4 != NFS4_OK) 00779 { 00780 cause2 = " cache_inode_access"; 00781 res_OPEN4.status = status4; 00782 cache_inode_put(pentry_newfile); 00783 goto out; 00784 } 00785 00786 #ifdef WITH_MODE_0_CHECK 00787 /* If file mode is 000 then NFS4ERR_ACCESS should be 00788 returned for all cases and users */ 00789 if(attr_newfile.mode == 0) 00790 { 00791 res_OPEN4.status = NFS4ERR_ACCESS; 00792 cause2 = " (mode is 0)"; 00793 goto out; 00794 } 00795 #endif 00796 00797 pthread_rwlock_wrlock(&pentry_newfile->state_lock); 00798 /* Try to find if the same open_owner already has acquired a 00799 stateid for this file */ 00800 glist_for_each(glist, &pentry_newfile->state_list) 00801 { 00802 pstate_iterate = glist_entry(glist, state_t, state_list); 00803 00804 // TODO FSF: currently only care about share types 00805 if(pstate_iterate->state_type != STATE_TYPE_SHARE) 00806 continue; 00807 00808 /* Check is open_owner is the same */ 00809 if((pstate_iterate->state_powner->so_owner.so_nfs4_owner 00810 .so_clientid == arg_OPEN4.owner.clientid) && 00811 ((pstate_iterate->state_powner->so_owner_len == 00812 arg_OPEN4.owner.owner.owner_len) && 00813 (!memcmp(arg_OPEN4.owner.owner.owner_val, 00814 pstate_iterate->state_powner->so_owner_val, 00815 pstate_iterate->state_powner->so_owner_len)))) 00816 { 00817 /* We'll be re-using the found state */ 00818 pfile_state = pstate_iterate; 00819 ReuseState = TRUE; 00820 } 00821 else 00822 { 00823 /* This is a different owner, check for possible conflicts */ 00824 if((pstate_iterate->state_data.share.share_access & 00825 OPEN4_SHARE_ACCESS_WRITE) 00826 && (arg_OPEN4.share_deny & OPEN4_SHARE_DENY_WRITE)) 00827 { 00828 res_OPEN4.status = NFS4ERR_SHARE_DENIED; 00829 cause2 = " (OPEN4_SHARE_DENY_WRITE)"; 00830 pthread_rwlock_unlock(&pentry_newfile->state_lock); 00831 cache_inode_put(pentry_newfile); 00832 goto out; 00833 } 00834 } 00835 00836 /* In all cases opening in read access a read denied 00837 * file or write access to a write denied file should 00838 * fail, even if the owner is the same, see discussion 00839 * in 14.2.16 and 8.9 00840 */ 00841 00842 /* deny read access on read denied file */ 00843 if((pstate_iterate->state_data.share.share_deny & 00844 OPEN4_SHARE_DENY_READ) 00845 && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_READ)) 00846 { 00847 res_OPEN4.status = NFS4ERR_SHARE_DENIED; 00848 cause2 = " (OPEN4_SHARE_ACCESS_READ)"; 00849 pthread_rwlock_unlock(&pentry_newfile->state_lock); 00850 cache_inode_put(pentry_newfile); 00851 goto out; 00852 } 00853 00854 /* deny write access on write denied file */ 00855 if((pstate_iterate->state_data.share.share_deny & 00856 OPEN4_SHARE_DENY_WRITE) 00857 && (arg_OPEN4.share_access & OPEN4_SHARE_ACCESS_WRITE)) 00858 { 00859 res_OPEN4.status = NFS4ERR_SHARE_DENIED; 00860 cause2 = " (OPEN4_SHARE_ACCESS_WRITE)"; 00861 pthread_rwlock_unlock(&pentry_newfile->state_lock); 00862 cache_inode_put(pentry_newfile); 00863 goto out; 00864 } 00865 } 00866 00867 status4 = nfs4_do_open(op, data, pentry_newfile, pentry_parent, 00868 powner, &pfile_state, &filename, openflags, &text); 00869 pthread_rwlock_unlock(&pentry_newfile->state_lock); 00870 if (status4 != NFS4_OK) 00871 { 00872 cause2 = text; 00873 res_OPEN4.status = status4; 00874 cache_inode_put(pentry_newfile); 00875 goto out; 00876 } 00877 break; 00878 00879 default: 00880 cause = "INVALID OPEN TYPE"; 00881 res_OPEN4.status = NFS4ERR_INVAL; 00882 goto out; 00883 } 00884 00885 break; 00886 00887 case CLAIM_PREVIOUS: 00888 powner->so_owner.so_nfs4_owner.so_confirmed = TRUE; 00889 00890 /* pentry_parent is actually the file to be reclaimed, not the parent */ 00891 pentry_newfile = pentry_parent; 00892 pthread_rwlock_wrlock(&pentry_newfile->state_lock); 00893 status4 = nfs4_do_open(op, data, pentry_newfile, NULL, powner, 00894 &pfile_state, NULL, openflags, &text); 00895 pthread_rwlock_unlock(&pentry_newfile->state_lock); 00896 if (status4 != NFS4_OK) 00897 { 00898 cause2 = text; 00899 res_OPEN4.status = status4; 00900 goto out; 00901 } 00902 goto out_prev; 00903 00904 case CLAIM_DELEGATE_CUR: 00905 case CLAIM_DELEGATE_PREV: 00906 /* Check for name length */ 00907 if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len > FSAL_MAX_NAME_LEN) 00908 { 00909 res_OPEN4.status = NFS4ERR_NAMETOOLONG; 00910 LogDebug(COMPONENT_STATE, 00911 "NFS4 OPEN returning NFS4ERR_NAMETOOLONG " 00912 "for CLAIM_DELEGATE"); 00913 dec_client_id_ref(pclientid); 00914 return res_OPEN4.status; 00915 } 00916 00917 /* get the filename from the argument, it should not be empty */ 00918 if(arg_OPEN4.claim.open_claim4_u.file.utf8string_len == 0) 00919 { 00920 res_OPEN4.status = NFS4ERR_INVAL; 00921 LogDebug(COMPONENT_STATE, 00922 "NFS4 OPEN returning NFS4ERR_INVAL for CLAIM_DELEGATE"); 00923 dec_client_id_ref(pclientid); 00924 return res_OPEN4.status; 00925 } 00926 00927 res_OPEN4.status = NFS4ERR_NOTSUPP; 00928 LogDebug(COMPONENT_STATE, 00929 "NFS4 OPEN returning NFS4ERR_NOTSUPP for CLAIM_DELEGATE"); 00930 dec_client_id_ref(pclientid); 00931 return res_OPEN4.status; 00932 00933 default: 00934 /* Invalid claim type */ 00935 cause = "INVALID CLAIM"; 00936 res_OPEN4.status = NFS4ERR_INVAL; 00937 goto out; 00938 } /* switch( arg_OPEN4.claim.claim ) */ 00939 00940 /* Decrement the current entry here, because nfs4_create_fh 00941 replaces the current fh. */ 00942 if (data->current_entry) { 00943 cache_inode_put(data->current_entry); 00944 data->current_entry = NULL; 00945 } 00946 status4 = nfs4_create_fh(data, pentry_newfile, &text); 00947 if(status4 != NFS4_OK) 00948 { 00949 cause2 = text; 00950 res_OPEN4.status = status4; 00951 goto out; 00952 } 00953 00954 /* Status of parent directory after the operation */ 00955 if((cache_status = cache_inode_getattr(pentry_parent, 00956 &attr_parent, 00957 data->pcontext, 00958 &cache_status)) 00959 != CACHE_INODE_SUCCESS) 00960 { 00961 res_OPEN4.status = nfs4_Errno(cache_status); 00962 cause2 = " cache_inode_getattr"; 00963 goto out; 00964 } 00965 00966 out_prev: 00967 00968 res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 3; 00969 if((res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_val = 00970 gsh_calloc(res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len, 00971 sizeof(uint32_t))) == NULL) 00972 { 00973 res_OPEN4.status = NFS4ERR_SERVERFAULT; 00974 res_OPEN4.OPEN4res_u.resok4.attrset.bitmap4_len = 0; 00975 cause2 = " (allocation of attr failed)"; 00976 goto out; 00977 } 00978 00979 if(arg_OPEN4.openhow.opentype == OPEN4_CREATE) 00980 { 00981 tmp_attr[0] = FATTR4_SIZE; 00982 tmp_attr[1] = FATTR4_MODE; 00983 nfs4_list_to_bitmap4(&(res_OPEN4.OPEN4res_u.resok4.attrset), 2, tmp_attr); 00984 } 00985 00986 res_OPEN4.OPEN4res_u.resok4.cinfo.after 00987 = cache_inode_get_changeid4(pentry_parent); 00988 res_OPEN4.OPEN4res_u.resok4.cinfo.atomic = FALSE; 00989 00990 /* No delegation */ 00991 res_OPEN4.OPEN4res_u.resok4.delegation.delegation_type |= OPEN_DELEGATE_NONE; 00992 00993 /* If server use OPEN_CONFIRM4, set the correct flag */ 00994 if(powner->so_owner.so_nfs4_owner.so_confirmed == FALSE) 00995 { 00996 res_OPEN4.OPEN4res_u.resok4.rflags |= 00997 OPEN4_RESULT_CONFIRM | OPEN4_RESULT_LOCKTYPE_POSIX; 00998 } 00999 else 01000 { 01001 res_OPEN4.OPEN4res_u.resok4.rflags |= OPEN4_RESULT_LOCKTYPE_POSIX ; 01002 } 01003 01004 out_success: 01005 01006 LogFullDebug(COMPONENT_STATE, "NFS4 OPEN returning NFS4_OK"); 01007 01008 /* regular exit */ 01009 res_OPEN4.status = NFS4_OK; 01010 01011 /* Handle stateid/seqid for success */ 01012 update_stateid(pfile_state, 01013 &res_OPEN4.OPEN4res_u.resok4.stateid, 01014 data, 01015 tag); 01016 01017 /* If we are re-using stateid, then release extra reference to open owner */ 01018 if(ReuseState) 01019 dec_state_owner_ref(powner); 01020 01021 out: 01022 01023 /* Save the response in the lock or open owner */ 01024 Copy_nfs4_state_req(powner, arg_OPEN4.seqid, op, data, resp, tag); 01025 01026 out2: 01027 01028 /* Update the lease before exit */ 01029 P(pclientid->cid_mutex); 01030 01031 update_lease(pclientid); 01032 01033 V(pclientid->cid_mutex); 01034 01035 dec_client_id_ref(pclientid); 01036 01037 out3: 01038 01039 if(res_OPEN4.status != NFS4_OK) 01040 { 01041 const char *cause3 = "", *cause4 = ""; 01042 01043 if(cache_status != CACHE_INODE_SUCCESS) 01044 { 01045 cause3 = " returned "; 01046 cause4 = cache_inode_err_str(cache_status); 01047 } 01048 01049 LogDebug(COMPONENT_STATE, 01050 "NFS4 OPEN returning %s for %s%s%s%s", 01051 nfsstat4_to_str(res_OPEN4.status), 01052 cause, cause2, cause3, cause4); 01053 01054 /* Clean up if we have an error exit */ 01055 if(pfile_state != NULL && !ReuseState) 01056 { 01057 /* Need to destroy open owner and state */ 01058 if(state_del(pfile_state, 01059 &state_status) != STATE_SUCCESS) 01060 LogDebug(COMPONENT_NFS_V4_LOCK, 01061 "state_del failed with status %s", 01062 state_err_str(state_status)); 01063 } 01064 else if(powner != NULL) 01065 { 01066 /* Need to release the open owner */ 01067 dec_state_owner_ref(powner); 01068 } 01069 } 01070 01071 return res_OPEN4.status; 01072 } /* nfs4_op_open */ 01073 01084 void nfs4_op_open_Free(OPEN4res * resp) 01085 { 01086 if(resp->OPEN4res_u.resok4.attrset.bitmap4_val != NULL) 01087 gsh_free(resp->OPEN4res_u.resok4.attrset.bitmap4_val); 01088 resp->OPEN4res_u.resok4.attrset.bitmap4_len = 0; 01089 } /* nfs4_op_open_Free */ 01090 01091 void nfs4_op_open_CopyRes(OPEN4res * resp_dst, OPEN4res * resp_src) 01092 { 01093 if(resp_src->OPEN4res_u.resok4.attrset.bitmap4_val != NULL) 01094 { 01095 if((resp_dst->OPEN4res_u.resok4.attrset.bitmap4_val = 01096 gsh_calloc(resp_dst->OPEN4res_u.resok4.attrset.bitmap4_len, 01097 sizeof(uint32_t))) == NULL) 01098 { 01099 resp_dst->OPEN4res_u.resok4.attrset.bitmap4_len = 0; 01100 } 01101 } 01102 } 01103 01104 static nfsstat4 01105 nfs4_chk_shrdny(struct nfs_argop4 *op, compound_data_t *data, 01106 cache_entry_t *pentry, fsal_accessflags_t rd_acc, 01107 fsal_accessflags_t wr_acc, fsal_openflags_t *openflags, 01108 bool_t AttrProvided, fsal_attrib_list_t *sattr, struct nfs_resop4 *resop) 01109 { 01110 OPEN4args *args = &op->nfs_argop4_u.opopen; 01111 OPEN4res *resp = &resop->nfs_resop4_u.opopen; 01112 cache_inode_status_t cache_status = CACHE_INODE_SUCCESS; 01113 01114 /* If the file is opened for write, OPEN4 while deny share 01115 * write access, in this case, check caller has write access 01116 * to the file */ 01117 if(args->share_deny & OPEN4_SHARE_DENY_WRITE) { 01118 if(cache_inode_access(pentry, wr_acc, 01119 data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) { 01120 return NFS4ERR_ACCESS; 01121 } 01122 } 01123 01124 /* Same check on read: check for readability of a file before opening 01125 * it for read */ 01126 if(args->share_access & OPEN4_SHARE_ACCESS_READ) { 01127 if(cache_inode_access(pentry, rd_acc, 01128 data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) { 01129 return NFS4ERR_ACCESS; 01130 } 01131 } 01132 01133 if(AttrProvided == TRUE) { /* Set the attribute if provided */ 01134 if(cache_inode_setattr(pentry, sattr, 01135 data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) { 01136 return nfs4_Errno(cache_status); 01137 } 01138 01139 resp->OPEN4res_u.resok4.attrset = 01140 args->openhow.openflag4_u.how.createhow4_u.createattrs. 01141 attrmask; 01142 } 01143 else 01144 resp->OPEN4res_u.resok4.attrset.bitmap4_len = 0; 01145 01146 /* Same check on write */ 01147 if(args->share_access & OPEN4_SHARE_ACCESS_WRITE) { 01148 if(cache_inode_access(pentry, wr_acc, 01149 data->pcontext, &cache_status) != CACHE_INODE_SUCCESS) { 01150 return NFS4ERR_ACCESS; 01151 } 01152 } 01153 01154 return NFS4_OK; 01155 } 01156 01157 static nfsstat4 nfs4_do_open(struct nfs_argop4 * op, 01158 compound_data_t * data, 01159 cache_entry_t * pentry_newfile, 01160 cache_entry_t * pentry_parent, 01161 state_owner_t * powner, 01162 state_t ** statep, 01163 fsal_name_t * filename, 01164 fsal_openflags_t openflags, 01165 char ** cause2) 01166 { 01167 OPEN4args *args = &op->nfs_argop4_u.opopen; 01168 state_data_t candidate_data; 01169 state_type_t candidate_type; 01170 state_status_t state_status; 01171 cache_inode_status_t cache_status = CACHE_INODE_SUCCESS; 01172 int new_state = 0; 01173 01174 /* Set the state for the related file */ 01175 /* Prepare state management structure */ 01176 candidate_type = STATE_TYPE_SHARE; 01177 candidate_data.share.share_access = args->share_access; 01178 candidate_data.share.share_deny = args->share_deny; 01179 candidate_data.share.share_access_prev = 0; 01180 candidate_data.share.share_deny_prev = 0; 01181 01182 /* Quick exit if there is any share conflict */ 01183 if(state_share_check_conflict(pentry_newfile, 01184 candidate_data.share.share_access, 01185 candidate_data.share.share_deny, 01186 &state_status) != STATE_SUCCESS) 01187 { 01188 *cause2 = " (share conflict)"; 01189 return nfs4_Errno_state(state_status); 01190 } 01191 01192 if(*statep == NULL) { 01193 new_state = 1; 01194 01195 /* If file is opened under mode EXCLUSIVE4, open verifier 01196 * should be kept to detect non vicious double open */ 01197 if(args->openhow.openflag4_u.how.mode == EXCLUSIVE4) { 01198 strncpy(candidate_data.share.share_oexcl_verifier, 01199 args->openhow.openflag4_u.how.createhow4_u.createverf, 01200 NFS4_VERIFIER_SIZE); 01201 } 01202 01203 if(state_add_impl(pentry_newfile, candidate_type, &candidate_data, 01204 powner, data->pcontext, statep, 01205 &state_status) != STATE_SUCCESS) { 01206 *cause2 = STATE_ADD; 01207 return nfs4_Errno_state(state_status); 01208 } 01209 01210 init_glist(&((*statep)->state_data.share.share_lockstates)); 01211 01212 /* Attach this open to an export */ 01213 (*statep)->state_pexport = data->pexport; 01214 P(data->pexport->exp_state_mutex); 01215 glist_add_tail(&data->pexport->exp_state_list, 01216 &(*statep)->state_export_list); 01217 V(data->pexport->exp_state_mutex); 01218 } else { 01219 /* Check if open from another export */ 01220 if((*statep)->state_pexport != data->pexport) 01221 { 01222 LogEvent(COMPONENT_STATE, 01223 "Lock Owner Export Conflict, Lock held for export %d (%s), request for export %d (%s)", 01224 (*statep)->state_pexport->id, 01225 (*statep)->state_pexport->fullpath, 01226 data->pexport->id, 01227 data->pexport->fullpath); 01228 return STATE_INVALID_ARGUMENT; 01229 } 01230 } 01231 01232 if (pentry_parent != NULL) { /* claim null */ 01233 /* Open the file */ 01234 if(cache_inode_open(pentry_newfile, openflags, data->pcontext, 01235 0, &cache_status) != CACHE_INODE_SUCCESS) { 01236 *cause2 = " cache_inode_open"; 01237 return NFS4ERR_ACCESS; 01238 } 01239 } else { /* claim previous */ 01240 if (cache_inode_open(pentry_newfile, openflags, 01241 data->pcontext, 0, &cache_status) != CACHE_INODE_SUCCESS) { 01242 *cause2 = CACHE_INODE_OPEN; 01243 return nfs4_Errno(cache_status); 01244 } 01245 } 01246 01247 /* Push share state to SAL (and FSAL) and update the union of file 01248 * share state. 01249 */ 01250 if(new_state) 01251 { 01252 if(state_share_add(pentry_newfile, data->pcontext, powner, *statep, 01253 &state_status) != STATE_SUCCESS) 01254 { 01255 if(cache_inode_close(pentry_newfile, 01256 0, &cache_status) != CACHE_INODE_SUCCESS) 01257 { 01258 /* Log bad close and continue. */ 01259 LogEvent(COMPONENT_STATE, "Failed to close cache inode: status=%d", 01260 cache_status); 01261 } 01262 *cause2 = STATE_SHARE_ADD; 01263 return nfs4_Errno_state(state_status); 01264 } 01265 } 01266 else 01267 { 01268 /* If we find the previous share state, update share state. */ 01269 if((candidate_type == STATE_TYPE_SHARE) && 01270 ((*statep)->state_type == STATE_TYPE_SHARE)) 01271 { 01272 LogFullDebug(COMPONENT_STATE, "Update existing share state"); 01273 if(state_share_upgrade(pentry_newfile, data->pcontext, 01274 &candidate_data, powner, *statep, 01275 &state_status) != STATE_SUCCESS) 01276 { 01277 if(cache_inode_close(pentry_newfile, 01278 0, &cache_status) != CACHE_INODE_SUCCESS) 01279 { 01280 /* Log bad close and continue. */ 01281 LogEvent(COMPONENT_STATE, "Failed to close cache inode: status=%d", 01282 cache_status); 01283 } 01284 LogEvent(COMPONENT_STATE, "Failed to update existing " 01285 "share state"); 01286 *cause2 = STATE_SHARE_UP; 01287 return nfs4_Errno_state(state_status); 01288 } 01289 } 01290 } 01291 01292 return NFS4_OK; 01293 } 01294 01295 static nfsstat4 01296 nfs4_create_fh(compound_data_t *data, cache_entry_t *pentry, char **cause2) 01297 { 01298 fsal_handle_t *pnewfsal_handle = NULL; 01299 nfs_fh4 newfh4; 01300 struct alloc_file_handle_v4 new_handle; 01301 01302 newfh4.nfs_fh4_val = (caddr_t) &new_handle; 01303 newfh4.nfs_fh4_len = sizeof(struct alloc_file_handle_v4); 01304 01305 /* Now produce the filehandle to this file */ 01306 pnewfsal_handle = &pentry->handle; 01307 01308 /* Building a new fh */ 01309 if(!nfs4_FSALToFhandle(&newfh4, pnewfsal_handle, data)) { 01310 *cause2 = " (nfs4_FSALToFhandle failed)"; 01311 cache_inode_put(pentry); 01312 return NFS4ERR_SERVERFAULT; 01313 } 01314 01315 /* This new fh replaces the current FH */ 01316 data->currentFH.nfs_fh4_len = newfh4.nfs_fh4_len; 01317 memcpy(data->currentFH.nfs_fh4_val, newfh4.nfs_fh4_val, 01318 newfh4.nfs_fh4_len); 01319 01320 data->current_entry = pentry; 01321 data->current_filetype = REGULAR_FILE; 01322 01323 return NFS4_OK; 01324 }