nfs-ganesha 1.4

cache_content_flush.c

Go to the documentation of this file.
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 */