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 00075 #define arg_LOCKT4 op->nfs_argop4_u.oplockt 00076 #define res_LOCKT4 resp->nfs_resop4_u.oplockt 00077 00078 int nfs4_op_lockt(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) 00079 { 00080 state_status_t state_status; 00081 nfs_client_id_t * pclientid; 00082 state_nfs4_owner_name_t owner_name; 00083 state_owner_t * plock_owner; 00084 state_owner_t * conflict_owner = NULL; 00085 fsal_lock_param_t lock_desc, conflict_desc; 00086 00087 LogDebug(COMPONENT_NFS_V4_LOCK, 00088 "Entering NFS v4 LOCKT handler -----------------------------------------------------"); 00089 00090 /* Initialize to sane default */ 00091 resp->resop = NFS4_OP_LOCKT; 00092 res_LOCKT4.status = NFS4_OK; 00093 00094 /* 00095 * Do basic checks on a filehandle 00096 * LOCKT is done only on a file 00097 */ 00098 res_LOCKT4.status = nfs4_sanity_check_FH(data, REGULAR_FILE); 00099 if(res_LOCKT4.status != NFS4_OK) 00100 return res_LOCKT4.status; 00101 00102 /* This can't be done on the pseudofs */ 00103 if(nfs4_Is_Fh_Pseudo(&(data->currentFH))) 00104 { 00105 res_LOCKT4.status = NFS4ERR_ROFS; 00106 LogDebug(COMPONENT_STATE, 00107 "NFS4 LOCKT returning NFS4ERR_ROFS"); 00108 return res_LOCKT4.status; 00109 } 00110 00111 if (nfs_export_check_security(data->reqp, data->pexport) == FALSE) 00112 { 00113 res_LOCKT4.status = NFS4ERR_PERM; 00114 return res_LOCKT4.status; 00115 } 00116 00117 /* Lock length should not be 0 */ 00118 if(arg_LOCKT4.length == 0LL) 00119 { 00120 res_LOCKT4.status = NFS4ERR_INVAL; 00121 return res_LOCKT4.status; 00122 } 00123 00124 if (nfs_in_grace()) 00125 { 00126 res_LOCKT4.status = NFS4ERR_GRACE; 00127 return res_LOCKT4.status; 00128 } 00129 00130 /* Convert lock parameters to internal types */ 00131 switch(arg_LOCKT4.locktype) 00132 { 00133 case READ_LT: 00134 case READW_LT: 00135 lock_desc.lock_type = FSAL_LOCK_R; 00136 break; 00137 00138 case WRITE_LT: 00139 case WRITEW_LT: 00140 lock_desc.lock_type = FSAL_LOCK_W; 00141 break; 00142 } 00143 00144 lock_desc.lock_start = arg_LOCKT4.offset; 00145 00146 if(arg_LOCKT4.length != STATE_LOCK_OFFSET_EOF) 00147 lock_desc.lock_length = arg_LOCKT4.length; 00148 else 00149 lock_desc.lock_length = 0; 00150 00151 /* Check for range overflow. 00152 * Comparing beyond 2^64 is not possible int 64 bits precision, 00153 * but off+len > 2^64-1 is equivalent to len > 2^64-1 - off 00154 */ 00155 if(lock_desc.lock_length > (STATE_LOCK_OFFSET_EOF - lock_desc.lock_start)) 00156 { 00157 res_LOCKT4.status = NFS4ERR_INVAL; 00158 return res_LOCKT4.status; 00159 } 00160 00161 /* Check clientid */ 00162 if(nfs_client_id_get_confirmed(arg_LOCKT4.owner.clientid, 00163 &pclientid) != CLIENT_ID_SUCCESS) 00164 { 00165 res_LOCKT4.status = NFS4ERR_STALE_CLIENTID; 00166 return res_LOCKT4.status; 00167 } 00168 00169 /* The protocol doesn't allow for EXPIRED, so return STALE_CLIENTID */ 00170 P(pclientid->cid_mutex); 00171 00172 if(!reserve_lease(pclientid)) 00173 { 00174 V(pclientid->cid_mutex); 00175 00176 dec_client_id_ref(pclientid); 00177 00178 res_LOCKT4.status = NFS4ERR_STALE_CLIENTID; 00179 return res_LOCKT4.status; 00180 } 00181 00182 V(pclientid->cid_mutex); 00183 00184 /* Is this lock_owner known ? */ 00185 convert_nfs4_lock_owner(&arg_LOCKT4.owner, &owner_name, 0LL); 00186 00187 if(!nfs4_owner_Get_Pointer(&owner_name, &plock_owner)) 00188 { 00189 /* This lock owner is not known yet, allocated and set up a new one */ 00190 plock_owner = create_nfs4_owner(&owner_name, 00191 pclientid, 00192 STATE_LOCK_OWNER_NFSV4, 00193 NULL, 00194 0); 00195 00196 if(plock_owner == NULL) 00197 { 00198 LogFullDebug(COMPONENT_NFS_V4_LOCK, 00199 "LOCKT unable to create lock owner"); 00200 res_LOCKT4.status = NFS4ERR_SERVERFAULT; 00201 goto out; 00202 } 00203 } 00204 else if(isFullDebug(COMPONENT_NFS_V4_LOCK)) 00205 { 00206 char str[HASHTABLE_DISPLAY_STRLEN]; 00207 00208 DisplayOwner(plock_owner, str); 00209 00210 LogFullDebug(COMPONENT_NFS_V4_LOCK, 00211 "LOCKT A previously known owner is used %s", 00212 str); 00213 } 00214 00215 LogLock(COMPONENT_NFS_V4_LOCK, NIV_FULL_DEBUG, 00216 "LOCKT", 00217 data->current_entry, 00218 data->pcontext, 00219 plock_owner, 00220 &lock_desc); 00221 00222 /* Now we have a lock owner and a stateid. 00223 * Go ahead and test the lock in SAL (and FSAL). 00224 */ 00225 if(state_test(data->current_entry, 00226 data->pcontext, 00227 data->pexport, 00228 plock_owner, 00229 &lock_desc, 00230 &conflict_owner, 00231 &conflict_desc, 00232 &state_status) == STATE_LOCK_CONFLICT) 00233 { 00234 /* A conflicting lock from a different lock_owner, returns NFS4ERR_DENIED */ 00235 Process_nfs4_conflict(&res_LOCKT4.LOCKT4res_u.denied, 00236 conflict_owner, 00237 &conflict_desc); 00238 } 00239 00240 /* Release NFS4 Open Owner reference */ 00241 dec_state_owner_ref(plock_owner); 00242 00243 /* Return result */ 00244 res_LOCKT4.status = nfs4_Errno_state(state_status); 00245 00246 out: 00247 00248 /* Update the lease before exit */ 00249 P(pclientid->cid_mutex); 00250 00251 update_lease(pclientid); 00252 00253 V(pclientid->cid_mutex); 00254 00255 dec_client_id_ref(pclientid); 00256 00257 return res_LOCKT4.status; 00258 00259 } /* nfs4_op_lockt */ 00260 00271 void nfs4_op_lockt_Free(LOCKT4res * resp) 00272 { 00273 if(resp->status == NFS4ERR_DENIED) 00274 Release_nfs4_denied(&resp->LOCKT4res_u.denied); 00275 } /* nfs4_op_lockt_Free */