nfs-ganesha 1.4

fsal_dirs.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright (C) 2010, The Linux Box Corporation
00005  * Contributor : Adam C. Emerson <aemerson@linuxbox.com>
00006  *
00007  * Some portions Copyright CEA/DAM/DIF  (2008)
00008  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00009  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00010  *
00011  *
00012  * This program is free software; you can redistribute it and/or
00013  * modify it under the terms of the GNU Lesser General Public
00014  * License as published by the Free Software Foundation; either
00015  * version 3 of the License, or (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00020  * Lesser General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU Lesser General Public
00023  * License along with this library; if not, write to the Free Software
00024  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00025  *
00026  * -------------
00027  */
00028 
00035 #ifdef HAVE_CONFIG_H
00036 #include "config.h"
00037 #endif
00038 
00039 #include "fsal.h"
00040 #include "fsal_internal.h"
00041 #include "fsal_convert.h"
00042 #include <string.h>
00043 
00068 fsal_status_t CEPHFSAL_opendir(fsal_handle_t * exthandle,
00069                                fsal_op_context_t * extcontext,
00070                                fsal_dir_t * extdescriptor,
00071                                fsal_attrib_list_t * dir_attributes)
00072 {
00073   cephfsal_handle_t* handle = (cephfsal_handle_t*) exthandle;
00074   cephfsal_op_context_t* context = (cephfsal_op_context_t*) extcontext;
00075   cephfsal_dir_t* descriptor = (cephfsal_dir_t*) extdescriptor;
00076   fsal_status_t status;
00077   int rc;
00078   int uid = FSAL_OP_CONTEXT_TO_UID(context);
00079   int gid = FSAL_OP_CONTEXT_TO_GID(context);
00080   struct ceph_dir_result *dh;
00081 
00082   /* sanity checks
00083    * note : dir_attributes is optional.
00084    */
00085   if(!handle || !context || !descriptor)
00086     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_opendir);
00087 
00088   TakeTokenFSCall();
00089   /* XXX ceph_ll_opendir has void in the interface, but Client::ll_opendir
00090    * is using dir_result_t. */
00091   rc = ceph_ll_opendir(context->export_context->cmount, VINODE(handle),
00092                        (void *) &dh, uid, gid);
00093   ReleaseTokenFSCall();
00094 
00095   if (rc < 0)
00096     Return(posix2fsal_error(rc), 0, INDEX_FSAL_opendir);
00097 
00098   descriptor->dh = dh;
00099   descriptor->vi = VINODE(handle);
00100   descriptor->ctx = *context;
00101 
00102   if(dir_attributes)
00103     {
00104       status = CEPHFSAL_getattrs(exthandle, extcontext, dir_attributes);
00105 
00106       if(FSAL_IS_ERROR(status))
00107         {
00108           FSAL_CLEAR_MASK(dir_attributes->asked_attributes);
00109           FSAL_SET_MASK(dir_attributes->asked_attributes, FSAL_ATTR_RDATTR_ERR);
00110         }
00111     }
00112 
00113   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_opendir);
00114 }
00115 
00151 fsal_status_t CEPHFSAL_readdir(fsal_dir_t *extdescriptor,
00152                                fsal_cookie_t extstart,
00153                                fsal_attrib_mask_t attrmask,
00154                                fsal_mdsize_t buffersize,
00155                                fsal_dirent_t *dirents,
00156                                fsal_cookie_t *extend,
00157                                fsal_count_t *count,
00158                                fsal_boolean_t *end_of_dir)
00159 {
00160   int rc = 0;
00161   fsal_status_t status;
00162   struct dirent de;
00163   cephfsal_dir_t* descriptor = (cephfsal_dir_t*) extdescriptor;
00164   struct ceph_mount_info *cmount = descriptor->ctx.export_context->cmount;
00165 
00166   loff_t start = ((cephfsal_cookie_t*) extstart.data)->cookie;
00167   loff_t* end = &((cephfsal_cookie_t*) extend->data)->cookie;
00168   unsigned int max_entries = buffersize / sizeof(fsal_dirent_t);
00169 
00170   /* sanity checks */
00171 
00172   if(!descriptor || !dirents || !end || !count || !end_of_dir)
00173     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir);
00174 
00175   *end_of_dir = FALSE;
00176   *count = 0;
00177 
00178   TakeTokenFSCall();
00179 
00180   (void) ceph_seekdir(cmount, DH(descriptor), start);
00181 
00182   while ((*count <= max_entries) && !(*end_of_dir)) {
00183       struct stat st;
00184 
00185       memset(&dirents[*count], sizeof(fsal_dirent_t), 0);
00186       memset(&de, sizeof(struct dirent), 0);
00187       memset(&st, sizeof(struct stat), 0);
00188       int stmask = 0;
00189 
00190       TakeTokenFSCall();
00191       rc = ceph_readdirplus_r(cmount, DH(descriptor), &de, &st, &stmask);
00192       if (rc < 0) /* Error */
00193           Return(posix2fsal_error(rc), 0, INDEX_FSAL_readdir);
00194       else if (rc == 1) {
00195           /* Got a dirent */
00196           cephfsal_handle_t* entryhandle
00197             = (cephfsal_handle_t*) &(dirents[*count].handle.data);
00198           cephfsal_cookie_t* entrycookie
00199             = (cephfsal_cookie_t*) &(dirents[*count].cookie);
00200           /* skip . and .. */
00201           if(!strcmp(de.d_name, ".") || !strcmp(de.d_name, ".."))
00202             continue;
00203 
00204           entryhandle->data.vi.ino.val = st.st_ino;
00205           entryhandle->data.vi.snapid.val = st.st_dev;
00206 
00207           status = FSAL_str2name(de.d_name, FSAL_MAX_NAME_LEN,
00208                                  &(dirents[*count].name));
00209           if(FSAL_IS_ERROR(status))
00210             ReturnStatus(status, INDEX_FSAL_readdir);
00211 
00212           entrycookie->data.cookie = ceph_telldir(cmount, DH(descriptor));
00213           dirents[*count].attributes.asked_attributes = attrmask;
00214 
00215           status =
00216             posix2fsal_attributes(&st,
00217                                   &(dirents[*count].attributes));
00218           if(FSAL_IS_ERROR(status)) {
00219               FSAL_CLEAR_MASK(dirents[*count].attributes
00220                               .asked_attributes);
00221               FSAL_SET_MASK(dirents[*count].attributes.asked_attributes,
00222                             FSAL_ATTR_RDATTR_ERR);
00223             }
00224           if (*count != 0) {
00225               dirents[(*count)-1].nextentry = &(dirents[*count]);
00226           }
00227           (*count)++;
00228       } else if (rc == 0) /* EOF */
00229           *end_of_dir = TRUE;
00230       else{
00231           /* Can't happen */ 
00232           abort();
00233       }
00234   } /* while */
00235 
00236   (*end) = ceph_telldir(cmount, DH(descriptor));
00237 
00238   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir);
00239 }
00240 
00254 fsal_status_t CEPHFSAL_closedir(fsal_dir_t * extdescriptor)
00255 {
00256   cephfsal_dir_t* descriptor = (cephfsal_dir_t*) extdescriptor;
00257   struct ceph_mount_info *cmount = descriptor->ctx.export_context->cmount;
00258   int rc = 0;
00259 
00260   /* sanity checks */
00261   if(!descriptor)
00262     Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_closedir);
00263 
00264   TakeTokenFSCall();
00265   rc = ceph_ll_releasedir(cmount, DH(descriptor));
00266   ReleaseTokenFSCall();
00267 
00268   if (rc < 0)
00269     Return(posix2fsal_error(rc), 0, INDEX_FSAL_closedir);
00270 
00271   Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_closedir);
00272 }