static inline void undo_rm_helper( entry_id_t * id, const char *last_known_path, #ifdef _HSM_LITE const char *bkpath #endif ) { entry_id_t new_id; recov_status_t st; attr_set_t attrs, new_attrs; int rc; /* XXX src path must be in the same filesystem as backend * because it we be renamed */ if ( EMPTY_STRING( last_known_path ) ) { fprintf(stderr, "Last filesystem path is not known for fid "DFID", backend_path=%s.\n", PFID(id), bkpath); fprintf(stderr, " ----> skipped\n"); return; } printf("Restoring '%s'...\n", last_known_path ); ATTR_MASK_INIT(&attrs); ATTR_MASK_SET(&attrs, fullpath); strcpy( ATTR(&attrs, fullpath), last_known_path ); if ( !EMPTY_STRING( bkpath ) ) { ATTR_MASK_SET(&attrs, backendpath); strcpy( ATTR(&attrs, backendpath), bkpath ); } /* copy file to Lustre */ ATTR_MASK_INIT(&new_attrs); st = rbhext_recover( id, &attrs, &new_id, &new_attrs, NULL ); if ((st == RS_FILE_OK) || (st == RS_FILE_DELTA)|| (st == RS_FILE_EMPTY) || (st == RS_NON_FILE)) { printf("Success\n"); /* discard entry from remove list */ if ( ListMgr_SoftRemove_Discard(&lmgr, id) != 0 ) fprintf(stderr, "Error: could not remove previous id "DFID" from database\n", PFID(id) ); /* clean read-only attrs */ new_attrs.attr_mask &= ~readonly_attr_set; /* insert or update it in the db */ rc = ListMgr_Insert( &lmgr, &new_id, &new_attrs, TRUE ); if ( rc == 0 ) printf("Entry successfully updated in the dabatase\n"); else fprintf(stderr, "ERROR %d inserting entry in the database\n", rc ); } else { printf("ERROR\n"); } }
int update_stripe_info(lmgr_t *p_mgr, PK_ARG_T pk, int validator, const stripe_info_t *p_stripe, const stripe_items_t *p_items, bool insert_if_absent) { attr_set_t fake_attr; attr_set_t *p_attr = &fake_attr; pktype list[1]; rh_strncpy(list[0], pk, sizeof(*list)); ATTR_MASK_INIT(&fake_attr); if (p_stripe) { ATTR_MASK_SET(&fake_attr, stripe_info); ATTR(&fake_attr, stripe_info) = *p_stripe; } if (p_items) { ATTR_MASK_SET(&fake_attr, stripe_items); ATTR(&fake_attr, stripe_items) = *p_items; } return batch_insert_stripe_info(p_mgr, list, &validator, &p_attr, 1, true); }
int EntryProc_db_flag_op( struct entry_proc_op_t *p_op, lmgr_t * lmgr ) { int rc; /* insert to DB */ switch ( p_op->db_op_type ) { attr_set_t attr_chg; lmgr_filter_t filter; filter_value_t val; case OP_TYPE_UPDATE: /* set previous_scan flag */ ATTR_MASK_INIT( &attr_chg ); ATTR_MASK_SET( &attr_chg, previous_scan ); ATTR( &attr_chg, previous_scan ) = TRUE; rc = ListMgr_MassUpdate( lmgr, NULL, &attr_chg ); break; case OP_TYPE_REMOVE: val.val_bool = TRUE; lmgr_simple_filter_init( &filter ); lmgr_simple_filter_add( &filter, ATTR_INDEX_previous_scan, EQUAL, val ); /* remove entries with previous_scan flag */ rc = ListMgr_MassRemove( lmgr, &filter ); lmgr_simple_filter_free( &filter ); break; default: printf( "unhandled\n" ); rc = -1; } if ( rc ) printf( "ERROR: ListMgr mass operation returned %d\n", rc ); if ( p_op->callback_func ) p_op->callback_func( lmgr, p_op, p_op->callback_param ); rc = EntryProcessor_Acknowledge( p_op, 0, TRUE ); return rc; }
/** retrieve directory attributes (nbr of entries, avg size of entries)*/ int listmgr_get_dirattrs( lmgr_t * p_mgr, PK_ARG_T dir_pk, attr_set_t * p_attrs ) { GString *req; result_handle_t result; char *str_info[1]; int rc = 0; int tmp_val; long long tmp_long; if (ATTR_MASK_TEST(p_attrs, type) && (strcmp(ATTR(p_attrs, type), STR_TYPE_DIR) != 0)) { DisplayLog(LVL_FULL, LISTMGR_TAG, "Type='%s' != 'dir' => unsetting dirattrs in attr mask", ATTR(p_attrs, type)); p_attrs->attr_mask = attr_mask_and_not(&p_attrs->attr_mask, &dir_attr_set); return 0; } req = g_string_new(NULL); /* get child entry count from DNAMES_TABLE */ if (ATTR_MASK_TEST(p_attrs, dircount)) { g_string_printf(req, "SELECT %s FROM "DNAMES_TABLE" WHERE parent_id="DPK, dirattr2str(ATTR_INDEX_dircount), dir_pk); rc = db_exec_sql(&p_mgr->conn, req->str, &result); if (rc) goto free_str; rc = db_next_record(&p_mgr->conn, &result, str_info, 1); if (rc == DB_END_OF_LIST) { ATTR_MASK_UNSET(p_attrs, dircount); rc = DB_SUCCESS; } else if (rc == DB_SUCCESS) { if (str_info[0] == NULL) /* count(*) should at least return 0 */ rc = DB_REQUEST_FAILED; else { tmp_val = str2int(str_info[0]); if (tmp_val != -1) { ATTR_MASK_SET(p_attrs, dircount); ATTR(p_attrs, dircount) = tmp_val; rc = DB_SUCCESS; } else /* invalid output format */ rc = DB_REQUEST_FAILED; } } db_result_free(&p_mgr->conn, &result); if (rc) goto free_str; } /* get avgsize of child entries from MAIN_TABLE */ if (ATTR_MASK_TEST(p_attrs, avgsize)) { g_string_printf(req, "SELECT %s FROM "MAIN_TABLE" m, "DNAMES_TABLE" d" " WHERE m.id = d.id and type='file' and d.parent_id="DPK, dirattr2str(ATTR_INDEX_avgsize), dir_pk); rc = db_exec_sql(&p_mgr->conn, req->str, &result); if (rc) goto free_str; rc = db_next_record(&p_mgr->conn, &result, str_info, 1); if (rc == DB_END_OF_LIST) ATTR_MASK_UNSET(p_attrs, avgsize); else if (rc == DB_SUCCESS) { if (str_info[0] == NULL) { /* NULL if no entry matches the criteria */ ATTR_MASK_UNSET(p_attrs, avgsize); rc = DB_SUCCESS; } else { tmp_long = str2bigint(str_info[0]); if (tmp_long != -1LL) { ATTR_MASK_SET(p_attrs, avgsize); ATTR(p_attrs, avgsize) = tmp_long; rc = DB_SUCCESS; } else /* invalid output format */ rc = DB_REQUEST_FAILED; } } db_result_free(&p_mgr->conn, &result); } free_str: g_string_free(req, TRUE); return rc; }
/** * Bulk filtering in the DB. */ static int list_bulk(void) { attr_set_t root_attrs, attrs; entry_id_t root_id, id; int rc; struct stat st; struct lmgr_iterator_t *it; /* no tranvsersal => no wagon * so we need the path from the DB. */ query_mask |= ATTR_MASK_fullpath; ATTR_MASK_INIT(&root_attrs); rc = retrieve_root_id(&root_id); if (rc) return rc; /* root is not a part of the DB: print it now */ ATTR_MASK_SET(&root_attrs, fullpath); strcpy(ATTR(&root_attrs, fullpath), config.global_config.fs_path); if (lstat(ATTR(&root_attrs, fullpath), &st) == 0) { PosixStat2EntryAttr(&st, &root_attrs, TRUE); ListMgr_GenerateFields(&root_attrs, disp_mask | query_mask); } /* root has no name... */ ATTR_MASK_SET(&root_attrs, name); ATTR(&root_attrs, name)[0] = '\0'; /* match condition on dirs parent */ if (!is_expr || (EntryMatches(&root_id, &root_attrs, &match_expr, NULL) == POLICY_MATCH)) { /* don't display dirs if no_dir is specified */ if (! (prog_options.no_dir && ATTR_MASK_TEST(&root_attrs, type) && !strcasecmp(ATTR(&root_attrs, type), STR_TYPE_DIR))) { wagon_t w; w.id = root_id; w.fullname = ATTR(&root_attrs, fullpath); print_entry(&w, &root_attrs); } } /* list all, including dirs */ it = ListMgr_Iterator(&lmgr, &entry_filter, NULL, NULL); if (!it) { DisplayLog(LVL_MAJOR, FIND_TAG, "ERROR: cannot retrieve entry list from database"); return -1; } attrs.attr_mask = disp_mask | query_mask; while ((rc = ListMgr_GetNext(it, &id, &attrs)) == DB_SUCCESS) { if (!is_expr || (EntryMatches(&id, &attrs, &match_expr, NULL) == POLICY_MATCH)) { /* don't display dirs if no_dir is specified */ if (! (prog_options.no_dir && ATTR_MASK_TEST(&attrs, type) && !strcasecmp(ATTR(&attrs, type), STR_TYPE_DIR))) { wagon_t w; w.id = id; w.fullname = ATTR(&attrs, fullpath); print_entry(&w, &attrs); } /* don't display non dirs is dir_only is specified */ else if (! (prog_options.dir_only && ATTR_MASK_TEST(&attrs, type) && strcasecmp(ATTR(&attrs, type), STR_TYPE_DIR))) { wagon_t w; w.id = id; w.fullname = ATTR(&attrs, fullpath); print_entry(&w, &attrs); } else /* return entry don't match? */ DisplayLog(LVL_DEBUG, FIND_TAG, "Warning: returned DB entry doesn't match filter: %s", ATTR(&attrs, fullpath)); } ListMgr_FreeAttrs(&attrs); /* prepare next call */ attrs.attr_mask = disp_mask | query_mask; } ListMgr_CloseIterator(it); return 0; }
/** * List contents of the given id/path list */ static int list_contents(char ** id_list, int id_count) { wagon_t *ids; int i, rc; attr_set_t root_attrs; entry_id_t root_id; int is_id; rc = retrieve_root_id(&root_id); if (rc) return rc; ids = MemCalloc(id_count, sizeof(wagon_t)); if (!ids) return -ENOMEM; for (i = 0; i < id_count; i++) { is_id = TRUE; /* is it a path or fid? */ if (sscanf(id_list[i], SFID, RFID(&ids[i].id)) != FID_SCAN_CNT) { is_id = FALSE; /* take it as a path */ rc = Path2Id(id_list[i], &ids[i].id); if (!rc) { ids[i].fullname = id_list[i]; if (FINAL_SLASH(ids[i].fullname)) REMOVE_FINAL_SLASH(ids[i].fullname); } } else { #if _HAVE_FID /* Take it as an FID. */ char path[RBH_PATH_MAX]; rc = Lustre_GetFullPath( &ids[i].id, path, sizeof(path)); if (!rc) ids[i].fullname = strdup(path); #endif } if (rc) { DisplayLog(LVL_MAJOR, FIND_TAG, "Invalid parameter: %s: %s", id_list[i], strerror(-rc)); goto out; } if ((prog_options.bulk != force_nobulk) && (id_count == 1) && entry_id_equal(&ids[i].id, &root_id)) { /* the ID is FS root: use list_bulk instead */ DisplayLog(LVL_DEBUG, FIND_TAG, "Optimization: switching to bulk DB request mode"); mkfilters(FALSE); /* keep dirs */ MemFree(ids); return list_bulk(); } /* get root attrs to print it (if it matches program options) */ root_attrs.attr_mask = disp_mask | query_mask; rc = ListMgr_Get(&lmgr, &ids[i].id, &root_attrs); if (rc == 0) dircb(&ids[i], &root_attrs, 1, NULL); else { DisplayLog(LVL_VERB, FIND_TAG, "Notice: no attrs in DB for %s", id_list[i]); if (!is_id) { struct stat st; ATTR_MASK_SET(&root_attrs, fullpath); strcpy(ATTR(&root_attrs, fullpath), id_list[i]); if (lstat(ATTR(&root_attrs, fullpath ), &st) == 0) { PosixStat2EntryAttr(&st, &root_attrs, TRUE); ListMgr_GenerateFields( &root_attrs, disp_mask | query_mask); } } else if (entry_id_equal(&ids[i].id, &root_id)) { /* this is root id */ struct stat st; ATTR_MASK_SET(&root_attrs, fullpath); strcpy(ATTR(&root_attrs, fullpath), config.global_config.fs_path); if (lstat(ATTR(&root_attrs, fullpath ), &st) == 0) { PosixStat2EntryAttr(&st, &root_attrs, TRUE); ListMgr_GenerateFields( &root_attrs, disp_mask | query_mask); } } dircb(&ids[i], &root_attrs, 1, NULL); } rc = rbh_scrub(&lmgr, &ids[i], 1, disp_mask | query_mask, dircb, NULL); } out: /* ids have been processed, free them */ MemFree(ids); return rc; }
void PosixStat2EntryAttr( struct stat *p_inode, attr_set_t * p_attr_set, int size_info ) { ATTR_MASK_SET( p_attr_set, owner ); uid2str( p_inode->st_uid, ATTR( p_attr_set, owner ) ); ATTR_MASK_SET( p_attr_set, gr_name ); gid2str( p_inode->st_gid, ATTR( p_attr_set, gr_name ) ); if ( size_info ) { ATTR_MASK_SET( p_attr_set, size ); ATTR( p_attr_set, size ) = p_inode->st_size; ATTR_MASK_SET( p_attr_set, blocks ); ATTR( p_attr_set, blocks ) = p_inode->st_blocks; #ifdef ATTR_INDEX_blksize ATTR_MASK_SET( p_attr_set, blksize ); ATTR( p_attr_set, blksize ) = p_inode->st_blksize; #endif } ATTR_MASK_SET( p_attr_set, last_access ); ATTR( p_attr_set, last_access ) = MAX3( p_inode->st_atime, p_inode->st_mtime, p_inode->st_ctime ); ATTR_MASK_SET( p_attr_set, last_mod ); /* @TODO is this really what we want? */ #if defined(_SHERPA) || defined(_HSM_LITE) ATTR( p_attr_set, last_mod ) = p_inode->st_mtime; #else ATTR( p_attr_set, last_mod ) = MAX2( p_inode->st_mtime, p_inode->st_ctime ); #endif #ifdef ATTR_INDEX_type if ( S_ISREG( p_inode->st_mode ) ) { ATTR_MASK_SET( p_attr_set, type ); strcpy( ATTR( p_attr_set, type ), STR_TYPE_FILE ); } else if ( S_ISDIR( p_inode->st_mode ) ) { ATTR_MASK_SET( p_attr_set, type ); strcpy( ATTR( p_attr_set, type ), STR_TYPE_DIR ); } else if ( S_ISCHR( p_inode->st_mode ) ) { ATTR_MASK_SET( p_attr_set, type ); strcpy( ATTR( p_attr_set, type ), STR_TYPE_CHR ); } else if ( S_ISBLK( p_inode->st_mode ) ) { ATTR_MASK_SET( p_attr_set, type ); strcpy( ATTR( p_attr_set, type ), STR_TYPE_BLK ); } else if ( S_ISFIFO( p_inode->st_mode ) ) { ATTR_MASK_SET( p_attr_set, type ); strcpy( ATTR( p_attr_set, type ), STR_TYPE_FIFO ); } else if ( S_ISLNK( p_inode->st_mode ) ) { ATTR_MASK_SET( p_attr_set, type ); strcpy( ATTR( p_attr_set, type ), STR_TYPE_LINK ); } else if ( S_ISSOCK( p_inode->st_mode ) ) { ATTR_MASK_SET( p_attr_set, type ); strcpy( ATTR( p_attr_set, type ), STR_TYPE_SOCK ); } #endif #ifdef ATTR_INDEX_nlink ATTR_MASK_SET( p_attr_set, nlink ); ATTR( p_attr_set, nlink ) = p_inode->st_nlink; #endif }
/** * check if the entry exists in the database and what info * must be retrieved. */ int EntryProc_get_info_db( struct entry_proc_op_t *p_op, lmgr_t * lmgr ) { int rc = 0; int next_stage = -1; /* -1 = skip */ attr_mask_t attr_allow_cached = null_mask; attr_mask_t attr_need_fresh = null_mask; uint32_t status_scope = 0; /* status mask only */ attr_mask_t tmp; const pipeline_stage_t *stage_info = &entry_proc_pipeline[p_op->pipeline_stage]; /* check if entry is in policies scope */ add_matching_scopes_mask(&p_op->entry_id, &p_op->fs_attrs, true, &status_scope); /* XXX also retrieve needed attributes to check the scope? */ /* get diff attributes from DB and FS (to allow comparison) */ p_op->db_attr_need = attr_mask_or(&p_op->db_attr_need, &diff_mask); tmp = attr_mask_and_not(&diff_mask, &p_op->fs_attrs.attr_mask); p_op->fs_attr_need = attr_mask_or(&p_op->fs_attr_need, &tmp); if (entry_proc_conf.detect_fake_mtime) attr_mask_set_index(&p_op->db_attr_need, ATTR_INDEX_creation_time); attr_allow_cached = attrs_for_status_mask(status_scope, false); attr_need_fresh = attrs_for_status_mask(status_scope, true); /* XXX check if entry is in policy scope? */ /* what must be retrieved from DB: */ tmp = attr_mask_and_not(&attr_allow_cached, &p_op->fs_attrs.attr_mask); p_op->db_attr_need = attr_mask_or(&p_op->db_attr_need, &tmp); /* no dircount for non-dirs */ if (ATTR_MASK_TEST(&p_op->fs_attrs, type) && !strcmp(ATTR(&p_op->fs_attrs, type), STR_TYPE_DIR)) { attr_mask_unset_index(&p_op->db_attr_need, ATTR_INDEX_dircount); } /* no readlink for non symlinks */ if (ATTR_MASK_TEST(&p_op->fs_attrs, type)) /* likely */ { if (!strcmp(ATTR(&p_op->fs_attrs, type), STR_TYPE_LINK)) { attr_mask_set_index(&p_op->db_attr_need, ATTR_INDEX_link); /* check if it is known */ /* no stripe for symlinks */ attr_mask_unset_index(&p_op->db_attr_need, ATTR_INDEX_stripe_info); attr_mask_unset_index(&p_op->db_attr_need, ATTR_INDEX_stripe_items); } else attr_mask_unset_index(&p_op->db_attr_need, ATTR_INDEX_link); } if (!attr_mask_is_null(p_op->db_attr_need)) { p_op->db_attrs.attr_mask = p_op->db_attr_need; rc = ListMgr_Get(lmgr, &p_op->entry_id, &p_op->db_attrs); if (rc == DB_SUCCESS) { p_op->db_exists = 1; } else if (rc == DB_NOT_EXISTS ) { p_op->db_exists = 0; ATTR_MASK_INIT( &p_op->db_attrs ); } else { /* ERROR */ DisplayLog(LVL_CRIT, ENTRYPROC_TAG, "Error %d retrieving entry "DFID" from DB: %s.", rc, PFID(&p_op->entry_id), lmgr_err2str(rc)); p_op->db_exists = 0; ATTR_MASK_INIT( &p_op->db_attrs ); } } else { p_op->db_exists = ListMgr_Exists( lmgr, &p_op->entry_id ); } /* get status for all policies with a matching scope */ add_matching_scopes_mask(&p_op->entry_id, &p_op->fs_attrs, true, &p_op->fs_attr_need.status); tmp = attr_mask_and_not(&attr_need_fresh, &p_op->fs_attrs.attr_mask); p_op->fs_attr_need = attr_mask_or(&p_op->fs_attr_need, &tmp); if ( !p_op->db_exists ) { /* new entry */ p_op->db_op_type = OP_TYPE_INSERT; /* set creation time if it was not set by scan module */ if (!ATTR_MASK_TEST(&p_op->fs_attrs, creation_time)) { ATTR_MASK_SET( &p_op->fs_attrs, creation_time ); ATTR( &p_op->fs_attrs, creation_time ) = time(NULL); /* XXX min(atime,mtime,ctime)? */ } #ifdef _LUSTRE if (ATTR_MASK_TEST(&p_op->fs_attrs, type) && !strcmp(ATTR( &p_op->fs_attrs, type ), STR_TYPE_FILE ) /* only if it was not retrieved during the scan */ && !(ATTR_MASK_TEST(&p_op->fs_attrs, stripe_info) && ATTR_MASK_TEST(&p_op->fs_attrs, stripe_items))) { attr_mask_set_index(&p_op->fs_attr_need, ATTR_INDEX_stripe_info); attr_mask_set_index(&p_op->fs_attr_need, ATTR_INDEX_stripe_items); } #endif /* readlink for symlinks (if not already known) */ if (ATTR_MASK_TEST(&p_op->fs_attrs, type) && !strcmp(ATTR( &p_op->fs_attrs, type ), STR_TYPE_LINK) && !ATTR_MASK_TEST(&p_op->fs_attrs, link)) { attr_mask_set_index(&p_op->fs_attr_need, ATTR_INDEX_link); } else { attr_mask_unset_index(&p_op->fs_attr_need, ATTR_INDEX_link); } #ifdef ATTR_INDEX_status /** @FIXME RBHv3 drop old-style status reference */ if (ATTR_MASK_TEST(&p_op->fs_attrs, type) #ifdef _LUSTRE_HSM && !strcmp( ATTR(&p_op->fs_attrs, type), STR_TYPE_FILE )) #elif defined (_HSM_LITE) && (strcmp( ATTR(&p_op->fs_attrs, type), STR_TYPE_DIR ) != 0) && !p_op->extra_info.not_supp) #endif { p_op->fs_attr_need |= ATTR_MASK_status; #ifdef _HSM_LITE p_op->fs_attr_need |= (attr_need_fresh & ~p_op->fs_attrs.attr_mask); #endif } else {
static inline int rebind_helper(const char *old_bk_id, const char *new_bk_id, const char *new_path, const char *new_fid_str) { int rc; attr_set_t old_attrs = ATTR_SET_INIT; attr_set_t new_attrs = ATTR_SET_INIT; entry_id_t new_fid; entry_id_t old_fid; bool old_fid_set = false; char *tmp; /* full path required */ tmp = realpath(new_path, NULL); if (tmp == NULL) { rc = -errno; DisplayLog(LVL_CRIT, LOGTAG, "Error in realpath(%s): %s", new_path, strerror(-rc)); return rc; } if (strlen(tmp) >= RBH_PATH_MAX) { DisplayLog(LVL_CRIT, LOGTAG, "Path length is too long!"); return -ENAMETOOLONG; } /* safe because of previous check */ strcpy(ATTR(&new_attrs, fullpath), tmp); ATTR_MASK_SET(&new_attrs, fullpath); strcpy(ATTR(&old_attrs, fullpath), tmp); ATTR_MASK_SET(&old_attrs, fullpath); /* now we can free tmp path */ free(tmp); if ((new_fid_str != NULL) && !EMPTY_STRING(new_fid_str)) rc = read_fid(new_fid_str, &new_fid); else /* get fid for the given file */ rc = Path2Id(new_path, &new_fid); if (rc) return rc; printf("Rebinding '%s' (" DFID ") from '%s' to '%s'...\n", new_path, PFID(&new_fid), old_bk_id, new_bk_id); /* parse old/new bk ids and set attr accordingly */ if (parse_bk_id(&old_attrs, old_bk_id, &old_fid, &old_fid_set)) return -EINVAL; if (parse_bk_id(&new_attrs, new_bk_id, &new_fid, NULL)) return -EINVAL; /* rebind is like undelete with 'already recovered = true' */ rc = smi->sm->undelete_func(smi, old_fid_set ? &old_fid : NULL, &old_attrs, &new_fid, &new_attrs, true); fprintf(stderr, "Rebind status for '%s': %s\n", ATTR(&new_attrs, fullpath), recov_status2str(rc)); if (rc == RS_NOBACKUP || rc == RS_ERROR) return -1; return 0; }