nfs-ganesha 1.4

fsal_dirs.c

Go to the documentation of this file.
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 }