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 /* _SOLARIS */ 00044 00045 #include "LRU_List.h" 00046 #include "log.h" 00047 #include "HashData.h" 00048 #include "HashTable.h" 00049 #include "fsal.h" 00050 #include "cache_inode.h" 00051 #include "cache_content.h" 00052 00053 #include <unistd.h> 00054 #include <sys/types.h> 00055 #include <sys/param.h> 00056 #include <time.h> 00057 #include <pthread.h> 00058 #include <errno.h> 00059 #include <fcntl.h> 00060 #include <string.h> 00061 00080 cache_content_entry_t *cache_content_new_entry(cache_entry_t * pentry_inode, 00081 cache_content_spec_data_t * pspecdata, 00082 cache_content_client_t * pclient, 00083 cache_content_add_behaviour_t how, 00084 fsal_op_context_t * pcontext, 00085 cache_content_status_t * pstatus) 00086 { 00087 cache_content_status_t status; 00088 cache_content_entry_t *pfc_pentry = NULL; 00089 int tmpfd; 00090 00091 /* Set the return default to CACHE_CONTENT_SUCCESS */ 00092 *pstatus = CACHE_CONTENT_SUCCESS; 00093 00094 /* stat */ 00095 pclient->stat.func_stats.nb_call[CACHE_CONTENT_NEW_ENTRY] += 1; 00096 00097 if(pentry_inode == NULL) 00098 { 00099 *pstatus = CACHE_CONTENT_INVALID_ARGUMENT; 00100 00101 /* stat */ 00102 pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_NEW_ENTRY] += 1; 00103 00104 return NULL; 00105 } 00106 00107 if(how != RENEW_ENTRY) 00108 { 00109 /* Get the entry from the preallocated pool */ 00110 pfc_pentry = pool_alloc(pclient->content_pool, NULL); 00111 00112 if(pfc_pentry == NULL) 00113 { 00114 *pstatus = CACHE_CONTENT_MALLOC_ERROR; 00115 00116 LogDebug(COMPONENT_CACHE_CONTENT, 00117 "cache_content_new_entry: can't allocate a new fc_entry from cache pool"); 00118 00119 /* stat */ 00120 pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_NEW_ENTRY] += 1; 00121 00122 return NULL; 00123 } 00124 } /* if( how != RENEW_ENTRY ) */ 00125 00126 /* Set the path to the local files */ 00127 if((status = cache_content_create_name(pfc_pentry->local_fs_entry.cache_path_index, 00128 CACHE_CONTENT_INDEX_FILE, 00129 pcontext, 00130 pentry_inode, pclient)) != CACHE_CONTENT_SUCCESS) 00131 { 00132 pool_free(pclient->content_pool, pfc_pentry); 00133 00134 *pstatus = CACHE_CONTENT_ENTRY_EXISTS; 00135 00136 /* stat */ 00137 pclient->stat.func_stats.nb_err_retryable[CACHE_CONTENT_NEW_ENTRY] += 1; 00138 00139 LogEvent(COMPONENT_CACHE_CONTENT, 00140 "cache_content_new_entry: entry's index pathname could not be created:%u", 00141 status ); 00142 00143 return NULL; 00144 } 00145 00146 if((status = cache_content_create_name(pfc_pentry->local_fs_entry.cache_path_data, 00147 CACHE_CONTENT_DATA_FILE, 00148 pcontext, 00149 pentry_inode, pclient)) != CACHE_CONTENT_SUCCESS) 00150 { 00151 pool_free(pclient->content_pool, pfc_pentry); 00152 00153 *pstatus = CACHE_CONTENT_ENTRY_EXISTS; 00154 00155 /* stat */ 00156 pclient->stat.func_stats.nb_err_retryable[CACHE_CONTENT_NEW_ENTRY] += 1; 00157 00158 LogEvent(COMPONENT_CACHE_CONTENT, 00159 "cache_content_new_entry: entry's data pathname could not be created"); 00160 00161 return NULL; 00162 } 00163 00164 LogDebug(COMPONENT_CACHE_CONTENT, 00165 "added file content cache entry: Data=%s Index=%s", 00166 pfc_pentry->local_fs_entry.cache_path_data, 00167 pfc_pentry->local_fs_entry.cache_path_index); 00168 00169 /* Set the sync state */ 00170 pfc_pentry->local_fs_entry.sync_state = JUST_CREATED; 00171 00172 /* Set the internal_md */ 00173 pfc_pentry->internal_md.read_time = 0; 00174 pfc_pentry->internal_md.mod_time = 0; 00175 pfc_pentry->internal_md.refresh_time = 0; 00176 pfc_pentry->internal_md.alloc_time = time(NULL); 00177 pfc_pentry->internal_md.last_flush_time = 0; 00178 pfc_pentry->internal_md.last_refresh_time = 0; 00179 pfc_pentry->internal_md.valid_state = STATE_OK; 00180 00181 /* Set the local fd info */ 00182 pfc_pentry->local_fs_entry.opened_file.local_fd = -1; 00183 pfc_pentry->local_fs_entry.opened_file.last_op = 0; 00184 00185 /* Create the data file if entry is not recoverd (in this case, it already exists) */ 00186 if(how == ADD_ENTRY || how == RENEW_ENTRY) 00187 { 00188 if((tmpfd = creat(pfc_pentry->local_fs_entry.cache_path_data, 0750)) == -1) 00189 { 00190 pool_free(pclient->content_pool, pfc_pentry); 00191 00192 *pstatus = CACHE_CONTENT_LOCAL_CACHE_ERROR; 00193 00194 LogEvent(COMPONENT_CACHE_CONTENT, 00195 "cache_content_new_entry: data cache file could not be created, errno=%d (%s)", 00196 errno, strerror(errno)); 00197 00198 /* stat */ 00199 pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_NEW_ENTRY] += 1; 00200 00201 return NULL; 00202 } 00203 00204 /* Close the new fd */ 00205 close(tmpfd); 00206 00207 } 00208 00209 /* if( how == ADD_ENTRY || how == RENEW_ENTRY ) */ 00210 /* Cache the data from FSAL if there are some */ 00211 /* Add the entry to the related cache inode entry */ 00212 pfc_pentry->pentry_inode = pentry_inode; 00213 00214 /* Data cache is considered as more pertinent as data below in case of crash recovery */ 00215 if(how != RECOVER_ENTRY) 00216 { 00217 /* Get the file content from the FSAL, populate the data cache */ 00218 if(pclient->flush_force_fsal == 0) 00219 cache_content_refresh(pfc_pentry, pclient, pcontext, DEFAULT_REFRESH, &status); 00220 else 00221 cache_content_refresh(pfc_pentry, pclient, pcontext, FORCE_FROM_FSAL, &status); 00222 00223 if(status != CACHE_CONTENT_SUCCESS) 00224 { 00225 pool_free(pclient->content_pool, pfc_pentry); 00226 00227 *pstatus = status; 00228 00229 LogEvent(COMPONENT_CACHE_CONTENT, 00230 "cache_content_new_entry: data cache file could not read from FSAL, status=%u", 00231 status); 00232 00233 /* stat */ 00234 pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_NEW_ENTRY] += 1; 00235 00236 return NULL; 00237 } 00238 } 00239 /* if ( how != RECOVER_ENTRY ) */ 00240 return pfc_pentry; 00241 } /* cache_content_new_entry */