nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 */ 00004 00013 #ifdef HAVE_CONFIG_H 00014 #include "config.h" 00015 #endif 00016 00017 #include "fsal.h" 00018 #include "fsal_internal.h" 00019 #include "fsal_convert.h" 00020 #include "fsal_common.h" 00021 00022 #include <string.h> 00023 00024 extern size_t i_snapshots; 00025 extern snapshot_t *p_snapshots; 00026 00062 fsal_status_t ZFSFSAL_lookup(fsal_handle_t * parent_hdl, /* IN */ 00063 fsal_name_t * p_filename, /* IN */ 00064 fsal_op_context_t * context, /* IN */ 00065 fsal_handle_t * obj_handle, /* OUT */ 00066 fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ 00067 ) 00068 { 00069 int rc; 00070 zfsfsal_handle_t * parent_directory_handle = (zfsfsal_handle_t *)parent_hdl; 00071 zfsfsal_op_context_t * p_context = (zfsfsal_op_context_t *)context; 00072 zfsfsal_handle_t * object_handle = (zfsfsal_handle_t *)obj_handle; 00073 00074 /* sanity checks 00075 * note : object_attributes is optionnal 00076 * parent_directory_handle may be null for getting FS root. 00077 */ 00078 if(!object_handle || !p_context) 00079 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup); 00080 00081 /* retrieves root handle */ 00082 00083 if(!parent_directory_handle) 00084 { 00085 /* check that p_filename is NULL, 00086 * else, parent_directory_handle should not 00087 * be NULL. 00088 */ 00089 if(p_filename != NULL) 00090 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup); 00091 00092 /* >> retrieve root handle filehandle here << */ 00093 if((rc = libzfswrap_getroot(p_context->export_context->p_vfs, &(object_handle->data.zfs_handle)))) 00094 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup); 00095 00096 object_handle->data.type = FSAL_TYPE_DIR; 00097 object_handle->data.i_snap = 0; 00098 00099 /* >> retrieves root attributes, if asked << */ 00100 00101 if(object_attributes) 00102 { 00103 fsal_status_t status = ZFSFSAL_getattrs(obj_handle, context, object_attributes); 00104 /* On error, we set a flag in the returned attributes */ 00105 if(FSAL_IS_ERROR(status)) 00106 { 00107 FSAL_CLEAR_MASK(object_attributes->asked_attributes); 00108 FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00109 } 00110 } 00111 00112 } 00113 else /* this is a real lookup(parent, name) */ 00114 { 00115 /* the filename should not be null */ 00116 if(p_filename == NULL) 00117 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookup); 00118 00119 /* >> Be careful about junction crossing, symlinks, hardlinks,... 00120 * You may check the parent type if it's sored into the handle << 00121 */ 00122 switch (parent_directory_handle->data.type) 00123 { 00124 case FSAL_TYPE_DIR: 00125 /* OK */ 00126 break; 00127 00128 case FSAL_TYPE_JUNCTION: 00129 /* This is a junction */ 00130 Return(ERR_FSAL_XDEV, 0, INDEX_FSAL_lookup); 00131 00132 case FSAL_TYPE_FILE: 00133 case FSAL_TYPE_LNK: 00134 case FSAL_TYPE_XATTR: 00135 /* not a directory */ 00136 Return(ERR_FSAL_NOTDIR, 0, INDEX_FSAL_lookup); 00137 00138 default: 00139 Return(ERR_FSAL_SERVERFAULT, 0, INDEX_FSAL_lookup); 00140 } 00141 00142 TakeTokenFSCall(); 00143 00144 /* >> Call your filesystem lookup function here << */ 00145 /* >> Be carefull you don't traverse junction nor follow symlinks << */ 00146 inogen_t object; 00147 int type; 00148 char i_snap = parent_directory_handle->data.i_snap; 00149 00150 /* Hook to add the hability to go inside a .zfs directory inside the root dir */ 00151 if(parent_directory_handle->data.zfs_handle.inode == 3 && 00152 !strcmp(p_filename->name, ZFS_SNAP_DIR)) 00153 { 00154 LogDebug(COMPONENT_FSAL, "Lookup for the .zfs/ pseudo-directory"); 00155 00156 object.inode = ZFS_SNAP_DIR_INODE; 00157 object.generation = 0; 00158 type = S_IFDIR; 00159 rc = 0; 00160 } 00161 00162 /* Hook for the files inside the .zfs directory */ 00163 else if(parent_directory_handle->data.zfs_handle.inode == ZFS_SNAP_DIR_INODE) 00164 { 00165 LogDebug(COMPONENT_FSAL, "Lookup inside the .zfs/ pseudo-directory"); 00166 00167 ZFSFSAL_VFS_RDLock(); 00168 int i; 00169 for(i = 1; i < i_snapshots + 1; i++) 00170 if(!strcmp(p_snapshots[i].psz_name, p_filename->name)) 00171 break; 00172 00173 if(i == i_snapshots + 1) 00174 { 00175 ReleaseTokenFSCall(); 00176 Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_lookup); 00177 } 00178 00179 libzfswrap_getroot(p_snapshots[i].p_vfs, &object); 00180 ZFSFSAL_VFS_Unlock(); 00181 00182 type = S_IFDIR; 00183 i_snap = i + 1; 00184 rc = 0; 00185 } 00186 else 00187 { 00188 /* Get the right VFS */ 00189 ZFSFSAL_VFS_RDLock(); 00190 libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(parent_directory_handle); 00191 if(!p_vfs) { 00192 rc = ENOENT; 00193 } else { 00194 creden_t cred; 00195 00196 cred.uid = p_context->credential.user; 00197 cred.gid = p_context->credential.group; 00198 rc = libzfswrap_lookup(p_vfs, &cred, 00199 parent_directory_handle->data.zfs_handle, p_filename->name, 00200 &object, &type); 00201 } 00202 ZFSFSAL_VFS_Unlock(); 00203 00204 //FIXME!!! Hook to remove the i_snap bit when going up from the .zfs directory 00205 if(object.inode == 3) 00206 i_snap = 0; 00207 } 00208 00209 ReleaseTokenFSCall(); 00210 00211 /* >> convert the error code and return on error << */ 00212 if(rc) 00213 Return(posix2fsal_error(rc), rc, INDEX_FSAL_lookup); 00214 00215 /* >> set output handle << */ 00216 object_handle->data.zfs_handle = object; 00217 object_handle->data.type = posix2fsal_type(type); 00218 object_handle->data.i_snap = i_snap; 00219 if(object_attributes) 00220 { 00221 fsal_status_t status = ZFSFSAL_getattrs(obj_handle, context, object_attributes); 00222 /* On error, we set a flag in the returned attributes */ 00223 if(FSAL_IS_ERROR(status)) 00224 { 00225 FSAL_CLEAR_MASK(object_attributes->asked_attributes); 00226 FSAL_SET_MASK(object_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR); 00227 } 00228 } 00229 } 00230 00231 /* lookup complete ! */ 00232 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookup); 00233 00234 } 00235 00263 fsal_status_t ZFSFSAL_lookupJunction(fsal_handle_t * p_junction_handle, /* IN */ 00264 fsal_op_context_t * p_context, /* IN */ 00265 fsal_handle_t * p_fsoot_handle, /* OUT */ 00266 fsal_attrib_list_t * p_fsroot_attributes /* [ IN/OUT ] */ 00267 ) 00268 { 00269 /* sanity checks 00270 * note : p_fsroot_attributes is optionnal 00271 */ 00272 if(!p_junction_handle || !p_fsoot_handle || !p_context) 00273 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookupJunction); 00274 00275 /* >> you can also check object type if it is in stored in the handle << */ 00276 00277 if(((zfsfsal_handle_t *)p_junction_handle)->data.type != FSAL_TYPE_JUNCTION) 00278 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_lookupJunction); 00279 00280 TakeTokenFSCall(); 00281 00282 /* >> traverse the junction here << */ 00283 00284 ReleaseTokenFSCall(); 00285 00286 /* >> convert the error code and return on error << */ 00287 00288 /* >> set output handle << */ 00289 00290 if(p_fsroot_attributes) 00291 { 00292 00293 /* >> fill output attributes if asked << */ 00294 00295 } 00296 00297 /* lookup complete ! */ 00298 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupJunction); 00299 } 00300 00335 fsal_status_t ZFSFSAL_lookupPath(fsal_path_t * p_path, /* IN */ 00336 fsal_op_context_t * p_context, /* IN */ 00337 fsal_handle_t * object_handle, /* OUT */ 00338 fsal_attrib_list_t * object_attributes /* [ IN/OUT ] */ 00339 ) 00340 { 00341 fsal_name_t obj_name = FSAL_NAME_INITIALIZER; /* empty string */ 00342 char *ptr_str; 00343 zfsfsal_handle_t out_hdl; 00344 fsal_status_t status; 00345 int b_is_last = FALSE; /* is it the last lookup ? */ 00346 00347 /*>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 00348 * this function may be adapted to most FSALs 00349 *<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/ 00350 00351 /* sanity checks 00352 * note : object_attributes is optionnal. 00353 */ 00354 00355 if(!object_handle || !p_context || !p_path) 00356 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_lookupPath); 00357 00358 /* test whether the path begins with a slash */ 00359 00360 if(p_path->path[0] != '/') 00361 Return(ERR_FSAL_INVAL, 0, INDEX_FSAL_lookupPath); 00362 00363 /* the pointer now points on the next name in the path, 00364 * skipping slashes. 00365 */ 00366 00367 ptr_str = p_path->path + 1; 00368 while(ptr_str[0] == '/') 00369 ptr_str++; 00370 00371 /* is the next name empty ? */ 00372 00373 if(ptr_str[0] == '\0') 00374 b_is_last = TRUE; 00375 00376 /* retrieves root directory */ 00377 00378 status = ZFSFSAL_lookup(NULL, /* looking up for root */ 00379 NULL, /* empty string to get root handle */ 00380 p_context, /* user's credentials */ 00381 (fsal_handle_t *) &out_hdl, /* output root handle */ 00382 /* retrieves attributes if this is the last lookup : */ 00383 (b_is_last ? object_attributes : NULL)); 00384 00385 if(FSAL_IS_ERROR(status)) 00386 Return(status.major, status.minor, INDEX_FSAL_lookupPath); 00387 00388 /* exits if this was the last lookup */ 00389 00390 if(b_is_last) 00391 { 00392 (*(zfsfsal_handle_t *)object_handle) = out_hdl; 00393 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupPath); 00394 } 00395 00396 /* proceed a step by step lookup */ 00397 00398 while(ptr_str[0]) 00399 { 00400 00401 zfsfsal_handle_t in_hdl; 00402 char *dest_ptr; 00403 00404 /* preparing lookup */ 00405 00406 in_hdl = out_hdl; 00407 00408 /* compute next name */ 00409 obj_name.len = 0; 00410 dest_ptr = obj_name.name; 00411 while(ptr_str[0] != '\0' && ptr_str[0] != '/') 00412 { 00413 dest_ptr[0] = ptr_str[0]; 00414 dest_ptr++; 00415 ptr_str++; 00416 obj_name.len++; 00417 } 00418 /* final null char */ 00419 dest_ptr[0] = '\0'; 00420 00421 /* skip multiple slashes */ 00422 while(ptr_str[0] == '/') 00423 ptr_str++; 00424 00425 /* is the next name empty ? */ 00426 if(ptr_str[0] == '\0') 00427 b_is_last = TRUE; 00428 00429 /*call to FSAL_lookup */ 00430 status = ZFSFSAL_lookup((fsal_handle_t *) &in_hdl, /* parent directory handle */ 00431 &obj_name, /* object name */ 00432 p_context, /* user's credentials */ 00433 (fsal_handle_t *) &out_hdl, /* output root handle */ 00434 /* retrieves attributes if this is the last lookup : */ 00435 (b_is_last ? object_attributes : NULL)); 00436 00437 if(FSAL_IS_ERROR(status)) 00438 Return(status.major, status.minor, INDEX_FSAL_lookupPath); 00439 00440 /* if the target object is a junction, an we allow cross junction lookups, 00441 * we cross it. 00442 */ 00443 if(global_fs_info.auth_exportpath_xdev 00444 && (out_hdl.data.type == FSAL_TYPE_JUNCTION)) 00445 { 00446 zfsfsal_handle_t tmp_hdl; 00447 00448 tmp_hdl = out_hdl; 00449 00450 /*call to FSAL_lookup */ 00451 status = ZFSFSAL_lookupJunction((fsal_handle_t *) &tmp_hdl, /* object handle */ 00452 p_context, /* user's credentials */ 00453 (fsal_handle_t *) &out_hdl, /* output root handle */ 00454 /* retrieves attributes if this is the last lookup : */ 00455 (b_is_last ? object_attributes : NULL)); 00456 00457 } 00458 00459 /* ptr_str is ok, we are ready for next loop */ 00460 } 00461 00462 (*(zfsfsal_handle_t *)object_handle) = out_hdl; 00463 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_lookupPath); 00464 00465 }