Ejemplo n.º 1
0
void cfs_walk_dir_generic(struct ceph_mount_info* _fs, const char* _entry_point, cfs_dentry_handler_t _handler, cfs_dentry_comparator_t _comparator, void* _data, unsigned int _level)
{
	int ceph_opendir_res = -1;
	int ceph_readdirplus_r_res = 0;
	int sb_mask = 0;
	char path[PATH_MAX];
	struct ceph_dir_result* cfs_dir = NULL;
	struct dirent entry;
	struct stat sb;

	pfcq_zero(&entry, sizeof(struct dirent));
	pfcq_zero(&sb, sizeof(struct stat));
	pfcq_zero(path, PATH_MAX);

	debug("Walking into %s entry...\n", _entry_point);

	ceph_opendir_res = ceph_opendir(_fs, _entry_point, &cfs_dir);
	if (unlikely(ceph_opendir_res != 0))
	{
		warning("ceph_opendir");
		goto out;
	}

	while (likely((ceph_readdirplus_r_res = ceph_readdirplus_r(_fs, cfs_dir, &entry, &sb, &sb_mask)) == 1))
	{
		if (unlikely(strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0))
			continue;

		if (likely(_comparator))
			if (unlikely(!_comparator(_entry_point, &entry, &sb, _level)))
				continue;

		if (likely(strcmp(_entry_point, "/") == 0))
		{
			if (unlikely(snprintf(path, PATH_MAX, "/%s", entry.d_name) < 0))
				continue;
		} else
		{
			if (unlikely(snprintf(path, PATH_MAX, "%s/%s", _entry_point, entry.d_name) < 0))
				continue;
		}
		if (likely(_handler))
			_handler(_fs, path, &entry, &sb, _data, _level);
	}

	if (unlikely(ceph_closedir(_fs, cfs_dir) != 0))
		warning("ceph_closedir");

out:
	debug("Walking out of %s entry...\n", _entry_point);

	return;
}
Ejemplo n.º 2
0
/**
 * FSAL_readdir :
 *     Read the entries of an opened directory.
 *
 * \param descriptor (input):
 *        Pointer to the directory descriptor filled by FSAL_opendir.
 * \param start_position (input):
 *        Cookie that indicates the first object to be read during
 *        this readdir operation.
 *        This should be :
 *        - FSAL_READDIR_FROM_BEGINNING for reading the content
 *          of the directory from the beginning.
 *        - The end_position parameter returned by the previous
 *          call to FSAL_readdir.
 * \param get_attr_mask (input)
 *        Specify the set of attributes to be retrieved for directory entries.
 * \param buffersize (input)
 *        The size (in bytes) of the buffer where
 *        the direntries are to be stored.
 * \param dirents (output)
 *        Adress of the buffer where the direntries are to be stored.
 * \param end_position (output)
 *        Cookie that indicates the current position in the directory.
 * \param count (output)
 *        Pointer to the number of entries read during the call.
 * \param end_of_dir (output)
 *        Pointer to a boolean that indicates if the end of dir
 *        has been reached during the call.
 *
 * \return Major error codes :
 *        - ERR_FSAL_NO_ERROR     (no error)
 *        - ERR_FSAL_FAULT        (a NULL pointer was passed as mandatory argument) 
 *        - Other error codes can be returned :
 *          ERR_FSAL_IO, ...
 */
