nfs-ganesha 1.4

fsal_init.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  */
00004 
00014 #ifdef HAVE_CONFIG_H
00015 #include "config.h"
00016 #endif
00017 
00018 #include "fsal.h"
00019 #include "fsal_internal.h"
00020 #include "fsal_common.h"
00021 
00022 #include <string.h>
00023 #include <unistd.h>
00024 
00025 
00026 extern size_t i_snapshots;
00027 extern snapshot_t *p_snapshots;
00028 extern pthread_rwlock_t vfs_lock;
00029 pthread_t snapshot_thread;
00030 
00031 __attribute(( unused )) static void *SnapshotThread(void *);
00032 
00033 size_t stack_size = 0;
00034 
00056 fsal_status_t ZFSFSAL_Init(fsal_parameter_t * init_info    /* IN */
00057     )
00058 {
00059   static int is_initialized = 0;
00060   fsal_status_t status;
00061   zfsfs_specific_initinfo_t *spec_info =
00062           (zfsfs_specific_initinfo_t *) &init_info->fs_specific_info;
00063 
00064   /* sanity check.  */
00065   if(is_initialized)
00066   {
00067     LogEvent(COMPONENT_FSAL, "INIT: blocking second call to FSAL_Init");
00068     Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_Init);
00069   }
00070 
00071   if(!init_info)
00072     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_Init);
00073 
00074   /* proceeds FSAL internal status initialization */
00075 
00076   status = fsal_internal_init_global(&(init_info->fsal_info),
00077                                      &(init_info->fs_common_info),
00078                                      &(init_info->fs_specific_info));
00079 
00080   if(FSAL_IS_ERROR(status))
00081     Return(status.major, status.minor, INDEX_FSAL_Init);
00082 
00083   /* Initilise the libzfswrap library */
00084   p_zhd = libzfswrap_init();
00085   if(!p_zhd)
00086   {
00087     LogCrit(COMPONENT_FSAL, "FSAL INIT: *** ERROR: Unable to initialize the libzfswrap library.");
00088     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_Init);
00089   }
00090 
00091   /* Mount the zpool */
00092   libzfswrap_vfs_t *p_vfs = libzfswrap_mount(spec_info->psz_zpool, "/tank", "");
00093   if(!p_vfs)
00094   {
00095     libzfswrap_exit(p_zhd);
00096     LogCrit(COMPONENT_FSAL, "FSAL INIT: *** ERROR: Unable to mount the file system.");
00097     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_Init);
00098   }
00099 
00100   /* List the snapshots of the given zpool and mount them */
00101   const char *psz_error;
00102   char **ppsz_snapshots;
00103   i_snapshots = libzfswrap_zfs_get_list_snapshots(p_zhd, spec_info->psz_zpool,
00104                                                   &ppsz_snapshots, &psz_error);
00105 
00106   if(i_snapshots > 0)
00107   {
00108     LogDebug(COMPONENT_FSAL, "FSAL INIT: Found %zu snapshots.", i_snapshots);
00109     p_snapshots = calloc(i_snapshots + 1, sizeof(*p_snapshots));
00110     p_snapshots[0].p_vfs = p_vfs;
00111     p_snapshots[0].index = 0;
00112 
00113     int i,j;
00114     for(i = 0; i < i_snapshots; i++)
00115     {
00116       libzfswrap_vfs_t *p_snap_vfs = libzfswrap_mount(ppsz_snapshots[i], ppsz_snapshots[i], "");
00117       if(!p_snap_vfs)
00118       {
00119         LogCrit(COMPONENT_FSAL, "FSAL INIT: *** ERROR: Unable to mount the snapshot %s", ppsz_snapshots[i]);
00120         for(j = i; j >= 0; j--)
00121           libzfswrap_umount(p_snapshots[j].p_vfs, 1);
00122 
00123         libzfswrap_exit(p_zhd);
00124         Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_Init);
00125       }
00126 
00127       /* Change the name of the snapshot from zpool_name@snap_name to snap_name
00128          The '@' character is allways present, so no need to check it */
00129       p_snapshots[i+1].psz_name = strdup(strchr(ppsz_snapshots[i], '@') + 1);
00130       p_snapshots[i+1].p_vfs = p_snap_vfs;
00131       p_snapshots[i+1].index = i + 1;
00132 
00133       free(ppsz_snapshots[i]);
00134     }
00135   }
00136   else
00137   {
00138     LogDebug(COMPONENT_FSAL, "FSAL INIT: No snapshot found.");
00139     p_snapshots = calloc(1, sizeof(*p_snapshots));
00140     p_snapshots[0].p_vfs = p_vfs;
00141     i_snapshots = 0;
00142   }
00143   pthread_rwlock_init(&vfs_lock, NULL);
00144 
00145   /* Create a thread to handle snapshot creation */
00146   if(spec_info->auto_snapshots)
00147   {
00148     LogDebug(COMPONENT_FSAL, "FSAL INIT: Creating the auto-snapshot thread");
00149     zfsfs_specific_initinfo_t *fs_configuration = malloc(sizeof(*fs_configuration));
00150     *fs_configuration = *spec_info;
00151 #if 0 
00152     if(pthread_create(&snapshot_thread, NULL, SnapshotThread, fs_configuration))
00153     {
00154       snapshot_thread = (pthread_t)NULL;
00155       ZFSFSAL_terminate();
00156       Return(ERR_FSAL_SERVERFAULT, 0, INDEX_FSAL_Init);
00157     }
00158 #endif
00159   }
00160   else
00161   {
00162     LogDebug(COMPONENT_FSAL, "FSAL INIT: No automatic snapshot creation");
00163     snapshot_thread = (pthread_t)NULL;
00164   }
00165 
00166   /* Everything went OK. */
00167   is_initialized = 1;
00168   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_Init);
00169 
00170 }
00171 
00172 /* To be called before exiting */
00173 fsal_status_t ZFSFSAL_terminate()
00174 {
00175   /* Join the snapshot thread if it does exist */
00176   if(snapshot_thread)
00177     pthread_join(snapshot_thread, NULL);
00178 
00179   /* Unmount every snapshots and free the memory */
00180   int i;
00181   for(i = i_snapshots; i >= 0; i--)
00182     libzfswrap_umount(p_snapshots[i].p_vfs, 1);
00183 
00184   for(i = 0; i < i_snapshots; i++)
00185     free(p_snapshots[i].psz_name);
00186   free(p_snapshots);
00187 
00188   pthread_rwlock_destroy(&vfs_lock);
00189 
00190   libzfswrap_exit(p_zhd);
00191   ReturnCode(ERR_FSAL_NO_ERROR, 0);
00192 }
00193 
00194 /* Take a snapshot */
00195 __attribute(( unused )) static libzfswrap_vfs_t *TakeSnapshotAndMount(const char *psz_zpool, const char *psz_prefix, char **ppsz_name)
00196 {
00197     char psz_buffer[FSAL_MAX_NAME_LEN];
00198     const char *psz_error;
00199     time_t time_now = time(NULL);
00200     struct tm *now = gmtime(&time_now);
00201 
00202     asprintf(ppsz_name, "%s%d_%02d_%02d-%02d_%02d",
00203              psz_prefix, now->tm_year + 1900, now->tm_mon,
00204              now->tm_mday, now->tm_hour, now->tm_min);
00205     libzfswrap_zfs_snapshot(p_zhd, psz_zpool, *ppsz_name, &psz_error);
00206 
00207     snprintf(psz_buffer, FSAL_MAX_NAME_LEN, "%s@%s%d_%02d_%02d-%02d_%02d",
00208              psz_zpool, psz_prefix, now->tm_year + 1900, now->tm_mon,
00209              now->tm_mday, now->tm_hour, now->tm_min);
00210 
00211     LogDebug(COMPONENT_FSAL, "SNAPSHOTS: creating a new snapshot '%s'", psz_buffer);
00212     return libzfswrap_mount(psz_buffer, psz_buffer, "");
00213 }
00214 
00215 __attribute(( unused )) static void AddSnapshot(libzfswrap_vfs_t *p_vfs, char *psz_name)
00216 {
00217     i_snapshots++;
00218     if( ( p_snapshots = realloc(p_snapshots, (i_snapshots + 1) * sizeof(*p_snapshots)) ) == NULL )
00219      {
00220        LogMajor(COMPONENT_FSAL, "SNAPSHOTS: recan't allocate memory... exiting");
00221        free( p_snapshots ) ;
00222        exit( 1 ) ;
00223        return ;
00224      }
00225 
00226     p_snapshots[i_snapshots].psz_name = psz_name;
00227     p_snapshots[i_snapshots].p_vfs = p_vfs;
00228     p_snapshots[i_snapshots].index = i_snapshots;
00229 }
00230 
00231 __attribute(( unused )) static int CountSnapshot(const char *psz_prefix)
00232 {
00233   int i,count = 0;
00234   size_t len = strlen(psz_prefix);
00235 
00236   for(i = 1; i < i_snapshots + 1; i++)
00237     if(!strncmp(p_snapshots[i].psz_name, psz_prefix, len))
00238       count++;
00239 
00240   return count;
00241 }
00242 
00243 __attribute(( unused )) static void RemoveOldSnapshots(const char *psz_prefix, int number)
00244 {
00245   int i;
00246   char *psz_name;
00247   const char *psz_error;
00248   libzfswrap_vfs_t *p_vfs;
00249   size_t len = strlen(psz_prefix);
00250 
00251   for(i = 0; i < number; i++)
00252   {
00253     int j, index = 1;
00254     for(j = 1; j < i_snapshots + 1; j++)
00255     {
00256       if(!strncmp(p_snapshots[j].psz_name, psz_prefix, len))
00257       {
00258         if(strcmp(p_snapshots[j].psz_name, p_snapshots[index].psz_name) < 0)
00259           index = j;
00260       }
00261     }
00262 
00263     /* We found a snapshot to remove */
00264     psz_name = p_snapshots[index].psz_name;
00265     p_vfs = p_snapshots[index].p_vfs;
00266 
00267     if(index != i_snapshots)
00268         memmove(&p_snapshots[index], &p_snapshots[index+1], (i_snapshots - index) * sizeof(*p_snapshots));
00269 
00270     i_snapshots--;
00271     if( ( p_snapshots = realloc(p_snapshots, (i_snapshots + 1) * sizeof(*p_snapshots)) ) == NULL )
00272      {
00273        LogMajor(COMPONENT_FSAL, "SNAPSHOTS: recan't allocate memory... exiting");
00274        free( p_snapshots ) ;
00275        exit( 1 ) ;
00276        return ;
00277      }
00278 
00279     /* Really remove the snapshot */
00280     LogDebug(COMPONENT_FSAL, "SNAPSHOTS: removing the snapshot '%s' (%d/%d)", psz_name, i + 1, number);
00281     libzfswrap_umount(p_vfs, 1);
00282     libzfswrap_zfs_snapshot_destroy(p_zhd, "tank", psz_name, &psz_error);
00283   }
00284 }
00285 
00286 /* Thread that handle snapshots */
00287 __attribute(( unused )) static void *SnapshotThread(void *data)
00288 {
00289   zfsfs_specific_initinfo_t *fs_info = (zfsfs_specific_initinfo_t*)data;
00290 
00291   while(1)
00292   {
00293     /* Compute the time of the next snapshot */
00294     time_t time_now = time(NULL);
00295     struct tm *now = gmtime(&time_now);
00296     unsigned int i_wait;
00297     char *psz_name;
00298 
00299     if(now->tm_min >= fs_info->snap_hourly_time)
00300       i_wait = 60 - (now->tm_min - fs_info->snap_hourly_time);
00301     else
00302       i_wait = fs_info->snap_hourly_time - now->tm_min;
00303 
00304     /* Sleep for the given time */
00305     LogDebug(COMPONENT_FSAL, "SNAPSHOTS: next snapshot in %u minutes", i_wait);
00306     sleep(i_wait*60);
00307 
00308     /* Create a snapshot */
00309     libzfswrap_vfs_t *p_new = TakeSnapshotAndMount(fs_info->psz_zpool,
00310                                                    fs_info->psz_snap_hourly_prefix,
00311                                                    &psz_name);
00312 
00313     /* Add the snapshot to the list of snapshots */
00314     ZFSFSAL_VFS_WRLock();
00315     AddSnapshot(p_new, psz_name);
00316 
00317     /* Remove spurious snapshots */
00318     int i_hourly_snap = CountSnapshot(fs_info->psz_snap_hourly_prefix);
00319     if(i_hourly_snap > fs_info->snap_hourly_number)
00320       RemoveOldSnapshots(fs_info->psz_snap_hourly_prefix, i_hourly_snap - fs_info->snap_hourly_number);
00321 
00322     ZFSFSAL_VFS_Unlock();
00323   }
00324 
00325   return NULL;
00326 }