nfs-ganesha 1.4
|
00001 /* 00002 * vim:expandtab:shiftwidth=8:tabstop=8: 00003 */ 00004 00014 #ifdef HAVE_CONFIG_H 00015 #include "config.h" 00016 #endif 00017 00018 #include "fsal.h" 00019 #include "fsal_internal.h" 00020 #include "fsal_convert.h" 00021 #include "fsal_common.h" 00022 #include <string.h> 00023 00024 extern size_t i_snapshots; 00025 extern snapshot_t *p_snapshots; 00026 extern time_t ServerBootTime; 00027 00052 fsal_status_t ZFSFSAL_opendir(fsal_handle_t * dir_hdl, /* IN */ 00053 fsal_op_context_t * p_context, /* IN */ 00054 fsal_dir_t * dir_desc, /* OUT */ 00055 fsal_attrib_list_t * dir_attributes /* [ IN/OUT ] */ 00056 ) 00057 { 00058 int rc; 00059 creden_t cred; 00060 zfsfsal_handle_t * dir_handle = (zfsfsal_handle_t *)dir_hdl; 00061 zfsfsal_dir_t * dir_descriptor = (zfsfsal_dir_t *)dir_desc; 00062 00063 /* sanity checks 00064 * note : dir_attributes is optionnal. 00065 */ 00066 if(!dir_handle || !p_context || !dir_descriptor) 00067 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir); 00068 00069 /* >> You can prepare your directory for beeing read 00070 * and check that the user has the right for reading its content <<*/ 00071 libzfswrap_vnode_t *p_vnode; 00072 00073 /* Get the right VFS */ 00074 ZFSFSAL_VFS_RDLock(); 00075 libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(dir_handle); 00076 if(!p_vfs) 00077 { 00078 ZFSFSAL_VFS_Unlock(); 00079 Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_opendir); 00080 } 00081 cred.uid = p_context->credential.user; 00082 cred.gid = p_context->credential.group; 00083 00084 /* Hook for the zfs snapshot directory */ 00085 if(dir_handle->data.zfs_handle.inode == ZFS_SNAP_DIR_INODE) 00086 { 00087 LogDebug(COMPONENT_FSAL, "Opening the .zfs pseudo-directory"); 00088 p_vnode = NULL; 00089 rc = 0; 00090 } 00091 else 00092 { 00093 TakeTokenFSCall(); 00094 rc = libzfswrap_opendir(p_vfs, &cred, 00095 dir_handle->data.zfs_handle, &p_vnode); 00096 ReleaseTokenFSCall(); 00097 } 00098 ZFSFSAL_VFS_Unlock(); 00099 00100 if(rc) 00101 Return(posix2fsal_error(rc), 0, INDEX_FSAL_opendir); 00102 00103 dir_descriptor->cred = cred; 00104 dir_descriptor->handle = *dir_handle; 00105 dir_descriptor->p_vnode = p_vnode; 00106 00107 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir); 00108 } 00109 00145 fsal_status_t ZFSFSAL_readdir(fsal_dir_t * dir_desc, /* IN */ 00146 fsal_cookie_t start_pos, /* IN */ 00147 fsal_attrib_mask_t get_attr_mask, /* IN */ 00148 fsal_mdsize_t buffersize, /* IN */ 00149 fsal_dirent_t * p_dirent, /* OUT */ 00150 fsal_cookie_t * end_pos, /* OUT */ 00151 fsal_count_t * nb_entries, /* OUT */ 00152 fsal_boolean_t * end_of_dir /* OUT */ 00153 ) 00154 { 00155 int rc; 00156 fsal_count_t max_dir_entries = buffersize / sizeof(fsal_dirent_t); 00157 zfsfsal_dir_t * dir_descriptor = (zfsfsal_dir_t *)dir_desc; 00158 zfsfsal_cookie_t start_position; 00159 zfsfsal_cookie_t * end_position = (zfsfsal_cookie_t *)end_pos; 00160 zfsfsal_handle_t *entry_hdl; 00161 00162 /* sanity checks */ 00163 00164 if(!dir_descriptor || !p_dirent || !end_position || !nb_entries || !end_of_dir) 00165 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir); 00166 00167 memcpy( (char *)&start_position.data.cookie, (char *)&start_pos.data, sizeof( off_t ) ) ; 00168 00169 /* Hook to create the pseudo directory */ 00170 if(dir_descriptor->handle.data.zfs_handle.inode == ZFS_SNAP_DIR_INODE) 00171 { 00172 LogDebug(COMPONENT_FSAL, "Listing the snapshots in .zfs/"); 00173 00174 int i; 00175 struct stat fstat; 00176 memset(&fstat, 0, sizeof(fstat)); 00177 fstat.st_mode = S_IFDIR | 0755; 00178 fstat.st_nlink = 3; 00179 fstat.st_ctime = ServerBootTime; 00180 fstat.st_atime = ServerBootTime; 00181 fstat.st_mtime = ServerBootTime; 00182 00183 00184 ZFSFSAL_VFS_RDLock(); 00185 for(i = 0; i < max_dir_entries && i < i_snapshots; i++) 00186 { 00187 entry_hdl = (zfsfsal_handle_t *) &p_dirent[i].handle; 00188 00189 libzfswrap_getroot(p_snapshots[i + start_position.data.cookie + 1].p_vfs, 00190 &entry_hdl->data.zfs_handle); 00191 entry_hdl->data.i_snap = i + start_position.data.cookie + 1; 00192 entry_hdl->data.type = FSAL_TYPE_DIR; 00193 strncpy(p_dirent[i].name.name, p_snapshots[i + start_position.data.cookie + 1].psz_name, 00194 FSAL_MAX_NAME_LEN); 00195 p_dirent[i].name.len = strlen(p_snapshots[i + start_position.data.cookie + 1].psz_name); 00196 00197 fstat.st_dev = i + start_position.data.cookie + 1; 00198 fstat.st_ino = entry_hdl->data.zfs_handle.inode; 00199 p_dirent[i].attributes.asked_attributes = get_attr_mask; 00200 posix2fsal_attributes(&fstat, &p_dirent[i].attributes); 00201 00202 p_dirent[i].nextentry = NULL; 00203 if(i) 00204 p_dirent[i-1].nextentry = &(p_dirent[i]); 00205 } 00206 *nb_entries = i; 00207 if(i == i_snapshots) 00208 *end_of_dir = 1; 00209 else 00210 end_position->data.cookie = start_position.data.cookie + i; 00211 ZFSFSAL_VFS_Unlock(); 00212 00213 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir); 00214 } 00215 00216 /* Check that the vfs is still existing */ 00217 ZFSFSAL_VFS_RDLock(); 00218 libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(&dir_descriptor->handle); 00219 if(p_vfs == NULL) 00220 { 00221 ZFSFSAL_VFS_Unlock(); 00222 Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_readdir); 00223 } 00224 00225 libzfswrap_entry_t *entries = malloc( max_dir_entries * sizeof(libzfswrap_entry_t)); 00226 TakeTokenFSCall(); 00227 00228 /* >> read some entry from you filesystem << */ 00229 rc = libzfswrap_readdir(p_vfs, &dir_descriptor->cred, dir_descriptor->p_vnode, entries, 00230 max_dir_entries, (off_t*)(&start_position)); 00231 00232 ReleaseTokenFSCall(); 00233 ZFSFSAL_VFS_Unlock(); 00234 00235 /* >> convert error code and return on error << */ 00236 if(rc) 00237 { 00238 free(entries); 00239 Return(posix2fsal_error(rc), 0, INDEX_FSAL_readdir); 00240 } 00241 00242 /* >> fill the output dirent array << */ 00243 00244 *nb_entries = 0; 00245 int index = 0; 00246 while(index < max_dir_entries) 00247 { 00248 entry_hdl = (zfsfsal_handle_t *) &p_dirent[*nb_entries].handle; 00249 00250 /* If psz_filename is NULL, that's the end of the list */ 00251 if(entries[index].psz_filename[0] == '\0') 00252 break; 00253 00254 /* Skip '.' and '..' */ 00255 if(!strcmp(entries[index].psz_filename, ".") || !strcmp(entries[index].psz_filename, "..")) 00256 { 00257 index++; 00258 continue; 00259 } 00260 00261 entry_hdl->data.zfs_handle = entries[index].object; 00262 entry_hdl->data.type = posix2fsal_type(entries[index].type); 00263 entry_hdl->data.i_snap = dir_descriptor->handle.data.i_snap; 00264 entries[index].stats.st_dev = dir_descriptor->handle.data.i_snap; 00265 FSAL_str2name(entries[index].psz_filename, FSAL_MAX_NAME_LEN, &(p_dirent[*nb_entries].name)); 00266 00267 /* Add the attributes */ 00268 p_dirent[*nb_entries].attributes.asked_attributes = get_attr_mask; 00269 posix2fsal_attributes(&(entries[index].stats), &p_dirent[*nb_entries].attributes); 00270 00271 p_dirent[*nb_entries].nextentry = NULL; 00272 00273 if(*nb_entries) 00274 p_dirent[*nb_entries - 1].nextentry = &(p_dirent[*nb_entries]); 00275 00276 (*nb_entries)++; 00277 index++; 00278 } 00279 free(entries); 00280 00281 /* until the requested count is reached 00282 * or the end of dir is reached... 00283 */ 00284 00285 /* Don't forget setting output vars : end_position, nb_entries, end_of_dir */ 00286 if(start_position.data.cookie == 0) 00287 *end_of_dir = 1; 00288 else 00289 *end_position = start_position; 00290 00291 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir); 00292 00293 } 00294 00308 fsal_status_t ZFSFSAL_closedir(fsal_dir_t * dir_desc /* IN */ 00309 ) 00310 { 00311 00312 int rc; 00313 zfsfsal_dir_t * dir_descriptor = (zfsfsal_dir_t *)dir_desc; 00314 00315 /* sanity checks */ 00316 if(!dir_descriptor) 00317 Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir); 00318 00319 /* Hook for the ZFS directory */ 00320 if(dir_descriptor->handle.data.zfs_handle.inode == ZFS_SNAP_DIR_INODE) 00321 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir); 00322 00323 /* Check that the vfs still exist */ 00324 ZFSFSAL_VFS_RDLock(); 00325 libzfswrap_vfs_t *p_vfs = ZFSFSAL_GetVFS(&dir_descriptor->handle); 00326 if(!p_vfs) 00327 { 00328 ZFSFSAL_VFS_Unlock(); 00329 Return(ERR_FSAL_NOENT, 0, INDEX_FSAL_closedir); 00330 } 00331 00332 /* >> release the resources used for reading your directory << */ 00333 rc = libzfswrap_closedir(p_vfs, &dir_descriptor->cred, dir_descriptor->p_vnode); 00334 ZFSFSAL_VFS_Unlock(); 00335 00336 if(rc) 00337 Return(posix2fsal_error(rc), 0, INDEX_FSAL_closedir); 00338 else 00339 Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir); 00340 }