fsal_status_t CEPHFSAL_readdir(fsal_dir_t *extdescriptor,
                               fsal_op_context_t * p_context,       /* IN */
                               fsal_cookie_t extstart,
                               fsal_attrib_mask_t attrmask,
                               fsal_mdsize_t buffersize,
                               fsal_dirent_t *dirents,
                               fsal_cookie_t *extend,
                               fsal_count_t *count,
                               fsal_boolean_t *end_of_dir)
{
  int rc = 0;
  fsal_status_t status;
  struct dirent de;
  cephfsal_dir_t* descriptor = (cephfsal_dir_t*) extdescriptor;
  struct ceph_mount_info *cmount = descriptor->ctx.export_context->cmount;

  loff_t start = ((cephfsal_cookie_t*) extstart.data)->cookie;
  loff_t* end = &((cephfsal_cookie_t*) extend->data)->cookie;
  unsigned int max_entries = buffersize / sizeof(fsal_dirent_t);

  /* sanity checks */

  if(!descriptor || !dirents || !end || !count || !end_of_dir)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_readdir);

  *end_of_dir = FALSE;
  *count = 0;

  TakeTokenFSCall();

  (void) ceph_seekdir(cmount, DH(descriptor), start);

  while ((*count <= max_entries) && !(*end_of_dir)) {
      struct stat st;

      memset(&dirents[*count], sizeof(fsal_dirent_t), 0);
      memset(&de, sizeof(struct dirent), 0);
      memset(&st, sizeof(struct stat), 0);
      int stmask = 0;

      TakeTokenFSCall();
      rc = ceph_readdirplus_r(cmount, DH(descriptor), &de, &st, &stmask);
      if (rc < 0) /* Error */
          Return(posix2fsal_error(rc), 0, INDEX_FSAL_readdir);
      else if (rc == 1) {
          /* Got a dirent */
          cephfsal_handle_t* entryhandle
            = (cephfsal_handle_t*) &(dirents[*count].handle.data);
          cephfsal_cookie_t* entrycookie
            = (cephfsal_cookie_t*) &(dirents[*count].cookie);
          /* skip . and .. */
          if(!strcmp(de.d_name, ".") || !strcmp(de.d_name, ".."))
            continue;

          entryhandle->data.vi.ino.val = st.st_ino;
          entryhandle->data.vi.snapid.val = st.st_dev;

          status = FSAL_str2name(de.d_name, FSAL_MAX_NAME_LEN,
                                 &(dirents[*count].name));
          if(FSAL_IS_ERROR(status))
            ReturnStatus(status, INDEX_FSAL_readdir);

          entrycookie->data.cookie = ceph_telldir(cmount, DH(descriptor));
          dirents[*count].attributes.asked_attributes = attrmask;

          status =
            posix2fsal_attributes(&st,
                                  &(dirents[*count].attributes));
          if(FSAL_IS_ERROR(status)) {
              FSAL_CLEAR_MASK(dirents[*count].attributes
                              .asked_attributes);
              FSAL_SET_MASK(dirents[*count].attributes.asked_attributes,
                            FSAL_ATTR_RDATTR_ERR);
            }
          if (*count != 0) {
              dirents[(*count)-1].nextentry = &(dirents[*count]);
          }
          (*count)++;
      } else if (rc == 0) /* EOF */
          *end_of_dir = TRUE;
      else{
          /* Can't happen */ 
          abort();
      }
  } /* while */

  (*end) = ceph_telldir(cmount, DH(descriptor));

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_readdir);
}
Ejemplo n.º 3
0
/*
 * Get the next file to backup.
 */
