nfs-ganesha 1.4
|
00001 /* 00002 * Copyright IBM Corporation, 2010 00003 * Contributor: Aneesh Kumar K.v <aneesh.kumar@linux.vnet.ibm.com> 00004 * 00005 * -------------------------- 00006 * 00007 * This program is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public License 00009 * as published by the Free Software Foundation; either version 3 of 00010 * the License, or (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, but 00013 * WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00020 * 02110-1301 USA 00021 * 00022 */ 00023 00024 #ifdef HAVE_CONFIG_H 00025 #include "config.h" 00026 #endif 00027 00028 #ifdef _SOLARIS 00029 #include "solaris_port.h" 00030 #endif 00031 00032 #include <stdio.h> 00033 #include <string.h> 00034 #include <pthread.h> 00035 #include "log.h" 00036 #include "ganesha_rpc.h" 00037 #include "nlm4.h" 00038 #include "sal_functions.h" 00039 #include "nlm_util.h" 00040 #include "nlm_async.h" 00041 00054 int nlm4_Lock(nfs_arg_t * parg, 00055 exportlist_t * pexport, 00056 fsal_op_context_t * pcontext, 00057 nfs_worker_data_t * pworker, 00058 struct svc_req * preq, 00059 nfs_res_t * pres) 00060 { 00061 nlm4_lockargs * arg = &parg->arg_nlm4_lock; 00062 cache_entry_t * pentry; 00063 state_status_t state_status = STATE_SUCCESS; 00064 char buffer[MAXNETOBJ_SZ * 2]; 00065 state_nsm_client_t * nsm_client; 00066 state_nlm_client_t * nlm_client; 00067 state_owner_t * nlm_owner, * holder; 00068 fsal_lock_param_t lock, conflict; 00069 int rc; 00070 int grace = nfs_in_grace(); 00071 state_block_data_t * pblock_data; 00072 const char * proc_name = "nlm4_Lock"; 00073 care_t care = CARE_MONITOR; 00074 00075 if(preq->rq_proc == NLMPROC4_NM_LOCK) 00076 { 00077 /* If call is a NM lock, indicate that we care about NLM client but 00078 * will not monitor. 00079 */ 00080 proc_name = "nlm4_NM_Lock"; 00081 care = CARE_NO_MONITOR; 00082 } 00083 00084 netobj_to_string(&arg->cookie, buffer, 1024); 00085 LogDebug(COMPONENT_NLM, 00086 "REQUEST PROCESSING: Calling %s svid=%d off=%llx len=%llx cookie=%s reclaim=%s", 00087 proc_name, 00088 (int) arg->alock.svid, 00089 (unsigned long long) arg->alock.l_offset, 00090 (unsigned long long) arg->alock.l_len, buffer, 00091 arg->reclaim ? "yes" : "no"); 00092 00093 if(!copy_netobj(&pres->res_nlm4test.cookie, &arg->cookie)) 00094 { 00095 pres->res_nlm4.stat.stat = NLM4_FAILED; 00096 LogDebug(COMPONENT_NLM, "REQUEST RESULT: %s %s", 00097 proc_name, lock_result_str(pres->res_nlm4.stat.stat)); 00098 return NFS_REQ_OK; 00099 } 00100 00101 /* allow only reclaim lock request during recovery and visa versa */ 00102 if((grace && !arg->reclaim) || 00103 (!grace && arg->reclaim)) 00104 { 00105 pres->res_nlm4.stat.stat = NLM4_DENIED_GRACE_PERIOD; 00106 LogDebug(COMPONENT_NLM, "REQUEST RESULT: %s %s", 00107 proc_name, lock_result_str(pres->res_nlm4.stat.stat)); 00108 return NFS_REQ_OK; 00109 } 00110 00111 rc = nlm_process_parameters(preq, 00112 arg->exclusive, 00113 &arg->alock, 00114 &lock, 00115 &pentry, 00116 pcontext, 00117 care, 00118 &nsm_client, 00119 &nlm_client, 00120 &nlm_owner, 00121 &pblock_data); 00122 00123 if(rc >= 0) 00124 { 00125 /* Present the error back to the client */ 00126 pres->res_nlm4.stat.stat = (nlm4_stats)rc; 00127 LogDebug(COMPONENT_NLM, "REQUEST RESULT: %s %s", 00128 proc_name, lock_result_str(pres->res_nlm4.stat.stat)); 00129 return NFS_REQ_OK; 00130 } 00131 00132 /* Cast the state number into a state pointer to protect 00133 * locks from a client that has rebooted from the SM_NOTIFY 00134 * that will release old locks 00135 */ 00136 if(state_lock(pentry, 00137 pcontext, 00138 pexport, 00139 nlm_owner, 00140 (void *) (ptrdiff_t) arg->state, 00141 arg->block ? STATE_NLM_BLOCKING : STATE_NON_BLOCKING, 00142 pblock_data, 00143 &lock, 00144 &holder, 00145 &conflict, 00146 &state_status) != STATE_SUCCESS) 00147 { 00148 pres->res_nlm4test.test_stat.stat = nlm_convert_state_error(state_status); 00149 00150 if(state_status == STATE_LOCK_CONFLICT) 00151 { 00152 nlm_process_conflict(&pres->res_nlm4test.test_stat.nlm4_testrply_u.holder, 00153 holder, 00154 &conflict); 00155 } 00156 00157 /* If we didn't block, release the block data */ 00158 if(state_status != STATE_LOCK_BLOCKED && pblock_data != NULL) 00159 gsh_free(pblock_data); 00160 } 00161 else 00162 { 00163 pres->res_nlm4.stat.stat = NLM4_GRANTED; 00164 } 00165 00166 /* Release the NLM Client and NLM Owner references we have */ 00167 dec_nsm_client_ref(nsm_client); 00168 dec_nlm_client_ref(nlm_client); 00169 dec_state_owner_ref(nlm_owner); 00170 cache_inode_put(pentry); 00171 00172 LogDebug(COMPONENT_NLM, "REQUEST RESULT: %s %s", 00173 proc_name, lock_result_str(pres->res_nlm4.stat.stat)); 00174 return NFS_REQ_OK; 00175 } 00176 00177 static void nlm4_lock_message_resp(state_async_queue_t *arg) 00178 { 00179 state_nlm_async_data_t * nlm_arg = &arg->state_async_data.state_nlm_async_data; 00180 00181 if(isFullDebug(COMPONENT_NLM)) 00182 { 00183 char buffer[1024]; 00184 netobj_to_string(&nlm_arg->nlm_async_args.nlm_async_res.res_nlm4test.cookie, buffer, 1024); 00185 LogFullDebug(COMPONENT_NLM, 00186 "Calling nlm_send_async cookie=%s status=%s", 00187 buffer, lock_result_str(nlm_arg->nlm_async_args.nlm_async_res.res_nlm4.stat.stat)); 00188 } 00189 nlm_send_async(NLMPROC4_LOCK_RES, 00190 nlm_arg->nlm_async_host, 00191 &(nlm_arg->nlm_async_args.nlm_async_res), 00192 NULL); 00193 nlm4_Lock_Free(&nlm_arg->nlm_async_args.nlm_async_res); 00194 dec_nsm_client_ref(nlm_arg->nlm_async_host->slc_nsm_client); 00195 dec_nlm_client_ref(nlm_arg->nlm_async_host); 00196 gsh_free(arg); 00197 } 00198 00210 int nlm4_Lock_Message(nfs_arg_t *parg, 00211 exportlist_t *pexport, 00212 fsal_op_context_t *pcontext, 00213 nfs_worker_data_t *pworker, 00214 struct svc_req *preq, 00215 nfs_res_t *pres) 00216 { 00217 state_nlm_client_t * nlm_client = NULL; 00218 state_nsm_client_t * nsm_client; 00219 nlm4_lockargs * arg = &parg->arg_nlm4_lock; 00220 int rc = NFS_REQ_OK; 00221 00222 LogDebug(COMPONENT_NLM, "REQUEST PROCESSING: Calling nlm_Lock_Message"); 00223 00224 nsm_client = get_nsm_client(CARE_NO_MONITOR, preq->rq_xprt, arg->alock.caller_name); 00225 00226 if(nsm_client != NULL) 00227 nlm_client = get_nlm_client(CARE_NO_MONITOR, preq->rq_xprt, nsm_client, arg->alock.caller_name); 00228 00229 if(nlm_client == NULL) 00230 rc = NFS_REQ_DROP; 00231 else 00232 rc = nlm4_Lock(parg, pexport, pcontext, pworker, preq, pres); 00233 00234 if(rc == NFS_REQ_OK) 00235 rc = nlm_send_async_res_nlm4(nlm_client, nlm4_lock_message_resp, pres); 00236 00237 if(rc == NFS_REQ_DROP) 00238 { 00239 if(nsm_client != NULL) 00240 dec_nsm_client_ref(nsm_client); 00241 if(nlm_client != NULL) 00242 dec_nlm_client_ref(nlm_client); 00243 LogCrit(COMPONENT_NLM, 00244 "Could not send async response for nlm_Lock_Message"); 00245 } 00246 00247 return NFS_REQ_DROP; 00248 00249 } 00250 00259 void nlm4_Lock_Free(nfs_res_t * pres) 00260 { 00261 netobj_free(&pres->res_nlm4test.cookie); 00262 return; 00263 }