nfs-ganesha 1.4

fsal_up_thread.c

Go to the documentation of this file.
00001 /*
00002  * This program is free software; you can redistribute it and/or
00003  * modify it under the terms of the GNU Lesser General Public
00004  * License as published by the Free Software Foundation; either
00005  * version 3 of the License, or (at your option) any later version.
00006  *
00007  * This program is distributed in the hope that it will be useful,
00008  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00009  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00010  * Lesser General Public License for more details.
00011  *
00012  * You should have received a copy of the GNU Lesser General Public
00013  * License along with this library; if not, write to the Free Software
00014  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00015  *
00016  * ---------------------------------------
00017  */
00018 
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026 
00027 #ifdef _SOLARIS
00028 #include "solaris_port.h"
00029 #endif
00030 
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <pthread.h>
00034 #include "nfs_core.h"
00035 #include "log.h"
00036 #include "fsal_up.h"
00037 #include "err_fsal.h"
00038 #include "nfs_tcb.h"
00039 
00040 extern fsal_status_t dumb_fsal_up_invalidate_step2(fsal_up_event_data_t *);
00041 
00042 static int fsal_up_thread_exists(exportlist_t *entry);
00043 static struct glist_head       fsal_up_process_queue;
00044 nfs_tcb_t                      fsal_up_process_tcb;
00045 
00046 fsal_status_t  schedule_fsal_up_event_process(fsal_up_event_t *arg)
00047 {
00048   int rc;
00049   fsal_status_t ret = {0, 0};
00050 
00051   /* Events which needs quick response, and locking events wich
00052      has its own queue gets processed here, rest will be queued. */
00053   if (arg->event_type == FSAL_UP_EVENT_LOCK_GRANT ||
00054       arg->event_type == FSAL_UP_EVENT_LOCK_AVAIL)
00055     {
00056       arg->event_process_func(&arg->event_data);
00057 
00058       gsh_free(arg->event_data.event_context.fsal_data.fh_desc.start);
00059       pthread_mutex_lock(&nfs_param.fsal_up_param.event_pool_lock);
00060       pool_free(nfs_param.fsal_up_param.event_pool, arg);
00061       pthread_mutex_unlock(&nfs_param.fsal_up_param.event_pool_lock);
00062       return ret;
00063     }
00064 
00065   if(arg->event_type == FSAL_UP_EVENT_INVALIDATE)
00066     {
00067       arg->event_process_func(&arg->event_data);
00068       /* Step2 where we perform close; which could be expensive operation
00069          so deffer it to the separate thread. */
00070       arg->event_process_func = dumb_fsal_up_invalidate_step2;
00071     }
00072 
00073   /* Now queue them for further process. */
00074   LogFullDebug(COMPONENT_FSAL_UP, "Schedule %p", arg);
00075 
00076   P(fsal_up_process_tcb.tcb_mutex);
00077   glist_add_tail(&fsal_up_process_queue, &arg->event_list);
00078   rc = pthread_cond_signal(&fsal_up_process_tcb.tcb_condvar);
00079   LogFullDebug(COMPONENT_FSAL_UP,"Signaling tcb_condvar\n");
00080   if (rc == -1)
00081     {
00082       LogDebug(COMPONENT_FSAL_UP,
00083                    "Unable to signal FSAL_UP Process Thread");
00084       glist_del(&arg->event_list);
00085       ret.major = ERR_FSAL_FAULT;
00086     }
00087   V(fsal_up_process_tcb.tcb_mutex);
00088   return ret;
00089 }
00090 
00091 /* This thread processes FSAL UP events. */
00092 void *fsal_up_process_thread(void *UnUsedArg)
00093 {
00094   struct timeval             now;
00095   struct timespec            timeout;
00096   fsal_up_event_t          * fupevent;
00097   int                        rc;
00098 
00099   SetNameFunction("fsal_up_process_thread");
00100 
00101   init_glist(&fsal_up_process_queue);
00102   tcb_new(&fsal_up_process_tcb, "FSAL_UP Process Thread");
00103 
00104   if (mark_thread_existing(&fsal_up_process_tcb) == PAUSE_EXIT)
00105     {
00106       /* Oops, that didn't last long... exit. */
00107       mark_thread_done(&fsal_up_process_tcb);
00108       LogDebug(COMPONENT_INIT,
00109                "FSAL_UP Process Thread: Exiting before initialization");
00110       return NULL;
00111     }
00112 
00113   LogFullDebug(COMPONENT_FSAL_UP,
00114           "FSAL_UP Process Thread: my pthread id is %p",
00115           (caddr_t) pthread_self());
00116 
00117   while(1)
00118     {
00119       /* Check without tcb lock*/
00120       if ((fsal_up_process_tcb.tcb_state != STATE_AWAKE) ||
00121           glist_empty(&fsal_up_process_queue))
00122         {
00123           while(1)
00124             {
00125               P(fsal_up_process_tcb.tcb_mutex);
00126               if ((fsal_up_process_tcb.tcb_state == STATE_AWAKE) &&
00127                   !glist_empty(&fsal_up_process_queue))
00128                 {
00129                   V(fsal_up_process_tcb.tcb_mutex);
00130                   LogDebug(COMPONENT_INIT, "FSAL_UP Process Thread: breaking..1");
00131                   break;
00132                 }
00133               switch(thread_sm_locked(&fsal_up_process_tcb))
00134                 {
00135                   case THREAD_SM_RECHECK:
00136                   V(fsal_up_process_tcb.tcb_mutex);
00137                   continue;
00138 
00139                   case THREAD_SM_BREAK:
00140                   if (glist_empty(&fsal_up_process_queue))
00141                     {
00142                       gettimeofday(&now, NULL);
00143                       timeout.tv_sec = 10 + now.tv_sec;
00144                       timeout.tv_nsec = 0;
00145                       rc = pthread_cond_timedwait(&fsal_up_process_tcb.tcb_condvar,
00146                                                   &fsal_up_process_tcb.tcb_mutex,
00147                                                   &timeout);
00148                       LogFullDebug(COMPONENT_INIT,
00149                                    "FSAL_UP Process Thread: wokeup:%d", rc);
00150                     }
00151                   V(fsal_up_process_tcb.tcb_mutex);
00152                   continue;
00153 
00154                   case THREAD_SM_EXIT:
00155                   V(fsal_up_process_tcb.tcb_mutex);
00156                   return NULL;
00157                 }
00158              }
00159           }
00160         P(fsal_up_process_tcb.tcb_mutex);
00161         fupevent = glist_first_entry(&fsal_up_process_queue,
00162                                      fsal_up_event_t,
00163                                      event_list);
00164         if(fupevent != NULL)
00165           {
00166             /* Pull the event off of the list */
00167             glist_del(&fupevent->event_list);
00168 
00169             /* Release the mutex */
00170             V(fsal_up_process_tcb.tcb_mutex);
00171             fupevent->event_process_func(&fupevent->event_data);
00172             gsh_free(fupevent->event_data.event_context.fsal_data.fh_desc.start);
00173             pthread_mutex_lock(&nfs_param.fsal_up_param.event_pool_lock);
00174             pool_free(nfs_param.fsal_up_param.event_pool, fupevent);
00175             pthread_mutex_unlock(&nfs_param.fsal_up_param.event_pool_lock);
00176 
00177             continue;
00178           }
00179         V(fsal_up_process_tcb.tcb_mutex);
00180     }
00181   tcb_remove(&fsal_up_process_tcb);
00182 }
00183 
00184 void create_fsal_up_threads()
00185 {
00186   int rc, id;
00187   pthread_attr_t attr_thr;
00188   fsal_up_arg_t *fsal_up_args;
00189   exportlist_t *pcurrent;
00190 
00191   memset(&attr_thr, 0, sizeof(attr_thr));
00192 
00193   /* Initialization of thread attrinbutes borrowed from nfs_init.c */
00194   if(pthread_attr_init(&attr_thr) != 0)
00195     LogDebug(COMPONENT_THREAD, "can't init pthread's attributes");
00196 
00197   if(pthread_attr_setscope(&attr_thr, PTHREAD_SCOPE_SYSTEM) != 0)
00198     LogDebug(COMPONENT_THREAD, "can't set pthread's scope");
00199 
00200   if(pthread_attr_setdetachstate(&attr_thr, PTHREAD_CREATE_JOINABLE) != 0)
00201     LogDebug(COMPONENT_THREAD, "can't set pthread's join state");
00202 
00203   if(pthread_attr_setstacksize(&attr_thr, THREAD_STACK_SIZE) != 0)
00204     LogDebug(COMPONENT_THREAD, "can't set pthread's stack size");
00205 
00206   /* The admin thread is the only other thread that may be
00207    * messing around with the export entries. */
00208 
00209   //  LOCK EXPORT LIST
00210   for(pcurrent = nfs_param.pexportlist;
00211       pcurrent != NULL;
00212       pcurrent = pcurrent->next)
00213     {
00214       if (pcurrent->use_fsal_up == FALSE)
00215         continue;
00216 
00217       /* Make sure there are not multiple fsal_up_threads handling multiple
00218        * exports on the same filesystem. This could potentially cause issues. */
00219       LogEvent(COMPONENT_INIT, "Checking if export id %d with filesystem "
00220                "id %llu.%llu already has an assigned FSAL_UP thread.",
00221                pcurrent->fsalid, pcurrent->filesystem_id.major,
00222                pcurrent->filesystem_id.minor);
00223 
00224       id = fsal_up_thread_exists(pcurrent);
00225       if (id)
00226         {
00227           LogEvent(COMPONENT_INIT, "Filesystem %llu.%llu already has an "
00228                    "assigned FSAL_UP with export id %d so export w/ id %d"
00229                    " is not being assigned a new FSAL_UP thread.",
00230                    pcurrent->filesystem_id.major,
00231                    pcurrent->filesystem_id.minor, id, pcurrent->id);
00232           continue;
00233         }
00234       else
00235         {
00236           LogEvent(COMPONENT_INIT, "Filesystem %llu.%llu export id %d does not"
00237                    " have an FSAL_UP thread yet, creating a thread now.",
00238                    pcurrent->filesystem_id.major, pcurrent->filesystem_id.minor,
00239                    pcurrent->id);
00240 
00241           if((fsal_up_args =
00242               gsh_calloc(1, sizeof(fsal_up_arg_t))) == NULL)
00243             {
00244               LogError(COMPONENT_INIT, ERR_SYS, ERR_MALLOC, errno);
00245               Fatal();
00246             }
00247 
00248           fsal_up_args->export_entry = pcurrent;
00249 
00250           if( ( rc = pthread_create( &pcurrent->fsal_up_thr, &attr_thr,
00251                                      fsal_up_thread,(void *)fsal_up_args)) != 0)
00252             {
00253               gsh_free(fsal_up_args);
00254               LogFatal(COMPONENT_THREAD,
00255                        "Could not create fsal_up_thread, error = %d (%s)",
00256                        errno, strerror(errno));
00257               Fatal();
00258             }
00259         }
00260     }
00261 }
00262 
00263 /* Given to pool_init() to be used as a constructor of
00264  * preallocated memory */
00265 void constructor_fsal_up_event_t(void *ptr,
00266                                  void *parameter)
00267 {
00268   return;
00269 }
00270 
00271 /* One pool can be used for all FSAL_UP used for exports. */
00272 void nfs_Init_FSAL_UP()
00273 {
00274   memset(&nfs_param.fsal_up_param, 0, sizeof(nfs_param.fsal_up_param));
00275 
00276   /* DEBUGGING */
00277   LogDebug(COMPONENT_INIT,
00278            "FSAL_UP: Initializing FSAL UP data pool");
00279   /* Allocation of the FSAL UP pool */
00280   nfs_param.fsal_up_param.event_pool
00281        = pool_init("FSAL UP Data Pool", sizeof(fsal_up_event_t),
00282                    pool_basic_substrate, NULL,
00283                    constructor_fsal_up_event_t, NULL);
00284   if(!(nfs_param.fsal_up_param.event_pool))
00285     {
00286       LogCrit(COMPONENT_INIT,
00287               "Error while allocating FSAL UP data pool");
00288       LogError(COMPONENT_INIT, ERR_SYS, ERR_MALLOC, errno);
00289       Fatal();
00290     }
00291 
00292   if(pthread_mutex_init(&nfs_param.fsal_up_param.event_pool_lock, NULL) != 0)
00293       LogCrit(COMPONENT_FSAL_UP, "FSAL_UP: Could not initialize event pool"
00294               " mutex.");
00295 
00296   return;
00297 }
00298 
00299 fsal_status_t process_event(fsal_up_event_t *myevent, fsal_up_event_functions_t *event_func)
00300 {
00301   fsal_status_t status = {0, 0};
00302 
00303   switch(myevent->event_type)
00304     {
00305     case FSAL_UP_EVENT_CREATE:
00306       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process CREATE event");
00307       myevent->event_process_func = event_func->fsal_up_create;
00308       break;
00309     case FSAL_UP_EVENT_UNLINK:
00310       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process UNLINK event");
00311       myevent->event_process_func = event_func->fsal_up_unlink;
00312       break;
00313     case FSAL_UP_EVENT_RENAME:
00314       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process RENAME event");
00315       myevent->event_process_func = event_func->fsal_up_rename;
00316       break;
00317     case FSAL_UP_EVENT_COMMIT:
00318       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process COMMIT event");
00319       myevent->event_process_func = event_func->fsal_up_commit;
00320       break;
00321     case FSAL_UP_EVENT_WRITE:
00322       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process WRITE event");
00323       myevent->event_process_func = event_func->fsal_up_write;
00324       break;
00325     case FSAL_UP_EVENT_LINK:
00326       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process LINK event");
00327       myevent->event_process_func = event_func->fsal_up_link;
00328       break;
00329     case FSAL_UP_EVENT_LOCK_GRANT:
00330       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process LOCK GRANT event");
00331       myevent->event_process_func = event_func->fsal_up_lock_grant;
00332       break;
00333     case FSAL_UP_EVENT_LOCK_AVAIL:
00334       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process LOCK AVAIL event");
00335       myevent->event_process_func = event_func->fsal_up_lock_avail;
00336       break;
00337     case FSAL_UP_EVENT_OPEN:
00338       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process OPEN event");
00339       myevent->event_process_func = event_func->fsal_up_open;
00340       break;
00341     case FSAL_UP_EVENT_CLOSE:
00342       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process CLOSE event");
00343       myevent->event_process_func = event_func->fsal_up_close;
00344       break;
00345     case FSAL_UP_EVENT_SETATTR:
00346       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process SETATTR event");
00347       myevent->event_process_func = event_func->fsal_up_setattr;
00348       break;
00349     case FSAL_UP_EVENT_UPDATE:
00350       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process UPDATE event");
00351       myevent->event_process_func = event_func->fsal_up_update;
00352       break;
00353     case FSAL_UP_EVENT_INVALIDATE:
00354       LogDebug(COMPONENT_FSAL_UP, "FSAL_UP: Process INVALIDATE event");
00355       myevent->event_process_func = event_func->fsal_up_invalidate;
00356       break;
00357     default:
00358       LogDebug(COMPONENT_FSAL_UP, "Unknown FSAL UP event type found: %d",
00359               myevent->event_type);
00360       gsh_free(myevent->event_data.event_context.fsal_data.fh_desc.start);
00361 
00362       pthread_mutex_lock(&nfs_param.fsal_up_param.event_pool_lock);
00363       pool_free(nfs_param.fsal_up_param.event_pool, myevent);
00364       pthread_mutex_unlock(&nfs_param.fsal_up_param.event_pool_lock);
00365 
00366       ReturnCode(ERR_FSAL_NO_ERROR, 0);
00367     }
00368 
00369   status = schedule_fsal_up_event_process(myevent);
00370   return status;
00371 }
00372 
00373 /* The admin exportlist must be locked before calling this function!! */
00374 static int fsal_up_thread_exists(exportlist_t *entry)
00375 {
00376   exportlist_t *pcurrent;
00377   pthread_t zeros;
00378   memset(&zeros, 0, sizeof(zeros));
00379 
00380   /* Loop through all export entries and if any have the same
00381    * filesystem id, assume they really do export a directory
00382    * from the same filesystem. In this case, check if there is
00383    * already an FSAL UP thread running. If there is, return TRUE
00384    * so we don't create multiple threads. */
00385   for(pcurrent = nfs_param.pexportlist;
00386       pcurrent != NULL;
00387       pcurrent = pcurrent->next)
00388     {
00389       if (pcurrent == entry)
00390         continue;
00391 
00392       if (pcurrent->use_fsal_up == FALSE)
00393         continue;
00394 
00395       /* Only check if major is different */
00396       if (pcurrent->filesystem_id.major != entry->filesystem_id.major)
00397         continue;
00398 
00399       /* Is this the right wayt to check if a pthread reference is valid? */
00400       if (memcmp(&pcurrent->fsal_up_thr, &zeros, sizeof(pthread_t)) != 0)
00401         return pcurrent->id; /* Meaning a thread exists, so exit this thread.*/
00402       else
00403         continue;
00404     }
00405  return 0; /* Meaning no there weren't other threads and we set ours. */
00406 }
00407 
00408 fsal_up_event_functions_t *get_fsal_up_functions(char *fsal_up_type)
00409 {
00410   if (strncmp(fsal_up_type, FSAL_UP_DUMB_TYPE, sizeof(FSAL_UP_DUMB_TYPE)) == 0)
00411     {
00412       LogEvent(COMPONENT_FSAL_UP, "Using the FSAL UP DUMB functions to handle"
00413                " FSAL UP events.");
00414       return get_fsal_up_dumb_functions();
00415     }
00416   else
00417     {
00418       return NULL;
00419     }
00420 }
00421 
00422 fsal_up_event_bus_filter_t *find_filter(char filtername[MAX_FILTER_NAMELEN])
00423 {
00424   return NULL;
00425 }
00426 
00427 void *fsal_up_thread(void *Arg)
00428 {
00429   fsal_status_t status;
00430   fsal_up_arg_t *fsal_up_args = (fsal_up_arg_t *)Arg;
00431   fsal_up_event_bus_context_t fsal_up_context;
00432   fsal_up_event_bus_parameter_t fsal_up_bus_param;
00433   fsal_up_event_bus_filter_t * pupebfilter = NULL;
00434   fsal_up_filter_list_t *filter = NULL;
00435   fsal_up_event_t *event;
00436   static struct glist_head pevent_head;
00437   fsal_up_event_functions_t *event_func;
00438   fsal_count_t nb_events_found, event_nb;
00439   fsal_time_t timeout;
00440   char thr_name[40];
00441 
00442   memset(&fsal_up_bus_param, 0, sizeof(fsal_up_event_bus_parameter_t));
00443   memset(&fsal_up_context, 0, sizeof(fsal_up_event_bus_context_t));
00444 
00445   snprintf(thr_name, sizeof(thr_name), "FSAL UP Thread for filesystem %llu.%llu",
00446            fsal_up_args->export_entry->filesystem_id.major,
00447            fsal_up_args->export_entry->filesystem_id.minor);
00448   SetNameFunction(thr_name);
00449 
00450   /* Set the FSAL UP functions that will be used to process events. */
00451   event_func = get_fsal_up_functions(fsal_up_args->export_entry->fsal_up_type);
00452   if (event_func == NULL)
00453     {
00454       LogCrit(COMPONENT_FSAL_UP, "Error: FSAL UP TYPE: %s does not exist. "
00455               "Exiting FSAL UP thread.", fsal_up_args->export_entry->fsal_up_type);
00456       gsh_free(Arg);
00457       return NULL;
00458     }
00459 
00460   /* Get fsal up context from FSAL */
00461   /* It is expected that the export entry and event_pool will be referenced
00462    * in the returned callback context structure. */
00463   memcpy(&fsal_up_context.FS_export_context,
00464          &fsal_up_args->export_entry->FS_export_context,
00465          sizeof(fsal_export_context_t));
00466 
00467   fsal_up_context.event_pool = nfs_param.fsal_up_param.event_pool;
00468   fsal_up_context.event_pool_lock = &nfs_param.fsal_up_param.event_pool_lock;
00469 
00470   LogDebug(COMPONENT_FSAL_UP, "Initializing FSAL Callback context.");
00471   status = FSAL_UP_Init(&fsal_up_bus_param, &fsal_up_context);
00472   if (FSAL_IS_ERROR(status))
00473     {
00474       LogCrit(COMPONENT_FSAL_UP, "Error: Could not initialize FSAL UP for"
00475               " filesystem %llu.%llu export %d. Exiting FSAL UP thread.",
00476               fsal_up_args->export_entry->filesystem_id.major,
00477               fsal_up_args->export_entry->filesystem_id.minor,
00478               fsal_up_args->export_entry->id);
00479     }
00480 
00481   /* Add filters ... later if needed we could add arguments to filters
00482    * configurable from configuration files. */
00483   for(filter = fsal_up_args->export_entry->fsal_up_filter_list;
00484       filter != NULL; filter = filter->next)
00485     {
00486       LogEvent(COMPONENT_FSAL_UP, "Applying filter \"%s\" to FSAL UP thread "
00487                "for filesystem id %llu.%llu export id %d.", filter->name,
00488               fsal_up_args->export_entry->filesystem_id.major,
00489               fsal_up_args->export_entry->filesystem_id.minor,
00490               fsal_up_args->export_entry->id);
00491 
00492       /* Find predefined filter */
00493       pupebfilter = find_filter(filter->name);
00494       if (pupebfilter == NULL)
00495         {
00496           LogCrit(COMPONENT_FSAL_UP, "Error: Could not find filter named \"%s\".",
00497                    filter->name);
00498         }
00499 
00500       /* Applying filter */
00501       FSAL_UP_AddFilter(pupebfilter, &fsal_up_context);
00502     }
00503 
00504 
00505   /* Set the timeout for getting events. */
00506   timeout = fsal_up_args->export_entry->fsal_up_timeout;
00507 
00508   /* Start querying for events and processing. */
00509   while(1)
00510     {
00511       /* pevent is passed in as a single empty node, it's expected the
00512        * FSAL will use the event_pool in the bus_context to populate
00513        * this array by adding to the pevent_head. */
00514       event_nb = 0;
00515       nb_events_found = 0;
00516       init_glist(&pevent_head);
00517       LogDebug(COMPONENT_FSAL_UP, "Requesting event from FSAL Callback interface.");
00518       status = FSAL_UP_GetEvents(&pevent_head,     /* out */
00519                                  &event_nb,        /* in/out */
00520                                  timeout,          /* in */
00521                                  &nb_events_found, /* out */
00522                                  &fsal_up_context);/* in */
00523       if (FSAL_IS_ERROR(status))
00524         {
00525           if (status.major == ERR_FSAL_TIMEOUT)
00526             LogDebug(COMPONENT_FSAL_UP, "FSAL_UP_EB_GetEvents() hit the timeout"
00527                      " limit of %u.%u seconds for filesystem id %llu.%llu export id"
00528                      " %d.", timeout.seconds, timeout.nseconds,
00529                      fsal_up_args->export_entry->filesystem_id.major,
00530                      fsal_up_args->export_entry->filesystem_id.minor,
00531                      fsal_up_args->export_entry->id);
00532           else if (status.major == ERR_FSAL_NOTSUPP)
00533             {
00534               LogCrit(COMPONENT_FSAL_UP, "Exiting FSAL UP Thread for filesystem"
00535                       " id %llu.%llu export id %u because the FSAL Callback"
00536                       " Interface is not supported for this FSAL type.",
00537                       fsal_up_args->export_entry->filesystem_id.major,
00538                       fsal_up_args->export_entry->filesystem_id.minor,
00539                       fsal_up_args->export_entry->id);
00540               return NULL;
00541             }
00542           else
00543             {
00544               LogDebug(COMPONENT_FSAL_UP, "Error: FSAL_UP_EB_GetEvents() "
00545                        "failed");
00546               continue;
00547             }
00548         }
00549 
00550       LogDebug(COMPONENT_FSAL_UP, "Received %lu events to process for filesystem"
00551                      " id %llu.%llu export id %u.",
00552                event_nb,
00553                fsal_up_args->export_entry->filesystem_id.major,
00554                fsal_up_args->export_entry->filesystem_id.minor,
00555                fsal_up_args->export_entry->id);
00556 
00557       /* process the list of events */
00558       while(!glist_empty(&pevent_head))
00559         {
00560           event = glist_first_entry(&pevent_head, fsal_up_event_t, event_list);
00561           glist_del(&event->event_list);
00562           status = process_event(event, event_func);
00563           if (FSAL_IS_ERROR(status))
00564             {
00565               LogDebug(COMPONENT_FSAL_UP, "Error: Event could not be processed "
00566                        "for filesystem %llu.%llu export id %u.",
00567                        fsal_up_args->export_entry->filesystem_id.major,
00568                        fsal_up_args->export_entry->filesystem_id.minor,
00569                        fsal_up_args->export_entry->id);
00570             }
00571         }
00572 
00573       LogDebug(COMPONENT_FSAL_UP, "%lu events not found for filesystem"
00574                " %llu.%llu export id %u", event_nb,
00575                fsal_up_args->export_entry->filesystem_id.major,
00576                fsal_up_args->export_entry->filesystem_id.minor,
00577                fsal_up_args->export_entry->id);
00578     }
00579 
00580   gsh_free(Arg);
00581   return NULL;
00582 }                               /* fsal_up_thread */
00583