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 nfs41_op_lockt(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) 00079 { 00080 state_status_t state_status; 00081 state_nfs4_owner_name_t owner_name; 00082 state_owner_t * plock_owner; 00083 state_owner_t * conflict_owner = NULL; 00084 fsal_lock_param_t lock_desc, conflict_desc; 00085 00086 LogDebug(COMPONENT_NFS_V4_LOCK, 00087 "Entering NFS v4.1 LOCKT handler -----------------------------------------------------"); 00088 00089 /* Initialize to sane default */ 00090 resp->resop = NFS4_OP_LOCKT; 00091 res_LOCKT4.status = NFS4_OK; 00092 00093 /* 00094 * Do basic checks on a filehandle 00095 * LOCKT is done only on a file 00096 */ 00097 res_LOCKT4.status = nfs4_sanity_check_FH(data, REGULAR_FILE); 00098 if(res_LOCKT4.status != NFS4_OK) 00099 return res_LOCKT4.status; 00100 00101 /* Lock length should not be 0 */ 00102 if(arg_LOCKT4.length == 0LL) 00103 { 00104 res_LOCKT4.status = NFS4ERR_INVAL; 00105 return res_LOCKT4.status; 00106 } 00107 00108 if (nfs_in_grace()) 00109 { 00110 res_LOCKT4.status = NFS4ERR_GRACE; 00111 return res_LOCKT4.status; 00112 } 00113 00114 /* Convert lock parameters to internal types */ 00115 switch(arg_LOCKT4.locktype) 00116 { 00117 case READ_LT: 00118 case READW_LT: 00119 lock_desc.lock_type = FSAL_LOCK_R; 00120 break; 00121 00122 case WRITE_LT: 00123 case WRITEW_LT: 00124 lock_desc.lock_type = FSAL_LOCK_W; 00125 break; 00126 } 00127 00128 lock_desc.lock_start = arg_LOCKT4.offset; 00129 00130 if(arg_LOCKT4.length != STATE_LOCK_OFFSET_EOF) 00131 lock_desc.lock_length = arg_LOCKT4.length; 00132 else 00133 lock_desc.lock_length = 0; 00134 00135 /* Check for range overflow. 00136 * Comparing beyond 2^64 is not possible int 64 bits precision, 00137 * but off+len > 2^64-1 is equivalent to len > 2^64-1 - off 00138 */ 00139 if(lock_desc.lock_length > (STATE_LOCK_OFFSET_EOF - lock_desc.lock_start)) 00140 { 00141 res_LOCKT4.status = NFS4ERR_INVAL; 00142 return res_LOCKT4.status; 00143 } 00144 00145 /* Is this lock_owner known ? */ 00146 convert_nfs4_lock_owner(&arg_LOCKT4.owner, &owner_name, 00147 data->psession->clientid); 00148 00149 if(!nfs4_owner_Get_Pointer(&owner_name, &plock_owner)) 00150 { 00151 /* This lock owner is not known yet, allocated and set up a new one */ 00152 plock_owner = create_nfs4_owner(&owner_name, 00153 data->psession->pclientid_record, 00154 STATE_LOCK_OWNER_NFSV4, 00155 NULL, 00156 0); 00157 00158 if(plock_owner == NULL) 00159 { 00160 LogFullDebug(COMPONENT_NFS_V4_LOCK, 00161 "LOCKT unable to create lock owner"); 00162 res_LOCKT4.status = NFS4ERR_SERVERFAULT; 00163 return res_LOCKT4.status; 00164 } 00165 } 00166 else if(isFullDebug(COMPONENT_NFS_V4_LOCK)) 00167 { 00168 char str[HASHTABLE_DISPLAY_STRLEN]; 00169 00170 DisplayOwner(plock_owner, str); 00171 00172 LogFullDebug(COMPONENT_NFS_V4_LOCK, 00173 "LOCKT A previously known owner is used %s", 00174 str); 00175 } 00176 00177 LogLock(COMPONENT_NFS_V4_LOCK, NIV_FULL_DEBUG, 00178 "LOCKT", 00179 data->current_entry, 00180 data->pcontext, 00181 plock_owner, 00182 &lock_desc); 00183 00184 /* Now we have a lock owner and a stateid. 00185 * Go ahead and test the lock in SAL (and FSAL). 00186 */ 00187 if(state_test(data->current_entry, 00188 data->pcontext, 00189 data->pexport, 00190 plock_owner, 00191 &lock_desc, 00192 &conflict_owner, 00193 &conflict_desc, 00194 &state_status) == STATE_LOCK_CONFLICT) 00195 { 00196 /* A conflicting lock from a different lock_owner, returns NFS4ERR_DENIED */ 00197 Process_nfs4_conflict(&res_LOCKT4.LOCKT4res_u.denied, 00198 conflict_owner, 00199 &conflict_desc); 00200 } 00201 00202 /* Release NFS4 Open Owner reference */ 00203 dec_state_owner_ref(plock_owner); 00204 00205 /* Return result */ 00206 res_LOCKT4.status = nfs4_Errno_state(state_status); 00207 return res_LOCKT4.status; 00208 00209 } /* nfs41_op_lockt */ 00210 00221 void nfs41_op_lockt_Free(LOCKT4res * resp) 00222 { 00223 if(resp->status == NFS4ERR_DENIED) 00224 Release_nfs4_denied(&resp->LOCKT4res_u.denied); 00225 } /* nfs41_op_lockt_Free */