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 /* _SOLARIS */ 00044 00045 #include <unistd.h> 00046 #include <sys/types.h> 00047 #include <sys/param.h> 00048 #include <time.h> 00049 #include <pthread.h> 00050 #include <string.h> 00051 #include <assert.h> 00052 00053 #include "fsal.h" 00054 #include "nfs_core.h" 00055 #include "nfs4.h" 00056 #include "sal_functions.h" 00057 #ifdef _USE_NLM 00058 #include "nlm_util.h" 00059 #endif 00060 #include "cache_inode_lru.h" 00061 00062 /* Update the ref counter of share state of given file. */ 00063 static void state_share_update_counter(cache_entry_t * pentry, 00064 int old_access, 00065 int old_deny, 00066 int new_access, 00067 int new_deny, 00068 bool_t v4); 00069 00070 /* Calculate the union of share access of given file. */ 00071 static unsigned int state_share_get_share_access(cache_entry_t * pentry); 00072 00073 /* Calculate the union of share deny of given file. */ 00074 static unsigned int state_share_get_share_deny(cache_entry_t * pentry); 00075 00076 /* Push share state down to FSAL. Only the union of share states should be 00077 * passed to this function. 00078 */ 00079 static state_status_t do_share_op(cache_entry_t * pentry, 00080 fsal_op_context_t * pcontext, 00081 state_owner_t * powner, 00082 fsal_share_param_t * pshare) 00083 { 00084 fsal_status_t fsal_status; 00085 state_status_t status = STATE_SUCCESS; 00086 fsal_staticfsinfo_t * pstatic = pcontext->export_context->fe_static_fs_info; 00087 00088 /* Quick exit if share reservation is not supported by FSAL */ 00089 if(!pstatic->share_support) 00090 return STATE_SUCCESS; 00091 00092 fsal_status = FSAL_share_op(cache_inode_fd(pentry), 00093 &pentry->handle, 00094 pcontext, 00095 NULL, 00096 *pshare); 00097 00098 status = state_error_convert(fsal_status); 00099 00100 LogFullDebug(COMPONENT_STATE, 00101 "FSAL_share_op returned %s", 00102 state_err_str(status)); 00103 00104 return status; 00105 } 00106 00107 /* This is called when new share state is added. The state lock MUST 00108 be held. */ 00109 state_status_t state_share_add(cache_entry_t * pentry, 00110 fsal_op_context_t * pcontext, 00111 state_owner_t * powner, 00112 state_t * pstate, /* state that holds share bits to be added */ 00113 state_status_t * pstatus) 00114 { 00115 state_status_t status = STATE_SUCCESS; 00116 unsigned int old_pentry_share_access = 0; 00117 unsigned int old_pentry_share_deny = 0; 00118 unsigned int new_pentry_share_access = 0; 00119 unsigned int new_pentry_share_deny = 0; 00120 unsigned int new_share_access = 0; 00121 unsigned int new_share_deny = 0; 00122 fsal_share_param_t share_param; 00123 00124 /* Check if new share state has conflicts. */ 00125 status = state_share_check_conflict(pentry, 00126 pstate->state_data.share.share_access, 00127 pstate->state_data.share.share_deny, 00128 pstatus); 00129 if(status != STATE_SUCCESS) 00130 { 00131 LogEvent(COMPONENT_STATE, "Share conflicts detected during add"); 00132 *pstatus = STATE_STATE_CONFLICT; 00133 return *pstatus; 00134 } 00135 00136 /* Get the current union of share states of this file. */ 00137 old_pentry_share_access = state_share_get_share_access(pentry); 00138 old_pentry_share_deny = state_share_get_share_deny(pentry); 00139 00140 /* Share state to be added. */ 00141 new_share_access = pstate->state_data.share.share_access; 00142 new_share_deny = pstate->state_data.share.share_deny; 00143 00144 /* Update the ref counted share state of this file. */ 00145 state_share_update_counter(pentry, 00146 OPEN4_SHARE_ACCESS_NONE, 00147 OPEN4_SHARE_DENY_NONE, 00148 new_share_access, 00149 new_share_deny, 00150 TRUE); 00151 00152 /* Get the updated union of share states of this file. */ 00153 new_pentry_share_access = state_share_get_share_access(pentry); 00154 new_pentry_share_deny = state_share_get_share_deny(pentry); 00155 00156 /* If this file's share bits are different from the supposed value, update 00157 * it. 00158 */ 00159 if((new_pentry_share_access != old_pentry_share_access) || 00160 (new_pentry_share_deny != old_pentry_share_deny)) 00161 { 00162 /* Try to push to FSAL. */ 00163 share_param.share_access = new_pentry_share_access; 00164 share_param.share_deny = new_pentry_share_deny; 00165 00166 status = do_share_op(pentry, pcontext, powner, &share_param); 00167 if(status != STATE_SUCCESS) 00168 { 00169 /* Revert the ref counted share state of this file. */ 00170 state_share_update_counter(pentry, 00171 new_share_access, 00172 new_share_deny, 00173 OPEN4_SHARE_ACCESS_NONE, 00174 OPEN4_SHARE_DENY_NONE, 00175 TRUE); 00176 LogDebug(COMPONENT_STATE, "do_share_op failed"); 00177 *pstatus = status; 00178 return *pstatus; 00179 } 00180 } 00181 00182 LogFullDebug(COMPONENT_STATE, "pstate %p: added share_access %u, " 00183 "share_deny %u", 00184 pstate, new_share_access, new_share_deny); 00185 00186 /* Update previously seen share state in the bitmap. */ 00187 state_share_set_prev(pstate, &(pstate->state_data)); 00188 00189 return status; 00190 } 00191 00192 /* This is called when a share state is removed. The state lock MUST 00193 be held. */ 00194 state_status_t state_share_remove(cache_entry_t * pentry, 00195 fsal_op_context_t * pcontext, 00196 state_owner_t * powner, 00197 state_t * pstate, /* state that holds share bits to be removed */ 00198 state_status_t * pstatus) 00199 { 00200 state_status_t status = STATE_SUCCESS; 00201 unsigned int old_pentry_share_access = 0; 00202 unsigned int old_pentry_share_deny = 0; 00203 unsigned int new_pentry_share_access = 0; 00204 unsigned int new_pentry_share_deny = 0; 00205 unsigned int removed_share_access = 0; 00206 unsigned int removed_share_deny = 0; 00207 fsal_share_param_t share_param; 00208 00209 /* Get the current union of share states of this file. */ 00210 old_pentry_share_access = state_share_get_share_access(pentry); 00211 old_pentry_share_deny = state_share_get_share_deny(pentry); 00212 00213 /* Share state to be removed. */ 00214 removed_share_access = pstate->state_data.share.share_access; 00215 removed_share_deny = pstate->state_data.share.share_deny; 00216 00217 /* Update the ref counted share state of this file. */ 00218 state_share_update_counter(pentry, 00219 removed_share_access, 00220 removed_share_deny, 00221 OPEN4_SHARE_ACCESS_NONE, 00222 OPEN4_SHARE_DENY_NONE, 00223 TRUE); 00224 00225 /* Get the updated union of share states of this file. */ 00226 new_pentry_share_access = state_share_get_share_access(pentry); 00227 new_pentry_share_deny = state_share_get_share_deny(pentry); 00228 00229 /* If this file's share bits are different from the supposed value, update 00230 * it. 00231 */ 00232 if((new_pentry_share_access != old_pentry_share_access) || 00233 (new_pentry_share_deny != old_pentry_share_deny)) 00234 { 00235 /* Try to push to FSAL. */ 00236 share_param.share_access = new_pentry_share_access; 00237 share_param.share_deny = new_pentry_share_deny; 00238 00239 status = do_share_op(pentry, pcontext, powner, &share_param); 00240 if(status != STATE_SUCCESS) 00241 { 00242 /* Revert the ref counted share state of this file. */ 00243 state_share_update_counter(pentry, 00244 OPEN4_SHARE_ACCESS_NONE, 00245 OPEN4_SHARE_DENY_NONE, 00246 removed_share_access, 00247 removed_share_deny, 00248 TRUE); 00249 LogDebug(COMPONENT_STATE, "do_share_op failed"); 00250 *pstatus = status; 00251 return *pstatus; 00252 } 00253 } 00254 00255 LogFullDebug(COMPONENT_STATE, "pstate %p: removed share_access %u, " 00256 "share_deny %u", 00257 pstate, 00258 removed_share_access, 00259 removed_share_deny); 00260 00261 return status; 00262 } 00263 00264 /* This is called when share state is upgraded during open. The 00265 state ock MUST be held. */ 00266 state_status_t state_share_upgrade(cache_entry_t * pentry, 00267 fsal_op_context_t * pcontext, 00268 state_data_t * pstate_data, /* new share bits */ 00269 state_owner_t * powner, 00270 state_t * pstate, /* state that holds current share bits */ 00271 state_status_t * pstatus) 00272 { 00273 state_status_t status = STATE_SUCCESS; 00274 unsigned int old_pentry_share_access = 0; 00275 unsigned int old_pentry_share_deny = 0; 00276 unsigned int new_pentry_share_access = 0; 00277 unsigned int new_pentry_share_deny = 0; 00278 unsigned int old_share_access = 0; 00279 unsigned int old_share_deny = 0; 00280 unsigned int new_share_access = 0; 00281 unsigned int new_share_deny = 0; 00282 fsal_share_param_t share_param; 00283 00284 /* Check if new share state has conflicts. */ 00285 status = state_share_check_conflict(pentry, 00286 pstate_data->share.share_access, 00287 pstate_data->share.share_deny, 00288 pstatus); 00289 if(status != STATE_SUCCESS) 00290 { 00291 LogEvent(COMPONENT_STATE, "Share conflicts detected during upgrade"); 00292 *pstatus = STATE_STATE_CONFLICT; 00293 return *pstatus; 00294 } 00295 00296 /* Get the current union of share states of this file. */ 00297 old_pentry_share_access = state_share_get_share_access(pentry); 00298 old_pentry_share_deny = state_share_get_share_deny(pentry); 00299 00300 /* Old share state. */ 00301 old_share_access = pstate->state_data.share.share_access; 00302 old_share_deny = pstate->state_data.share.share_deny; 00303 00304 /* New share state. */ 00305 new_share_access = pstate_data->share.share_access; 00306 new_share_deny = pstate_data->share.share_deny; 00307 00308 /* Update the ref counted share state of this file. */ 00309 state_share_update_counter(pentry, 00310 old_share_access, 00311 old_share_deny, 00312 new_share_access, 00313 new_share_deny, 00314 TRUE); 00315 00316 /* Get the updated union of share states of this file. */ 00317 new_pentry_share_access = state_share_get_share_access(pentry); 00318 new_pentry_share_deny = state_share_get_share_deny(pentry); 00319 00320 /* If this file's share bits are different from the supposed value, update 00321 * it. 00322 */ 00323 if((new_pentry_share_access != old_pentry_share_access) || 00324 (new_pentry_share_deny != old_pentry_share_deny)) 00325 { 00326 /* Try to push to FSAL. */ 00327 share_param.share_access = new_pentry_share_access; 00328 share_param.share_deny = new_pentry_share_deny; 00329 00330 status = do_share_op(pentry, pcontext, powner, &share_param); 00331 if(status != STATE_SUCCESS) 00332 { 00333 /* Revert the ref counted share state of this file. */ 00334 state_share_update_counter(pentry, 00335 new_share_access, 00336 new_share_deny, 00337 old_share_access, 00338 old_share_deny, 00339 TRUE); 00340 LogDebug(COMPONENT_STATE, "do_share_op failed"); 00341 *pstatus = status; 00342 return *pstatus; 00343 } 00344 } 00345 00346 /* Update share state. */ 00347 pstate->state_data.share.share_access = new_share_access; 00348 pstate->state_data.share.share_deny = new_share_deny; 00349 LogFullDebug(COMPONENT_STATE, "pstate %p: upgraded share_access %u, share_deny %u", 00350 pstate, 00351 pstate->state_data.share.share_access, 00352 pstate->state_data.share.share_deny); 00353 00354 /* Update previously seen share state. */ 00355 state_share_set_prev(pstate, pstate_data); 00356 00357 return status; 00358 } 00359 00360 /* This is called when share is downgraded via open_downgrade op. 00361 The state lock MUST be held. */ 00362 state_status_t state_share_downgrade(cache_entry_t * pentry, 00363 fsal_op_context_t * pcontext, 00364 state_data_t * pstate_data, /* new share bits */ 00365 state_owner_t * powner, 00366 state_t * pstate, /* state that holds current share bits */ 00367 state_status_t * pstatus) 00368 { 00369 state_status_t status = STATE_SUCCESS; 00370 unsigned int old_pentry_share_access = 0; 00371 unsigned int old_pentry_share_deny = 0; 00372 unsigned int new_pentry_share_access = 0; 00373 unsigned int new_pentry_share_deny = 0; 00374 unsigned int old_share_access = 0; 00375 unsigned int old_share_deny = 0; 00376 unsigned int new_share_access = 0; 00377 unsigned int new_share_deny = 0; 00378 fsal_share_param_t share_param; 00379 00380 /* Get the current union of share states of this file. */ 00381 old_pentry_share_access = state_share_get_share_access(pentry); 00382 old_pentry_share_deny = state_share_get_share_deny(pentry); 00383 00384 /* Old share state. */ 00385 old_share_access = pstate->state_data.share.share_access; 00386 old_share_deny = pstate->state_data.share.share_deny; 00387 00388 /* New share state. */ 00389 new_share_access = pstate_data->share.share_access; 00390 new_share_deny = pstate_data->share.share_deny; 00391 00392 /* Update the ref counted share state of this file. */ 00393 state_share_update_counter(pentry, 00394 old_share_access, 00395 old_share_deny, 00396 new_share_access, 00397 new_share_deny, 00398 TRUE); 00399 00400 /* Get the updated union of share states of this file. */ 00401 new_pentry_share_access = state_share_get_share_access(pentry); 00402 new_pentry_share_deny = state_share_get_share_deny(pentry); 00403 00404 /* If this file's share bits are different from the supposed value, update 00405 * it. 00406 */ 00407 if((new_pentry_share_access != old_pentry_share_access) || 00408 (new_pentry_share_deny != old_pentry_share_deny)) 00409 { 00410 /* Try to push to FSAL. */ 00411 share_param.share_access = new_pentry_share_access; 00412 share_param.share_deny = new_pentry_share_deny; 00413 00414 status = do_share_op(pentry, pcontext, powner, &share_param); 00415 if(status != STATE_SUCCESS) 00416 { 00417 /* Revert the ref counted share state of this file. */ 00418 state_share_update_counter(pentry, 00419 new_share_access, 00420 new_share_deny, 00421 old_share_access, 00422 old_share_deny, 00423 TRUE); 00424 LogDebug(COMPONENT_STATE, "do_share_op failed"); 00425 *pstatus = status; 00426 return *pstatus; 00427 } 00428 } 00429 00430 /* Update share state. */ 00431 pstate->state_data.share.share_access = new_share_access; 00432 pstate->state_data.share.share_deny = new_share_deny; 00433 LogFullDebug(COMPONENT_STATE, "pstate %p: downgraded share_access %u, " 00434 "share_deny %u", 00435 pstate, 00436 pstate->state_data.share.share_access, 00437 pstate->state_data.share.share_deny); 00438 00439 return status; 00440 } 00441 00442 /* Update the bitmap of previously seen share access and deny bits for the 00443 * given state. 00444 */ 00445 state_status_t state_share_set_prev(state_t * pstate, 00446 state_data_t * pstate_data) 00447 { 00448 state_status_t status = STATE_SUCCESS; 00449 00450 pstate->state_data.share.share_access_prev |= 00451 (1 << pstate_data->share.share_access); 00452 00453 pstate->state_data.share.share_deny_prev |= 00454 (1 << pstate_data->share.share_deny); 00455 00456 return status; 00457 } 00458 00459 /* Check if the given state has seen the given share access and deny bits 00460 * before. This is needed when we check validity of open downgrade. 00461 */ 00462 state_status_t state_share_check_prev(state_t * pstate, 00463 state_data_t * pstate_data) 00464 { 00465 state_status_t status = STATE_SUCCESS; 00466 00467 if((pstate->state_data.share.share_access_prev & 00468 (1 << pstate_data->share.share_access)) == 0) 00469 return STATE_STATE_ERROR; 00470 00471 if((pstate->state_data.share.share_deny_prev & 00472 (1 << pstate_data->share.share_deny)) == 0) 00473 return STATE_STATE_ERROR; 00474 00475 return status; 00476 } 00477 00478 /* Check if the given share access and deny bits have conflict. The 00479 state lock MUST be held. */ 00480 state_status_t state_share_check_conflict(cache_entry_t * pentry, 00481 int share_acccess, 00482 int share_deny, 00483 state_status_t * pstatus) 00484 { 00485 char * cause = ""; 00486 00487 if((share_acccess & OPEN4_SHARE_ACCESS_READ) != 0 && 00488 pentry->object.file.share_state.share_deny_read > 0) 00489 { 00490 cause = "access read denied by existing deny read"; 00491 goto out_conflict; 00492 } 00493 00494 if((share_acccess & OPEN4_SHARE_ACCESS_WRITE) != 0 && 00495 pentry->object.file.share_state.share_deny_write > 0) 00496 { 00497 cause = "access write denied by existing deny write"; 00498 goto out_conflict; 00499 } 00500 00501 if((share_deny & OPEN4_SHARE_DENY_READ) != 0 && 00502 pentry->object.file.share_state.share_access_read > 0) 00503 { 00504 cause = "deny read denied by existing access read"; 00505 goto out_conflict; 00506 } 00507 00508 if((share_deny & OPEN4_SHARE_DENY_WRITE) != 0 && 00509 pentry->object.file.share_state.share_access_write > 0) 00510 { 00511 cause = "deny write denied by existing access write"; 00512 goto out_conflict; 00513 } 00514 00515 *pstatus = STATE_SUCCESS; 00516 return *pstatus; 00517 00518 out_conflict: 00519 00520 LogDebug(COMPONENT_STATE, "Share conflict detected: %s", cause); 00521 *pstatus = STATE_STATE_CONFLICT; 00522 return *pstatus; 00523 } 00524 00525 /* Update the ref counter of share state. This function should be called with 00526 * the state lock held 00527 */ 00528 static void state_share_update_counter(cache_entry_t * pentry, 00529 int old_access, 00530 int old_deny, 00531 int new_access, 00532 int new_deny, 00533 bool_t v4) 00534 { 00535 int access_read_inc = ((new_access & OPEN4_SHARE_ACCESS_READ) != 0) - ((old_access & OPEN4_SHARE_ACCESS_READ) != 0); 00536 int access_write_inc = ((new_access & OPEN4_SHARE_ACCESS_WRITE) != 0) - ((old_access & OPEN4_SHARE_ACCESS_WRITE) != 0); 00537 int deny_read_inc = ((new_deny & OPEN4_SHARE_ACCESS_READ) != 0) - ((old_deny & OPEN4_SHARE_ACCESS_READ) != 0); 00538 int deny_write_inc = ((new_deny & OPEN4_SHARE_ACCESS_WRITE) != 0) - ((old_deny & OPEN4_SHARE_ACCESS_WRITE) != 0); 00539 00540 pentry->object.file.share_state.share_access_read += access_read_inc; 00541 pentry->object.file.share_state.share_access_write += access_write_inc; 00542 pentry->object.file.share_state.share_deny_read += deny_read_inc; 00543 pentry->object.file.share_state.share_deny_write += deny_write_inc; 00544 if(v4) 00545 pentry->object.file.share_state.share_deny_write_v4 += deny_write_inc; 00546 00547 LogFullDebug(COMPONENT_STATE, "pentry %p: share counter: " 00548 "access_read %u, access_write %u, " 00549 "deny_read %u, deny_write %u, deny_write_v4 %u", 00550 pentry, 00551 pentry->object.file.share_state.share_access_read, 00552 pentry->object.file.share_state.share_access_write, 00553 pentry->object.file.share_state.share_deny_read, 00554 pentry->object.file.share_state.share_deny_write, 00555 pentry->object.file.share_state.share_deny_write_v4); 00556 } 00557 00558 /* Utility function to calculate the union of share access of given file. */ 00559 static unsigned int state_share_get_share_access(cache_entry_t * pentry) 00560 { 00561 unsigned int share_access = 0; 00562 00563 if(pentry->object.file.share_state.share_access_read > 0) 00564 share_access |= OPEN4_SHARE_ACCESS_READ; 00565 00566 if(pentry->object.file.share_state.share_access_write > 0) 00567 share_access |= OPEN4_SHARE_ACCESS_WRITE; 00568 00569 LogFullDebug(COMPONENT_STATE, "pentry %p: union share access = %u", 00570 pentry, share_access); 00571 00572 return share_access; 00573 } 00574 00575 /* Utility function to calculate the union of share deny of given file. */ 00576 static unsigned int state_share_get_share_deny(cache_entry_t * pentry) 00577 { 00578 unsigned int share_deny = 0; 00579 00580 if(pentry->object.file.share_state.share_deny_read > 0) 00581 share_deny |= OPEN4_SHARE_DENY_READ; 00582 00583 if(pentry->object.file.share_state.share_deny_write > 0) 00584 share_deny |= OPEN4_SHARE_DENY_WRITE; 00585 00586 LogFullDebug(COMPONENT_STATE, "pentry %p: union share deny = %u", 00587 pentry, share_deny); 00588 00589 return share_deny; 00590 } 00591 00592 state_status_t state_share_anonymous_io_start(cache_entry_t * pentry, 00593 int share_access, 00594 state_status_t * pstatus) 00595 { 00596 pthread_rwlock_wrlock(&pentry->state_lock); 00597 00598 if(state_share_check_conflict(pentry, 00599 share_access, 00600 0, 00601 pstatus) == STATE_SUCCESS) 00602 { 00603 /* Temporarily bump the access counters, v4 mode doesn't matter 00604 * since there is no deny mode associated with anonymous I/O. 00605 */ 00606 state_share_update_counter(pentry, 00607 OPEN4_SHARE_ACCESS_NONE, 00608 OPEN4_SHARE_DENY_NONE, 00609 share_access, 00610 OPEN4_SHARE_DENY_NONE, 00611 FALSE); 00612 } 00613 00614 pthread_rwlock_unlock(&pentry->state_lock); 00615 00616 return *pstatus; 00617 } 00618 00619 void state_share_anonymous_io_done(cache_entry_t * pentry, 00620 int share_access) 00621 { 00622 pthread_rwlock_wrlock(&pentry->state_lock); 00623 00624 /* Undo the temporary bump to the access counters, v4 mode doesn't 00625 * matter since there is no deny mode associated with anonymous I/O. 00626 */ 00627 state_share_update_counter(pentry, 00628 share_access, 00629 OPEN4_SHARE_DENY_NONE, 00630 OPEN4_SHARE_ACCESS_NONE, 00631 OPEN4_SHARE_DENY_NONE, 00632 FALSE); 00633 00634 pthread_rwlock_unlock(&pentry->state_lock); 00635 } 00636 00637 #ifdef _USE_NLM 00638 state_status_t state_nlm_share(cache_entry_t * pentry, 00639 fsal_op_context_t * pcontext, 00640 exportlist_t * pexport, 00641 int share_access, 00642 int share_deny, 00643 state_owner_t * powner, 00644 state_status_t * pstatus) 00645 { 00646 unsigned int old_pentry_share_access; 00647 unsigned int old_pentry_share_deny; 00648 unsigned int new_pentry_share_access; 00649 unsigned int new_pentry_share_deny; 00650 fsal_share_param_t share_param; 00651 state_nlm_share_t * nlm_share; 00652 cache_inode_status_t cache_status; 00653 00654 cache_status = cache_inode_inc_pin_ref(pentry); 00655 00656 if(cache_status != CACHE_INODE_SUCCESS) 00657 { 00658 *pstatus = cache_inode_status_to_state_status(cache_status); 00659 LogDebug(COMPONENT_STATE, 00660 "Could not pin file"); 00661 return *pstatus; 00662 } 00663 00664 if(cache_inode_open(pentry, 00665 FSAL_O_RDWR, 00666 pcontext, 00667 0, 00668 &cache_status) != CACHE_INODE_SUCCESS) 00669 { 00670 cache_inode_dec_pin_ref(pentry); 00671 00672 *pstatus = cache_inode_status_to_state_status(cache_status); 00673 00674 LogFullDebug(COMPONENT_STATE, 00675 "Could not open file"); 00676 00677 return *pstatus; 00678 } 00679 00680 pthread_rwlock_wrlock(&pentry->state_lock); 00681 00682 /* Check if new share state has conflicts. */ 00683 if(state_share_check_conflict(pentry, 00684 share_access, 00685 share_deny, 00686 pstatus) != STATE_SUCCESS) 00687 { 00688 pthread_rwlock_unlock(&pentry->state_lock); 00689 00690 cache_inode_dec_pin_ref(pentry); 00691 00692 LogEvent(COMPONENT_STATE, "Share conflicts detected during add"); 00693 00694 return *pstatus; 00695 } 00696 00697 /* Create a new NLM Share object */ 00698 nlm_share = gsh_calloc(1, sizeof(state_nlm_share_t)); 00699 00700 if(nlm_share == NULL) 00701 { 00702 pthread_rwlock_unlock(&pentry->state_lock); 00703 00704 cache_inode_dec_pin_ref(pentry); 00705 00706 LogEvent(COMPONENT_STATE, "Can not allocate memory for share"); 00707 00708 *pstatus = STATE_MALLOC_ERROR; 00709 00710 return *pstatus; 00711 } 00712 00713 nlm_share->sns_powner = powner; 00714 nlm_share->sns_pentry = pentry; 00715 nlm_share->sns_access = share_access; 00716 nlm_share->sns_deny = share_deny; 00717 nlm_share->sns_pexport = pexport; 00718 00719 /* Add share to list for NLM Owner */ 00720 P(powner->so_mutex); 00721 00722 glist_add_tail(&powner->so_owner.so_nlm_owner.so_nlm_shares, &nlm_share->sns_share_per_owner); 00723 00724 inc_state_owner_ref_locked(powner); 00725 /* implicit V(powner->so_mutex); */ 00726 00727 /* Add share to list for NSM Client */ 00728 P(powner->so_owner.so_nlm_owner.so_client->slc_nsm_client->ssc_mutex); 00729 00730 glist_add_tail(&powner->so_owner.so_nlm_owner.so_client->slc_nsm_client->ssc_share_list, 00731 &nlm_share->sns_share_per_client); 00732 00733 inc_nsm_client_ref_locked(powner->so_owner.so_nlm_owner.so_client->slc_nsm_client); 00734 /* implicit V(powner->so_owner.so_nlm_owner.so_client->slc_nsm_client->ssc_mutex); */ 00735 00736 /* Add share to list for file, if list was empty take a pin ref to keep this 00737 * file pinned in the inode cache. 00738 */ 00739 if(glist_empty(&pentry->object.file.nlm_share_list)) 00740 cache_inode_inc_pin_ref(pentry); 00741 00742 glist_add_tail(&pentry->object.file.nlm_share_list, &nlm_share->sns_share_per_file); 00743 00744 /* Get the current union of share states of this file. */ 00745 old_pentry_share_access = state_share_get_share_access(pentry); 00746 old_pentry_share_deny = state_share_get_share_deny(pentry); 00747 00748 /* Update the ref counted share state of this file. */ 00749 state_share_update_counter(pentry, 00750 OPEN4_SHARE_ACCESS_NONE, 00751 OPEN4_SHARE_DENY_NONE, 00752 share_access, 00753 share_deny, 00754 TRUE); 00755 00756 /* Get the updated union of share states of this file. */ 00757 new_pentry_share_access = state_share_get_share_access(pentry); 00758 new_pentry_share_deny = state_share_get_share_deny(pentry); 00759 00760 /* If this file's share bits are different from the supposed value, update 00761 * it. 00762 */ 00763 if((new_pentry_share_access != old_pentry_share_access) || 00764 (new_pentry_share_deny != old_pentry_share_deny)) 00765 { 00766 /* Try to push to FSAL. */ 00767 share_param.share_access = new_pentry_share_access; 00768 share_param.share_deny = new_pentry_share_deny; 00769 00770 *pstatus = do_share_op(pentry, pcontext, powner, &share_param); 00771 00772 if(*pstatus != STATE_SUCCESS) 00773 { 00774 /* Revert the ref counted share state of this file. */ 00775 state_share_update_counter(pentry, 00776 share_access, 00777 share_deny, 00778 OPEN4_SHARE_ACCESS_NONE, 00779 OPEN4_SHARE_DENY_NONE, 00780 TRUE); 00781 00782 /* Remove the share from the list for the file. If the list is now 00783 * empty also remove the extra pin ref. 00784 */ 00785 glist_del(&nlm_share->sns_share_per_file); 00786 00787 if(glist_empty(&pentry->object.file.nlm_share_list)) 00788 cache_inode_dec_pin_ref(pentry); 00789 00790 /* Remove the share from the NSM Client list */ 00791 P(powner->so_owner.so_nlm_owner.so_client->slc_nsm_client->ssc_mutex); 00792 00793 glist_del(&nlm_share->sns_share_per_client); 00794 00795 dec_nsm_client_ref_locked(powner->so_owner.so_nlm_owner.so_client->slc_nsm_client); 00796 /* implicit V(powner->so_owner.so_nlm_owner.so_client->slc_nsm_client->ssc_mutex); */ 00797 00798 /* Remove the share from the NLM Owner list */ 00799 P(powner->so_mutex); 00800 00801 glist_del(&nlm_share->sns_share_per_owner); 00802 00803 dec_state_owner_ref_locked(powner); 00804 /* implicit V(powner->so_mutex); */ 00805 00806 /* Free the NLM Share and exit */ 00807 gsh_free(nlm_share); 00808 00809 pthread_rwlock_unlock(&pentry->state_lock); 00810 00811 cache_inode_dec_pin_ref(pentry); 00812 00813 LogDebug(COMPONENT_STATE, "do_share_op failed"); 00814 00815 return *pstatus; 00816 } 00817 } 00818 00819 LogFullDebug(COMPONENT_STATE, "added share_access %u, " 00820 "share_deny %u", 00821 share_access, share_deny); 00822 00823 pthread_rwlock_unlock(&pentry->state_lock); 00824 00825 cache_inode_dec_pin_ref(pentry); 00826 00827 return *pstatus; 00828 } 00829 00830 state_status_t state_nlm_unshare(cache_entry_t * pentry, 00831 fsal_op_context_t * pcontext, 00832 int share_access, 00833 int share_deny, 00834 state_owner_t * powner, 00835 state_status_t * pstatus) 00836 { 00837 struct glist_head *glist, *glistn; 00838 unsigned int old_pentry_share_access; 00839 unsigned int old_pentry_share_deny; 00840 unsigned int new_pentry_share_access; 00841 unsigned int new_pentry_share_deny; 00842 unsigned int removed_share_access; 00843 unsigned int removed_share_deny; 00844 fsal_share_param_t share_param; 00845 state_nlm_share_t * nlm_share; 00846 cache_inode_status_t cache_status; 00847 00848 cache_status = cache_inode_inc_pin_ref(pentry); 00849 00850 if(cache_status != CACHE_INODE_SUCCESS) 00851 { 00852 *pstatus = cache_inode_status_to_state_status(cache_status); 00853 LogDebug(COMPONENT_STATE, 00854 "Could not pin file"); 00855 return *pstatus; 00856 } 00857 00858 pthread_rwlock_wrlock(&pentry->state_lock); 00859 00860 glist_for_each_safe(glist, glistn, &pentry->object.file.nlm_share_list) 00861 { 00862 nlm_share = glist_entry(glist, state_nlm_share_t, sns_share_per_file); 00863 00864 if(different_owners(powner, nlm_share->sns_powner)) 00865 continue; 00866 00867 /* share_access == OPEN4_SHARE_ACCESS_NONE indicates that any share 00868 * should be matched for unshare. 00869 */ 00870 if(share_access != OPEN4_SHARE_ACCESS_NONE && 00871 (nlm_share->sns_access != share_access || 00872 nlm_share->sns_deny != share_deny)) 00873 continue; 00874 00875 /* Get the current union of share states of this file. */ 00876 old_pentry_share_access = state_share_get_share_access(pentry); 00877 old_pentry_share_deny = state_share_get_share_deny(pentry); 00878 00879 /* Share state to be removed. */ 00880 removed_share_access = nlm_share->sns_access; 00881 removed_share_deny = nlm_share->sns_deny; 00882 00883 /* Update the ref counted share state of this file. */ 00884 state_share_update_counter(pentry, 00885 removed_share_access, 00886 removed_share_deny, 00887 OPEN4_SHARE_ACCESS_NONE, 00888 OPEN4_SHARE_DENY_NONE, 00889 TRUE); 00890 00891 /* Get the updated union of share states of this file. */ 00892 new_pentry_share_access = state_share_get_share_access(pentry); 00893 new_pentry_share_deny = state_share_get_share_deny(pentry); 00894 00895 /* If this file's share bits are different from the supposed value, update 00896 * it. 00897 */ 00898 if((new_pentry_share_access != old_pentry_share_access) || 00899 (new_pentry_share_deny != old_pentry_share_deny)) 00900 { 00901 /* Try to push to FSAL. */ 00902 share_param.share_access = new_pentry_share_access; 00903 share_param.share_deny = new_pentry_share_deny; 00904 00905 *pstatus = do_share_op(pentry, pcontext, powner, &share_param); 00906 00907 if(*pstatus != STATE_SUCCESS) 00908 { 00909 /* Revert the ref counted share state of this file. */ 00910 state_share_update_counter(pentry, 00911 OPEN4_SHARE_ACCESS_NONE, 00912 OPEN4_SHARE_DENY_NONE, 00913 removed_share_access, 00914 removed_share_deny, 00915 TRUE); 00916 00917 pthread_rwlock_unlock(&pentry->state_lock); 00918 00919 cache_inode_dec_pin_ref(pentry); 00920 00921 LogDebug(COMPONENT_STATE, "do_share_op failed"); 00922 00923 return *pstatus; 00924 } 00925 } 00926 00927 LogFullDebug(COMPONENT_STATE, 00928 "removed share_access %u, share_deny %u", 00929 removed_share_access, 00930 removed_share_deny); 00931 00932 /* Remove the share from the list for the file. If the list is now 00933 * empty also remove the extra pin ref. 00934 */ 00935 glist_del(&nlm_share->sns_share_per_file); 00936 00937 if(glist_empty(&pentry->object.file.nlm_share_list)) 00938 cache_inode_dec_pin_ref(pentry); 00939 00940 /* Remove the share from the NSM Client list */ 00941 P(powner->so_owner.so_nlm_owner.so_client->slc_nsm_client->ssc_mutex); 00942 00943 glist_del(&nlm_share->sns_share_per_client); 00944 00945 dec_nsm_client_ref_locked(powner->so_owner.so_nlm_owner.so_client->slc_nsm_client); 00946 /* implicit V(powner->so_owner.so_nlm_owner.so_client->slc_nsm_client->ssc_mutex); */ 00947 00948 /* Remove the share from the NLM Owner list */ 00949 P(powner->so_mutex); 00950 00951 glist_del(&nlm_share->sns_share_per_owner); 00952 00953 dec_state_owner_ref_locked(powner); 00954 /* implicit V(powner->so_mutex); */ 00955 00956 /* Free the NLM Share (and continue to look for more) */ 00957 gsh_free(nlm_share); 00958 } 00959 00960 pthread_rwlock_unlock(&pentry->state_lock); 00961 00962 cache_inode_dec_pin_ref(pentry); 00963 00964 return *pstatus; 00965 } 00966 00967 #endif /* _USE_NLM */