nfs-ganesha 1.4
|
00001 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*- 00002 * vim:expandtab:shiftwidth=4:tabstop=4: 00003 */ 00004 #ifdef HAVE_CONFIG_H 00005 #include "config.h" 00006 #endif 00007 #include <string.h> 00008 #include "posixdb_internal.h" 00009 #include "posixdb_consistency.h" 00010 #include "RW_Lock.h" 00011 00012 /* cyclic cache of paths */ 00013 00014 typedef struct cache_path_entry__ 00015 { 00016 int is_set; 00017 int path_is_set; 00018 int info_is_set; 00019 posixfsal_handle_t handle; 00020 fsal_path_t path; 00021 rw_lock_t entry_lock; 00022 00023 } cache_path_entry_t; 00024 00025 #define CACHE_PATH_SIZE 509 /* prime near 512 */ 00026 00027 int fsal_posixdb_cache_init() 00028 { 00029 #ifdef _ENABLE_CACHE_PATH 00030 unsigned int i; 00031 00032 memset((char *)cache_array, 0, CACHE_PATH_SIZE * sizeof(cache_path_entry_t)); 00033 00034 for(i = 0; i < CACHE_PATH_SIZE; i++) 00035 { 00036 if(rw_lock_init(&cache_array[i].entry_lock)) 00037 return -1; 00038 00039 cache_array[i].is_set = 0; 00040 cache_array[i].path_is_set = 0; 00041 cache_array[i].info_is_set = 0; 00042 } 00043 00044 #endif 00045 return 0; 00046 } 00047 00048 /* @todo pour augmenter les performances d'acces au cache, 00049 * on hash le handle, et on considere qu'un seul element 00050 * ayant un hash donne peut occuper une case du tableau. 00051 */ 00052 00053 void fsal_posixdb_CachePath(posixfsal_handle_t * p_handle, /* IN */ 00054 fsal_path_t * p_path /* IN */ ) 00055 { 00056 00057 #ifdef _ENABLE_CACHE_PATH 00058 00059 unsigned int i; 00060 00061 LogDebug(COMPONENT_FSAL, "fsal_posixdb_CachePath: %u, %u = %s", (unsigned int)(p_handle->id), 00062 (unsigned int)(p_handle->ts), p_path->path); 00063 00064 i = hash_cache_path(p_handle->id, p_handle->ts); 00065 00066 /* in the handle already in cache ? */ 00067 P_w(&cache_array[i].entry_lock); 00068 00069 if(cache_array[i].is_set 00070 && cache_array[i].handle.id == p_handle->id 00071 && cache_array[i].handle.ts == p_handle->ts) 00072 { 00073 cache_array[i].path_is_set = TRUE; 00074 00075 /* override it */ 00076 cache_array[i].path = *p_path; 00077 00078 V_w(&cache_array[i].entry_lock); 00079 return; 00080 } 00081 00082 /* add it (replace previous handle) */ 00083 cache_array[i].is_set = TRUE; 00084 cache_array[i].path_is_set = TRUE; 00085 cache_array[i].info_is_set = FALSE; 00086 cache_array[i].handle = *p_handle; 00087 cache_array[i].path = *p_path; 00088 V_w(&cache_array[i].entry_lock); 00089 00090 #endif 00091 return; 00092 } 00093 00094 /* set/update informations about a handle */ 00095 int fsal_posixdb_UpdateInodeCache(posixfsal_handle_t * p_handle) /* IN */ 00096 { 00097 #ifdef _ENABLE_CACHE_PATH 00098 00099 unsigned int i; 00100 00101 LogDebug(COMPONENT_FSAL, "UpdateInodeCache: inode_id=%llu", p_handle->info.inode); 00102 00103 i = hash_cache_path(p_handle->id, p_handle->ts); 00104 00105 /* in the handle in cache ? */ 00106 P_w(&cache_array[i].entry_lock); 00107 00108 if(cache_array[i].is_set 00109 && cache_array[i].handle.id == p_handle->id 00110 && cache_array[i].handle.ts == p_handle->ts) 00111 { 00112 /* update its inode info */ 00113 cache_array[i].handle.info = p_handle->info; 00114 cache_array[i].info_is_set = TRUE; 00115 00116 LogDebug(COMPONENT_FSAL, "fsal_posixdb_UpdateInodeCache: %u, %u (existing entry)", 00117 (unsigned int)(p_handle->id), (unsigned int)(p_handle->ts)); 00118 00119 V_w(&cache_array[i].entry_lock); 00120 00121 return TRUE; 00122 } 00123 LogDebug(COMPONENT_FSAL, "fsal_posixdb_UpdateInodeCache: %u, %u (new entry)", 00124 (unsigned int)(p_handle->id), (unsigned int)(p_handle->ts)); 00125 00126 /* add it (replace previous handle) */ 00127 cache_array[i].is_set = TRUE; 00128 cache_array[i].path_is_set = FALSE; 00129 cache_array[i].info_is_set = TRUE; 00130 cache_array[i].handle = *p_handle; 00131 memset(&cache_array[i].path, 0, sizeof(fsal_path_t)); 00132 00133 V_w(&cache_array[i].entry_lock); 00134 #endif 00135 return FALSE; 00136 00137 } 00138 00139 /* retrieve last informations about a handle */ 00140 int fsal_posixdb_GetInodeCache(posixfsal_handle_t * p_handle) /* IN/OUT */ 00141 { 00142 #ifdef _ENABLE_CACHE_PATH 00143 unsigned int i; 00144 00145 i = hash_cache_path(p_handle->id, p_handle->ts); 00146 00147 /* in the handle in cache ? */ 00148 P_r(&cache_array[i].entry_lock); 00149 if(cache_array[i].is_set 00150 && cache_array[i].handle.id == p_handle->id 00151 && cache_array[i].handle.ts == p_handle->ts) 00152 { 00153 if(cache_array[i].info_is_set) 00154 { 00155 p_handle->info = cache_array[i].handle.info; 00156 00157 LogDebug(COMPONENT_FSAL, "fsal_posixdb_GetInodeCache(%u, %u)", (unsigned int)(p_handle->id), 00158 (unsigned int)(p_handle->ts)); 00159 V_r(&cache_array[i].entry_lock); 00160 00161 return TRUE; 00162 } 00163 } 00164 V_r(&cache_array[i].entry_lock); 00165 #endif 00166 return FALSE; 00167 00168 } 00169 00170 void fsal_posixdb_InvalidateCache() 00171 { 00172 #ifdef _ENABLE_CACHE_PATH 00173 unsigned int i; 00174 00175 LogDebug(COMPONENT_FSAL, "fsal_posixdb_InvalidateCache"); 00176 00177 for(i = 0; i < CACHE_PATH_SIZE; i++) 00178 { 00179 P_w(&cache_array[i].entry_lock); 00180 cache_array[i].is_set = FALSE; 00181 cache_array[i].path_is_set = FALSE; 00182 cache_array[i].info_is_set = FALSE; 00183 cache_array[i].handle.id = 0; 00184 cache_array[i].handle.ts = 0; 00185 V_w(&cache_array[i].entry_lock); 00186 } 00187 00188 #endif 00189 } 00190 00191 int fsal_posixdb_GetPathCache(posixfsal_handle_t * p_handle, /* IN */ 00192 fsal_path_t * p_path /* OUT */ ) 00193 { 00194 #ifdef _ENABLE_CACHE_PATH 00195 00196 unsigned int i; 00197 00198 i = hash_cache_path(p_handle->id, p_handle->ts); 00199 00200 /* in the handle in cache ? */ 00201 P_r(&cache_array[i].entry_lock); 00202 if(cache_array[i].is_set 00203 && cache_array[i].handle.id == p_handle->id 00204 && cache_array[i].handle.ts == p_handle->ts) 00205 { 00206 if(cache_array[i].path_is_set) 00207 { 00208 /* return path it */ 00209 memcpy(p_path, &cache_array[i].path, sizeof(fsal_path_t)); 00210 V_r(&cache_array[i].entry_lock); 00211 00212 LogDebug(COMPONENT_FSAL, "fsal_posixdb_GetPathCache(%u, %u)=%s", 00213 (unsigned int)p_handle->id, (unsigned int)p_handle->ts, 00214 p_path->path); 00215 return TRUE; 00216 } 00217 } 00218 V_r(&cache_array[i].entry_lock); 00219 #endif 00220 return FALSE; 00221 } 00222 00223 fsal_posixdb_status_t mysql_error_convert(int err) 00224 { 00225 switch (err) 00226 { 00227 case 0: 00228 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00229 case ER_NO_SUCH_TABLE: 00230 ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, err); 00231 case ER_DUP_ENTRY: 00232 ReturnCodeDB(ERR_FSAL_POSIXDB_CONSISTENCY, err); 00233 case ER_BAD_FIELD_ERROR: 00234 case ER_PARSE_ERROR: 00235 LogCrit(COMPONENT_FSAL, "SQL request parse error or invalid field"); 00236 ReturnCodeDB(ERR_FSAL_POSIXDB_CMDFAILED, err); 00237 default: 00238 LogMajor(COMPONENT_FSAL, 00239 "Unhandled error %d: default conversion to ERR_FSAL_POSIXDB_CMDFAILED", 00240 err); 00241 ReturnCodeDB(ERR_FSAL_POSIXDB_CMDFAILED, err); 00242 } 00243 } 00244 00245 int db_is_retryable(int sql_err) 00246 { 00247 switch (sql_err) 00248 { 00249 case ER_SERVER_SHUTDOWN: 00250 case CR_CONNECTION_ERROR: 00251 case CR_SERVER_GONE_ERROR: 00252 case CR_SERVER_LOST: 00253 return TRUE; 00254 default: 00255 return FALSE; 00256 } 00257 } 00258 00259 fsal_posixdb_status_t db_exec_sql(fsal_posixdb_conn * conn, const char *query, 00260 result_handle_t * p_result) 00261 { 00262 int rc; 00263 /* TODO manage retry period */ 00264 /* unsigned int retry = lmgr_config.connect_retry_min; */ 00265 unsigned int retry = 1; 00266 00267 LogFullDebug(COMPONENT_FSAL, "SQL query: %s", query); 00268 00269 do 00270 { 00271 rc = mysql_real_query(&conn->db_conn, query, strlen(query)); 00272 00273 if(rc && db_is_retryable(mysql_errno(&conn->db_conn))) 00274 { 00275 LogMajor(COMPONENT_FSAL, "Connection to database lost... Retrying in %u sec.", 00276 retry); 00277 sleep(retry); 00278 retry *= 2; 00279 /*if ( retry > lmgr_config.connect_retry_max ) 00280 retry = lmgr_config.connect_retry_max; */ 00281 } 00282 00283 } 00284 while(rc && db_is_retryable(mysql_errno(&conn->db_conn))); 00285 00286 if(rc) 00287 { 00288 LogMajor(COMPONENT_FSAL, "DB request failed: %s (query: %s)", 00289 mysql_error(&conn->db_conn), query); 00290 return mysql_error_convert(mysql_errno(&conn->db_conn)); 00291 } 00292 else 00293 { 00294 if(p_result) 00295 *p_result = mysql_store_result(&conn->db_conn); 00296 00297 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00298 } 00299 } 00300 00301 fsal_posixdb_status_t fsal_posixdb_buildOnePath(fsal_posixdb_conn * p_conn, 00302 posixfsal_handle_t * p_handle, 00303 fsal_path_t * p_path) 00304 { 00305 unsigned int shift; 00306 char *new_pos; 00307 int toomanypaths = 0; 00308 00309 MYSQL_BIND input[2]; /* input = id, timestamp */ 00310 00311 const int output_num = 3; 00312 MYSQL_BIND output[output_num]; /* output = path, id, timestamp */ 00313 my_bool is_null[output_num]; 00314 unsigned long length[output_num]; 00315 my_bool error[output_num]; 00316 00317 unsigned long long last_id; 00318 unsigned int last_ts; 00319 unsigned long long id; 00320 unsigned int ts; 00321 00322 char name[FSAL_MAX_NAME_LEN]; 00323 int root_reached = FALSE; 00324 MYSQL_STMT *stmt; 00325 int rc; 00326 00327 memset(output, 0, sizeof(MYSQL_BIND) * output_num); 00328 memset(is_null, 0, sizeof(my_bool) * output_num); 00329 memset(length, 0, sizeof(unsigned long) * output_num); 00330 memset(error, 0, sizeof(my_bool) * output_num); 00331 00332 if(!p_conn || !p_handle || !p_path) 00333 { 00334 ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); 00335 } 00336 00337 stmt = p_conn->stmt_tab[BUILDONEPATH]; 00338 00339 /* init values */ 00340 memset(p_path, 0, sizeof(fsal_path_t)); 00341 00342 /* Nothing to do, it's the root path */ 00343 if(p_handle->data.id == 0 && p_handle->data.ts == 0) 00344 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00345 00346 /* check if the entry is in the cache */ 00347 if(fsal_posixdb_GetPathCache(p_handle, p_path)) 00348 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00349 00350 last_id = p_handle->data.id; 00351 last_ts = p_handle->data.ts; 00352 00353 /* Bind input parameters */ 00354 00355 input[0].buffer_type = MYSQL_TYPE_LONGLONG; 00356 input[0].buffer = (char *)&last_id; 00357 input[0].is_null = (my_bool *) 0; 00358 input[0].is_unsigned = 1; 00359 input[0].length = NULL; 00360 00361 input[1].buffer_type = MYSQL_TYPE_LONG; 00362 input[1].buffer = (char *)&last_ts; 00363 input[1].is_null = (my_bool *) 0; 00364 input[1].is_unsigned = 1; 00365 input[1].length = NULL; 00366 00367 if(mysql_stmt_bind_param(stmt, input)) 00368 { 00369 LogCrit(COMPONENT_FSAL, "mysql_stmt_bind_param() failed: %s", mysql_stmt_error(stmt)); 00370 return mysql_error_convert(mysql_stmt_errno(stmt)); 00371 } 00372 00373 /* Bind output values */ 00374 00375 output[0].buffer_type = MYSQL_TYPE_STRING; 00376 output[0].buffer = (char *)name; 00377 output[0].buffer_length = FSAL_MAX_NAME_LEN; 00378 output[0].is_null = &is_null[0]; 00379 output[0].length = &length[0]; 00380 output[0].error = &error[0]; 00381 00382 output[1].buffer_type = MYSQL_TYPE_LONGLONG; 00383 output[1].buffer = (char *)&id; 00384 output[1].is_unsigned = 1; 00385 output[1].is_null = &is_null[1]; 00386 output[1].length = &length[1]; 00387 output[1].error = &error[1]; 00388 00389 output[2].buffer_type = MYSQL_TYPE_LONG; 00390 output[2].buffer = (char *)&ts; 00391 output[2].is_unsigned = 1; 00392 output[2].is_null = &is_null[2]; 00393 output[2].length = &length[2]; 00394 output[2].error = &error[2]; 00395 00396 if(mysql_stmt_bind_result(stmt, output)) 00397 { 00398 LogCrit(COMPONENT_FSAL, "mysql_stmt_bind_result() failed: %s", mysql_stmt_error(stmt)); 00399 return mysql_error_convert(mysql_stmt_errno(stmt)); 00400 } 00401 00402 root_reached = FALSE; 00403 00404 while(!root_reached) 00405 { 00406 00407 rc = mysql_stmt_execute(stmt); 00408 if(rc) 00409 return mysql_error_convert(mysql_stmt_errno(stmt)); 00410 00411 if(mysql_stmt_store_result(stmt)) 00412 { 00413 LogCrit(COMPONENT_FSAL, "mysql_stmt_store_result() failed: %s", mysql_stmt_error(stmt)); 00414 return mysql_error_convert(mysql_stmt_errno(stmt)); 00415 } 00416 00417 /* retrieve result */ 00418 rc = mysql_stmt_fetch(stmt); 00419 if(rc == MYSQL_NO_DATA) 00420 { 00421 /* clean prepared statement */ 00422 mysql_stmt_free_result(stmt); 00423 ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0); /* not found */ 00424 } 00425 else if(rc) 00426 { 00427 /* clean prepared statement */ 00428 mysql_stmt_free_result(stmt); 00429 LogCrit(COMPONENT_FSAL, "mysql_stmt_fetch() failed: %s", mysql_stmt_error(stmt)); 00430 return mysql_error_convert(mysql_stmt_errno(stmt)); 00431 } 00432 00433 /* @TODO check if several results are returned */ 00434 00435 if((id == last_id) && (ts == last_ts)) /* handle is equal to its parent handle (root reached) */ 00436 { 00437 root_reached = TRUE; 00438 break; 00439 } 00440 00441 /* prepare next step */ 00442 last_id = id; 00443 last_ts = ts; 00444 00445 /* insert the name at the beginning of the path */ 00446 shift = strlen(name); 00447 if(p_path->len + shift >= FSAL_MAX_PATH_LEN) 00448 ReturnCodeDB(ERR_FSAL_POSIXDB_PATHTOOLONG, 0); 00449 new_pos = p_path->path + shift; 00450 memmove(new_pos, p_path->path, p_path->len); 00451 memcpy(p_path->path, name, shift); 00452 p_path->len += shift; 00453 } 00454 00455 /* clean prepared statement */ 00456 mysql_stmt_free_result(stmt); 00457 00458 if(toomanypaths) 00459 { 00460 LogCrit(COMPONENT_FSAL, "Returned path: %s", p_path->path); 00461 ReturnCodeDB(ERR_FSAL_POSIXDB_TOOMANYPATHS, toomanypaths); /* too many entries */ 00462 } 00463 else 00464 { 00465 /* set result in cache and return */ 00466 fsal_posixdb_CachePath(p_handle, p_path); 00467 00468 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00469 } 00470 } 00471 00472 fsal_posixdb_status_t fsal_posixdb_recursiveDelete(fsal_posixdb_conn * p_conn, 00473 unsigned long long id, unsigned int ts, 00474 fsal_nodetype_t ftype) 00475 { 00476 fsal_posixdb_status_t st; 00477 fsal_nodetype_t ftype_tmp; 00478 char query[2048]; 00479 result_handle_t res; 00480 MYSQL_ROW row; 00481 00482 /* Sanity check */ 00483 if(!p_conn) 00484 { 00485 ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); 00486 } 00487 00488 if(ftype == FSAL_TYPE_DIR) 00489 { 00490 /* find all the children of the directory in order to delete them, and then we delete the current handle */ 00491 00492 snprintf(query, 2048, 00493 "SELECT Handle.handleid, Handle.handlets, Handle.ftype, Parent.name, Handle.nlink " 00494 "FROM Parent INNER JOIN Handle ON Handle.handleid=Parent.handleid " 00495 "AND Handle.handlets=Parent.handlets " 00496 "WHERE Parent.handleidparent=%llu AND Parent.handletsparent=%u " 00497 "AND NOT (Parent.handleidparent = Parent.handleid AND Parent.handletsparent = Parent.handlets) " 00498 "FOR UPDATE", id, ts); 00499 st = db_exec_sql(p_conn, query, &res); 00500 if(FSAL_POSIXDB_IS_ERROR(st)) 00501 return st; 00502 00503 while((row = mysql_fetch_row(res)) != NULL) 00504 { 00505 ftype_tmp = (fsal_nodetype_t) atoi(row[2]); 00506 if(ftype_tmp == FSAL_TYPE_DIR) 00507 { 00508 st = fsal_posixdb_recursiveDelete(p_conn, atoll(row[0]), atoi(row[1]), 00509 ftype_tmp); 00510 } 00511 else 00512 { 00513 st = fsal_posixdb_deleteParent(p_conn, atoll(row[0]), /* handleidparent */ 00514 atoi(row[1]), /* handletsparent */ 00515 id, ts, row[3], /* filename */ 00516 atoi(row[4])); /* nlink */ 00517 } 00518 if(FSAL_POSIXDB_IS_ERROR(st)) 00519 { 00520 mysql_free_result(res); 00521 return st; 00522 } 00523 } 00524 mysql_free_result(res); 00525 } 00526 00527 /* invalidate name cache */ 00528 fsal_posixdb_InvalidateCache(); 00529 00530 /* Delete the Handle (this also delete entries in Parent, thanks to DELETE CASCADE) */ 00531 snprintf(query, 2048, "DELETE FROM Handle WHERE handleid=%llu AND handlets=%u", id, ts); 00532 00533 st = db_exec_sql(p_conn, query, NULL); 00534 if(FSAL_POSIXDB_IS_ERROR(st)) 00535 return st; 00536 00537 #ifdef _NO_DELETE_CASCADE 00538 /* Delete this handle from parent table (it is supposed not having children now) */ 00539 00540 snprintf(query, 2048, "DELETE FROM Parent WHERE (handleid=%llu AND handlets=%u)", id, 00541 ts); 00542 00543 st = db_exec_sql(p_conn, query, NULL); 00544 if(FSAL_POSIXDB_IS_ERROR(st)) 00545 return st; 00546 #endif 00547 00548 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00549 } 00550 00551 fsal_posixdb_status_t fsal_posixdb_deleteParent(fsal_posixdb_conn * p_conn, /* IN */ 00552 unsigned long long id, /* IN */ 00553 unsigned int ts, /* IN */ 00554 unsigned long long idparent, /* IN */ 00555 unsigned int tsparent, /* IN */ 00556 char *filename, /* IN */ 00557 int nlink) /* IN */ 00558 { 00559 char query[1024]; 00560 fsal_posixdb_status_t st; 00561 00562 /* Sanity check */ 00563 if(!p_conn || !filename || nlink < 1) 00564 { 00565 ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); 00566 } 00567 00568 snprintf(query, 1024, 00569 "DELETE FROM Parent WHERE handleidparent=%llu AND handletsparent=%u AND name='%s'", 00570 idparent, tsparent, filename); 00571 st = db_exec_sql(p_conn, query, NULL); 00572 if(FSAL_POSIXDB_IS_ERROR(st)) 00573 return st; 00574 00575 /* delete the handle or update it */ 00576 if(nlink == 1) 00577 { 00578 00579 /* invalidate cache */ 00580 fsal_posixdb_InvalidateCache(); 00581 00582 /* delete the handle */ 00583 00584 snprintf(query, 1024, "DELETE FROM Handle WHERE handleid=%llu AND handlets=%u", id, 00585 ts); 00586 st = db_exec_sql(p_conn, query, NULL); 00587 if(FSAL_POSIXDB_IS_ERROR(st)) 00588 return st; 00589 00590 #ifdef _NO_DELETE_CASCADE 00591 /* Delete from parent table */ 00592 00593 snprintf(query, 1024, "DELETE FROM Parent WHERE handleid=%llu AND handlets=%u", id, 00594 ts); 00595 st = db_exec_sql(p_conn, query, NULL); 00596 if(FSAL_POSIXDB_IS_ERROR(st)) 00597 return st; 00598 #endif 00599 00600 } 00601 else 00602 { 00603 /* invalidate cache */ 00604 fsal_posixdb_InvalidateCache(); 00605 00606 /* update the Handle entry ( Handle.nlink <- (nlink - 1) ) */ 00607 snprintf(query, 1024, 00608 "UPDATE Handle SET nlink=%u WHERE handleid=%llu AND handlets=%u", 00609 nlink - 1, id, ts); 00610 st = db_exec_sql(p_conn, query, NULL); 00611 if(FSAL_POSIXDB_IS_ERROR(st)) 00612 return st; 00613 } 00614 00615 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00616 } 00617 00618 fsal_posixdb_status_t fsal_posixdb_internal_delete(fsal_posixdb_conn * p_conn, /* IN */ 00619 unsigned long long idparent, /* IN */ 00620 unsigned int tsparent, /* IN */ 00621 char *filename, /* IN */ 00622 fsal_posixdb_fileinfo_t * 00623 p_object_info /* IN */ ) 00624 { 00625 unsigned long long id; 00626 unsigned int ts; 00627 char query[2048]; 00628 00629 fsal_posixdb_status_t st; 00630 fsal_posixdb_fileinfo_t infodb; 00631 result_handle_t res; 00632 MYSQL_ROW row; 00633 00634 if(!p_conn || !filename) 00635 ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); 00636 00637 snprintf(query, 2048, 00638 "SELECT Parent.handleid, Parent.handlets, Handle.deviceid, Handle.inode, Handle.nlink, Handle.ctime, Handle.ftype " 00639 "FROM Parent INNER JOIN Handle ON Parent.handleid = Handle.handleid AND Parent.handlets=Handle.handlets " 00640 "WHERE handleidparent=%llu AND handletsparent=%u AND name='%s' " 00641 "FOR UPDATE", idparent, tsparent, filename); 00642 00643 st = db_exec_sql(p_conn, query, &res); 00644 if(FSAL_POSIXDB_IS_ERROR(st)) 00645 return st; 00646 00647 /* result contains : handleid, handlets, deviceId, inode, nlink, ctime, ftype */ 00648 00649 /* no entry found */ 00650 if((mysql_num_rows(res) < 1) || ((row = mysql_fetch_row(res)) == NULL)) 00651 { 00652 mysql_free_result(res); 00653 ReturnCodeDB(ERR_FSAL_POSIXDB_NOENT, 0); 00654 } 00655 00656 id = atoll(row[0]); 00657 ts = atoi(row[1]); 00658 00659 /* consistency check */ 00660 /* fill 'infodb' with information about the handle in the database */ 00661 /* no need to compare inode & devid, they are the same */ 00662 posixdb_internal_fillFileinfoFromStrValues(&infodb, row[2], row[3], row[4], row[5], 00663 row[6]); 00664 mysql_free_result(res); 00665 00666 if(p_object_info && fsal_posixdb_consistency_check(&infodb, p_object_info)) 00667 { 00668 /* not consistent, the bad handle have to be deleted */ 00669 LogCrit(COMPONENT_FSAL, "Consistency check failed while deleting a Path : Handle deleted"); 00670 infodb.ftype = FSAL_TYPE_DIR; /* considers that the entry is a directory in order to delete all its Parent entries and its Handle */ 00671 } 00672 00673 switch (infodb.ftype) 00674 { 00675 case FSAL_TYPE_DIR: 00676 /* directory */ 00677 st = fsal_posixdb_recursiveDelete(p_conn, id, ts, infodb.ftype); 00678 break; 00679 default: 00680 st = fsal_posixdb_deleteParent(p_conn, 00681 id, ts, idparent, tsparent, filename, infodb.nlink); 00682 } 00683 return st; 00684 } 00685 00686 fsal_posixdb_status_t posixdb_internal_fillFileinfoFromStrValues(fsal_posixdb_fileinfo_t * 00687 p_info, char *devid_str, 00688 char *inode_str, 00689 char *nlink_str, 00690 char *ctime_str, 00691 char *ftype_str) 00692 { 00693 00694 if(!p_info) 00695 ReturnCodeDB(ERR_FSAL_POSIXDB_FAULT, 0); 00696 00697 p_info->devid = devid_str ? (dev_t) atoll(devid_str) : 0; 00698 p_info->inode = inode_str ? (ino_t) atoll(inode_str) : 0; 00699 p_info->nlink = nlink_str ? atoi(nlink_str) : 0; 00700 p_info->ctime = ctime_str ? (time_t) atoi(ctime_str) : 0; 00701 p_info->ftype = ftype_str ? (fsal_nodetype_t) atoi(ftype_str) : 0; 00702 00703 ReturnCodeDB(ERR_FSAL_POSIXDB_NOERR, 0); 00704 }