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 00033 #ifdef HAVE_CONFIG_H 00034 #include "config.h" 00035 #endif 00036 00037 #ifdef _SOLARIS 00038 #include "solaris_port.h" 00039 #endif 00040 00041 #include "HashData.h" 00042 #include "HashTable.h" 00043 #include "log.h" 00044 #include "nfs_core.h" 00045 #include "nfs_exports.h" 00046 #include "config_parsing.h" 00047 #include <stdlib.h> 00048 #include <string.h> 00049 #include <sys/socket.h> 00050 #include <netinet/in.h> 00051 #include <arpa/inet.h> 00052 #include <pthread.h> 00053 00054 typedef struct fridge_entry__ 00055 { 00056 pthread_t thrid ; 00057 pthread_mutex_t condmutex ; 00058 pthread_cond_t condvar ; 00059 unsigned int frozen ; 00060 void * arg ; 00061 struct fridge_entry__ * pprev ; 00062 struct fridge_entry__ * pnext ; 00063 } fridge_entry_t ; 00064 00065 static pthread_mutex_t fridge_mutex ; 00066 static fridge_entry_t * fridge_content = NULL ; 00067 static pthread_attr_t attr_thr ; 00068 00069 static void fridgethr_remove( fridge_entry_t * pfe ) 00070 { 00071 if( pfe == NULL ) 00072 return ; 00073 00074 P( fridge_mutex ) ; 00075 00076 if( pfe->pprev != NULL ) pfe->pprev->pnext = pfe->pnext ; 00077 if( pfe->pnext != NULL ) pfe->pnext->pprev = pfe->pprev ; 00078 00079 if( pfe->pnext == NULL && pfe->pprev == NULL ) /* Is the fridge empty ? */ 00080 fridge_content = NULL ; 00081 00082 V( fridge_mutex ) ; 00083 00084 gsh_free(pfe) ; 00085 00086 return ; 00087 } /* fridgethr_remove */ 00088 00089 int fridgethr_get( pthread_t * pthrid, void *(*thrfunc)(void*), void * thrarg ) 00090 { 00091 fridge_entry_t * pfe = NULL ; 00092 00093 P( fridge_mutex ) ; 00094 if( fridge_content == NULL ) 00095 { 00096 V( fridge_mutex ) ; 00097 return pthread_create( pthrid, &attr_thr, thrfunc, thrarg ) ; 00098 } 00099 00100 pfe = fridge_content ; 00101 pfe->frozen = FALSE ; 00102 if( pfe->pprev != NULL ) 00103 pfe->pprev->pnext = pfe->pnext ; 00104 00105 if( pfe->pnext != NULL ) 00106 pfe->pnext->pprev = pfe->pprev ; 00107 00108 fridge_content = fridge_content->pprev ; 00109 00110 pfe->arg = thrarg ; 00111 if( pthread_cond_signal( &pfe->condvar ) ) 00112 { 00113 V( fridge_mutex ) ; 00114 return -1 ; 00115 } 00116 00117 *pthrid = pfe->thrid ; 00118 00119 V( fridge_mutex ) ; 00120 return 0 ; 00121 } /* fridgethr_get */ 00122 00123 void * fridgethr_freeze( ) 00124 { 00125 fridge_entry_t * pfe = NULL ; 00126 struct timespec timeout ; 00127 struct timeval tp; 00128 int rc = 0 ; 00129 void *arg = NULL; 00130 00131 if( ( rc = gettimeofday( &tp, NULL ) ) != 0 ) 00132 return NULL ; 00133 00134 /* Be careful : pthread_cond_timedwait take an *absolute* time as time specification, not a duration */ 00135 timeout.tv_sec = tp.tv_sec + nfs_param.core_param.tcp_fridge_expiration_delay ; 00136 timeout.tv_nsec = 0 ; 00137 00138 if ((pfe = gsh_malloc(sizeof(fridge_entry_t))) == NULL) 00139 return NULL ; 00140 00141 pfe->thrid = pthread_self(); 00142 pthread_mutex_init(&(pfe->condmutex), NULL); 00143 pthread_cond_init(&(pfe->condvar), NULL); 00144 pfe->pprev = NULL; 00145 pfe->pnext = NULL; 00146 pfe->frozen = TRUE; 00147 00148 P(fridge_mutex); 00149 if( fridge_content == NULL ) 00150 { 00151 pfe->pprev = NULL ; 00152 pfe->pnext = NULL ; 00153 } 00154 else 00155 { 00156 pfe->pprev = fridge_content ; 00157 pfe->pnext = NULL ; 00158 fridge_content->pnext = pfe ; 00159 } 00160 fridge_content = pfe ; 00161 V( fridge_mutex ) ; 00162 00163 P( pfe->condmutex ) ; 00164 while( pfe->frozen == TRUE && rc == 0 ) 00165 if( nfs_param.core_param.tcp_fridge_expiration_delay > 0 ) 00166 rc = pthread_cond_timedwait( &pfe->condvar, &pfe->condmutex, &timeout ) ; 00167 else 00168 rc = pthread_cond_wait( &pfe->condvar, &pfe->condmutex ) ; 00169 00170 if( rc != ETIMEDOUT ) 00171 arg = pfe->arg; 00172 00173 fridgethr_remove( pfe ); 00174 return arg; 00175 } /* fridgethr_freeze */ 00176 00177 int fridgethr_init( ) 00178 { 00179 /* Spawns a new thread to handle the connection */ 00180 pthread_attr_init(&attr_thr) ; 00181 pthread_attr_setscope(&attr_thr, PTHREAD_SCOPE_SYSTEM); 00182 pthread_attr_setdetachstate(&attr_thr, PTHREAD_CREATE_DETACHED); /* If not, the conn mgr will be "defunct" threads */ 00183 pthread_attr_setstacksize(&attr_thr, THREAD_STACK_SIZE); 00184 00185 fridge_content = NULL ; 00186 00187 if( pthread_mutex_init( &fridge_mutex, NULL ) != 0 ) 00188 return -1 ; 00189 00190 return 0 ; 00191 } /* fridgethr_init */