nfs-ganesha 1.4
|
00001 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; -*- 00002 * vim:expandtab:shiftwidth=4:tabstop=4: 00003 */ 00011 #ifdef HAVE_CONFIG_H 00012 #include "config.h" 00013 #endif 00014 00015 #include "fsal.h" 00016 #include "fsal_internal.h" 00017 #include "fsal_convert.h" 00018 00019 #include <string.h> 00020 #include <time.h> 00021 #include <sys/types.h> 00022 #include <attr/xattr.h> 00023 #include "abstract_mem.h" 00024 00025 /* generic definitions for extended attributes */ 00026 00027 #define XATTR_FOR_FILE 0x00000001 00028 #define XATTR_FOR_DIR 0x00000002 00029 #define XATTR_FOR_SYMLINK 0x00000004 00030 #define XATTR_FOR_ALL 0x0000000F 00031 #define XATTR_RO 0x00000100 00032 #define XATTR_RW 0x00000200 00033 00034 /* function for getting an attribute value */ 00035 00036 typedef int (*xattr_getfunc_t) (fsal_handle_t *, /* object handle */ 00037 fsal_op_context_t *, /* context */ 00038 caddr_t, /* output buff */ 00039 size_t, /* output buff size */ 00040 size_t *, /* output size */ 00041 void *arg); /* optionnal argument */ 00042 00043 typedef int (*xattr_setfunc_t) (fsal_handle_t *, /* object handle */ 00044 fsal_op_context_t *, /* context */ 00045 caddr_t, /* input buff */ 00046 size_t, /* input size */ 00047 int, /* creation flag */ 00048 void *arg); /* optionnal argument */ 00049 00050 typedef struct fsal_xattr_def__ 00051 { 00052 char xattr_name[FSAL_MAX_NAME_LEN]; 00053 xattr_getfunc_t get_func; 00054 xattr_setfunc_t set_func; 00055 int flags; 00056 void *arg; 00057 } fsal_xattr_def_t; 00058 00059 /* 00060 * DEFINE GET/SET FUNCTIONS 00061 */ 00062 00063 int print_fid(fsal_handle_t * p_objecthandle, /* object handle */ 00064 fsal_op_context_t * p_context, /* IN */ 00065 caddr_t buffer_addr, /* IN/OUT */ 00066 size_t buffer_size, /* IN */ 00067 size_t * p_output_size, /* OUT */ 00068 void *arg) 00069 { 00070 *p_output_size = snprintf(buffer_addr, buffer_size, DFID_NOBRACE "\n", 00071 PFID(&((lustrefsal_handle_t *)p_objecthandle)->data.fid)); 00072 return 0; 00073 } /* print_fid */ 00074 00075 #define ARG_STRIPE_SIZE ((long)0) 00076 #define ARG_STRIPE_COUNT ((long)1) 00077 #define ARG_STORAGE_TGT ((long)2) 00078 #define ARG_POOL ((long)3) 00079 00080 #ifdef _LUSTRE_HSM 00081 #define ARG_HSM_STATE ((long)0) 00082 #define ARG_HSM_ACTION ((long)1) 00083 #define ARG_HSM_ARCH_NUM ((long)2) 00084 #endif 00085 00086 int print_stripe(fsal_handle_t * p_objecthandle, /* object handle */ 00087 fsal_op_context_t * p_context, /* IN */ 00088 caddr_t buffer_addr, /* IN/OUT */ 00089 size_t buffer_size, /* IN */ 00090 size_t * p_output_size, /* OUT */ 00091 void *arg) 00092 { 00093 /* buffer userd for llapi_get_stripe. 00094 * oversize it to 4kB because there can be many stripe entries 00095 * in the case of join'ed files. 00096 */ 00097 int rc; 00098 char lum_buffer[4096]; 00099 fsal_path_t entry_path; 00100 fsal_status_t st; 00101 unsigned int i; 00102 char *curr; 00103 struct lov_user_md *p_lum = (struct lov_user_md *)lum_buffer; 00104 00105 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &entry_path); 00106 if(FSAL_IS_ERROR(st)) 00107 return st.major; 00108 00109 memset(lum_buffer, 0, sizeof(lum_buffer)); 00110 rc = llapi_file_get_stripe(entry_path.path, p_lum); 00111 00112 if(rc != 0) 00113 { 00114 if(abs(rc) == ENODATA) 00115 { 00116 LogDebug(COMPONENT_FSAL, "%s has no stripe information", entry_path.path); 00117 *p_output_size = sprintf(buffer_addr, "none\n"); 00118 return 0; 00119 } 00120 else 00121 LogCrit(COMPONENT_FSAL, "Error %d getting stripe info for %s", rc, entry_path.path); 00122 return posix2fsal_error(abs(rc)); 00123 } 00124 00125 /* Check for protocol version number */ 00126 if(p_lum->lmm_magic == LOV_USER_MAGIC_V1) 00127 { 00128 00129 switch ((long)arg) 00130 { 00131 case ARG_STRIPE_SIZE: 00132 *p_output_size = 00133 snprintf(buffer_addr, buffer_size, "%u\n", p_lum->lmm_stripe_size); 00134 break; 00135 00136 case ARG_STRIPE_COUNT: 00137 *p_output_size = 00138 snprintf(buffer_addr, buffer_size, "%u\n", p_lum->lmm_stripe_count); 00139 break; 00140 00141 case ARG_POOL: /* no pool if the structure is LOV V1 */ 00142 ((char*)buffer_addr)[0]='\0'; 00143 *p_output_size = 0; 00144 break; 00145 00146 case ARG_STORAGE_TGT: 00147 *p_output_size = 0; 00148 curr = buffer_addr; 00149 curr[0] = '\0'; 00150 00151 for(i = 0; i < p_lum->lmm_stripe_count; i++) 00152 { 00153 int sz; 00154 if(i != p_lum->lmm_stripe_count - 1) 00155 sz = snprintf(curr, buffer_size - *p_output_size, "%u,", 00156 p_lum->lmm_objects[i].l_ost_idx); 00157 else 00158 sz = snprintf(curr, buffer_size - *p_output_size, "%u\n", 00159 p_lum->lmm_objects[i].l_ost_idx); 00160 curr += sz; 00161 *p_output_size += sz; 00162 } 00163 00164 break; 00165 } 00166 } 00167 #ifdef LOV_USER_MAGIC_V3 /* pool support */ 00168 else if(p_lum->lmm_magic == LOV_USER_MAGIC_V3) 00169 { 00170 struct lov_user_md_v3 *p_lum3 = ( struct lov_user_md_v3 * ) p_lum; 00171 00172 switch ((long)arg) 00173 { 00174 case ARG_STRIPE_SIZE: 00175 *p_output_size = 00176 snprintf(buffer_addr, buffer_size, "%u\n", p_lum3->lmm_stripe_size); 00177 break; 00178 00179 case ARG_STRIPE_COUNT: 00180 *p_output_size = 00181 snprintf(buffer_addr, buffer_size, "%u\n", p_lum3->lmm_stripe_count); 00182 break; 00183 00184 case ARG_POOL: /* pool structure in LOV V3 */ 00185 *p_output_size = snprintf( buffer_addr, buffer_size, "%s\n", 00186 p_lum3->lmm_pool_name ); 00187 break; 00188 00189 case ARG_STORAGE_TGT: 00190 *p_output_size = 0; 00191 curr = buffer_addr; 00192 curr[0] = '\0'; 00193 00194 for(i = 0; i < p_lum3->lmm_stripe_count; i++) 00195 { 00196 int sz; 00197 if(i != p_lum3->lmm_stripe_count - 1) 00198 sz = snprintf(curr, buffer_size - *p_output_size, "%u,", 00199 p_lum3->lmm_objects[i].l_ost_idx); 00200 else 00201 sz = snprintf(curr, buffer_size - *p_output_size, "%u\n", 00202 p_lum3->lmm_objects[i].l_ost_idx); 00203 curr += sz; 00204 *p_output_size += sz; 00205 } 00206 00207 break; 00208 } 00209 00210 } 00211 #endif 00212 else 00213 { 00214 LogCrit(COMPONENT_FSAL, "Wrong Luster magic number for %s: %#X <> %#X", 00215 entry_path.path, p_lum->lmm_magic, LOV_USER_MAGIC_V1); 00216 return ERR_FSAL_INVAL; 00217 } 00218 00219 return 0; 00220 } 00221 00222 /* ------------ Lustre-HSM specific attributes ------------ */ 00223 #ifdef _LUSTRE_HSM 00224 00225 #define TEST_FLAG_APPEND( _mask, _flg_val, _flg_name, _p_sz ) \ 00226 do { if ((_mask) & (_flg_val)) { \ 00227 size_t sz = 0; \ 00228 if ( (*_p_sz) > 0 ) \ 00229 sz = snprintf(curr, buffer_size-(*_p_sz), " %s", _flg_name); \ 00230 else \ 00231 sz = snprintf(curr, buffer_size-(*_p_sz), "%s", _flg_name); \ 00232 curr += sz; \ 00233 (*_p_sz) += sz; \ 00234 }} while(0) 00235 00236 00237 int print_hsm_info(lustrefsal_handle_t * p_objecthandle, /* object handle */ 00238 lustrefsal_op_context_t * p_context, /* IN */ 00239 caddr_t buffer_addr, /* IN/OUT */ 00240 size_t buffer_size, /* IN */ 00241 size_t * p_output_size, /* OUT */ 00242 void *arg) 00243 { 00244 int rc; 00245 fsal_path_t entry_path; 00246 fsal_status_t st; 00247 unsigned int i; 00248 struct hsm_user_state hus = {0}; 00249 00250 /* set empty output, by default */ 00251 ((char*)buffer_addr)[0]='\0'; 00252 *p_output_size = 0; 00253 00254 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &entry_path); 00255 if(FSAL_IS_ERROR(st)) 00256 return st.major; 00257 00258 rc = llapi_hsm_state_get(entry_path.path, &hus); 00259 00260 if(rc != 0) 00261 return posix2fsal_error(-rc); 00262 00263 switch ((long)arg) 00264 { 00265 case ARG_HSM_STATE: 00266 if ( hus.hus_states == 0 ) 00267 { 00268 *p_output_size = 00269 snprintf(buffer_addr, buffer_size, "new\n" ); 00270 } 00271 else 00272 { 00273 char * curr = (char*)buffer_addr; 00274 00275 TEST_FLAG_APPEND( hus.hus_states, HS_RELEASED, "released", 00276 p_output_size ); 00277 TEST_FLAG_APPEND( hus.hus_states, HS_EXISTS, "exists", 00278 p_output_size ); 00279 TEST_FLAG_APPEND( hus.hus_states, HS_DIRTY, "dirty", 00280 p_output_size ); 00281 TEST_FLAG_APPEND( hus.hus_states, HS_ARCHIVED, "archived", 00282 p_output_size ); 00283 TEST_FLAG_APPEND( hus.hus_states, HS_NORELEASE, "never_release", 00284 p_output_size ); 00285 TEST_FLAG_APPEND( hus.hus_states, HS_NOARCHIVE, "never_archive", 00286 p_output_size ); 00287 TEST_FLAG_APPEND( hus.hus_states, HS_LOST, "lost_from_hsm", 00288 p_output_size ); 00289 if ( (*p_output_size) > 0 ) 00290 (*p_output_size) += snprintf( curr, 00291 buffer_size-(*p_output_size), 00292 "\n" ); 00293 } 00294 break; 00295 00296 case ARG_HSM_ACTION: 00297 if ( hus.hus_in_progress_action != HUA_NONE ) 00298 { 00299 *p_output_size = 00300 snprintf(buffer_addr, buffer_size, "%s (%s)\n", 00301 hsm_user_action2name(hus.hus_in_progress_action), 00302 hsm_progress_state2name(hus.hus_in_progress_state)); 00303 } 00304 else 00305 *p_output_size = 00306 snprintf(buffer_addr, buffer_size, "%s\n", 00307 hsm_user_action2name(hus.hus_in_progress_action)); 00308 break; 00309 00310 case ARG_HSM_ARCH_NUM: 00311 if (hus.hus_archive_num != 0) 00312 { 00313 *p_output_size = 00314 snprintf(buffer_addr, buffer_size, "%u\n", 00315 hus.hus_archive_num); 00316 } 00317 break; 00318 } 00319 00320 return 0; 00321 } 00322 #endif 00323 00324 /* DEFINE HERE YOUR ATTRIBUTES LIST */ 00325 00326 static fsal_xattr_def_t xattr_list[] = { 00327 {"fid", print_fid, NULL, XATTR_FOR_ALL | XATTR_RO, NULL}, 00328 {"stripe_size", print_stripe, NULL, XATTR_FOR_FILE | XATTR_FOR_DIR | XATTR_RO, 00329 (void *)ARG_STRIPE_SIZE}, 00330 {"stripe_count", print_stripe, NULL, XATTR_FOR_FILE | XATTR_FOR_DIR | XATTR_RO, 00331 (void *)ARG_STRIPE_COUNT}, 00332 {"pool", print_stripe, NULL, XATTR_FOR_FILE | XATTR_FOR_DIR | XATTR_RO, 00333 (void *)ARG_POOL}, 00334 {"OSTs", print_stripe, NULL, XATTR_FOR_FILE | XATTR_RO, 00335 (void *)ARG_STORAGE_TGT}, 00336 #ifdef _LUSTRE_HSM 00337 /* additionnal attributes from HSM state */ 00338 {"hsm_state", print_hsm_info, NULL, XATTR_FOR_FILE | XATTR_RO, 00339 (void *)ARG_HSM_STATE }, 00340 {"hsm_action", print_hsm_info, NULL, XATTR_FOR_FILE | XATTR_RO, 00341 (void *)ARG_HSM_ACTION }, 00342 #endif 00343 }; 00344 00345 #ifdef _LUSTRE_HSM 00346 #define XATTR_COUNT 7 00347 #else 00348 #define XATTR_COUNT 5 00349 #endif 00350 00351 /* we assume that this number is < 254 */ 00352 #if ( XATTR_COUNT > 254 ) 00353 #error "ERROR: xattr count > 254" 00354 #endif 00355 00356 /* YOUR SHOULD NOT HAVE TO MODIFY THE FOLLOWING FUNCTIONS */ 00357 00358 /* test if an object has a given attribute */ 00359 static int do_match_type(int xattr_flag, fsal_nodetype_t obj_type) 00360 { 00361 switch (obj_type) 00362 { 00363 case FSAL_TYPE_FILE: 00364 return ((xattr_flag & XATTR_FOR_FILE) == XATTR_FOR_FILE); 00365 00366 case FSAL_TYPE_DIR: 00367 return ((xattr_flag & XATTR_FOR_DIR) == XATTR_FOR_DIR); 00368 00369 case FSAL_TYPE_LNK: 00370 return ((xattr_flag & XATTR_FOR_SYMLINK) == XATTR_FOR_SYMLINK); 00371 00372 default: 00373 return ((xattr_flag & XATTR_FOR_ALL) == XATTR_FOR_ALL); 00374 } 00375 } 00376 00377 static int attr_is_read_only(unsigned int attr_index) 00378 { 00379 if(attr_index < XATTR_COUNT) 00380 { 00381 if(xattr_list[attr_index].flags & XATTR_RO) 00382 return TRUE; 00383 } 00384 /* else : standard xattr */ 00385 return FALSE; 00386 } 00387 00388 static int file_attributes_to_xattr_attrs(fsal_attrib_list_t * file_attrs, 00389 fsal_attrib_list_t * p_xattr_attrs, 00390 unsigned int attr_index) 00391 { 00392 /* supported attributes are: 00393 * - owner (same as the objet) 00394 * - group (same as the objet) 00395 * - type FSAL_TYPE_XATTR 00396 * - fileid (attr index ? or (fileid^((index+1)<<24)) ) 00397 * - mode (config & file) 00398 * - atime, mtime, ctime = these of the object ? 00399 * - size=1block, used=1block 00400 * - rdev=0 00401 * - nlink=1 00402 */ 00403 fsal_attrib_mask_t supported = FSAL_ATTR_SUPPATTR | FSAL_ATTR_MODE | FSAL_ATTR_FILEID 00404 | FSAL_ATTR_TYPE | FSAL_ATTR_OWNER | FSAL_ATTR_GROUP 00405 | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_CTIME 00406 | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_SIZE 00407 | FSAL_ATTR_SPACEUSED | FSAL_ATTR_NUMLINKS | FSAL_ATTR_RAWDEV | FSAL_ATTR_FSID; 00408 fsal_attrib_mask_t unsupp; 00409 00410 /* only those supported by filesystem */ 00411 supported &= global_fs_info.supported_attrs; 00412 00413 if(p_xattr_attrs->asked_attributes == 0) 00414 { 00415 p_xattr_attrs->asked_attributes = supported; 00416 00417 LogCrit(COMPONENT_FSAL, 00418 "Error: p_xattr_attrs->asked_attributes was 0 in %s() line %d, file %s", 00419 __FUNCTION__, __LINE__, __FILE__); 00420 } 00421 00422 unsupp = p_xattr_attrs->asked_attributes & (~supported); 00423 00424 if(unsupp) 00425 { 00426 LogDebug(COMPONENT_FSAL, 00427 "Asking for unsupported attributes in %s(): %#llX removing it from asked attributes", 00428 __FUNCTION__, unsupp); 00429 00430 p_xattr_attrs->asked_attributes &= (~unsupp); 00431 } 00432 00433 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SUPPATTR) 00434 p_xattr_attrs->supported_attributes = supported; 00435 00436 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_MODE) 00437 { 00438 p_xattr_attrs->mode = file_attrs->mode & global_fs_info.xattr_access_rights; 00439 00440 if(attr_is_read_only(attr_index)) 00441 p_xattr_attrs->mode &= ~(0222); 00442 } 00443 00444 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_FILEID) 00445 { 00446 unsigned int i; 00447 unsigned long hash = attr_index + 1; 00448 char *str = (char *)&file_attrs->fileid; 00449 00450 for(i = 0; i < sizeof(p_xattr_attrs->fileid); i++, str++) 00451 { 00452 hash = (hash << 5) - hash + (unsigned long)(*str); 00453 } 00454 p_xattr_attrs->fileid = hash; 00455 } 00456 00457 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_TYPE) 00458 p_xattr_attrs->type = FSAL_TYPE_XATTR; 00459 00460 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_OWNER) 00461 p_xattr_attrs->owner = file_attrs->owner; 00462 00463 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_GROUP) 00464 p_xattr_attrs->group = file_attrs->group; 00465 00466 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_ATIME) 00467 p_xattr_attrs->atime = file_attrs->atime; 00468 00469 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_MTIME) 00470 p_xattr_attrs->mtime = file_attrs->mtime; 00471 00472 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CTIME) 00473 p_xattr_attrs->ctime = file_attrs->ctime; 00474 00475 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CREATION) 00476 p_xattr_attrs->creation = file_attrs->creation; 00477 00478 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_CHGTIME) 00479 { 00480 p_xattr_attrs->chgtime = file_attrs->chgtime; 00481 p_xattr_attrs->change = (uint64_t) p_xattr_attrs->chgtime.seconds; 00482 } 00483 00484 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SIZE) 00485 p_xattr_attrs->filesize = DEV_BSIZE; 00486 00487 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_SPACEUSED) 00488 p_xattr_attrs->spaceused = DEV_BSIZE; 00489 00490 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_NUMLINKS) 00491 p_xattr_attrs->numlinks = 1; 00492 00493 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_RAWDEV) 00494 { 00495 p_xattr_attrs->rawdev.major = 0; 00496 p_xattr_attrs->rawdev.minor = 0; 00497 } 00498 00499 if(p_xattr_attrs->asked_attributes & FSAL_ATTR_FSID) 00500 { 00501 p_xattr_attrs->fsid = file_attrs->fsid; 00502 } 00503 00504 /* if mode==0, then owner is set to root and mode is set to 0600 */ 00505 if((p_xattr_attrs->asked_attributes & FSAL_ATTR_OWNER) 00506 && (p_xattr_attrs->asked_attributes & FSAL_ATTR_MODE) && (p_xattr_attrs->mode == 0)) 00507 { 00508 p_xattr_attrs->owner = 0; 00509 p_xattr_attrs->mode = 0600; 00510 if(attr_is_read_only(attr_index)) 00511 p_xattr_attrs->mode &= ~(0200); 00512 } 00513 00514 return 0; 00515 00516 } 00517 00526 fsal_status_t LUSTREFSAL_GetXAttrAttrs(fsal_handle_t * p_objecthandle, /* IN */ 00527 fsal_op_context_t * p_context, /* IN */ 00528 unsigned int xattr_id, /* IN */ 00529 fsal_attrib_list_t * p_attrs 00531 ) 00532 { 00533 int rc; 00534 fsal_status_t st; 00535 fsal_attrib_list_t file_attrs; 00536 00537 /* sanity checks */ 00538 if(!p_objecthandle || !p_context || !p_attrs) 00539 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrAttrs); 00540 00541 /* object attributes we want to retrieve from parent */ 00542 file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER 00543 | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_TYPE 00544 | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID; 00545 00546 /* don't retrieve attributes not asked */ 00547 file_attrs.asked_attributes &= p_attrs->asked_attributes; 00548 00549 st = LUSTREFSAL_getattrs(p_objecthandle, p_context, &file_attrs); 00550 00551 if(FSAL_IS_ERROR(st)) 00552 Return(st.major, st.minor, INDEX_FSAL_GetXAttrAttrs); 00553 00554 /* check that this index match the type of entry */ 00555 if(xattr_id < XATTR_COUNT 00556 && !do_match_type(xattr_list[xattr_id].flags, file_attrs.type)) 00557 { 00558 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrAttrs); 00559 } 00560 else if(xattr_id >= XATTR_COUNT) 00561 { 00562 /* This is user defined xattr */ 00563 LogFullDebug(COMPONENT_FSAL, 00564 "Getting attributes for xattr #%u", xattr_id - XATTR_COUNT); 00565 } 00566 00567 if((rc = file_attributes_to_xattr_attrs(&file_attrs, p_attrs, xattr_id))) 00568 { 00569 Return(ERR_FSAL_INVAL, rc, INDEX_FSAL_GetXAttrAttrs); 00570 } 00571 00572 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrAttrs); 00573 00574 } /* FSAL_GetXAttrAttrs */ 00575 00588 fsal_status_t LUSTREFSAL_ListXAttrs(fsal_handle_t * p_objecthandle, /* IN */ 00589 unsigned int argcookie, /* IN */ 00590 fsal_op_context_t * p_context, /* IN */ 00591 fsal_xattrent_t * xattrs_tab, /* IN/OUT */ 00592 unsigned int xattrs_tabsize, /* IN */ 00593 unsigned int *p_nb_returned, /* OUT */ 00594 int *end_of_list /* OUT */ 00595 ) 00596 { 00597 unsigned int index; 00598 unsigned int out_index; 00599 fsal_status_t st; 00600 fsal_attrib_list_t file_attrs; 00601 fsal_path_t lustre_path; 00602 unsigned int cookie = argcookie ; 00603 00604 char names[MAXPATHLEN], *ptr; 00605 size_t namesize; 00606 int xattr_idx; 00607 00608 /* sanity checks */ 00609 if(!p_objecthandle || !p_context || !xattrs_tab || !p_nb_returned || !end_of_list) 00610 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_ListXAttrs); 00611 00612 /* Deal with special cookie */ 00613 if( argcookie == FSAL_XATTR_RW_COOKIE ) cookie = XATTR_COUNT ; 00614 00615 /* object attributes we want to retrieve from parent */ 00616 file_attrs.asked_attributes = FSAL_ATTR_MODE | FSAL_ATTR_FILEID | FSAL_ATTR_OWNER 00617 | FSAL_ATTR_GROUP | FSAL_ATTR_ATIME | FSAL_ATTR_MTIME | FSAL_ATTR_TYPE 00618 | FSAL_ATTR_CTIME | FSAL_ATTR_CREATION | FSAL_ATTR_CHGTIME | FSAL_ATTR_FSID; 00619 00620 /* don't retrieve unsuipported attributes */ 00621 file_attrs.asked_attributes &= global_fs_info.supported_attrs; 00622 00623 st = LUSTREFSAL_getattrs(p_objecthandle, p_context, &file_attrs); 00624 00625 if(FSAL_IS_ERROR(st)) 00626 Return(st.major, st.minor, INDEX_FSAL_ListXAttrs); 00627 00628 for(index = cookie, out_index = 0; 00629 index < XATTR_COUNT && out_index < xattrs_tabsize; index++) 00630 { 00631 if(do_match_type(xattr_list[index].flags, file_attrs.type)) 00632 { 00633 /* fills an xattr entry */ 00634 xattrs_tab[out_index].xattr_id = index; 00635 FSAL_str2name(xattr_list[index].xattr_name, FSAL_MAX_NAME_LEN, 00636 &xattrs_tab[out_index].xattr_name); 00637 xattrs_tab[out_index].xattr_cookie = index + 1; 00638 00639 /* set asked attributes (all supported) */ 00640 xattrs_tab[out_index].attributes.asked_attributes = 00641 global_fs_info.supported_attrs; 00642 00643 if(file_attributes_to_xattr_attrs 00644 (&file_attrs, &xattrs_tab[out_index].attributes, index)) 00645 { 00646 /* set error flag */ 00647 xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR; 00648 } 00649 00650 /* next output slot */ 00651 out_index++; 00652 } 00653 } 00654 00655 /* save a call if output array is full */ 00656 if(out_index == xattrs_tabsize) 00657 { 00658 *end_of_list = FALSE; 00659 *p_nb_returned = out_index; 00660 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs); 00661 } 00662 00663 /* get the path of the file in Lustre */ 00664 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &lustre_path); 00665 if(FSAL_IS_ERROR(st)) 00666 ReturnStatus(st, INDEX_FSAL_ListXAttrs); 00667 00668 /* get xattrs */ 00669 00670 TakeTokenFSCall(); 00671 namesize = llistxattr(lustre_path.path, names, sizeof(names)); 00672 ReleaseTokenFSCall(); 00673 00674 if(namesize >= 0) 00675 { 00676 size_t len = 0; 00677 00678 errno = 0; 00679 00680 for(ptr = names, xattr_idx = 0; 00681 (ptr < names + namesize) && (out_index < xattrs_tabsize); 00682 xattr_idx++, ptr += len + 1) 00683 { 00684 len = strlen(ptr); 00685 index = XATTR_COUNT + xattr_idx; 00686 00687 /* skip if index is before cookie */ 00688 if(index < cookie) 00689 continue; 00690 00691 /* fills an xattr entry */ 00692 xattrs_tab[out_index].xattr_id = index; 00693 FSAL_str2name(ptr, len + 1, &xattrs_tab[out_index].xattr_name); 00694 xattrs_tab[out_index].xattr_cookie = index + 1; 00695 00696 /* set asked attributes (all supported) */ 00697 xattrs_tab[out_index].attributes.asked_attributes = 00698 global_fs_info.supported_attrs; 00699 00700 if(file_attributes_to_xattr_attrs(&file_attrs, 00701 &xattrs_tab[out_index].attributes, index)) 00702 { 00703 /* set error flag */ 00704 xattrs_tab[out_index].attributes.asked_attributes = FSAL_ATTR_RDATTR_ERR; 00705 } 00706 00707 /* next output slot */ 00708 out_index++; 00709 } 00710 /* all xattrs are in the output array */ 00711 if(ptr >= names + namesize) 00712 *end_of_list = TRUE; 00713 else 00714 *end_of_list = FALSE; 00715 } 00716 else /* no xattrs */ 00717 *end_of_list = TRUE; 00718 00719 *p_nb_returned = out_index; 00720 00721 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_ListXAttrs); 00722 00723 } 00724 00725 static int xattr_id_to_name(char *lustre_path, unsigned int xattr_id, char *name) 00726 { 00727 unsigned int index; 00728 unsigned int curr_idx; 00729 char names[MAXPATHLEN], *ptr; 00730 size_t namesize; 00731 size_t len = 0; 00732 00733 if(xattr_id < XATTR_COUNT) 00734 return ERR_FSAL_INVAL; 00735 00736 index = xattr_id - XATTR_COUNT; 00737 00738 /* get xattrs */ 00739 00740 TakeTokenFSCall(); 00741 namesize = llistxattr(lustre_path, names, sizeof(names)); 00742 ReleaseTokenFSCall(); 00743 00744 if(namesize < 0) 00745 return ERR_FSAL_NOENT; 00746 00747 errno = 0; 00748 00749 for(ptr = names, curr_idx = 0; ptr < names + namesize; curr_idx++, ptr += len + 1) 00750 { 00751 len = strlen(ptr); 00752 if(curr_idx == index) 00753 { 00754 strcpy(name, ptr); 00755 return ERR_FSAL_NO_ERROR; 00756 } 00757 } 00758 return ERR_FSAL_NOENT; 00759 } 00760 00765 static int xattr_name_to_id(char *lustre_path, const char *name) 00766 { 00767 unsigned int i; 00768 char names[MAXPATHLEN], *ptr; 00769 size_t namesize; 00770 00771 /* get xattrs */ 00772 00773 TakeTokenFSCall(); 00774 namesize = llistxattr(lustre_path, names, sizeof(names)); 00775 ReleaseTokenFSCall(); 00776 00777 if(namesize < 0) 00778 return -ERR_FSAL_NOENT; 00779 00780 for(ptr = names, i = 0; ptr < names + namesize; i++, ptr += strlen(ptr) + 1) 00781 { 00782 if(!strcmp(name, ptr)) 00783 return i + XATTR_COUNT; 00784 } 00785 return -ERR_FSAL_NOENT; 00786 } 00787 00788 static int xattr_format_value(caddr_t buffer, size_t * datalen, size_t maxlen) 00789 { 00790 size_t size_in = *datalen; 00791 size_t len = strnlen((char *)buffer, size_in); 00792 int i; 00793 00794 if(len == size_in - 1 || len == size_in) 00795 { 00796 int ascii = TRUE; 00797 char *str = buffer; 00798 int i; 00799 00800 for(i = 0; i < len; i++) 00801 { 00802 if(!isprint(str[i]) && !isspace(str[i])) 00803 { 00804 ascii = FALSE; 00805 break; 00806 } 00807 } 00808 00809 if(ascii) 00810 { 00811 *datalen = size_in; 00812 /* add additional '\n', if missing */ 00813 if((size_in + 1 < maxlen) && (str[len - 1] != '\n')) 00814 { 00815 str[len] = '\n'; 00816 str[len + 1] = '\0'; 00817 (*datalen) += 2; 00818 } 00819 return ERR_FSAL_NO_ERROR; 00820 } 00821 } 00822 00823 /* byte, word, 32 or 64 bits */ 00824 if(size_in == 1) 00825 { 00826 unsigned char val = *((unsigned char *)buffer); 00827 *datalen = 1 + snprintf((char *)buffer, maxlen, "%hhu\n", val); 00828 return ERR_FSAL_NO_ERROR; 00829 } 00830 else if(size_in == 2) 00831 { 00832 unsigned short val = *((unsigned short *)buffer); 00833 *datalen = 1 + snprintf((char *)buffer, maxlen, "%hu\n", val); 00834 return ERR_FSAL_NO_ERROR; 00835 } 00836 else if(size_in == 4) 00837 { 00838 unsigned int val = *((unsigned int *)buffer); 00839 *datalen = 1 + snprintf((char *)buffer, maxlen, "%u\n", val); 00840 return ERR_FSAL_NO_ERROR; 00841 } 00842 else if(size_in == 8) 00843 { 00844 unsigned long long val = *((unsigned long long *)buffer); 00845 *datalen = 1 + snprintf((char *)buffer, maxlen, "%llu\n", val); 00846 return ERR_FSAL_NO_ERROR; 00847 } 00848 else 00849 { 00850 /* 2 bytes per initial byte +'0x' +\n +\0 */ 00851 char *curr_out; 00852 char *tmp_buf = gsh_malloc(3 * size_in + 4); 00853 if(!tmp_buf) 00854 return ERR_FSAL_NOMEM; 00855 curr_out = tmp_buf; 00856 curr_out += sprintf(curr_out, "0x"); 00857 /* hexa representation */ 00858 for(i = 0; i < size_in; i++) 00859 { 00860 unsigned char *p8 = (unsigned char *)(buffer + i); 00861 if((i % 4 == 3) && (i != size_in - 1)) 00862 curr_out += sprintf(curr_out, "%02hhX.", *p8); 00863 else 00864 curr_out += sprintf(curr_out, "%02hhX", *p8); 00865 } 00866 *curr_out = '\n'; 00867 curr_out++; 00868 *curr_out = '\0'; 00869 curr_out++; 00870 strncpy((char *)buffer, tmp_buf, maxlen); 00871 *datalen = strlen(tmp_buf) + 1; 00872 if(*datalen > maxlen) 00873 *datalen = maxlen; 00874 gsh_free(tmp_buf); 00875 return ERR_FSAL_NO_ERROR; 00876 } 00877 } 00878 00889 fsal_status_t LUSTREFSAL_GetXAttrValueById(fsal_handle_t * p_objecthandle, /* IN */ 00890 unsigned int xattr_id, /* IN */ 00891 fsal_op_context_t * p_context, /* IN */ 00892 caddr_t buffer_addr, /* IN/OUT */ 00893 size_t buffer_size, /* IN */ 00894 size_t * p_output_size /* OUT */ 00895 ) 00896 { 00897 int rc; 00898 fsal_attrib_list_t file_attrs; 00899 fsal_status_t st; 00900 00901 /* sanity checks */ 00902 if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr) 00903 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue); 00904 00905 /* get type for checking it */ 00906 file_attrs.asked_attributes = FSAL_ATTR_TYPE; 00907 00908 st = LUSTREFSAL_getattrs(p_objecthandle, p_context, &file_attrs); 00909 00910 if(FSAL_IS_ERROR(st)) 00911 ReturnStatus(st, INDEX_FSAL_GetXAttrValue); 00912 00913 /* check that this index match the type of entry */ 00914 if((xattr_id < XATTR_COUNT) 00915 && !do_match_type(xattr_list[xattr_id].flags, file_attrs.type)) 00916 { 00917 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_GetXAttrValue); 00918 } 00919 else if(xattr_id >= XATTR_COUNT) 00920 { 00921 fsal_path_t lustre_path; 00922 char attr_name[MAXPATHLEN]; 00923 00924 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &lustre_path); 00925 if(FSAL_IS_ERROR(st)) 00926 ReturnStatus(st, INDEX_FSAL_GetXAttrValue); 00927 00928 /* get the name for this attr */ 00929 rc = xattr_id_to_name(lustre_path.path, xattr_id, attr_name); 00930 if(rc) 00931 Return(rc, errno, INDEX_FSAL_GetXAttrValue); 00932 00933 rc = lgetxattr(lustre_path.path, attr_name, buffer_addr, buffer_size); 00934 if(rc < 0) 00935 Return(posix2fsal_error(errno), errno, INDEX_FSAL_GetXAttrValue); 00936 00937 /* the xattr value can be a binary, or a string. 00938 * trying to determine its type... 00939 */ 00940 *p_output_size = rc; 00941 xattr_format_value(buffer_addr, p_output_size, buffer_size); 00942 00943 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue); 00944 } 00945 else /* built-in attr */ 00946 { 00947 /* get the value */ 00948 rc = xattr_list[xattr_id].get_func(p_objecthandle, p_context, 00949 buffer_addr, buffer_size, 00950 p_output_size, xattr_list[xattr_id].arg); 00951 Return(rc, 0, INDEX_FSAL_GetXAttrValue); 00952 } 00953 00954 } 00955 00966 fsal_status_t LUSTREFSAL_GetXAttrIdByName(fsal_handle_t * p_objecthandle, /* IN */ 00967 const fsal_name_t * xattr_name, /* IN */ 00968 fsal_op_context_t * p_context, /* IN */ 00969 unsigned int *pxattr_id /* OUT */ 00970 ) 00971 { 00972 fsal_status_t st; 00973 unsigned int index; 00974 int rc; 00975 int found = FALSE; 00976 00977 /* sanity checks */ 00978 if(!p_objecthandle || !xattr_name) 00979 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue); 00980 00981 for(index = 0; index < XATTR_COUNT; index++) 00982 { 00983 if(!strcmp(xattr_list[index].xattr_name, xattr_name->name)) 00984 { 00985 found = TRUE; 00986 break; 00987 } 00988 } 00989 00990 /* search in xattrs */ 00991 if(!found) 00992 { 00993 fsal_path_t lustre_path; 00994 00995 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &lustre_path); 00996 if(FSAL_IS_ERROR(st)) 00997 ReturnStatus(st, INDEX_FSAL_GetXAttrValue); 00998 00999 errno = 0; 01000 rc = xattr_name_to_id(lustre_path.path, xattr_name->name); 01001 if(rc < 0) 01002 Return(-rc, errno, INDEX_FSAL_GetXAttrValue); 01003 else 01004 { 01005 index = rc; 01006 found = TRUE; 01007 } 01008 } 01009 01010 if(found) 01011 { 01012 *pxattr_id = index; 01013 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue); 01014 } 01015 else 01016 Return(ERR_FSAL_NOENT, ENOENT, INDEX_FSAL_GetXAttrValue); 01017 } /* FSAL_GetXAttrIdByName */ 01018 01029 fsal_status_t LUSTREFSAL_GetXAttrValueByName(fsal_handle_t * p_objecthandle, /* IN */ 01030 const fsal_name_t * xattr_name, /* IN */ 01031 fsal_op_context_t * p_context, /* IN */ 01032 caddr_t buffer_addr, /* IN/OUT */ 01033 size_t buffer_size, /* IN */ 01034 size_t * p_output_size /* OUT */ 01035 ) 01036 { 01037 unsigned int index; 01038 fsal_attrib_list_t file_attrs; 01039 fsal_status_t st; 01040 fsal_path_t lustre_path; 01041 int rc; 01042 01043 /* sanity checks */ 01044 if(!p_objecthandle || !p_context || !p_output_size || !buffer_addr || !xattr_name) 01045 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_GetXAttrValue); 01046 01047 /* get type for checking it */ 01048 file_attrs.asked_attributes = FSAL_ATTR_TYPE; 01049 01050 st = LUSTREFSAL_getattrs(p_objecthandle, p_context, &file_attrs); 01051 01052 if(FSAL_IS_ERROR(st)) 01053 ReturnStatus(st, INDEX_FSAL_GetXAttrValue); 01054 01055 /* look for this name */ 01056 01057 for(index = 0; index < XATTR_COUNT; index++) 01058 { 01059 if(do_match_type(xattr_list[index].flags, file_attrs.type) 01060 && !strcmp(xattr_list[index].xattr_name, xattr_name->name)) 01061 { 01062 01063 return LUSTREFSAL_GetXAttrValueById(p_objecthandle, index, p_context, 01064 buffer_addr, buffer_size, p_output_size); 01065 } 01066 } 01067 01068 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &lustre_path); 01069 if(FSAL_IS_ERROR(st)) 01070 ReturnStatus(st, INDEX_FSAL_GetXAttrValue); 01071 01072 /* is it an xattr? */ 01073 rc = lgetxattr(lustre_path.path, xattr_name->name, buffer_addr, buffer_size); 01074 if(rc < 0) 01075 Return(posix2fsal_error(errno), errno, INDEX_FSAL_GetXAttrValue); 01076 01077 /* the xattr value can be a binary, or a string. 01078 * trying to determine its type... 01079 */ 01080 *p_output_size = rc; 01081 xattr_format_value(buffer_addr, p_output_size, buffer_size); 01082 01083 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_GetXAttrValue); 01084 } 01085 01086 static void chomp_attr_value(char *str, size_t size) 01087 { 01088 int len; 01089 01090 if(str == NULL) 01091 return; 01092 01093 /* security: set last char to '\0' */ 01094 str[size - 1] = '\0'; 01095 01096 len = strnlen(str, size); 01097 if((len > 0) && (str[len - 1] == '\n')) 01098 str[len - 1] = '\0'; 01099 } 01100 01101 fsal_status_t LUSTREFSAL_SetXAttrValue(fsal_handle_t * p_objecthandle, /* IN */ 01102 const fsal_name_t * xattr_name, /* IN */ 01103 fsal_op_context_t * p_context, /* IN */ 01104 caddr_t buffer_addr, /* IN */ 01105 size_t buffer_size, /* IN */ 01106 int create /* IN */ 01107 ) 01108 { 01109 int rc; 01110 fsal_status_t st; 01111 fsal_path_t lustre_path; 01112 size_t len; 01113 01114 /* remove final '\n', if any */ 01115 chomp_attr_value((char *)buffer_addr, buffer_size); 01116 01117 /* build fid path in lustre */ 01118 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &lustre_path); 01119 if(FSAL_IS_ERROR(st)) 01120 ReturnStatus(st, INDEX_FSAL_SetXAttrValue); 01121 01122 len = strnlen((char *)buffer_addr, buffer_size); 01123 TakeTokenFSCall(); 01124 if(len == 0) 01125 rc = lsetxattr(lustre_path.path, xattr_name->name, "", 1, 01126 create ? XATTR_CREATE : XATTR_REPLACE); 01127 else 01128 rc = lsetxattr(lustre_path.path, xattr_name->name, (char *)buffer_addr, 01129 len, create ? XATTR_CREATE : XATTR_REPLACE); 01130 01131 ReleaseTokenFSCall(); 01132 if(rc != 0) 01133 Return(posix2fsal_error(errno), errno, INDEX_FSAL_SetXAttrValue); 01134 else 01135 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_SetXAttrValue); 01136 } 01137 01138 fsal_status_t LUSTREFSAL_SetXAttrValueById(fsal_handle_t * p_objecthandle, /* IN */ 01139 unsigned int xattr_id, /* IN */ 01140 fsal_op_context_t * p_context, /* IN */ 01141 caddr_t buffer_addr, /* IN */ 01142 size_t buffer_size /* IN */ 01143 ) 01144 { 01145 int rc; 01146 fsal_status_t st; 01147 fsal_path_t lustre_path; 01148 fsal_name_t attr_name; 01149 char name[FSAL_MAX_NAME_LEN]; 01150 01151 if(attr_is_read_only(xattr_id)) 01152 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue); 01153 else if(xattr_id < XATTR_COUNT) 01154 /* this is not a UDA (setattr not supported) */ 01155 Return(ERR_FSAL_PERM, 0, INDEX_FSAL_SetXAttrValue); 01156 01157 /* build fid path in lustre */ 01158 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &lustre_path); 01159 if(FSAL_IS_ERROR(st)) 01160 ReturnStatus(st, INDEX_FSAL_SetXAttrValue); 01161 01162 rc = xattr_id_to_name(lustre_path.path, xattr_id, name); 01163 if(rc) 01164 Return(rc, errno, INDEX_FSAL_SetXAttrValue); 01165 01166 FSAL_str2name(name, FSAL_MAX_NAME_LEN, &attr_name); 01167 01168 return LUSTREFSAL_SetXAttrValue(p_objecthandle, &attr_name, 01169 p_context, buffer_addr, buffer_size, FALSE); 01170 } 01171 01179 fsal_status_t LUSTREFSAL_RemoveXAttrById(fsal_handle_t * p_objecthandle, /* IN */ 01180 fsal_op_context_t * p_context, /* IN */ 01181 unsigned int xattr_id) /* IN */ 01182 { 01183 int rc; 01184 fsal_status_t st; 01185 fsal_path_t lustre_path; 01186 char name[FSAL_MAX_NAME_LEN]; 01187 01188 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &lustre_path); 01189 if(FSAL_IS_ERROR(st)) 01190 ReturnStatus(st, INDEX_FSAL_SetXAttrValue); 01191 01192 rc = xattr_id_to_name(lustre_path.path, xattr_id, name); 01193 if(rc) 01194 Return(rc, errno, INDEX_FSAL_SetXAttrValue); 01195 01196 TakeTokenFSCall(); 01197 rc = lremovexattr(lustre_path.path, name); 01198 ReleaseTokenFSCall(); 01199 01200 if(rc != 0) 01201 ReturnCode(posix2fsal_error(errno), errno); 01202 01203 ReturnCode(ERR_FSAL_NO_ERROR, 0); 01204 } /* FSAL_RemoveXAttrById */ 01205 01213 fsal_status_t LUSTREFSAL_RemoveXAttrByName(fsal_handle_t * p_objecthandle, /* IN */ 01214 fsal_op_context_t * p_context, /* IN */ 01215 const fsal_name_t * xattr_name) /* IN */ 01216 { 01217 int rc; 01218 fsal_status_t st; 01219 fsal_path_t lustre_path; 01220 01221 st = fsal_internal_Handle2FidPath(p_context, p_objecthandle, &lustre_path); 01222 if(FSAL_IS_ERROR(st)) 01223 ReturnStatus(st, INDEX_FSAL_SetXAttrValue); 01224 01225 TakeTokenFSCall(); 01226 rc = lremovexattr(lustre_path.path, xattr_name->name); 01227 ReleaseTokenFSCall(); 01228 01229 if(rc != 0) 01230 ReturnCode(posix2fsal_error(errno), errno); 01231 01232 ReturnCode(ERR_FSAL_NO_ERROR, 0); 01233 } /* FSAL_RemoveXAttrById */ 01234 01235 int LUSTREFSAL_GetXattrOffsetSetable( void ) 01236 { 01237 return XATTR_COUNT ; 01238 }