static bRC get_next_file_to_backup(bpContext *ctx)
{
   int status;
   struct save_pkt sp;
   struct dirent *entry;
   plugin_ctx *p_ctx = (plugin_ctx *)ctx->pContext;

   /*
    * See if we just saved the directory then we are done processing this directory.
    */
   switch (p_ctx->type) {
   case FT_DIREND:
      /*
       * See if there is anything on the dir stack to pop off and continue reading that directory.
       */
      if (!p_ctx->dir_stack->empty()) {
         const char *cwd;
         struct dir_stack_entry *new_entry;

         /*
          * Change the GLFS cwd back one dir.
          */
         status = ceph_chdir(p_ctx->cmount, "..");
         if (status < 0) {
            berrno be;

            Jmsg(ctx, M_ERROR, "ceph_chdir(%s) failed: %s\n", "..", be.bstrerror(-status));
            return bRC_Error;
         }

         /*
          * Save where we are in the tree.
          */
         cwd = ceph_getcwd(p_ctx->cmount);
         pm_strcpy(p_ctx->cwd, cwd);

         /*
          * Pop the previous directory handle and continue processing that.
          */
         new_entry = (struct dir_stack_entry *)p_ctx->dir_stack->pop();
         memcpy(&p_ctx->statp, &new_entry->statp, sizeof(p_ctx->statp));
         p_ctx->cdir = new_entry->cdir;
         free(new_entry);
      } else {
         return bRC_OK;
      }
      break;
   default:
      break;
   }

   if (!p_ctx->cdir) {
      return bRC_Error;
   }

   /*
    * Loop until we know what file is next or when we are done.
    */
   while (1) {
      int stmask = 0;

      memset(&p_ctx->statp, 0, sizeof(p_ctx->statp));
      memset(&p_ctx->de, 0, sizeof(p_ctx->de));
      status = ceph_readdirplus_r(p_ctx->cmount, p_ctx->cdir, &p_ctx->de, &p_ctx->statp, &stmask);

      /*
       * No more entries in this directory ?
       */
      if (status == 0) {
         status = ceph_stat(p_ctx->cmount, p_ctx->cwd, &p_ctx->statp);
         if (status < 0) {
            berrno be;

            Jmsg(ctx, M_ERROR, "ceph_stat(%s) failed: %s\n", p_ctx->cwd, be.bstrerror(-status));
            return bRC_Error;
         }

         status = ceph_closedir(p_ctx->cmount, p_ctx->cdir);
         if (status < 0) {
            berrno be;

            Jmsg(ctx, M_ERROR, "ceph_closedir(%s) failed: %s\n", p_ctx->cwd, be.bstrerror(-status));
            return bRC_Error;
         }

         p_ctx->cdir = NULL;
         p_ctx->type = FT_DIREND;

         pm_strcpy(p_ctx->next_filename, p_ctx->cwd);

         Dmsg(ctx, dbglvl, "cephfs-fd: next file to backup %s\n", p_ctx->next_filename);

         return bRC_More;
      }

      entry = &p_ctx->de;

      /*
       * Skip `.', `..', and excluded file names.
       */
      if (entry->d_name[0] == '\0' ||
         (entry->d_name[0] == '.' && (entry->d_name[1] == '\0' ||
         (entry->d_name[1] == '.' && entry->d_name[2] == '\0')))) {
         continue;
      }

      Mmsg(p_ctx->next_filename, "%s/%s", p_ctx->cwd, entry->d_name);

      /*
       * Determine the FileType.
       */
      switch (p_ctx->statp.st_mode & S_IFMT) {
      case S_IFREG:
         p_ctx->type = FT_REG;
         break;
      case S_IFLNK:
         p_ctx->type = FT_LNK;
         status = ceph_readlink(p_ctx->cmount, p_ctx->next_filename,
                                p_ctx->link_target, sizeof_pool_memory(p_ctx->link_target));
         if (status < 0) {
            berrno be;

            Jmsg(ctx, M_ERROR, "ceph_readlink(%s) failed: %s\n", p_ctx->next_filename, be.bstrerror(-status));
            p_ctx->type = FT_NOFOLLOW;
         }
         p_ctx->link_target[status] = '\0';
         break;
      case S_IFDIR:
         p_ctx->type = FT_DIRBEGIN;
         break;
      case S_IFCHR:
      case S_IFBLK:
      case S_IFIFO:
#ifdef S_IFSOCK
      case S_IFSOCK:
#endif
         p_ctx->type = FT_SPEC;
         break;
      default:
         Jmsg(ctx, M_FATAL, "Unknown filetype encountered %ld for %s\n",
              p_ctx->statp.st_mode & S_IFMT, p_ctx->next_filename);
         return bRC_Error;
      }

      /*
       * See if we accept this file under the currently loaded fileset.
       */
      memset(&sp, 0, sizeof(sp));
      sp.pkt_size = sizeof(sp);
      sp.pkt_end = sizeof(sp);
      sp.fname = p_ctx->next_filename;
      sp.type = p_ctx->type;
      memcpy(&sp.statp, &p_ctx->statp, sizeof(sp.statp));

      if (bfuncs->AcceptFile(ctx, &sp) == bRC_Skip) {
         Dmsg(ctx, dbglvl, "cephfs-fd: file %s skipped due to current fileset settings\n", p_ctx->next_filename);
         continue;
      }

      /*
       * If we made it here we have the next file to backup.
       */
      break;
   }

   Dmsg(ctx, dbglvl, "cephfs-fd: next file to backup %s\n", p_ctx->next_filename);

   return bRC_More;
}