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 00036 #ifdef HAVE_CONFIG_H 00037 #include "config.h" 00038 #endif 00039 00040 #ifdef _SOLARIS 00041 #include "solaris_port.h" 00042 #endif 00043 00044 #include <pthread.h> 00045 #include "log.h" 00046 #include "nfs4.h" 00047 #include "sal_functions.h" 00048 #include "nfs_proto_tools.h" 00049 #include "nfs_proto_functions.h" 00050 00065 #define arg_CLOSE4 op->nfs_argop4_u.opclose 00066 #define res_CLOSE4 resp->nfs_resop4_u.opclose 00067 00068 int nfs4_op_close(struct nfs_argop4 *op, compound_data_t * data, struct nfs_resop4 *resp) 00069 { 00070 char __attribute__ ((__unused__)) funcname[] = "nfs4_op_close"; 00071 00072 int rc = 0; 00073 state_t * pstate_found = NULL; 00074 cache_inode_status_t cache_status; 00075 state_status_t state_status; 00076 state_owner_t * popen_owner; 00077 const char * tag = "CLOSE"; 00078 struct glist_head * glist, * glistn; 00079 00080 LogDebug(COMPONENT_STATE, 00081 "Entering NFS v4 CLOSE handler -----------------------------------------------------"); 00082 00083 memset(&res_CLOSE4, 0, sizeof(res_CLOSE4)); 00084 resp->resop = NFS4_OP_CLOSE; 00085 res_CLOSE4.status = NFS4_OK; 00086 00087 /* 00088 * Do basic checks on a filehandle 00089 * Object should be a file 00090 */ 00091 res_CLOSE4.status = nfs4_sanity_check_FH(data, REGULAR_FILE); 00092 if(res_CLOSE4.status != NFS4_OK) 00093 return res_CLOSE4.status; 00094 00095 if(data->current_entry == NULL) 00096 { 00097 res_CLOSE4.status = NFS4ERR_SERVERFAULT; 00098 return res_CLOSE4.status; 00099 } 00100 00101 00102 /* Check stateid correctness and get pointer to state */ 00103 if((rc = nfs4_Check_Stateid(&arg_CLOSE4.open_stateid, 00104 data->current_entry, 00105 &pstate_found, 00106 data, 00107 STATEID_SPECIAL_FOR_LOCK, 00108 tag)) != NFS4_OK) 00109 { 00110 res_CLOSE4.status = rc; 00111 LogDebug(COMPONENT_STATE, 00112 "CLOSE failed nfs4_Check_Stateid"); 00113 return res_CLOSE4.status; 00114 } 00115 00116 popen_owner = pstate_found->state_powner; 00117 00118 P(popen_owner->so_mutex); 00119 00120 /* Check seqid */ 00121 if(!Check_nfs4_seqid(popen_owner, arg_CLOSE4.seqid, op, data, resp, tag)) 00122 { 00123 /* Response is all setup for us and LogDebug told what was wrong */ 00124 V(popen_owner->so_mutex); 00125 return res_CLOSE4.status; 00126 } 00127 00128 V(popen_owner->so_mutex); 00129 00130 pthread_rwlock_wrlock(&data->current_entry->state_lock); 00131 /* Check is held locks remain */ 00132 glist_for_each(glist, &pstate_found->state_data.share.share_lockstates) 00133 { 00134 state_t * plock_state = glist_entry(glist, 00135 state_t, 00136 state_data.lock.state_sharelist); 00137 00138 if(!glist_empty(&plock_state->state_data.lock.state_locklist)) 00139 { 00140 res_CLOSE4.status = NFS4ERR_LOCKS_HELD; 00141 00142 pthread_rwlock_unlock(&data->current_entry->state_lock); 00143 LogDebug(COMPONENT_STATE, 00144 "NFS4 Close with existing locks"); 00145 00146 /* Save the response in the open owner */ 00147 Copy_nfs4_state_req(popen_owner, arg_CLOSE4.seqid, op, data, resp, tag); 00148 00149 return res_CLOSE4.status; 00150 } 00151 } 00152 00153 00154 /* Handle stateid/seqid for success */ 00155 update_stateid(pstate_found, 00156 &res_CLOSE4.CLOSE4res_u.open_stateid, 00157 data, 00158 tag); 00159 00160 /* Save the response in the open owner */ 00161 Copy_nfs4_state_req(popen_owner, arg_CLOSE4.seqid, op, data, resp, tag); 00162 00163 /* File is closed, release the corresponding lock states */ 00164 glist_for_each_safe(glist, glistn, &pstate_found->state_data.share.share_lockstates) 00165 { 00166 state_t * plock_state = glist_entry(glist, 00167 state_t, 00168 state_data.lock.state_sharelist); 00169 00170 if((state_status 00171 = state_del_locked(plock_state, 00172 data->current_entry)) != STATE_SUCCESS) 00173 { 00174 LogDebug(COMPONENT_STATE, 00175 "CLOSE failed to release lock stateid error %s", 00176 state_err_str(state_status)); 00177 } 00178 } 00179 00180 /* File is closed, release the share state */ 00181 if(pstate_found->state_type == STATE_TYPE_SHARE) 00182 { 00183 if(state_share_remove(pstate_found->state_pentry, 00184 data->pcontext, 00185 popen_owner, 00186 pstate_found, 00187 &state_status) != STATE_SUCCESS) 00188 { 00189 LogDebug(COMPONENT_STATE, 00190 "CLOSE failed to release share state error %s", 00191 state_err_str(state_status)); 00192 } 00193 } 00194 00195 /* File is closed, release the corresponding state */ 00196 if((state_status 00197 = state_del_locked(pstate_found, 00198 data->current_entry)) != STATE_SUCCESS) 00199 { 00200 LogDebug(COMPONENT_STATE, 00201 "CLOSE failed to release stateid error %s", 00202 state_err_str(state_status)); 00203 } 00204 00205 /* Close the file in FSAL through the cache inode */ 00206 if(cache_inode_close(data->current_entry, 00207 0, 00208 &cache_status) != CACHE_INODE_SUCCESS) 00209 { 00210 res_CLOSE4.status = nfs4_Errno(cache_status); 00211 pthread_rwlock_unlock(&data->current_entry->state_lock); 00212 00213 /* Save the response in the open owner */ 00214 Copy_nfs4_state_req(popen_owner, arg_CLOSE4.seqid, op, data, resp, tag); 00215 00216 return res_CLOSE4.status; 00217 } 00218 00219 pthread_rwlock_unlock(&data->current_entry->state_lock); 00220 res_CLOSE4.status = NFS4_OK; 00221 00222 if(isFullDebug(COMPONENT_STATE) && isFullDebug(COMPONENT_MEMLEAKS)) 00223 { 00224 nfs_State_PrintAll(); 00225 nfs4_owner_PrintAll(); 00226 } 00227 00228 return NFS4_OK; 00229 } /* nfs4_op_close */ 00230 00241 void nfs4_op_close_Free(CLOSE4res * resp) 00242 { 00243 /* Nothing to be done */ 00244 return; 00245 } /* nfs4_op_close_Free */ 00246 00247 void nfs4_op_close_CopyRes(CLOSE4res * resp_dst, CLOSE4res * resp_src) 00248 { 00249 /* Nothing to be done */ 00250 return; 00251 }