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 /* _SOLARIS */ 00043 00044 #include "LRU_List.h" 00045 #include "log.h" 00046 #include "HashData.h" 00047 #include "HashTable.h" 00048 #include "fsal.h" 00049 #include "cache_inode.h" 00050 #include "cache_content.h" 00051 00052 #include <unistd.h> 00053 #include <sys/types.h> 00054 #include <sys/param.h> 00055 #include <time.h> 00056 #include <pthread.h> 00057 #include <errno.h> 00058 #include <string.h> 00059 00078 cache_content_status_t cache_content_flush(cache_content_entry_t * pentry, 00079 cache_content_flush_behaviour_t flushhow, 00080 cache_content_client_t * pclient, 00081 fsal_op_context_t * pcontext, 00082 cache_content_status_t * pstatus) 00083 { 00084 fsal_handle_t *pfsal_handle = NULL; 00085 fsal_status_t fsal_status; 00086 fsal_path_t local_path; 00087 00088 *pstatus = CACHE_CONTENT_SUCCESS; 00089 00090 /* stat */ 00091 pclient->stat.func_stats.nb_call[CACHE_CONTENT_FLUSH] += 1; 00092 00093 /* Get the fsal handle */ 00094 pfsal_handle = &pentry->pentry_inode->handle; 00095 00096 /* Lock related Cache Inode pentry to avoid concurrency while read/write operation */ 00097 pthread_rwlock_wrlock(&pentry->pentry_inode->content_lock); 00098 00099 /* Convert the path to FSAL path */ 00100 fsal_status = 00101 FSAL_str2path(pentry->local_fs_entry.cache_path_data, MAXPATHLEN, &local_path); 00102 00103 if(FSAL_IS_ERROR(fsal_status)) 00104 { 00105 *pstatus = CACHE_CONTENT_FSAL_ERROR; 00106 00107 /* Unlock related Cache Inode pentry */ 00108 pthread_rwlock_unlock(&pentry->pentry_inode->content_lock); 00109 00110 /* stat */ 00111 pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_FLUSH] += 1; 00112 00113 return *pstatus; 00114 } 00115 /* Write the data from the local data file to the fs file */ 00116 fsal_status = FSAL_rcp(pfsal_handle, pcontext, &local_path, FSAL_RCP_LOCAL_TO_FS); 00117 if(FSAL_IS_ERROR(fsal_status)) 00118 { 00119 LogMajor(COMPONENT_CACHE_CONTENT, 00120 "Error %d,%d from FSAL_rcp when flushing file", fsal_status.major, 00121 fsal_status.minor); 00122 00123 /* Unlock related Cache Inode pentry */ 00124 pthread_rwlock_unlock(&pentry->pentry_inode->content_lock); 00125 00126 *pstatus = CACHE_CONTENT_FSAL_ERROR; 00127 00128 /* stat */ 00129 pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_FLUSH] += 1; 00130 00131 return *pstatus; 00132 } 00133 00134 /* To delete or not to delete ? That is the question ... */ 00135 if(flushhow == CACHE_CONTENT_FLUSH_AND_DELETE) 00136 { 00137 /* Remove the index file from the data cache */ 00138 if(unlink(pentry->local_fs_entry.cache_path_index)) 00139 { 00140 /* Unlock related Cache Inode pentry */ 00141 pthread_rwlock_unlock(&pentry->pentry_inode->content_lock); 00142 00143 LogCrit(COMPONENT_CACHE_CONTENT, "Can't unlink flushed index %s, errno=%u(%s)", 00144 pentry->local_fs_entry.cache_path_index, errno, strerror(errno)); 00145 *pstatus = CACHE_CONTENT_LOCAL_CACHE_ERROR; 00146 return *pstatus; 00147 } 00148 00149 /* Remove the data file from the data cache */ 00150 if(unlink(pentry->local_fs_entry.cache_path_data)) 00151 { 00152 /* Unlock related Cache Inode pentry */ 00153 pthread_rwlock_unlock(&pentry->pentry_inode->content_lock); 00154 00155 LogCrit(COMPONENT_CACHE_CONTENT, "Can't unlink flushed index %s, errno=%u(%s)", 00156 pentry->local_fs_entry.cache_path_data, errno, strerror(errno)); 00157 *pstatus = CACHE_CONTENT_LOCAL_CACHE_ERROR; 00158 return *pstatus; 00159 } 00160 } 00161 00162 /* Unlock related Cache Inode pentry */ 00163 pthread_rwlock_unlock(&pentry->pentry_inode->content_lock); 00164 00165 /* Exit the function with no error */ 00166 pclient->stat.func_stats.nb_success[CACHE_CONTENT_FLUSH] += 1; 00167 00168 /* Update the internal metadata */ 00169 pentry->internal_md.last_flush_time = time(NULL); 00170 pentry->local_fs_entry.sync_state = SYNC_OK; 00171 00172 return *pstatus; 00173 } /* cache_content_flush */ 00174 00193 cache_content_status_t cache_content_refresh(cache_content_entry_t * pentry, 00194 cache_content_client_t * pclient, 00195 fsal_op_context_t * pcontext, 00196 cache_content_refresh_how_t how, 00197 cache_content_status_t * pstatus) 00198 { 00199 fsal_handle_t *pfsal_handle = NULL; 00200 fsal_status_t fsal_status; 00201 cache_entry_t *pentry_inode = NULL; 00202 fsal_path_t local_path; 00203 struct stat buffstat; 00204 00205 *pstatus = CACHE_CONTENT_SUCCESS; 00206 00207 /* stat */ 00208 pclient->stat.func_stats.nb_call[CACHE_CONTENT_REFRESH] += 1; 00209 00210 /* Get the related cache inode entry */ 00211 pentry_inode = (cache_entry_t *) pentry->pentry_inode; 00212 00213 /* Get the fsal handle */ 00214 pfsal_handle = &pentry_inode->handle; 00215 00216 /* Convert the path to FSAL path */ 00217 fsal_status = 00218 FSAL_str2path(pentry->local_fs_entry.cache_path_data, MAXPATHLEN, &local_path); 00219 00220 if(FSAL_IS_ERROR(fsal_status)) 00221 { 00222 *pstatus = CACHE_CONTENT_FSAL_ERROR; 00223 00224 /* stat */ 00225 pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_FLUSH] += 1; 00226 00227 return *pstatus; 00228 } 00229 00230 /* Stat the data file to check for incoherency (this can occur in a crash recovery context) */ 00231 if(stat(pentry->local_fs_entry.cache_path_data, &buffstat) == -1) 00232 { 00233 *pstatus = CACHE_CONTENT_FSAL_ERROR; 00234 00235 LogMajor(COMPONENT_CACHE_CONTENT, 00236 "cache_content_refresh: could'nt stat on %s, errno=%u(%s)", 00237 pentry->local_fs_entry.cache_path_data, errno, strerror(errno)); 00238 00239 /* stat */ 00240 pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_FLUSH] += 1; 00241 00242 return *pstatus; 00243 } 00244 00245 if(how == FORCE_FROM_FSAL) 00246 LogFullDebug(COMPONENT_FSAL,"FORCE FROM FSAL"); 00247 else 00248 LogFullDebug(COMPONENT_FSAL,"FORCE FROM FSAL INACTIVE"); 00249 00250 00251 if((how != FORCE_FROM_FSAL) 00252 && (buffstat.st_mtime > (time_t) pentry_inode->attributes.mtime.seconds)) 00253 { 00254 *pstatus = CACHE_CONTENT_SUCCESS; 00255 00256 LogDebug(COMPONENT_CACHE_CONTENT, 00257 "Entry %p is more recent in data cache, keeping it", pentry); 00258 pentry_inode->attributes.mtime.seconds = buffstat.st_mtime; 00259 pentry_inode->attributes.mtime.nseconds = 0; 00260 pentry_inode->attributes.atime.seconds = buffstat.st_atime; 00261 pentry_inode->attributes.atime.nseconds = 0; 00262 pentry_inode->attributes.ctime.seconds = buffstat.st_ctime; 00263 pentry_inode->attributes.ctime.nseconds = 0; 00264 } 00265 else 00266 { 00267 /* Write the data from the local data file to the fs file */ 00268 fsal_status = FSAL_rcp(pfsal_handle, pcontext, &local_path, 00269 FSAL_RCP_FS_TO_LOCAL); 00270 if(FSAL_IS_ERROR(fsal_status)) 00271 { 00272 *pstatus = CACHE_CONTENT_FSAL_ERROR; 00273 LogMajor(COMPONENT_CACHE_CONTENT, 00274 "FSAL_rcp failed for %s: fsal_status.major=%u fsal_status.minor=%u", 00275 pentry->local_fs_entry.cache_path_data, fsal_status.major, 00276 fsal_status.minor); 00277 00278 /* stat */ 00279 pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_REFRESH] += 1; 00280 00281 return *pstatus; 00282 } 00283 00284 /* Exit the function with no error */ 00285 pclient->stat.func_stats.nb_success[CACHE_CONTENT_REFRESH] += 1; 00286 00287 /* Update the internal metadata */ 00288 pentry->internal_md.last_refresh_time = time(NULL); 00289 pentry->local_fs_entry.sync_state = SYNC_OK; 00290 00291 } 00292 00293 return *pstatus; 00294 } /* cache_content_refresh */ 00295 00296 cache_content_status_t cache_content_sync_all(cache_content_client_t * pclient, 00297 fsal_op_context_t * pcontext, 00298 cache_content_status_t * pstatus) 00299 { 00300 *pstatus = CACHE_CONTENT_SUCCESS; 00301 return *pstatus; 00302 } /* cache_content_sync_all */