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 00038 #ifdef HAVE_CONFIG_H 00039 #include "config.h" 00040 #endif 00041 00042 #ifdef _SOLARIS 00043 #include "solaris_port.h" 00044 #endif 00045 00046 #include <assert.h> 00047 #include <stdio.h> 00048 #include <stdbool.h> 00049 #include <string.h> 00050 #include <pthread.h> 00051 #include <fcntl.h> 00052 #include <sys/file.h> /* for having FNDELAY */ 00053 #include <sys/signal.h> 00054 #include <poll.h> 00055 #include "HashData.h" 00056 #include "HashTable.h" 00057 #include "log.h" 00058 #include "ganesha_rpc.h" 00059 #include "nfs23.h" 00060 #include "nfs4.h" 00061 #include "mount.h" 00062 #include "nlm4.h" 00063 #include "rquota.h" 00064 #include "nfs_core.h" 00065 #include "cache_inode.h" 00066 #include "nfs_exports.h" 00067 #include "nfs_creds.h" 00068 #include "nfs_proto_functions.h" 00069 #include "nfs_dupreq.h" 00070 #include "nfs_file_handle.h" 00071 #include "nfs_stat.h" 00072 #include "nfs_tcb.h" 00073 #include "SemN.h" 00074 00075 extern nfs_worker_data_t *workers_data; 00076 00077 pool_t *request_pool; 00078 pool_t *request_data_pool; 00079 pool_t *dupreq_pool; 00080 pool_t *ip_stats_pool; 00081 00082 /* These two variables keep state of the thread that gc at this time */ 00083 unsigned int nb_current_gc_workers; 00084 pthread_mutex_t lock_nb_current_gc_workers; 00085 00086 const nfs_function_desc_t invalid_funcdesc = 00087 {nfs_Null, nfs_Null_Free, (xdrproc_t) xdr_void, (xdrproc_t) xdr_void, 00088 "invalid_function", NOTHING_SPECIAL}; 00089 00090 const nfs_function_desc_t *INVALID_FUNCDESC = &invalid_funcdesc; 00091 00092 /* Static array : all the function pointer per nfs v2 functions */ 00093 const nfs_function_desc_t nfs2_func_desc[] = { 00094 {nfs_Null, nfs_Null_Free, (xdrproc_t) xdr_void, 00095 (xdrproc_t) xdr_void, "nfs_Null", 00096 NOTHING_SPECIAL}, 00097 {nfs_Getattr, nfs_Getattr_Free, (xdrproc_t) xdr_fhandle2, 00098 (xdrproc_t) xdr_ATTR2res, "nfs_Getattr", 00099 NEEDS_CRED | SUPPORTS_GSS}, 00100 {nfs_Setattr, nfs_Setattr_Free, (xdrproc_t) xdr_SETATTR2args, 00101 (xdrproc_t) xdr_ATTR2res, "nfs_Setattr", 00102 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00103 {nfs2_Root, nfs2_Root_Free, (xdrproc_t) xdr_void, 00104 (xdrproc_t) xdr_void, "nfs2_Root", 00105 NOTHING_SPECIAL}, 00106 {nfs_Lookup, nfs2_Lookup_Free, (xdrproc_t) xdr_diropargs2, 00107 (xdrproc_t) xdr_DIROP2res, "nfs_Lookup", 00108 NEEDS_CRED | SUPPORTS_GSS}, 00109 {nfs_Readlink, nfs2_Readlink_Free, (xdrproc_t) xdr_fhandle2, 00110 (xdrproc_t) xdr_READLINK2res, "nfs_Readlink", 00111 NEEDS_CRED | SUPPORTS_GSS}, 00112 {nfs_Read, nfs2_Read_Free, (xdrproc_t) xdr_READ2args, 00113 (xdrproc_t) xdr_READ2res, "nfs_Read", 00114 NEEDS_CRED | SUPPORTS_GSS}, 00115 {nfs2_Writecache, nfs2_Writecache_Free, (xdrproc_t) xdr_void, 00116 (xdrproc_t) xdr_void, "nfs_Writecache", 00117 NOTHING_SPECIAL}, 00118 {nfs_Write, nfs_Write_Free, (xdrproc_t) xdr_WRITE2args, 00119 (xdrproc_t) xdr_ATTR2res, "nfs_Write", 00120 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00121 {nfs_Create, nfs_Create_Free, (xdrproc_t) xdr_CREATE2args, 00122 (xdrproc_t) xdr_DIROP2res, "nfs_Create", 00123 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00124 {nfs_Remove, nfs_Remove_Free, (xdrproc_t) xdr_diropargs2, 00125 (xdrproc_t) xdr_nfsstat2, "nfs_Remove", 00126 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00127 {nfs_Rename, nfs_Rename_Free, (xdrproc_t) xdr_RENAME2args, 00128 (xdrproc_t) xdr_nfsstat2, "nfs_Rename", 00129 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00130 {nfs_Link, nfs_Link_Free, (xdrproc_t) xdr_LINK2args, 00131 (xdrproc_t) xdr_nfsstat2, "nfs_Link", 00132 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00133 {nfs_Symlink, nfs_Symlink_Free, (xdrproc_t) xdr_SYMLINK2args, 00134 (xdrproc_t) xdr_nfsstat2, "nfs_Symlink", 00135 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00136 {nfs_Mkdir, nfs_Mkdir_Free, (xdrproc_t) xdr_CREATE2args, 00137 (xdrproc_t) xdr_DIROP2res, "nfs_Mkdir", 00138 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00139 {nfs_Rmdir, nfs_Rmdir_Free, (xdrproc_t) xdr_diropargs2, 00140 (xdrproc_t) xdr_nfsstat2, "nfs_Rmdir", 00141 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00142 {nfs_Readdir, nfs2_Readdir_Free, (xdrproc_t) xdr_READDIR2args, 00143 (xdrproc_t) xdr_READDIR2res, "nfs_Readdir", 00144 NEEDS_CRED | SUPPORTS_GSS}, 00145 {nfs_Fsstat, nfs_Fsstat_Free, (xdrproc_t) xdr_fhandle2, 00146 (xdrproc_t) xdr_STATFS2res, "nfs_Fsstat", 00147 NEEDS_CRED | SUPPORTS_GSS} 00148 }; 00149 00150 const nfs_function_desc_t nfs3_func_desc[] = { 00151 {nfs_Null, nfs_Null_Free, (xdrproc_t) xdr_void, 00152 (xdrproc_t) xdr_void, 00153 "nfs_Null", 00154 NOTHING_SPECIAL}, 00155 {nfs_Getattr, nfs_Getattr_Free, (xdrproc_t) xdr_GETATTR3args, 00156 (xdrproc_t) xdr_GETATTR3res, "nfs_Getattr", NEEDS_CRED | SUPPORTS_GSS}, 00157 {nfs_Setattr, nfs_Setattr_Free, (xdrproc_t) xdr_SETATTR3args, 00158 (xdrproc_t) xdr_SETATTR3res, "nfs_Setattr", 00159 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00160 {nfs_Lookup, nfs3_Lookup_Free, (xdrproc_t) xdr_LOOKUP3args, 00161 (xdrproc_t) xdr_LOOKUP3res, "nfs_Lookup", 00162 NEEDS_CRED | SUPPORTS_GSS}, 00163 {nfs3_Access, nfs3_Access_Free, (xdrproc_t) xdr_ACCESS3args, 00164 (xdrproc_t) xdr_ACCESS3res, "nfs3_Access", 00165 NEEDS_CRED | SUPPORTS_GSS}, 00166 {nfs_Readlink, nfs3_Readlink_Free, (xdrproc_t) xdr_READLINK3args, 00167 (xdrproc_t) xdr_READLINK3res, "nfs_Readlink", 00168 NEEDS_CRED | SUPPORTS_GSS}, 00169 {nfs_Read, nfs3_Read_Free, (xdrproc_t) xdr_READ3args, 00170 (xdrproc_t) xdr_READ3res, "nfs_Read", 00171 NEEDS_CRED | SUPPORTS_GSS}, 00172 {nfs_Write, nfs_Write_Free, (xdrproc_t) xdr_WRITE3args, 00173 (xdrproc_t) xdr_WRITE3res, "nfs_Write", 00174 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00175 {nfs_Create, nfs_Create_Free, (xdrproc_t) xdr_CREATE3args, 00176 (xdrproc_t) xdr_CREATE3res, "nfs_Create", 00177 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00178 {nfs_Mkdir, nfs_Mkdir_Free, (xdrproc_t) xdr_MKDIR3args, 00179 (xdrproc_t) xdr_MKDIR3res, "nfs_Mkdir", 00180 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00181 {nfs_Symlink, nfs_Symlink_Free, (xdrproc_t) xdr_SYMLINK3args, 00182 (xdrproc_t) xdr_SYMLINK3res, "nfs_Symlink", 00183 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00184 {nfs3_Mknod, nfs3_Mknod_Free, (xdrproc_t) xdr_MKNOD3args, 00185 (xdrproc_t) xdr_MKNOD3res, "nfs3_Mknod", 00186 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00187 {nfs_Remove, nfs_Remove_Free, (xdrproc_t) xdr_REMOVE3args, 00188 (xdrproc_t) xdr_REMOVE3res, "nfs_Remove", 00189 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00190 {nfs_Rmdir, nfs_Rmdir_Free, (xdrproc_t) xdr_RMDIR3args, 00191 (xdrproc_t) xdr_RMDIR3res, "nfs_Rmdir", 00192 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00193 {nfs_Rename, nfs_Rename_Free, (xdrproc_t) xdr_RENAME3args, 00194 (xdrproc_t) xdr_RENAME3res, "nfs_Rename", 00195 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00196 {nfs_Link, nfs_Link_Free, (xdrproc_t) xdr_LINK3args, 00197 (xdrproc_t) xdr_LINK3res, "nfs_Link", 00198 MAKES_WRITE | NEEDS_CRED | CAN_BE_DUP | SUPPORTS_GSS}, 00199 {nfs_Readdir, nfs3_Readdir_Free, (xdrproc_t) xdr_READDIR3args, 00200 (xdrproc_t) xdr_READDIR3res, "nfs_Readdir", 00201 NEEDS_CRED | SUPPORTS_GSS}, 00202 {nfs3_Readdirplus, nfs3_Readdirplus_Free, (xdrproc_t) xdr_READDIRPLUS3args, 00203 (xdrproc_t) xdr_READDIRPLUS3res, "nfs3_Readdirplus", 00204 NEEDS_CRED | SUPPORTS_GSS}, 00205 {nfs_Fsstat, nfs_Fsstat_Free, (xdrproc_t) xdr_FSSTAT3args, 00206 (xdrproc_t) xdr_FSSTAT3res, "nfs_Fsstat", 00207 NEEDS_CRED | SUPPORTS_GSS}, 00208 {nfs3_Fsinfo, nfs3_Fsinfo_Free, (xdrproc_t) xdr_FSINFO3args, 00209 (xdrproc_t) xdr_FSINFO3res, "nfs3_Fsinfo", 00210 NEEDS_CRED}, 00211 {nfs3_Pathconf, nfs3_Pathconf_Free, (xdrproc_t) xdr_PATHCONF3args, 00212 (xdrproc_t) xdr_PATHCONF3res, "nfs3_Pathconf", 00213 NEEDS_CRED | SUPPORTS_GSS}, 00214 {nfs3_Commit, nfs3_Commit_Free, (xdrproc_t) xdr_COMMIT3args, 00215 (xdrproc_t) xdr_COMMIT3res, "nfs3_Commit", 00216 MAKES_WRITE | NEEDS_CRED | SUPPORTS_GSS} 00217 }; 00218 00219 /* Remeber that NFSv4 manages authentication though junction crossing, and 00220 * so does it for RO FS management (for each operation) */ 00221 const nfs_function_desc_t nfs4_func_desc[] = { 00222 {nfs_Null, nfs_Null_Free, (xdrproc_t) xdr_void, 00223 (xdrproc_t) xdr_void, "nfs_Null", 00224 NOTHING_SPECIAL}, 00225 {nfs4_Compound, nfs4_Compound_Free, (xdrproc_t) xdr_COMPOUND4args, 00226 (xdrproc_t) xdr_COMPOUND4res, "nfs4_Compound", NEEDS_CRED} 00227 }; 00228 00229 const nfs_function_desc_t mnt1_func_desc[] = { 00230 {mnt_Null, mnt_Null_Free, (xdrproc_t) xdr_void, 00231 (xdrproc_t) xdr_void, "mnt_Null", 00232 NOTHING_SPECIAL}, 00233 {mnt_Mnt, mnt1_Mnt_Free, (xdrproc_t) xdr_dirpath, 00234 (xdrproc_t) xdr_fhstatus2, "mnt_Mnt", 00235 NEEDS_CRED}, 00236 {mnt_Dump, mnt_Dump_Free, (xdrproc_t) xdr_void, 00237 (xdrproc_t) xdr_mountlist, "mnt_Dump", 00238 NOTHING_SPECIAL}, 00239 {mnt_Umnt, mnt_Umnt_Free, (xdrproc_t) xdr_dirpath, 00240 (xdrproc_t) xdr_void, "mnt_Umnt", 00241 NOTHING_SPECIAL}, 00242 {mnt_UmntAll, mnt_UmntAll_Free, (xdrproc_t) xdr_void, 00243 (xdrproc_t) xdr_void, "mnt_UmntAll", 00244 NOTHING_SPECIAL}, 00245 {mnt_Export, mnt_Export_Free, (xdrproc_t) xdr_void, 00246 (xdrproc_t) xdr_exports, "mnt_Export", 00247 NOTHING_SPECIAL} 00248 }; 00249 00250 const nfs_function_desc_t mnt3_func_desc[] = { 00251 {mnt_Null, mnt_Null_Free, (xdrproc_t) xdr_void, 00252 (xdrproc_t) xdr_void, "mnt_Null", 00253 NOTHING_SPECIAL}, 00254 {mnt_Mnt, mnt3_Mnt_Free, (xdrproc_t) xdr_dirpath, 00255 (xdrproc_t) xdr_mountres3, "mnt_Mnt", 00256 NEEDS_CRED}, 00257 {mnt_Dump, mnt_Dump_Free, (xdrproc_t) xdr_void, 00258 (xdrproc_t) xdr_mountlist, "mnt_Dump", 00259 NOTHING_SPECIAL}, 00260 {mnt_Umnt, mnt_Umnt_Free, (xdrproc_t) xdr_dirpath, 00261 (xdrproc_t) xdr_void, "mnt_Umnt", 00262 NOTHING_SPECIAL}, 00263 {mnt_UmntAll, mnt_UmntAll_Free, (xdrproc_t) xdr_void, 00264 (xdrproc_t) xdr_void, "mnt_UmntAll", 00265 NOTHING_SPECIAL}, 00266 {mnt_Export, mnt_Export_Free, (xdrproc_t) xdr_void, 00267 (xdrproc_t) xdr_exports, "mnt_Export", 00268 NOTHING_SPECIAL} 00269 }; 00270 00271 #define nlm4_Unsupported nlm_Null 00272 #define nlm4_Unsupported_Free nlm_Null_Free 00273 00274 #ifdef _USE_NLM 00275 const nfs_function_desc_t nlm4_func_desc[] = { 00276 [NLMPROC4_NULL] = { 00277 nlm_Null, nlm_Null_Free, (xdrproc_t) xdr_void, 00278 (xdrproc_t) xdr_void, "nlm_Null", 00279 NOTHING_SPECIAL}, 00280 [NLMPROC4_TEST] = { 00281 nlm4_Test, nlm4_Test_Free, (xdrproc_t) xdr_nlm4_testargs, 00282 (xdrproc_t) xdr_nlm4_testres, "nlm4_Test", 00283 NEEDS_CRED}, 00284 [NLMPROC4_LOCK] = { 00285 nlm4_Lock, nlm4_Lock_Free, (xdrproc_t) xdr_nlm4_lockargs, 00286 (xdrproc_t) xdr_nlm4_res, "nlm4_Lock", 00287 NEEDS_CRED}, 00288 [NLMPROC4_CANCEL] = { 00289 nlm4_Cancel, nlm4_Cancel_Free, (xdrproc_t) xdr_nlm4_cancargs, 00290 (xdrproc_t) xdr_nlm4_res, "nlm4_Cancel", 00291 NEEDS_CRED}, 00292 [NLMPROC4_UNLOCK] = { 00293 nlm4_Unlock, nlm4_Unlock_Free, (xdrproc_t) xdr_nlm4_unlockargs, 00294 (xdrproc_t) xdr_nlm4_res, "nlm4_Unlock", 00295 NEEDS_CRED}, 00296 [NLMPROC4_GRANTED] = { 00297 nlm4_Unsupported, nlm4_Unsupported_Free, (xdrproc_t) xdr_void, 00298 (xdrproc_t) xdr_void, "nlm4_Granted", 00299 NOTHING_SPECIAL}, 00300 [NLMPROC4_TEST_MSG] = { 00301 nlm4_Test_Message, nlm4_Test_Free, 00302 (xdrproc_t) xdr_nlm4_testargs, 00303 (xdrproc_t) xdr_void, "nlm4_Test_msg", 00304 NEEDS_CRED}, 00305 [NLMPROC4_LOCK_MSG] = { 00306 nlm4_Lock_Message, nlm4_Lock_Free, 00307 (xdrproc_t) xdr_nlm4_lockargs, 00308 (xdrproc_t) xdr_void, "nlm4_Lock_msg", 00309 NEEDS_CRED}, 00310 [NLMPROC4_CANCEL_MSG] = { 00311 nlm4_Cancel_Message, nlm4_Cancel_Free, 00312 (xdrproc_t) xdr_nlm4_cancargs, 00313 (xdrproc_t) xdr_void, "nlm4_Cancel_msg", 00314 NEEDS_CRED}, 00315 [NLMPROC4_UNLOCK_MSG] = { 00316 nlm4_Unlock_Message, nlm4_Unlock_Free, 00317 (xdrproc_t) xdr_nlm4_unlockargs, 00318 (xdrproc_t) xdr_void, "nlm4_Unlock_msg", 00319 NEEDS_CRED}, 00320 [NLMPROC4_GRANTED_MSG] = { 00321 nlm4_Unsupported, nlm4_Unsupported_Free, (xdrproc_t) xdr_void, 00322 (xdrproc_t) xdr_void, "nlm4_Granted_msg", 00323 NOTHING_SPECIAL}, 00324 [NLMPROC4_TEST_RES] = { 00325 nlm4_Unsupported, nlm4_Unsupported_Free, (xdrproc_t) xdr_void, 00326 (xdrproc_t) xdr_void, "nlm4_Test_res", 00327 NOTHING_SPECIAL}, 00328 [NLMPROC4_LOCK_RES] = { 00329 nlm4_Unsupported, nlm4_Unsupported_Free, (xdrproc_t) xdr_void, 00330 (xdrproc_t) xdr_void, "nlm4_Lock_res", 00331 NOTHING_SPECIAL}, 00332 [NLMPROC4_CANCEL_RES] = { 00333 nlm4_Unsupported, nlm4_Unsupported_Free, (xdrproc_t) xdr_void, 00334 (xdrproc_t) xdr_void, "nlm4_Cancel_res", 00335 NOTHING_SPECIAL}, 00336 [NLMPROC4_UNLOCK_RES] = { 00337 nlm4_Unsupported, nlm4_Unsupported_Free, (xdrproc_t) xdr_void, 00338 (xdrproc_t) xdr_void, "nlm4_Unlock_res", 00339 NOTHING_SPECIAL}, 00340 [NLMPROC4_GRANTED_RES] = { 00341 nlm4_Granted_Res, nlm4_Granted_Res_Free, (xdrproc_t) xdr_nlm4_res, 00342 (xdrproc_t) xdr_void, "nlm4_Granted_res", 00343 NEEDS_CRED}, 00344 [NLMPROC4_SM_NOTIFY] = { 00345 nlm4_Sm_Notify, nlm4_Sm_Notify_Free, 00346 (xdrproc_t) xdr_nlm4_sm_notifyargs, (xdrproc_t) xdr_void, 00347 "nlm4_sm_notify", 00348 NOTHING_SPECIAL}, 00349 [17] = { 00350 nlm4_Unsupported, nlm4_Unsupported_Free, 00351 (xdrproc_t) xdr_void, (xdrproc_t) xdr_void, 00352 "nlm4_Granted_res", 00353 NOTHING_SPECIAL}, 00354 [18] = { 00355 nlm4_Unsupported, nlm4_Unsupported_Free, 00356 (xdrproc_t) xdr_void, (xdrproc_t) xdr_void, 00357 "nlm4_Granted_res", 00358 NOTHING_SPECIAL}, 00359 [19] = { 00360 nlm4_Unsupported, nlm4_Unsupported_Free, 00361 (xdrproc_t) xdr_void, (xdrproc_t) xdr_void, 00362 "nlm4_Granted_res", 00363 NOTHING_SPECIAL}, 00364 [NLMPROC4_SHARE] {nlm4_Share, nlm4_Share_Free, 00365 (xdrproc_t) xdr_nlm4_shareargs, (xdrproc_t) xdr_nlm4_shareres, 00366 "nlm4_Share", 00367 NEEDS_CRED}, 00368 [NLMPROC4_UNSHARE] = {nlm4_Unshare, nlm4_Unshare_Free, 00369 (xdrproc_t) xdr_nlm4_shareargs, (xdrproc_t) xdr_nlm4_shareres, 00370 "nlm4_Unshare", 00371 NEEDS_CRED}, 00372 [NLMPROC4_NM_LOCK] = { 00373 /* NLM_NM_LOCK uses the same handling as NLM_LOCK except for 00374 * monitoring, nlm4_Lock will make that determination. 00375 */ 00376 nlm4_Lock, nlm4_Lock_Free, 00377 (xdrproc_t) xdr_nlm4_lockargs, (xdrproc_t) xdr_nlm4_res, 00378 "nlm4_Nm_lock", 00379 NEEDS_CRED}, 00380 [NLMPROC4_FREE_ALL] = {nlm4_Free_All, nlm4_Free_All_Free, 00381 (xdrproc_t) xdr_nlm4_free_allargs, (xdrproc_t) xdr_void, 00382 "nlm4_Free_all", 00383 NOTHING_SPECIAL}, 00384 }; 00385 #endif /* _USE_NLM */ 00386 00387 #ifdef _USE_RQUOTA 00388 const nfs_function_desc_t rquota1_func_desc[] = { 00389 [0] = { 00390 rquota_Null, rquota_Null_Free, (xdrproc_t) xdr_void, 00391 (xdrproc_t) xdr_void, "rquota_Null", 00392 NOTHING_SPECIAL}, 00393 [RQUOTAPROC_GETQUOTA] = { 00394 rquota_getquota, rquota_getquota_Free, 00395 (xdrproc_t) xdr_getquota_args, 00396 (xdrproc_t) xdr_getquota_rslt, "rquota_Getquota", 00397 NEEDS_CRED}, 00398 [RQUOTAPROC_GETACTIVEQUOTA] = { 00399 rquota_getactivequota, rquota_getactivequota_Free, 00400 (xdrproc_t) xdr_getquota_args, 00401 (xdrproc_t) xdr_getquota_rslt, "rquota_Getactivequota", 00402 NEEDS_CRED}, 00403 [RQUOTAPROC_SETQUOTA] = { 00404 rquota_setquota, rquota_setquota_Free, 00405 (xdrproc_t) xdr_setquota_args, 00406 (xdrproc_t) xdr_setquota_rslt, "rquota_Setactivequota", 00407 NEEDS_CRED}, 00408 [RQUOTAPROC_SETACTIVEQUOTA] = { 00409 rquota_setactivequota, rquota_setactivequota_Free, 00410 (xdrproc_t) xdr_setquota_args, 00411 (xdrproc_t) xdr_setquota_rslt, "rquota_Getactivequota", 00412 NEEDS_CRED} 00413 }; 00414 00415 const nfs_function_desc_t rquota2_func_desc[] = { 00416 [0] = { 00417 rquota_Null, rquota_Null_Free, (xdrproc_t) xdr_void, 00418 (xdrproc_t) xdr_void, "rquota_Null", 00419 NOTHING_SPECIAL}, 00420 [RQUOTAPROC_GETQUOTA] = { 00421 rquota_getquota, rquota_getquota_Free, 00422 (xdrproc_t) xdr_ext_getquota_args, 00423 (xdrproc_t) xdr_getquota_rslt, "rquota_Ext_Getquota", 00424 NEEDS_CRED}, 00425 [RQUOTAPROC_GETACTIVEQUOTA] = { 00426 rquota_getactivequota, rquota_getactivequota_Free, 00427 (xdrproc_t) xdr_ext_getquota_args, 00428 (xdrproc_t) xdr_getquota_rslt, 00429 "rquota_Ext_Getactivequota", 00430 NEEDS_CRED}, 00431 [RQUOTAPROC_SETQUOTA] = { 00432 rquota_setquota, rquota_setquota_Free, 00433 (xdrproc_t) xdr_ext_setquota_args, 00434 (xdrproc_t) xdr_setquota_rslt, "rquota_Ext_Setactivequota", 00435 NEEDS_CRED}, 00436 [RQUOTAPROC_SETACTIVEQUOTA] = { 00437 rquota_setactivequota, rquota_setactivequota_Free, 00438 (xdrproc_t) xdr_ext_setquota_args, 00439 (xdrproc_t) xdr_setquota_rslt, 00440 "rquota_Ext_Getactivequota", 00441 NEEDS_CRED} 00442 }; 00443 00444 #endif /* _USE_RQUOTA */ 00445 00446 extern const char *pause_state_str[]; 00447 00461 int nfs_Init_gc_counter(void) 00462 { 00463 pthread_mutexattr_t mutexattr; 00464 00465 if(pthread_mutexattr_init(&mutexattr) != 0) 00466 return -1; 00467 00468 if(pthread_mutex_init(&lock_nb_current_gc_workers, &mutexattr) != 0) 00469 return -1; 00470 00471 nb_current_gc_workers = 0; 00472 00473 return 0; /* Success */ 00474 } /* nfs_Init_gc_counter */ 00475 00476 struct timeval time_diff(struct timeval time_from, struct timeval time_to) 00477 { 00478 00479 struct timeval result; 00480 00481 if(time_to.tv_usec < time_from.tv_usec) 00482 { 00483 result.tv_sec = time_to.tv_sec - time_from.tv_sec - 1; 00484 result.tv_usec = 1000000 + time_to.tv_usec - time_from.tv_usec; 00485 } 00486 else 00487 { 00488 result.tv_sec = time_to.tv_sec - time_from.tv_sec; 00489 result.tv_usec = time_to.tv_usec - time_from.tv_usec; 00490 } 00491 00492 return result; 00493 } 00494 00499 int is_rpc_call_valid(SVCXPRT *xprt, struct svc_req *preq) 00500 { 00501 int lo_vers, hi_vers; 00502 00503 if(preq->rq_prog == nfs_param.core_param.program[P_NFS]) 00504 { 00505 /* If we go there, preq->rq_prog == nfs_param.core_param.program[P_NFS] */ 00506 if(((preq->rq_vers != NFS_V2) || ((nfs_param.core_param.core_options & CORE_OPTION_NFSV2) == 0)) && 00507 ((preq->rq_vers != NFS_V3) || ((nfs_param.core_param.core_options & CORE_OPTION_NFSV3) == 0)) && 00508 ((preq->rq_vers != NFS_V4) || ((nfs_param.core_param.core_options & CORE_OPTION_NFSV4) == 0))) 00509 { 00510 if(xprt != NULL) 00511 { 00512 LogFullDebug(COMPONENT_DISPATCH, 00513 "Invalid NFS Version #%d", 00514 (int)preq->rq_vers); 00515 lo_vers = NFS_V4; 00516 hi_vers = NFS_V2; 00517 if((nfs_param.core_param.core_options & CORE_OPTION_NFSV2) != 0) 00518 lo_vers = NFS_V2; 00519 if((nfs_param.core_param.core_options & CORE_OPTION_NFSV3) != 0) 00520 { 00521 if(lo_vers == NFS_V4) 00522 lo_vers = NFS_V3; 00523 hi_vers = NFS_V3; 00524 } 00525 if((nfs_param.core_param.core_options & CORE_OPTION_NFSV4) != 0) 00526 hi_vers = NFS_V4; 00527 svcerr_progvers2(xprt, preq, lo_vers, hi_vers); /* Bad NFS version */ 00528 } 00529 return FALSE; 00530 } 00531 else if(((preq->rq_vers == NFS_V2) && (preq->rq_proc > NFSPROC_STATFS)) || 00532 ((preq->rq_vers == NFS_V3) && (preq->rq_proc > NFSPROC3_COMMIT)) || 00533 ((preq->rq_vers == NFS_V4) && (preq->rq_proc > NFSPROC4_COMPOUND))) 00534 { 00535 if(xprt != NULL) 00536 svcerr_noproc2(xprt, preq); 00537 return FALSE; 00538 } 00539 return TRUE; 00540 } 00541 00542 if(preq->rq_prog == nfs_param.core_param.program[P_MNT] && 00543 ((nfs_param.core_param.core_options & (CORE_OPTION_NFSV2 | CORE_OPTION_NFSV3)) != 0)) 00544 { 00545 /* Call is with MOUNTPROG */ 00546 /* Verify mount version and report error if invalid */ 00547 lo_vers = MOUNT_V1; 00548 hi_vers = MOUNT_V3; 00549 00550 /* Some clients may use the wrong mount version to umount, so always allow umount, 00551 * otherwise only allow request if the appropriate mount version is enabled. 00552 * also need to allow dump and export, so just disallow mount if version not supported 00553 */ 00554 if((preq->rq_vers == MOUNT_V1) && 00555 (((nfs_param.core_param.core_options & CORE_OPTION_NFSV2) != 0) || 00556 (preq->rq_proc != MOUNTPROC2_MNT))) 00557 { 00558 if(preq->rq_proc > MOUNTPROC2_EXPORT) 00559 { 00560 if(xprt != NULL) 00561 svcerr_noproc2(xprt, preq); 00562 return FALSE; 00563 } 00564 return TRUE; 00565 } 00566 else if((preq->rq_vers == MOUNT_V3) && 00567 (((nfs_param.core_param.core_options & CORE_OPTION_NFSV3) != 0) || 00568 (preq->rq_proc != MOUNTPROC2_MNT))) 00569 { 00570 if(preq->rq_proc > MOUNTPROC3_EXPORT) 00571 { 00572 if(xprt != NULL) 00573 svcerr_noproc2(xprt, preq); 00574 return FALSE; 00575 } 00576 return TRUE; 00577 } 00578 00579 if(xprt != NULL) 00580 { 00581 /* Bad MOUNT version - set the hi and lo versions and report error */ 00582 if((nfs_param.core_param.core_options & CORE_OPTION_NFSV2) == 0) 00583 lo_vers = MOUNT_V3; 00584 if((nfs_param.core_param.core_options & CORE_OPTION_NFSV3) == 0) 00585 hi_vers = MOUNT_V1; 00586 00587 LogFullDebug(COMPONENT_DISPATCH, 00588 "Invalid Mount Version #%d", 00589 (int)preq->rq_vers); 00590 svcerr_progvers2(xprt, preq, lo_vers, hi_vers); 00591 } 00592 return FALSE; 00593 } 00594 00595 #ifdef _USE_NLM 00596 if(preq->rq_prog == nfs_param.core_param.program[P_NLM] && 00597 ((nfs_param.core_param.core_options & CORE_OPTION_NFSV3) != 0)) 00598 { 00599 /* Call is with NLMPROG */ 00600 if(preq->rq_vers != NLM4_VERS) 00601 { 00602 /* Bad NLM version */ 00603 LogFullDebug(COMPONENT_DISPATCH, 00604 "Invalid NLM Version #%d", 00605 (int)preq->rq_vers); 00606 if(xprt != NULL) 00607 svcerr_progvers2(xprt, preq, NLM4_VERS, NLM4_VERS); 00608 return FALSE; 00609 } 00610 if(preq->rq_proc > NLMPROC4_FREE_ALL) 00611 { 00612 if(xprt != NULL) 00613 svcerr_noproc2(xprt, preq); 00614 return FALSE; 00615 } 00616 return TRUE; 00617 } 00618 #endif /* _USE_NLM */ 00619 00620 #ifdef _USE_RQUOTA 00621 if(preq->rq_prog == nfs_param.core_param.program[P_RQUOTA]) 00622 { 00623 /* Call is with NLMPROG */ 00624 if((preq->rq_vers != RQUOTAVERS) && 00625 (preq->rq_vers != EXT_RQUOTAVERS)) 00626 { 00627 /* Bad NLM version */ 00628 if(xprt != NULL) 00629 { 00630 LogFullDebug(COMPONENT_DISPATCH, 00631 "Invalid RQUOTA Version #%d", 00632 (int)preq->rq_vers); 00633 svcerr_progvers2(xprt, preq, RQUOTAVERS, EXT_RQUOTAVERS); 00634 } 00635 return FALSE; 00636 } 00637 if (((preq->rq_vers == RQUOTAVERS) && 00638 (preq->rq_proc > RQUOTAPROC_SETACTIVEQUOTA)) || 00639 ((preq->rq_vers == EXT_RQUOTAVERS) && 00640 (preq->rq_proc > RQUOTAPROC_SETACTIVEQUOTA))) 00641 { 00642 if(xprt != NULL) 00643 svcerr_noproc2(xprt, preq); 00644 return FALSE; 00645 } 00646 return TRUE; 00647 } 00648 #endif /* _USE_QUOTA */ 00649 00650 /* No such program */ 00651 if(xprt != NULL) 00652 { 00653 LogFullDebug(COMPONENT_DISPATCH, 00654 "Invalid Program number #%d", 00655 (int)preq->rq_prog); 00656 svcerr_noprog2(xprt, preq); /* This is no NFS, MOUNT program, exit... */ 00657 } 00658 return FALSE; 00659 } 00660 00661 /* 00662 * Extract nfs function descriptor from nfs request. 00663 */ 00664 const nfs_function_desc_t *nfs_rpc_get_funcdesc(nfs_request_data_t *preqnfs) 00665 { 00666 struct svc_req *req = &preqnfs->req; 00667 00668 /* Validate rpc call, but don't report any errors here */ 00669 if(is_rpc_call_valid(preqnfs->xprt, req) == FALSE) 00670 { 00671 LogFullDebug(COMPONENT_DISPATCH, 00672 "INVALID_FUNCDESC for Program %d, Version %d, " 00673 "Function %d after is_rpc_call_valid", 00674 (int)req->rq_prog, (int)req->rq_vers, (int)req->rq_proc); 00675 return INVALID_FUNCDESC; 00676 } 00677 00678 if(req->rq_prog == nfs_param.core_param.program[P_NFS]) 00679 { 00680 if(req->rq_vers == NFS_V2) 00681 return &nfs2_func_desc[req->rq_proc]; 00682 else if(req->rq_vers == NFS_V3) 00683 return &nfs3_func_desc[req->rq_proc]; 00684 else 00685 return &nfs4_func_desc[req->rq_proc]; 00686 } 00687 00688 if(req->rq_prog == nfs_param.core_param.program[P_MNT]) 00689 { 00690 if(req->rq_vers == MOUNT_V1) 00691 return &mnt1_func_desc[req->rq_proc]; 00692 else 00693 return &mnt3_func_desc[req->rq_proc]; 00694 } 00695 00696 #ifdef _USE_NLM 00697 if(req->rq_prog == nfs_param.core_param.program[P_NLM]) 00698 { 00699 return &nlm4_func_desc[req->rq_proc]; 00700 } 00701 #endif /* _USE_NLM */ 00702 00703 #ifdef _USE_RQUOTA 00704 if(req->rq_prog == nfs_param.core_param.program[P_RQUOTA]) 00705 { 00706 if(req->rq_vers == RQUOTAVERS) 00707 return &rquota1_func_desc[req->rq_proc]; 00708 else 00709 return &rquota2_func_desc[req->rq_proc]; 00710 } 00711 #endif /* _USE_RQUOTA */ 00712 00713 /* Oops, should never get here! */ 00714 svcerr_noprog2(preqnfs->xprt, req); 00715 LogFullDebug(COMPONENT_DISPATCH, 00716 "INVALID_FUNCDESC for Program %d, Version %d, Function %d", 00717 (int)req->rq_prog, (int)req->rq_vers, (int)req->rq_proc); 00718 return INVALID_FUNCDESC; 00719 } 00720 00721 /* 00722 * Extract RPC argument. 00723 */ 00724 int nfs_rpc_get_args(nfs_request_data_t *preqnfs, const nfs_function_desc_t *pfuncdesc) 00725 { 00726 SVCXPRT *xprt = preqnfs->xprt; 00727 nfs_arg_t *parg_nfs = &preqnfs->arg_nfs; 00728 00729 memset(parg_nfs, 0, sizeof(nfs_arg_t)); 00730 00731 LogFullDebug(COMPONENT_DISPATCH, 00732 "Before svc_getargs on socket %d, xprt=%p", 00733 xprt->xp_fd, xprt); 00734 00735 if(svc_getargs(xprt, pfuncdesc->xdr_decode_func, (caddr_t) parg_nfs) == FALSE) 00736 { 00737 struct svc_req *req = &preqnfs->req; 00738 LogMajor(COMPONENT_DISPATCH, 00739 "svc_getargs failed for Program %d, Version %d, Function %d xid=%u", 00740 (int)req->rq_prog, (int)req->rq_vers, (int)req->rq_proc, 00741 req->rq_xid); 00742 svcerr_decode2(xprt, req); 00743 return FALSE; 00744 } 00745 00746 return TRUE; 00747 } 00748 00757 static void nfs_rpc_execute(request_data_t *preq, 00758 nfs_worker_data_t *pworker_data) 00759 { 00760 unsigned int export_check_result; 00761 exportlist_t *pexport = NULL; 00762 nfs_request_data_t *preqnfs = preq->r_u.nfs; 00763 nfs_arg_t *parg_nfs = &preqnfs->arg_nfs; 00764 nfs_res_t res_nfs; 00765 short exportid; 00766 LRU_list_t *lru_dupreq = NULL; 00767 struct svc_req *req = &preqnfs->req; 00768 SVCXPRT *xprt = preqnfs->xprt; 00769 nfs_stat_type_t stat_type; 00770 sockaddr_t hostaddr; 00771 int port; 00772 int rc; 00773 int do_dupreq_cache; 00774 dupreq_status_t dpq_status; 00775 exportlist_client_entry_t related_client; 00776 struct user_cred user_credentials; 00777 int update_per_share_stats; 00778 fsal_op_context_t * pfsal_op_ctx = NULL ; 00779 00780 struct timeval *timer_start = &pworker_data->timer_start; 00781 struct timeval timer_end; 00782 struct timeval timer_diff; 00783 struct timeval queue_timer_diff; 00784 nfs_request_latency_stat_t latency_stat; 00785 00786 memset(&related_client, 0, sizeof(exportlist_client_entry_t)); 00787 00788 /* Get the value from the worker data */ 00789 lru_dupreq = pworker_data->duplicate_request; 00790 00791 /* initializing RPC structure */ 00792 memset(&res_nfs, 0, sizeof(res_nfs)); 00793 00794 /* If we reach this point, there was no dupreq cache hit or no dup req cache 00795 * was necessary. Get NFS function descriptor. */ 00796 pworker_data->pfuncdesc = nfs_rpc_get_funcdesc(preqnfs); 00797 if(pworker_data->pfuncdesc == INVALID_FUNCDESC) 00798 return; 00799 00800 /* XXX must hold lock when calling any TI-RPC channel function, 00801 * including svc_sendreply2 and the svcerr_* calls */ 00802 00803 if(copy_xprt_addr(&hostaddr, xprt) == 0) 00804 { 00805 LogFullDebug(COMPONENT_DISPATCH, 00806 "copy_xprt_addr failed for Program %d, Version %d, " 00807 "Function %d", 00808 (int)req->rq_prog, (int)req->rq_vers, 00809 (int)req->rq_proc); 00810 /* XXX move lock wrapper into RPC API */ 00811 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 00812 svcerr_systemerr2(xprt, req); 00813 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 00814 return; 00815 } 00816 00817 port = get_port(&hostaddr); 00818 00819 if(isDebug(COMPONENT_DISPATCH)) 00820 { 00821 char addrbuf[SOCK_NAME_MAX]; 00822 sprint_sockaddr(&hostaddr, addrbuf, sizeof(addrbuf)); 00823 LogDebug(COMPONENT_DISPATCH, 00824 "Request from %s for Program %d, Version %d, Function %d " 00825 "has xid=%u", 00826 addrbuf, 00827 (int)req->rq_prog, (int)req->rq_vers, (int)req->rq_proc, 00828 req->rq_xid); 00829 } 00830 00831 do_dupreq_cache = pworker_data->pfuncdesc->dispatch_behaviour & CAN_BE_DUP; 00832 LogFullDebug(COMPONENT_DISPATCH, "do_dupreq_cache = %d", do_dupreq_cache); 00833 dpq_status = nfs_dupreq_add_not_finished(req, &res_nfs); 00834 switch(dpq_status) 00835 { 00836 /* a new request, continue processing it */ 00837 case DUPREQ_SUCCESS: 00838 LogFullDebug(COMPONENT_DISPATCH, "Current request is not duplicate."); 00839 break; 00840 /* Found the reuqest in the dupreq cache. It's an old request so resend 00841 * old reply. */ 00842 case DUPREQ_ALREADY_EXISTS: 00843 if(do_dupreq_cache) 00844 { 00845 /* Request was known, use the previous reply */ 00846 LogFullDebug(COMPONENT_DISPATCH, 00847 "NFS DISPATCHER: DupReq Cache Hit: using previous " 00848 "reply, rpcxid=%u", 00849 req->rq_xid); 00850 00851 LogFullDebug(COMPONENT_DISPATCH, 00852 "Before svc_sendreply on socket %d (dup req)", 00853 xprt->xp_fd); 00854 00855 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 00856 if(svc_sendreply2 00857 (xprt, req, pworker_data->pfuncdesc->xdr_encode_func, 00858 (caddr_t) &res_nfs) == FALSE) 00859 { 00860 LogDebug(COMPONENT_DISPATCH, 00861 "NFS DISPATCHER: FAILURE: Error while calling " 00862 "svc_sendreply"); 00863 svcerr_systemerr2(xprt, req); 00864 } 00865 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 00866 00867 LogFullDebug(COMPONENT_DISPATCH, 00868 "After svc_sendreply on socket %d (dup req)", 00869 xprt->xp_fd); 00870 return; 00871 } 00872 else 00873 { 00874 LogCrit(COMPONENT_DISPATCH, 00875 "Error: Duplicate request rejected because it was found " 00876 "in the cache but is not allowed to be cached."); 00877 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 00878 svcerr_systemerr2(xprt, req); 00879 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 00880 return; 00881 } 00882 break; 00883 00884 /* Another thread owns the request */ 00885 case DUPREQ_BEING_PROCESSED: 00886 LogFullDebug(COMPONENT_DISPATCH, 00887 "Dupreq xid=%u was asked for process since another thread " 00888 "manage it, reject for avoiding threads starvation...", 00889 req->rq_xid); 00890 /* Free the arguments */ 00891 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 00892 if((preqnfs->req.rq_vers == 2) || 00893 (preqnfs->req.rq_vers == 3) || 00894 (preqnfs->req.rq_vers == 4)) 00895 if(!SVC_FREEARGS(xprt, pworker_data->pfuncdesc->xdr_decode_func, 00896 (caddr_t) parg_nfs)) 00897 { 00898 LogCrit(COMPONENT_DISPATCH, 00899 "NFS DISPATCHER: FAILURE: Bad SVC_FREEARGS for %s", 00900 pworker_data->pfuncdesc->funcname); 00901 } 00902 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 00903 /* Ignore the request, send no error */ 00904 return; 00905 00906 /* something is very wrong with the duplicate request cache */ 00907 case DUPREQ_NOT_FOUND: 00908 LogCrit(COMPONENT_DISPATCH, 00909 "Did not find the request in the duplicate request cache and " 00910 "couldn't add the request."); 00911 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 00912 svcerr_systemerr2(xprt, req); 00913 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 00914 return; 00915 00916 /* oom */ 00917 case DUPREQ_INSERT_MALLOC_ERROR: 00918 LogCrit(COMPONENT_DISPATCH, 00919 "Cannot process request, not enough memory available!"); 00920 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 00921 svcerr_systemerr2(xprt, req); 00922 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 00923 return; 00924 00925 default: 00926 LogCrit(COMPONENT_DISPATCH, 00927 "Unknown duplicate request cache status. This should never be " 00928 "reached!"); 00929 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 00930 svcerr_systemerr2(xprt, req); 00931 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 00932 return; 00933 } 00934 00935 /* Get the export entry */ 00936 if(req->rq_prog == nfs_param.core_param.program[P_NFS]) 00937 { 00938 /* The NFSv2 and NFSv3 functions'arguments always begin with the file 00939 * handle (but not the NULL function). This hook is used to get the 00940 * fhandle with the arguments and so determine the export entry to be 00941 * used. In NFSv4, junction traversal is managed by the protocol itself 00942 * so the whole export list is provided to NFSv4 request. */ 00943 00944 switch (req->rq_vers) 00945 { 00946 case NFS_V2: 00947 if(req->rq_proc != NFSPROC_NULL) 00948 { 00949 exportid = nfs2_FhandleToExportId((fhandle2 *) parg_nfs); 00950 00951 if(exportid < 0 || 00952 (pexport = nfs_Get_export_by_id(nfs_param.pexportlist, 00953 exportid)) == NULL || 00954 (pexport->options & EXPORT_OPTION_NFSV2) == 0) 00955 { 00956 /* Reject the request for authentication reason (incompatible 00957 * file handle) */ 00958 if(isInfo(COMPONENT_DISPATCH)) 00959 { 00960 char dumpfh[1024]; 00961 char *reason; 00962 char addrbuf[SOCK_NAME_MAX]; 00963 sprint_sockaddr(&hostaddr, addrbuf, sizeof(addrbuf)); 00964 if(exportid < 0) 00965 reason = "has badly formed handle"; 00966 else if(pexport == NULL) 00967 reason = "has invalid export"; 00968 else 00969 reason = "V2 not allowed on this export"; 00970 sprint_fhandle2(dumpfh, (fhandle2 *) parg_nfs); 00971 LogMajor(COMPONENT_DISPATCH, 00972 "NFS2 Request from host %s %s, proc=%d, FH=%s", 00973 addrbuf, reason, 00974 (int)req->rq_proc, dumpfh); 00975 } 00976 /* Bad argument */ 00977 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 00978 svcerr_auth2(xprt, req, AUTH_FAILED); 00979 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 00980 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 00981 { 00982 LogCrit(COMPONENT_DISPATCH, 00983 "Attempt to delete duplicate request failed on " 00984 "line %d", __LINE__); 00985 } 00986 return; 00987 } 00988 00989 LogFullDebug(COMPONENT_DISPATCH, 00990 "Found export entry for dirname=%s as exportid=%d", 00991 pexport->dirname, pexport->id); 00992 } 00993 else 00994 pexport = nfs_param.pexportlist; 00995 00996 break; 00997 00998 case NFS_V3: 00999 if(req->rq_proc != NFSPROC_NULL) 01000 { 01001 exportid = nfs3_FhandleToExportId((nfs_fh3 *) parg_nfs); 01002 01003 if(exportid < 0 || 01004 (pexport = nfs_Get_export_by_id(nfs_param.pexportlist, 01005 exportid)) == NULL || 01006 (pexport->options & EXPORT_OPTION_NFSV3) == 0) 01007 { 01008 /* Reject the request for authentication reason (incompatible 01009 * file handle) */ 01010 if(isInfo(COMPONENT_DISPATCH)) 01011 { 01012 char dumpfh[1024]; 01013 char *reason; 01014 char addrbuf[SOCK_NAME_MAX]; 01015 sprint_sockaddr(&hostaddr, addrbuf, sizeof(addrbuf)); 01016 if(exportid < 0) 01017 reason = "has badly formed handle"; 01018 else if(pexport == NULL) 01019 reason = "has invalid export"; 01020 else 01021 reason = "V3 not allowed on this export"; 01022 sprint_fhandle3(dumpfh, (nfs_fh3 *) parg_nfs); 01023 LogMajor(COMPONENT_DISPATCH, 01024 "NFS3 Request from host %s %s, proc=%d, FH=%s", 01025 addrbuf, reason, 01026 (int)req->rq_proc, dumpfh); 01027 } 01028 /* Bad argument */ 01029 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 01030 svcerr_auth2(xprt, req, AUTH_FAILED); 01031 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 01032 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01033 { 01034 LogCrit(COMPONENT_DISPATCH, 01035 "Attempt to delete duplicate request failed on " 01036 "line %d", __LINE__); 01037 } 01038 return; 01039 } 01040 01041 LogFullDebug(COMPONENT_DISPATCH, 01042 "Found export entry for dirname=%s as exportid=%d", 01043 pexport->dirname, pexport->id); 01044 } 01045 else 01046 pexport = nfs_param.pexportlist; 01047 01048 break; 01049 01050 case NFS_V4: 01051 /* NFSv4 requires entire export list */ 01052 pexport = nfs_param.pexportlist; 01053 break; 01054 01055 default: 01056 /* NFSv4 or invalid version (which should never get here) */ 01057 pexport = nfs_param.pexportlist; 01058 break; 01059 } /* switch( ptr_req->rq_vers ) */ 01060 } 01061 #ifdef _USE_NLM 01062 else if(req->rq_prog == nfs_param.core_param.program[P_NLM]) 01063 { 01064 netobj *pfh3 = NULL; 01065 01066 switch(req->rq_proc) 01067 { 01068 case NLMPROC4_NULL: 01069 case NLMPROC4_TEST_RES: 01070 case NLMPROC4_LOCK_RES: 01071 case NLMPROC4_CANCEL_RES: 01072 case NLMPROC4_UNLOCK_RES: 01073 case NLMPROC4_GRANTED_RES: 01074 case NLMPROC4_SM_NOTIFY: 01075 case NLMPROC4_FREE_ALL: 01076 break; 01077 01078 case NLMPROC4_TEST: 01079 case NLMPROC4_TEST_MSG: 01080 case NLMPROC4_GRANTED: 01081 case NLMPROC4_GRANTED_MSG: 01082 pfh3 = &parg_nfs->arg_nlm4_test.alock.fh; 01083 break; 01084 01085 case NLMPROC4_LOCK: 01086 case NLMPROC4_LOCK_MSG: 01087 case NLMPROC4_NM_LOCK: 01088 pfh3 = &parg_nfs->arg_nlm4_lock.alock.fh; 01089 break; 01090 01091 case NLMPROC4_CANCEL: 01092 case NLMPROC4_CANCEL_MSG: 01093 pfh3 = &parg_nfs->arg_nlm4_cancel.alock.fh; 01094 break; 01095 01096 case NLMPROC4_UNLOCK: 01097 case NLMPROC4_UNLOCK_MSG: 01098 pfh3 = &parg_nfs->arg_nlm4_unlock.alock.fh; 01099 break; 01100 01101 case NLMPROC4_SHARE: 01102 case NLMPROC4_UNSHARE: 01103 pfh3 = &parg_nfs->arg_nlm4_share.share.fh; 01104 break; 01105 } 01106 if(pfh3 != NULL) 01107 { 01108 exportid = nlm4_FhandleToExportId(pfh3); 01109 01110 if(exportid < 0 || 01111 (pexport = nfs_Get_export_by_id(nfs_param.pexportlist, 01112 exportid)) == NULL || 01113 (pexport->options & EXPORT_OPTION_NFSV3) == 0) 01114 { 01115 /* Reject the request for authentication reason (incompatible 01116 * file handle) */ 01117 if(isInfo(COMPONENT_DISPATCH)) 01118 { 01119 char dumpfh[1024]; 01120 char *reason; 01121 char addrbuf[SOCK_NAME_MAX]; 01122 sprint_sockaddr(&hostaddr, addrbuf, sizeof(addrbuf)); 01123 if(exportid < 0) 01124 reason = "has badly formed handle"; 01125 else if(pexport == NULL) 01126 reason = "has invalid export"; 01127 else 01128 reason = "V3 not allowed on this export"; 01129 sprint_fhandle_nlm(dumpfh, pfh3); 01130 LogMajor(COMPONENT_DISPATCH, 01131 "NLM4 Request from host %s %s, proc=%d, FH=%s", 01132 addrbuf, reason, 01133 (int)req->rq_proc, dumpfh); 01134 } 01135 /* Bad argument */ 01136 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 01137 svcerr_auth2(xprt, req, AUTH_FAILED); 01138 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 01139 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01140 { 01141 LogCrit(COMPONENT_DISPATCH, 01142 "Attempt to delete duplicate request failed on line " 01143 "%d", __LINE__); 01144 } 01145 return; 01146 } 01147 01148 LogFullDebug(COMPONENT_DISPATCH, 01149 "Found export entry for dirname=%s as exportid=%d", 01150 pexport->dirname, pexport->id); 01151 } 01152 else 01153 pexport = nfs_param.pexportlist; 01154 } 01155 #endif /* _USE_NLM */ 01156 else 01157 { 01158 /* All other protocols use the whole export list */ 01159 pexport = nfs_param.pexportlist; 01160 } 01161 01162 if(pworker_data->pfuncdesc->dispatch_behaviour & SUPPORTS_GSS) 01163 { 01164 /* Test if export allows the authentication provided */ 01165 if (nfs_export_check_security(req, pexport) == FALSE) 01166 { 01167 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 01168 svcerr_auth2(xprt, req, AUTH_TOOWEAK); 01169 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 01170 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01171 { 01172 LogCrit(COMPONENT_DISPATCH, 01173 "Attempt to delete duplicate request failed on " 01174 "line %d", __LINE__); 01175 } 01176 return; 01177 } 01178 } 01179 01180 /* Zero out timers prior to starting processing */ 01181 memset(&timer_end, 0, sizeof(struct timeval)); 01182 memset(&timer_diff, 0, sizeof(struct timeval)); 01183 memset(&queue_timer_diff, 0, sizeof(struct timeval)); 01184 01185 /* 01186 * It is now time for checking if export list allows the machine to perform 01187 * the request 01188 */ 01189 pworker_data->hostaddr = hostaddr; 01190 01191 /* Check if client is using a privileged port, but only for NFS protocol */ 01192 if ((req->rq_prog == nfs_param.core_param.program[P_NFS]) && 01193 (req->rq_proc != 0)) 01194 { 01195 if ((pexport->options & EXPORT_OPTION_PRIVILEGED_PORT) && 01196 (port >= IPPORT_RESERVED)) 01197 { 01198 LogInfo(COMPONENT_DISPATCH, 01199 "Port %d is too high for this export entry, rejecting client", 01200 port); 01201 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 01202 svcerr_auth2(xprt, req, AUTH_TOOWEAK); 01203 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 01204 /* XXX */ 01205 pworker_data->current_xid = 0; /* No more xid managed */ 01206 01207 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01208 { 01209 LogCrit(COMPONENT_DISPATCH, 01210 "Attempt to delete duplicate request failed on line %d", 01211 __LINE__); 01212 } 01213 return; 01214 } 01215 } 01216 01217 if (pworker_data->pfuncdesc->dispatch_behaviour & NEEDS_CRED) 01218 { 01219 if (get_req_uid_gid(req, pexport, &user_credentials) == FALSE) 01220 { 01221 LogInfo(COMPONENT_DISPATCH, 01222 "could not get uid and gid, rejecting client"); 01223 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 01224 svcerr_auth2(xprt, req, AUTH_TOOWEAK); 01225 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 01226 /* XXX */ 01227 pworker_data->current_xid = 0; /* No more xid managed */ 01228 01229 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01230 { 01231 LogCrit(COMPONENT_DISPATCH, 01232 "Attempt to delete duplicate request failed on line %d", 01233 __LINE__); 01234 } 01235 return; 01236 } 01237 } 01238 01239 /* Be careful (Issue #66) : it makes no sense to check access for 01240 * a MOUNT request */ 01241 if(req->rq_prog != nfs_param.core_param.program[P_MNT]) 01242 { 01243 LogFullDebug(COMPONENT_DISPATCH, 01244 "nfs_rpc_execute about to call nfs_export_check_access"); 01245 export_check_result = nfs_export_check_access(&pworker_data->hostaddr, 01246 req, 01247 pexport, 01248 nfs_param.core_param.program[P_NFS], 01249 nfs_param.core_param.program[P_MNT], 01250 pworker_data->ht_ip_stats, 01251 ip_stats_pool, 01252 &related_client, 01253 &user_credentials, 01254 (pworker_data->pfuncdesc->dispatch_behaviour & MAKES_WRITE) == MAKES_WRITE); 01255 } 01256 else 01257 { 01258 LogFullDebug(COMPONENT_DISPATCH, 01259 "Call to a function from the MOUNT protocol, no call to nfs_export_check_access() required" ) ; 01260 export_check_result = EXPORT_PERMISSION_GRANTED ; 01261 } 01262 01263 if (export_check_result == EXPORT_PERMISSION_DENIED) 01264 { 01265 char addrbuf[SOCK_NAME_MAX]; 01266 sprint_sockaddr(&hostaddr, addrbuf, sizeof(addrbuf)); 01267 LogInfo(COMPONENT_DISPATCH, 01268 "Host %s is not allowed to access this export entry, vers=%d, proc=%d", 01269 addrbuf, 01270 (int)req->rq_vers, (int)req->rq_proc); 01271 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 01272 svcerr_auth2(xprt, req, AUTH_TOOWEAK); 01273 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 01274 /* XXX */ 01275 pworker_data->current_xid = 0; /* No more xid managed */ 01276 01277 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01278 { 01279 LogCrit(COMPONENT_DISPATCH, 01280 "Attempt to delete duplicate request failed on line %d", 01281 __LINE__); 01282 } 01283 return; 01284 } 01285 else if ((export_check_result == EXPORT_WRITE_ATTEMPT_WHEN_RO) || 01286 (export_check_result == EXPORT_WRITE_ATTEMPT_WHEN_MDONLY_RO)) 01287 { 01288 LogDebug(COMPONENT_DISPATCH, 01289 "Dropping request because nfs_export_check_access() reported this is a RO filesystem."); 01290 if(req->rq_prog == nfs_param.core_param.program[P_NFS]) 01291 { 01292 if(req->rq_vers == NFS_V2) 01293 { 01294 /* All the nfs_res structure in V2 have the status at the same place (because it is an union) */ 01295 res_nfs.res_attr2.status = NFSERR_ROFS; 01296 rc = NFS_REQ_OK; /* Processing of the request is done */ 01297 } 01298 else 01299 { 01300 /* V3 request */ 01301 /* All the nfs_res structure in V2 have the status at the same place, and so does V3 ones */ 01302 res_nfs.res_attr2.status = (nfsstat2) NFS3ERR_ROFS; 01303 rc = NFS_REQ_OK; /* Processing of the request is done */ 01304 } 01305 } 01306 else /* unexpected protocol (mount doesn't make write) */ 01307 rc = NFS_REQ_DROP; 01308 } 01309 else if ((export_check_result != EXPORT_PERMISSION_GRANTED) && 01310 (export_check_result != EXPORT_MDONLY_GRANTED)) 01311 { 01312 /* If not EXPORT_PERMISSION_GRANTED, then we are all out of options! */ 01313 LogMajor(COMPONENT_DISPATCH, 01314 "nfs_export_check_access() returned none of the expected flags. This is an unexpected state!"); 01315 rc = NFS_REQ_DROP; 01316 } 01317 else /* export_check_result == EXPORT_PERMISSION_GRANTED is TRUE */ 01318 { 01319 LogFullDebug(COMPONENT_DISPATCH, 01320 "nfs_export_check_access() reported PERMISSION GRANTED."); 01321 01322 /* Do the authentication stuff, if needed */ 01323 if(pworker_data->pfuncdesc->dispatch_behaviour & NEEDS_CRED) 01324 { 01325 /* Swap the anonymous uid/gid if the user should be anonymous */ 01326 if(nfs_check_anon(&related_client, pexport, &user_credentials) == FALSE 01327 || nfs_build_fsal_context(req, 01328 pexport, 01329 &pworker_data->thread_fsal_context, 01330 &user_credentials) == FALSE) 01331 { 01332 LogInfo(COMPONENT_DISPATCH, 01333 "authentication failed, rejecting client"); 01334 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 01335 svcerr_auth2(xprt, req, AUTH_TOOWEAK); 01336 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 01337 /* XXX */ 01338 pworker_data->current_xid = 0; /* No more xid managed */ 01339 01340 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01341 { 01342 LogCrit(COMPONENT_DISPATCH, 01343 "Attempt to delete duplicate request failed on line %d", 01344 __LINE__); 01345 } 01346 return; 01347 } 01348 } 01349 01350 /* processing */ 01351 P(pworker_data->request_pool_mutex); 01352 gettimeofday(timer_start, NULL); 01353 01354 LogDebug(COMPONENT_DISPATCH, 01355 "NFS DISPATCHER: Calling service function %s start_time %llu.%.6llu", 01356 pworker_data->pfuncdesc->funcname, 01357 (unsigned long long)timer_start->tv_sec, 01358 (unsigned long long)timer_start->tv_usec); 01359 01360 V(pworker_data->request_pool_mutex); 01361 01362 #ifdef _ERROR_INJECTION 01363 if(worker_delay_time != 0) 01364 sleep(worker_delay_time); 01365 else if(next_worker_delay_time != 0) 01366 { 01367 sleep(next_worker_delay_time); 01368 next_worker_delay_time = 0; 01369 } 01370 #endif 01371 01372 pfsal_op_ctx = &pworker_data->thread_fsal_context ; 01373 01374 rc = pworker_data->pfuncdesc->service_function(parg_nfs, 01375 pexport, 01376 pfsal_op_ctx, 01377 pworker_data, 01378 req, 01379 &res_nfs); 01380 } 01381 01382 /* Perform statistics here */ 01383 gettimeofday(&timer_end, NULL); 01384 01385 /* process time */ 01386 stat_type = (rc == NFS_REQ_OK) ? GANESHA_STAT_SUCCESS : GANESHA_STAT_DROP; 01387 P(pworker_data->request_pool_mutex); 01388 timer_diff = time_diff(*timer_start, timer_end); 01389 01390 /* this thread is done, reset the timer start to avoid long processing */ 01391 memset(timer_start, 0, sizeof(struct timeval)); 01392 V(pworker_data->request_pool_mutex); 01393 latency_stat.type = SVC_TIME; 01394 latency_stat.latency = timer_diff.tv_sec * 1000000 01395 + timer_diff.tv_usec; /* microseconds */ 01396 nfs_stat_update(stat_type, &(pworker_data->stats.stat_req), req, 01397 &latency_stat); 01398 01399 if ((req->rq_prog == nfs_param.core_param.program[P_MNT]) || 01400 ((req->rq_prog == nfs_param.core_param.program[P_NFS]) && 01401 (req->rq_proc == 0 /*NULL RPC*/ ))) { 01402 update_per_share_stats = FALSE; 01403 } else { 01404 update_per_share_stats = TRUE; 01405 } 01406 /* Update per-share counter and process time */ 01407 if (update_per_share_stats) { 01408 nfs_stat_update(stat_type, 01409 &(pexport->worker_stats[pworker_data->worker_index].stat_req), 01410 req, &latency_stat); 01411 } 01412 01413 /* process time + queue time */ 01414 queue_timer_diff = time_diff(preqnfs->time_queued, timer_end); 01415 latency_stat.type = AWAIT_TIME; 01416 latency_stat.latency = queue_timer_diff.tv_sec * 1000000 01417 + queue_timer_diff.tv_usec; /* microseconds */ 01418 nfs_stat_update(GANESHA_STAT_SUCCESS, &(pworker_data->stats.stat_req), req, 01419 &latency_stat); 01420 01421 /* Update per-share process time + queue time */ 01422 if (update_per_share_stats) { 01423 nfs_stat_update(GANESHA_STAT_SUCCESS, 01424 &(pexport->worker_stats[pworker_data->worker_index].stat_req), 01425 req, &latency_stat); 01426 01427 /* Update per-share total counters */ 01428 pexport->worker_stats[pworker_data->worker_index].nb_total_req += 1; 01429 } 01430 01431 /* Update total counters */ 01432 pworker_data->stats.nb_total_req += 1; 01433 01434 if(timer_diff.tv_sec >= nfs_param.core_param.long_processing_threshold) 01435 LogEvent(COMPONENT_DISPATCH, 01436 "Function %s xid=%u exited with status %d taking %llu.%.6llu seconds to process", 01437 pworker_data->pfuncdesc->funcname, req->rq_xid, rc, 01438 (unsigned long long)timer_diff.tv_sec, 01439 (unsigned long long)timer_diff.tv_usec); 01440 else 01441 LogDebug(COMPONENT_DISPATCH, 01442 "Function %s xid=%u exited with status %d taking %llu.%.6llu seconds to process", 01443 pworker_data->pfuncdesc->funcname, req->rq_xid, rc, 01444 (unsigned long long)timer_diff.tv_sec, 01445 (unsigned long long)timer_diff.tv_usec); 01446 01447 LogFullDebug(COMPONENT_DISPATCH, 01448 "Function %s xid=%u: process %llu.%.6llu await %llu.%.6llu", 01449 pworker_data->pfuncdesc->funcname, req->rq_xid, 01450 (unsigned long long int)timer_diff.tv_sec, 01451 (unsigned long long int)timer_diff.tv_usec, 01452 (unsigned long long int)queue_timer_diff.tv_sec, 01453 (unsigned long long int)queue_timer_diff.tv_usec); 01454 01455 /* Perform NFSv4 operations statistics if required */ 01456 if(req->rq_vers == NFS_V4) 01457 if(req->rq_proc == NFSPROC4_COMPOUND) 01458 nfs4_op_stat_update(parg_nfs, &res_nfs, 01459 &(pworker_data->stats.stat_req)); 01460 01461 /* XXX */ 01462 pworker_data->current_xid = 0; /* No more xid managed */ 01463 01464 /* If request is dropped, no return to the client */ 01465 if(rc == NFS_REQ_DROP) 01466 { 01467 /* The request was dropped */ 01468 LogDebug(COMPONENT_DISPATCH, 01469 "Drop request rpc_xid=%u, program %u, version %u, function %u", 01470 req->rq_xid, (int)req->rq_prog, 01471 (int)req->rq_vers, (int)req->rq_proc); 01472 01473 /* If the request is not normally cached, then the entry will be removed 01474 * later. We only remove a reply that is normally cached that has been 01475 * dropped. */ 01476 if(do_dupreq_cache) 01477 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01478 { 01479 LogCrit(COMPONENT_DISPATCH, 01480 "Attempt to delete duplicate request failed on line %d", 01481 __LINE__); 01482 } 01483 } 01484 else 01485 { 01486 LogFullDebug(COMPONENT_DISPATCH, 01487 "Before svc_sendreply on socket %d", 01488 xprt->xp_fd); 01489 01490 svc_dplx_lock_x(xprt, &pworker_data->sigmask); 01491 01492 /* encoding the result on xdr output */ 01493 if(svc_sendreply2(xprt, req, pworker_data->pfuncdesc->xdr_encode_func, 01494 (caddr_t) &res_nfs) == FALSE) 01495 { 01496 LogDebug(COMPONENT_DISPATCH, 01497 "NFS DISPATCHER: FAILURE: Error while calling svc_sendreply"); 01498 svcerr_systemerr2(xprt, req); 01499 01500 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01501 { 01502 LogCrit(COMPONENT_DISPATCH, 01503 "Attempt to delete duplicate request failed on line %d", 01504 __LINE__); 01505 } 01506 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 01507 return; 01508 } 01509 01510 LogFullDebug(COMPONENT_DISPATCH, 01511 "After svc_sendreply on socket %d", 01512 xprt->xp_fd); 01513 01514 /* Mark request as finished */ 01515 LogFullDebug(COMPONENT_DUPREQ, "YES?: %d", do_dupreq_cache); 01516 if(do_dupreq_cache) 01517 { 01518 dpq_status = nfs_dupreq_finish(req, &res_nfs, lru_dupreq); 01519 } 01520 } /* rc == NFS_REQ_DROP */ 01521 01522 /* Free the allocated resources once the work is done */ 01523 /* Free the arguments */ 01524 if((preqnfs->req.rq_vers == 2) || 01525 (preqnfs->req.rq_vers == 3) || 01526 (preqnfs->req.rq_vers == 4)) 01527 if(!SVC_FREEARGS(xprt, pworker_data->pfuncdesc->xdr_decode_func, 01528 (caddr_t) parg_nfs)) 01529 { 01530 LogCrit(COMPONENT_DISPATCH, 01531 "NFS DISPATCHER: FAILURE: Bad SVC_FREEARGS for %s", 01532 pworker_data->pfuncdesc->funcname); 01533 } 01534 01535 /* XXX we must hold xprt lock across SVC_FREEARGS */ 01536 svc_dplx_unlock_x(xprt, &pworker_data->sigmask); 01537 01538 /* Free the reply. 01539 * This should not be done if the request is dupreq cached because this will 01540 * mark the dupreq cached info eligible for being reuse by other requests */ 01541 if(!do_dupreq_cache) 01542 { 01543 if (nfs_dupreq_delete(req) != DUPREQ_SUCCESS) 01544 { 01545 LogCrit(COMPONENT_DISPATCH, 01546 "Attempt to delete duplicate request failed on line %d", 01547 __LINE__); 01548 } 01549 /* Free only the non dropped requests */ 01550 if(rc == NFS_REQ_OK) { 01551 pworker_data->pfuncdesc->free_function(&res_nfs); 01552 } 01553 } 01554 01555 /* By now the dupreq cache entry should have been completed w/ a request 01556 * that is reusable or the dupreq cache entry should have been removed. */ 01557 return; 01558 } /* nfs_rpc_execute */ 01559 01573 int nfs_Init_worker_data(nfs_worker_data_t * pdata) 01574 { 01575 LRU_status_t status = LRU_LIST_SUCCESS; 01576 char name[256]; 01577 01578 if(pthread_mutex_init(&(pdata->request_pool_mutex), NULL) != 0) 01579 return -1; 01580 01581 sprintf(name, "Worker Thread #%u", (int)pdata->worker_index); 01582 if(tcb_new(&(pdata->wcb), name) != 0) 01583 return -1; 01584 01585 init_glist(&pdata->pending_request); 01586 pdata->pending_request_len = 0; 01587 01588 sprintf(name, "Worker Thread #%u Duplicate Request", pdata->worker_index); 01589 nfs_param.worker_param.lru_dupreq.lp_name = name; 01590 01591 if((pdata->duplicate_request = 01592 LRU_Init(nfs_param.worker_param.lru_dupreq, &status)) == NULL) 01593 { 01594 LogError(COMPONENT_DISPATCH, ERR_LRU, ERR_LRU_LIST_INIT, status); 01595 return -1; 01596 } 01597 01598 pdata->passcounter = 0; 01599 pdata->wcb.tcb_ready = FALSE; 01600 pdata->gc_in_progress = FALSE; 01601 pdata->pfuncdesc = INVALID_FUNCDESC; 01602 01603 return 0; 01604 } /* nfs_Init_worker_data */ 01605 01606 void DispatchWorkNFS(request_data_t *nfsreq, unsigned int worker_index) 01607 { 01608 struct svc_req *req = NULL; 01609 uint32_t rpcxid = 0; 01610 01611 switch (nfsreq->rtype) { 01612 case NFS_CALL: 01613 break; 01614 default: 01615 req = &nfsreq->r_u.nfs->req; 01616 rpcxid = req->rq_xid; 01617 } 01618 01619 LogDebug(COMPONENT_DISPATCH, 01620 "Awaking Worker Thread #%u for request %p, rtype=%d xid=%u", 01621 worker_index, nfsreq, nfsreq->rtype, rpcxid); 01622 01623 P(workers_data[worker_index].wcb.tcb_mutex); 01624 P(workers_data[worker_index].request_pool_mutex); 01625 01626 glist_add_tail(&workers_data[worker_index].pending_request, &nfsreq->pending_req_queue); 01627 workers_data[worker_index].pending_request_len++; 01628 01629 if(pthread_cond_signal(&(workers_data[worker_index].wcb.tcb_condvar)) == -1) 01630 { 01631 V(workers_data[worker_index].request_pool_mutex); 01632 V(workers_data[worker_index].wcb.tcb_mutex); 01633 LogMajor(COMPONENT_THREAD, 01634 "Error %d (%s) while signalling Worker Thread #%u... Exiting", 01635 errno, strerror(errno), worker_index); 01636 Fatal(); 01637 } 01638 V(workers_data[worker_index].request_pool_mutex); 01639 V(workers_data[worker_index].wcb.tcb_mutex); 01640 } 01641 01642 enum auth_stat AuthenticateRequest(nfs_request_data_t *nfsreq, 01643 bool_t *no_dispatch) 01644 { 01645 struct rpc_msg *msg; 01646 struct svc_req *req; 01647 SVCXPRT *xprt; 01648 enum auth_stat why; 01649 01650 /* A few words of explanation are required here: 01651 * In authentication is AUTH_NONE or AUTH_UNIX, then the value of no_dispatch 01652 * remains FALSE and the request is proceeded normally. 01653 * If authentication is RPCSEC_GSS, no_dispatch may have value TRUE, this 01654 * means that gc->gc_proc != RPCSEC_GSS_DATA and that the message is in fact 01655 * an internal negociation message from RPCSEC_GSS using GSSAPI. It then 01656 * should not be proceed by the worker and SVC_STAT should be returned to 01657 * the dispatcher. 01658 */ 01659 01660 *no_dispatch = FALSE; 01661 01662 /* Set pointers */ 01663 msg = &(nfsreq->msg); 01664 req = &(nfsreq->req); 01665 xprt = nfsreq->xprt; 01666 01667 req->rq_xprt = nfsreq->xprt; 01668 req->rq_prog = msg->rm_call.cb_prog; 01669 req->rq_vers = msg->rm_call.cb_vers; 01670 req->rq_proc = msg->rm_call.cb_proc; 01671 req->rq_xid = msg->rm_xid; 01672 01673 LogFullDebug(COMPONENT_DISPATCH, 01674 "About to authenticate Prog=%d, vers=%d, proc=%d xid=%u xprt=%p", 01675 (int)req->rq_prog, (int)req->rq_vers, 01676 (int)req->rq_proc, req->rq_xid, req->rq_xprt); 01677 01678 /* XXX Restore previously saved GssData. 01679 * I'm not clear what we're restoring here. Operating on xprt means that 01680 * we do (did) not share buffers with xprt_copy. 01681 */ 01682 #ifdef _HAVE_GSSAPI 01683 if((why = Rpcsecgss__authenticate(req, msg, no_dispatch)) != AUTH_OK) 01684 #else 01685 if((why = _authenticate(req, msg)) != AUTH_OK) 01686 #endif 01687 { 01688 char auth_str[AUTH_STR_LEN]; 01689 auth_stat2str(why, auth_str); 01690 LogInfo(COMPONENT_DISPATCH, 01691 "Could not authenticate request... rejecting with AUTH_STAT=%s", 01692 auth_str); 01693 svcerr_auth2(xprt, req, why); 01694 *no_dispatch = TRUE; 01695 return why; 01696 } 01697 else 01698 { 01699 #ifdef _HAVE_GSSAPI 01700 struct rpc_gss_cred *gc; 01701 01702 if(req->rq_xprt->xp_verf.oa_flavor == RPCSEC_GSS) 01703 { 01704 gc = (struct rpc_gss_cred *) req->rq_clntcred; 01705 LogFullDebug(COMPONENT_DISPATCH, 01706 "AuthenticateRequest no_dispatch=%d gc->gc_proc=(%u) %s", 01707 *no_dispatch, gc->gc_proc, str_gc_proc(gc->gc_proc)); 01708 } 01709 #endif 01710 } /* else from if( ( why = _authenticate( preq, pmsg) ) != AUTH_OK) */ 01711 return AUTH_OK; 01712 } 01713 01714 #ifdef _USE_9P 01715 01726 static void _9p_execute( _9p_request_data_t * preq9p, 01727 nfs_worker_data_t * pworker_data) 01728 { 01729 _9p_process_request( preq9p, pworker_data ) ; 01730 return ; 01731 } /* _9p_execute */ 01732 #endif 01733 01734 static inline enum xprt_stat 01735 cond_multi_dispatch(nfs_worker_data_t *pmydata, request_data_t *nfsreq, 01736 bool *locked) 01737 { 01738 enum xprt_stat stat; 01739 bool_t try_multi = FALSE, dispatched = FALSE; 01740 SVCXPRT *xprt = nfsreq->r_u.nfs->xprt; 01741 01742 stat = SVC_STAT(xprt); 01743 svc_dplx_unlock_x(xprt, &pmydata->sigmask); 01744 *locked = FALSE; 01745 01746 if (stat == XPRT_MOREREQS) 01747 try_multi = TRUE; 01748 01749 #if 0 /* XXX */ 01750 try_multi = FALSE; 01751 #endif 01752 01753 if (try_multi) { 01754 process_status_t rc_multi __attribute__((unused)); 01755 gsh_xprt_private_t *xu; 01756 pthread_rwlock_wrlock(&xprt->lock); 01757 xu = (gsh_xprt_private_t *) xprt->xp_u1; 01758 01759 LogDebug(COMPONENT_DISPATCH, "xprt=%p try_multi=TRUE multi_cnt=%u " 01760 "refcnt=%u", 01761 xprt, 01762 xu->multi_cnt, 01763 xu->refcnt); 01764 01765 /* we need an atomic total-outstanding counter, check against hiwat */ 01766 if (xu->multi_cnt < nfs_param.core_param.dispatch_multi_xprt_max) { 01767 ++(xu->multi_cnt); 01768 /* dispatch it */ 01769 rc_multi = dispatch_rpc_subrequest(pmydata, nfsreq); 01770 dispatched = TRUE; 01771 } 01772 pthread_rwlock_unlock(&xprt->lock); 01773 } 01774 01775 if (! dispatched) { 01776 /* Execute it */ 01777 nfs_rpc_execute(nfsreq, pmydata); 01778 } 01779 01780 return (stat); 01781 } 01782 01788 #define DISP_LOCK(x) do { \ 01789 if (! locked) { \ 01790 svc_dplx_lock_x(xprt, &pmydata->sigmask); \ 01791 locked = TRUE; \ 01792 }\ 01793 } while (0); 01794 01795 #define DISP_UNLOCK(x) do { \ 01796 if (locked) { \ 01797 svc_dplx_unlock_x(xprt, &pmydata->sigmask); \ 01798 locked = FALSE; \ 01799 }\ 01800 } while (0); 01801 01802 process_status_t 01803 nfs_worker_process_rpc_requests(nfs_worker_data_t *pmydata, 01804 request_data_t *nfsreq) 01805 { 01806 enum xprt_stat stat = XPRT_IDLE; 01807 struct rpc_msg *pmsg; 01808 struct svc_req *preq; 01809 const nfs_function_desc_t *pfuncdesc; 01810 bool_t no_dispatch = TRUE, recv_status; 01811 process_status_t rc = PROCESS_DONE; 01812 SVCXPRT *xprt; 01813 bool locked = FALSE; 01814 again: 01815 /* 01816 * Receive from socket. 01817 * Will block until the client operates on the socket 01818 */ 01819 xprt = nfsreq->r_u.nfs->xprt; 01820 01821 LogFullDebug(COMPONENT_DISPATCH, 01822 "Before calling SVC_RECV on socket %d", 01823 xprt->xp_fd); 01824 01825 rc = PROCESS_DONE; 01826 01827 preq = &nfsreq->r_u.nfs->req; 01828 pmsg = &nfsreq->r_u.nfs->msg; 01829 01830 DISP_LOCK(xprt); 01831 recv_status = SVC_RECV(xprt, pmsg); 01832 01833 LogFullDebug(COMPONENT_DISPATCH, 01834 "Status for SVC_RECV on socket %d is %d, xid=%lu", 01835 xprt->xp_fd, 01836 recv_status, 01837 (unsigned long)pmsg->rm_xid); 01838 01839 /* If status is ok, the request will be processed by the related 01840 * worker, otherwise, it should be released by being tagged as invalid. */ 01841 if (!recv_status) 01842 { 01843 /* RPC over TCP specific: RPC/UDP's xprt know only one state: XPRT_IDLE, 01844 * because UDP is mostly a stateless protocol. With RPC/TCP, they can be 01845 * XPRT_DIED especially when the client closes the peer's socket. We 01846 * have to cope with this aspect in the next lines. Finally, xdrrec 01847 * uses XPRT_MOREREQS to indicate that additional records are ready to 01848 * be consumed immediately. */ 01849 01850 /* XXXX */ 01851 sockaddr_t addr; 01852 char addrbuf[SOCK_NAME_MAX]; 01853 01854 if(copy_xprt_addr(&addr, xprt) == 1) 01855 sprint_sockaddr(&addr, addrbuf, sizeof(addrbuf)); 01856 else 01857 sprintf(addrbuf, "<unresolved>"); 01858 01859 stat = SVC_STAT(xprt); 01860 DISP_UNLOCK(xprt); 01861 01862 if(stat == XPRT_DIED) 01863 { 01864 01865 LogDebug(COMPONENT_DISPATCH, 01866 "Client on socket=%d, addr=%s disappeared...", 01867 xprt->xp_fd, addrbuf); 01868 DISP_LOCK(xprt); 01869 gsh_xprt_destroy(xprt); 01870 rc = PROCESS_LOST_CONN; 01871 } 01872 else if(stat == XPRT_MOREREQS) 01873 { 01874 /* unexpected case */ 01875 LogDebug(COMPONENT_DISPATCH, 01876 "Client on socket=%d, addr=%s has status XPRT_MOREREQS", 01877 xprt->xp_fd, addrbuf); 01878 } 01879 else if(stat == XPRT_IDLE) 01880 { 01881 LogDebug(COMPONENT_DISPATCH, 01882 "Client on socket=%d, addr=%s has status XPRT_IDLE", 01883 xprt->xp_fd, addrbuf); 01884 } 01885 else 01886 { 01887 LogDebug(COMPONENT_DISPATCH, 01888 "Client on socket=%d, addr=%s has status unknown (%d)", 01889 xprt->xp_fd, addrbuf, (int)stat); 01890 } 01891 goto unblock; 01892 } 01893 else 01894 { 01895 nfsreq->r_u.nfs->req.rq_prog = pmsg->rm_call.cb_prog; 01896 nfsreq->r_u.nfs->req.rq_vers = pmsg->rm_call.cb_vers; 01897 nfsreq->r_u.nfs->req.rq_proc = pmsg->rm_call.cb_proc; 01898 nfsreq->r_u.nfs->req.rq_xid = pmsg->rm_xid; 01899 01900 pfuncdesc = nfs_rpc_get_funcdesc(nfsreq->r_u.nfs); 01901 if(pfuncdesc == INVALID_FUNCDESC) 01902 goto unblock; 01903 01904 DISP_LOCK(xprt); 01905 if(AuthenticateRequest(nfsreq->r_u.nfs, 01906 &no_dispatch) != AUTH_OK || no_dispatch) { 01907 goto unblock; 01908 } 01909 01910 if(!nfs_rpc_get_args(nfsreq->r_u.nfs, pfuncdesc)) 01911 goto unblock; 01912 01913 preq->rq_xprt = xprt; 01914 01915 /* Validate the rpc request as being a valid program, version, 01916 * and proc. If not, report the error. Otherwise, execute the 01917 * funtion. */ 01918 if(is_rpc_call_valid(preq->rq_xprt, preq) == TRUE) 01919 stat = cond_multi_dispatch(pmydata, nfsreq, &locked); 01920 01921 rc = PROCESS_DISPATCHED; 01922 } 01923 01924 unblock: 01925 /* continue receiving if data is available--this isn't optional, because 01926 * irrespective of TI-RPC "nonblock" mode, we will frequently have consumed 01927 * additional RPC records (TCP). Also, we expect to move the SVC_RECV 01928 * into the worker thread, so this will asynchronous wrt to the shared 01929 * event loop */ 01930 if (rc == PROCESS_DISPATCHED) { 01931 if (stat == XPRT_MOREREQS) 01932 goto again; 01933 else { 01934 /* XXX dont bother re-arming epoll for xprt if there is data 01935 * waiting */ 01936 struct pollfd fd; 01937 fd.fd = xprt->xp_fd; 01938 fd.events = POLLIN; 01939 if (poll(&fd, 1, 0 /* ms, ie, now */) > 0) 01940 goto again; 01941 } 01942 } 01943 01944 DISP_UNLOCK(xprt); 01945 01946 if (rc != PROCESS_LOST_CONN) 01947 (void) svc_rqst_unblock_events(nfsreq->r_u.nfs->xprt, 01948 SVC_RQST_FLAG_NONE); 01949 01950 return (rc); 01951 } 01952 01966 void *worker_thread(void *IndexArg) 01967 { 01968 request_data_t *nfsreq; 01969 int rc = 0; 01970 unsigned int gc_allowed = FALSE; 01971 unsigned long worker_index = (unsigned long) IndexArg; 01972 nfs_worker_data_t *pmydata = &(workers_data[worker_index]); 01973 char thr_name[32]; 01974 gsh_xprt_private_t *xu = NULL; 01975 01976 #ifdef _USE_SHARED_FSAL 01977 unsigned int i = 0 ; 01978 unsigned int fsalid = 0 ; 01979 #endif 01980 01981 snprintf(thr_name, sizeof(thr_name), "Worker Thread #%lu", worker_index); 01982 SetNameFunction(thr_name); 01983 01984 /* save current signal mask */ 01985 rc = pthread_sigmask(SIG_SETMASK, (sigset_t *) 0, &pmydata->sigmask); 01986 if (rc) { 01987 LogFatal(COMPONENT_DISPATCH, 01988 "pthread_sigmask returned %d", rc); 01989 } 01990 01991 if(mark_thread_existing(&(pmydata->wcb)) == PAUSE_EXIT) 01992 { 01993 /* Oops, that didn't last long... exit. */ 01994 mark_thread_done(&(pmydata->wcb)); 01995 LogDebug(COMPONENT_DISPATCH, 01996 "Worker exiting before initialization"); 01997 return NULL; 01998 } 01999 02000 LogFullDebug(COMPONENT_DISPATCH, 02001 "Starting, pending=%d", pmydata->pending_request_len); 02002 02003 LogDebug(COMPONENT_DISPATCH, "NFS WORKER #%lu: my pthread id is %p", 02004 worker_index, (caddr_t) pthread_self()); 02005 02006 /* Initialisation of credential for current thread */ 02007 LogFullDebug(COMPONENT_DISPATCH, 02008 "NFS WORKER #%lu: Initialization of thread's credential", 02009 worker_index); 02010 02011 if(FSAL_IS_ERROR(FSAL_InitClientContext(&pmydata->thread_fsal_context))) 02012 { 02013 /* Failed init */ 02014 LogFatal(COMPONENT_DISPATCH, 02015 "Error initializing thread's credential"); 02016 } 02017 02018 LogInfo(COMPONENT_DISPATCH, "Worker successfully initialized"); 02019 02020 /* Worker's infinite loop */ 02021 while(1) 02022 { 02023 /* update memory and FSAL stats, 02024 * twice often than stats display. 02025 */ 02026 if(time(NULL) - pmydata->stats.last_stat_update > 02027 (int)nfs_param.core_param.stats_update_delay / 2) 02028 { 02029 02030 FSAL_get_stats(&pmydata->stats.fsal_stats, FALSE); 02031 02032 /* reset last stat */ 02033 pmydata->stats.last_stat_update = time(NULL); 02034 } 02035 02036 /* Wait on condition variable for work to be done */ 02037 LogFullDebug(COMPONENT_DISPATCH, 02038 "waiting for requests to process, pending=%d", 02039 pmydata->pending_request_len); 02040 02041 /* Get the state without lock first, if things are fine 02042 * don't bother to check under lock. 02043 */ 02044 if((pmydata->wcb.tcb_state != STATE_AWAKE) || 02045 (pmydata->pending_request_len == 0)) { 02046 while(1) 02047 { 02048 P(pmydata->wcb.tcb_mutex); 02049 if(pmydata->wcb.tcb_state == STATE_AWAKE && 02050 (pmydata->pending_request_len != 0)) { 02051 V(pmydata->wcb.tcb_mutex); 02052 break; 02053 } 02054 switch(thread_sm_locked(&pmydata->wcb)) 02055 { 02056 case THREAD_SM_RECHECK: 02057 V(pmydata->wcb.tcb_mutex); 02058 continue; 02059 02060 case THREAD_SM_BREAK: 02061 if(pmydata->pending_request_len == 0) { 02062 /* No work; wait */ 02063 pthread_cond_wait(&(pmydata->wcb.tcb_condvar), 02064 &(pmydata->wcb.tcb_mutex)); 02065 V(pmydata->wcb.tcb_mutex); 02066 continue; 02067 } 02068 02069 case THREAD_SM_EXIT: 02070 LogDebug(COMPONENT_DISPATCH, "Worker exiting as requested"); 02071 V(pmydata->wcb.tcb_mutex); 02072 return NULL; 02073 } 02074 } 02075 } 02076 02077 LogFullDebug(COMPONENT_DISPATCH, 02078 "Processing a new request, pause_state: %s, pending=%u", 02079 pause_state_str[pmydata->wcb.tcb_state], 02080 pmydata->pending_request_len); 02081 02082 P(pmydata->request_pool_mutex); 02083 nfsreq = glist_first_entry(&pmydata->pending_request, request_data_t, 02084 pending_req_queue); 02085 if (nfsreq == NULL) { 02086 V(pmydata->request_pool_mutex); 02087 LogMajor(COMPONENT_DISPATCH, "No pending request available"); 02088 continue; /* return to main loop */ 02089 } 02090 glist_del(&nfsreq->pending_req_queue); 02091 pmydata->pending_request_len--; 02092 V(pmydata->request_pool_mutex); 02093 02094 /* Check for destroyed xprts */ 02095 switch(nfsreq->rtype) { 02096 case NFS_REQUEST_LEADER: 02097 case NFS_REQUEST: 02098 xu = (gsh_xprt_private_t *) nfsreq->r_u.nfs->xprt->xp_u1; 02099 pthread_rwlock_rdlock(&nfsreq->r_u.nfs->xprt->lock); 02100 if (xu->flags & XPRT_PRIVATE_FLAG_DESTROYED) { 02101 pthread_rwlock_unlock(&nfsreq->r_u.nfs->xprt->lock); 02102 goto finalize_req; 02103 } 02104 pthread_rwlock_unlock(&nfsreq->r_u.nfs->xprt->lock); 02105 break; 02106 default: 02107 break; 02108 } 02109 02110 switch(nfsreq->rtype) 02111 { 02112 case NFS_REQUEST_LEADER: 02113 LogDebug(COMPONENT_DISPATCH, 02114 "Multi-dispatch leader, nfsreq=%p, pending=%d, " 02115 "xid=%u xprt=%p refcnt=%u", 02116 nfsreq, 02117 pmydata->pending_request_len, 02118 nfsreq->r_u.nfs->msg.rm_xid, 02119 nfsreq->r_u.nfs->xprt, 02120 xu->refcnt); 02121 02122 if(nfsreq->r_u.nfs->xprt->xp_fd == 0) 02123 { 02124 LogFullDebug(COMPONENT_DISPATCH, 02125 "RPC dispatch error: nfsreq=%p, xp_fd==0", 02126 nfsreq); 02127 } 02128 else 02129 { 02130 /* Process the sequence */ 02131 (void) nfs_worker_process_rpc_requests(pmydata, nfsreq); 02132 } 02133 break; 02134 02135 case NFS_REQUEST: 02136 LogDebug(COMPONENT_DISPATCH, 02137 "Multi-dispatch subrequest, nfsreq=%p, pending=%d, " 02138 "xid=%u xprt=%p refcnt=%u", 02139 nfsreq, 02140 pmydata->pending_request_len, 02141 nfsreq->r_u.nfs->msg.rm_xid, 02142 nfsreq->r_u.nfs->xprt, 02143 xu->refcnt); 02144 nfs_rpc_execute(nfsreq, pmydata); 02145 break; 02146 02147 case NFS_CALL: 02148 /* NFSv4 rpc call (callback) */ 02149 nfs_rpc_dispatch_call(nfsreq->r_u.call, 0 /* XXX flags */); 02150 break; 02151 02152 case _9P_REQUEST: 02153 #ifdef _USE_9P 02154 _9p_execute(&nfsreq->r_u._9p, pmydata); 02155 #else 02156 LogCrit(COMPONENT_DISPATCH, "Implementation error, 9P message " 02157 "when 9P support is disabled" ) ; 02158 #endif 02159 break; 02160 } 02161 02162 finalize_req: 02163 /* XXX Signal the request processing has completed, though at 02164 * present there may be no effect. */ 02165 LogInfo(COMPONENT_DISPATCH, "Signaling completion of request"); 02166 02167 /* Drop multi_cnt and xprt refcnt, if appropriate */ 02168 switch(nfsreq->rtype) { 02169 case NFS_REQUEST_LEADER: 02170 gsh_xprt_unref( 02171 nfsreq->r_u.nfs->xprt, XPRT_PRIVATE_FLAG_NONE); 02172 break; 02173 case NFS_REQUEST: 02174 pthread_rwlock_wrlock(&nfsreq->r_u.nfs->xprt->lock); 02175 --(xu->multi_cnt); 02176 gsh_xprt_unref( 02177 nfsreq->r_u.nfs->xprt, XPRT_PRIVATE_FLAG_LOCKED); 02178 break; 02179 case NFS_CALL: 02180 break; 02181 default: 02182 break; 02183 } 02184 02185 /* Free the req by releasing the entry */ 02186 LogFullDebug(COMPONENT_DISPATCH, 02187 "Invalidating processed entry"); 02188 if( nfsreq->rtype != _9P_REQUEST && nfsreq->r_u.nfs ) 02189 pool_free(request_data_pool, nfsreq->r_u.nfs); 02190 pool_free(request_pool, nfsreq); 02191 02192 if(pmydata->passcounter > nfs_param.worker_param.nb_before_gc) 02193 { 02194 /* Garbage collection on dup req cache */ 02195 LogFullDebug(COMPONENT_DISPATCH, 02196 "before dupreq invalidation nb_entry=%d nb_invalid=%d", 02197 pmydata->duplicate_request->nb_entry, 02198 pmydata->duplicate_request->nb_invalid); 02199 if((rc = 02200 LRU_invalidate_by_function(pmydata->duplicate_request, 02201 nfs_dupreq_gc_function, 02202 NULL)) != LRU_LIST_SUCCESS) 02203 { 02204 LogCrit(COMPONENT_DISPATCH, 02205 "FAILURE: Impossible to invalidate entries for duplicate " 02206 "request cache (error %d)", 02207 rc); 02208 } 02209 LogFullDebug(COMPONENT_DISPATCH, 02210 "after dupreq invalidation nb_entry=%d nb_invalid=%d", 02211 pmydata->duplicate_request->nb_entry, 02212 pmydata->duplicate_request->nb_invalid); 02213 if((rc = 02214 LRU_gc_invalid(pmydata->duplicate_request, NULL) 02215 != LRU_LIST_SUCCESS)) 02216 LogCrit(COMPONENT_DISPATCH, 02217 "FAILURE: Impossible to gc entries for duplicate request " 02218 "cache (error %d)", 02219 rc); 02220 else 02221 LogFullDebug(COMPONENT_DISPATCH, 02222 "gc entries for duplicate request cache OK"); 02223 02224 LogFullDebug(COMPONENT_DISPATCH, 02225 "after dupreq gc nb_entry=%d nb_invalid=%d", 02226 pmydata->duplicate_request->nb_entry, 02227 pmydata->duplicate_request->nb_invalid); 02228 02229 /* Performing garbabbge collection */ 02230 LogFullDebug(COMPONENT_DISPATCH, 02231 "Garbage collecting on pending request list"); 02232 pmydata->passcounter = 0; 02233 } 02234 else 02235 LogFullDebug(COMPONENT_DISPATCH, 02236 "garbage collection isn't necessary count=%d, max=%d", 02237 pmydata->passcounter, 02238 nfs_param.worker_param.nb_before_gc); 02239 pmydata->passcounter += 1; 02240 02241 /* If needed, perform garbage collection on cache_inode layer */ 02242 P(lock_nb_current_gc_workers); 02243 if(nb_current_gc_workers < nfs_param.core_param.nb_max_concurrent_gc) 02244 { 02245 nb_current_gc_workers += 1; 02246 gc_allowed = TRUE; 02247 } 02248 else 02249 gc_allowed = FALSE; 02250 V(lock_nb_current_gc_workers); 02251 02252 P(pmydata->wcb.tcb_mutex); 02253 if(gc_allowed == TRUE && pmydata->wcb.tcb_state == STATE_AWAKE) 02254 { 02255 pmydata->gc_in_progress = TRUE; 02256 V(pmydata->wcb.tcb_mutex); 02257 LogFullDebug(COMPONENT_DISPATCH, 02258 "There are %d concurrent garbage collection", 02259 nb_current_gc_workers); 02260 02261 P(lock_nb_current_gc_workers); 02262 nb_current_gc_workers -= 1; 02263 V(lock_nb_current_gc_workers); 02264 02265 P(pmydata->wcb.tcb_mutex); 02266 pmydata->gc_in_progress = FALSE; 02267 } 02268 V(pmydata->wcb.tcb_mutex); 02269 02270 } /* while( 1 ) */ 02271 tcb_remove(&pmydata->wcb); 02272 return NULL; 02273 } /* worker_thread */