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 00034 #ifdef HAVE_CONFIG_H 00035 #include "config.h" 00036 #endif 00037 00038 #ifdef _SOLARIS 00039 #include "solaris_port.h" 00040 #endif 00041 00042 #include <pthread.h> 00043 #include <stdint.h> 00044 #include "log.h" 00045 #include "nfs4.h" 00046 #include "sal_functions.h" 00047 #include "nfs_proto_functions.h" 00048 #include "nfs_proto_tools.h" 00049 00064 #define arg_CLOSE4 op->nfs_argop4_u.opclose 00065 #define res_CLOSE4 resp->nfs_resop4_u.opclose 00066 00067 int nfs41_op_close(struct nfs_argop4 *op, compound_data_t * data, 00068 struct nfs_resop4 *resp) 00069 { 00070 int rc = 0; 00071 state_t * pstate_found = NULL; 00072 cache_inode_status_t cache_status; 00073 state_status_t state_status; 00074 const char * tag = "CLOSE"; 00075 struct glist_head * glist, * glistn; 00076 #ifdef _PNFS_MDS 00077 bool_t last_close = TRUE; 00078 #endif /* _PNFS_MDS */ 00079 00080 LogDebug(COMPONENT_STATE, 00081 "Entering NFS v4.1 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 /* Check stateid correctness and get pointer to state */ 00102 if((rc = nfs4_Check_Stateid(&arg_CLOSE4.open_stateid, 00103 data->current_entry, 00104 &pstate_found, 00105 data, 00106 STATEID_SPECIAL_FOR_LOCK, 00107 tag)) != NFS4_OK) 00108 { 00109 res_CLOSE4.status = rc; 00110 LogDebug(COMPONENT_STATE, 00111 "CLOSE failed nfs4_Check_Stateid"); 00112 return res_CLOSE4.status; 00113 } 00114 00115 /* Check is held locks remain */ 00116 glist_for_each(glist, &pstate_found->state_data.share.share_lockstates) 00117 { 00118 state_t * plock_state = glist_entry(glist, 00119 state_t, 00120 state_data.lock.state_sharelist); 00121 00122 if(!glist_empty(&plock_state->state_data.lock.state_locklist)) 00123 { 00124 res_CLOSE4.status = NFS4ERR_LOCKS_HELD; 00125 00126 LogDebug(COMPONENT_STATE, 00127 "NFS4 Close with existing locks"); 00128 00129 return res_CLOSE4.status; 00130 } 00131 } 00132 00133 00134 /* Handle stateid/seqid for success */ 00135 update_stateid(pstate_found, 00136 &res_CLOSE4.CLOSE4res_u.open_stateid, 00137 data, 00138 tag); 00139 00140 /* File is closed, release the corresponding lock states */ 00141 glist_for_each_safe(glist, glistn, &pstate_found->state_data.share.share_lockstates) 00142 { 00143 state_t * plock_state = glist_entry(glist, 00144 state_t, 00145 state_data.lock.state_sharelist); 00146 00147 if(state_del(plock_state, 00148 &state_status) != STATE_SUCCESS) 00149 { 00150 LogDebug(COMPONENT_STATE, 00151 "CLOSE failed to release lock stateid error %s", 00152 state_err_str(state_status)); 00153 } 00154 } 00155 00156 /* File is closed, release the corresponding state */ 00157 if(state_del(pstate_found, 00158 &state_status) != STATE_SUCCESS) 00159 { 00160 LogDebug(COMPONENT_STATE, 00161 "CLOSE failed to release stateid error %s", 00162 state_err_str(state_status)); 00163 } 00164 00165 #ifdef _PNFS_MDS 00166 /* We can't simply grab a pointer to a layout state and free it 00167 later, since a client could have multiple layout states (since a 00168 layout state covers layouts of only one layout type) each marked 00169 return_on_close. */ 00170 00171 glist_for_each(glist, &data->current_entry->object.file.state_list) 00172 { 00173 state_t *pstate = glist_entry(glist, state_t, state_list); 00174 00175 if ((pstate->state_type == STATE_TYPE_SHARE) && 00176 (pstate->state_powner->so_type == STATE_OPEN_OWNER_NFSV4) && 00177 (pstate->state_powner->so_owner.so_nfs4_owner.so_clientid == 00178 data->psession->clientid)) 00179 { 00180 last_close = FALSE; 00181 break; 00182 } 00183 } 00184 00185 if (last_close) 00186 { 00187 glist_for_each_safe(glist, 00188 glistn, 00189 &data->current_entry->object.file.state_list) 00190 { 00191 state_t *pstate = glist_entry(glist, state_t, state_list); 00192 bool_t deleted = FALSE; 00193 struct pnfs_segment entire = { 00194 .io_mode = LAYOUTIOMODE4_ANY, 00195 .offset = 0, 00196 .length = NFS4_UINT64_MAX 00197 }; 00198 00199 if ((pstate->state_type == STATE_TYPE_LAYOUT) && 00200 (pstate->state_powner->so_type == STATE_CLIENTID_OWNER_NFSV4) && 00201 (pstate->state_powner->so_owner.so_nfs4_owner.so_clientid == 00202 data->psession->clientid) && 00203 pstate->state_data.layout.state_return_on_close) 00204 { 00205 nfs4_return_one_state(data->current_entry, 00206 data->pcontext, 00207 TRUE, 00208 FALSE, 00209 0, 00210 pstate, 00211 entire, 00212 0, 00213 NULL, 00214 &deleted); 00215 if (!deleted) 00216 { 00217 LogCrit(COMPONENT_PNFS, 00218 "Layout state not destroyed on last close return."); 00219 } 00220 } 00221 } 00222 } 00223 #endif /* _PNFS_MDS */ 00224 00225 00226 /* Close the file in FSAL through the cache inode */ 00227 if(cache_inode_close(data->current_entry, 00228 0, 00229 &cache_status) != CACHE_INODE_SUCCESS) 00230 { 00231 res_CLOSE4.status = nfs4_Errno(cache_status); 00232 return res_CLOSE4.status; 00233 } 00234 00235 res_CLOSE4.status = NFS4_OK; 00236 00237 if(isFullDebug(COMPONENT_STATE) && isFullDebug(COMPONENT_MEMLEAKS)) 00238 { 00239 nfs_State_PrintAll(); 00240 nfs4_owner_PrintAll(); 00241 } 00242 00243 return NFS4_OK; 00244 } /* nfs41_op_close */ 00245 00256 void nfs41_op_close_Free(CLOSE4res * resp) 00257 { 00258 /* Nothing to be done */ 00259 return; 00260 } /* nfs41_op_close_Free */