nfs-ganesha 1.4

nfs_reaper_thread.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 3 of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00017  *
00018  * ---------------------------------------
00019  */
00020 
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #ifdef _SOLARIS
00030 #include "solaris_port.h"
00031 #endif
00032 
00033 #include <pthread.h>
00034 #include <unistd.h>
00035 #include "log.h"
00036 #include "nfs4.h"
00037 #include "sal_functions.h"
00038 #include "nfs_proto_functions.h"
00039 #include "nfs_core.h"
00040 #include "log.h"
00041 
00042 #define REAPER_DELAY 10
00043 
00044 unsigned int reaper_delay = REAPER_DELAY;
00045 
00046 static void reap_hash_table(hash_table_t * ht_reap)
00047 {
00048   struct rbt_head     * head_rbt;
00049   hash_data_t         * pdata = NULL;
00050   uint32_t              i;
00051   int                   v4, rc;
00052   struct rbt_node     * pn;
00053   nfs_client_id_t     * pclientid;
00054   nfs_client_record_t * precord;
00055 
00056   /* For each bucket of the requested hashtable */
00057   for(i = 0; i < ht_reap->parameter.index_size; i++)
00058     {
00059       head_rbt = &ht_reap->partitions[i].rbt;
00060 
00061  restart:
00062       /* acquire mutex */
00063       pthread_rwlock_wrlock(&ht_reap->partitions[i].lock);
00064 
00065       /* go through all entries in the red-black-tree*/
00066       RBT_LOOP(head_rbt, pn)
00067         {
00068           pdata = RBT_OPAQ(pn);
00069 
00070           pclientid = (nfs_client_id_t *)pdata->buffval.pdata;
00071           /*
00072            * little hack: only want to reap v4 clients
00073            * 4.1 initializess this field to '1'
00074            */
00075           v4 = (pclientid->cid_create_session_sequence == 0);
00076 
00077           P(pclientid->cid_mutex);
00078 
00079           if(!valid_lease(pclientid) && v4)
00080             {
00081               inc_client_id_ref(pclientid);
00082 
00083               /* Take a reference to the client record */
00084               precord = pclientid->cid_client_record;
00085               inc_client_record_ref(precord);
00086 
00087               V(pclientid->cid_mutex);
00088 
00089               pthread_rwlock_unlock(&ht_reap->partitions[i].lock);
00090 
00091               if(isDebug(COMPONENT_CLIENTID))
00092                 {
00093                   char str[HASHTABLE_DISPLAY_STRLEN];
00094 
00095                   display_client_id_rec(pclientid, str);
00096 
00097                   LogFullDebug(COMPONENT_CLIENTID,
00098                                "Expire index %d %s",
00099                                i, str);
00100                 }
00101 
00102               /* Take cr_mutex and expire clientid */
00103               P(precord->cr_mutex);
00104 
00105               rc = nfs_client_id_expire(pclientid);
00106 
00107               V(precord->cr_mutex);
00108 
00109               dec_client_id_ref(pclientid);
00110               dec_client_record_ref(precord);
00111               if(rc)
00112                 goto restart;
00113             }
00114           else
00115             {
00116               V(pclientid->cid_mutex);
00117             }
00118 
00119           RBT_INCREMENT(pn);
00120         }
00121 
00122       pthread_rwlock_unlock(&ht_reap->partitions[i].lock);
00123     }
00124 }
00125 
00126 void *reaper_thread(void *UnusedArg)
00127 {
00128   int old_state_cleaned = 0;
00129 
00130   SetNameFunction("reaper_thr");
00131 
00132   if(nfs_param.nfsv4_param.lease_lifetime < (2 * REAPER_DELAY))
00133     reaper_delay = nfs_param.nfsv4_param.lease_lifetime / 2;
00134 
00135   while(1)
00136     {
00137       /* Initial wait */
00139       /* sleep(nfs_param.core_param.reaper_delay); */
00140       sleep(reaper_delay);
00141 
00142       if (old_state_cleaned == 0)
00143         {
00144           /* if not in grace period, clean up the old state */
00145           if(!nfs_in_grace())
00146             {
00147               nfs4_clean_old_recov_dir();
00148               old_state_cleaned = 1;
00149             }
00150         }
00151 
00152       LogFullDebug(COMPONENT_CLIENTID,
00153                    "Now checking NFS4 clients for expiration%s",
00154                    nfs_in_grace() ? " IN GRACE" : "");
00155 
00156       reap_hash_table(ht_confirmed_client_id);
00157       reap_hash_table(ht_unconfirmed_client_id);
00158     }                           /* while ( 1 ) */
00159 
00160   return NULL;
00161 }