Пример #1
0
static fsal_status_t file_read(struct fsal_obj_handle *obj_hdl,
			       const struct req_op_context *opctx,
			       uint64_t seek_descriptor, size_t buffer_size,
			       void *buffer, size_t * read_amount,
			       bool * end_of_file)
{
	int rc = 0;
	fsal_status_t status = { ERR_FSAL_NO_ERROR, 0 };
	struct glusterfs_handle *objhandle =
	    container_of(obj_hdl, struct glusterfs_handle, handle);
#ifdef GLTIMING
	struct timespec s_time, e_time;

	now(&s_time);
#endif

	rc = glfs_pread(objhandle->glfd, buffer, buffer_size, seek_descriptor,
			0 /*TODO: flags is unused, so pass in something */ );
	if (rc < 0) {
		status = gluster2fsal_error(errno);
		goto out;
	}

	if (rc < buffer_size) {
		*end_of_file = true;
	}

	*read_amount = rc;

 out:
#ifdef GLTIMING
	now(&e_time);
	latency_update(&s_time, &e_time, lat_file_read);
#endif
	return status;
}
int
main (int argc, char *argv[])
{
        glfs_t                   *fs = NULL;
        glfs_t                   *fs2 = NULL;
        glfs_t                   *fs_tmp = NULL;
        glfs_t                   *fs_tmp2 = NULL;
        int                       ret = 0, i;
        glfs_fd_t                *fd = NULL;
        glfs_fd_t                *fd2 = NULL;
        glfs_fd_t                *fd_tmp = NULL;
        glfs_fd_t                *fd_tmp2 = NULL;
        char                      readbuf[32];
        char                     *filename = "file_tmp";
        char                     *writebuf = NULL;
        char                     *vol_id  = NULL;
        unsigned int              cnt = 1;
        struct glfs_upcall       *cbk = NULL;
        char                     *logfile = NULL;
        char                     *volname = NULL;
        char                     *hostname = NULL;

        if (argc != 4) {
                fprintf (stderr, "Invalid argument\n");
                exit(1);
        }

        hostname = argv[1];
        volname = argv[2];
        logfile = argv[3];

        fs = glfs_new (volname);
        if (!fs) {
                fprintf (stderr, "glfs_new: returned NULL\n");
                return -1;
        }

        ret = glfs_set_volfile_server (fs, "tcp", hostname, 24007);
        LOG_ERR("glfs_set_volfile_server", ret);

        ret = glfs_set_logging (fs, logfile, 7);
        LOG_ERR("glfs_set_logging", ret);

        ret = glfs_init (fs);
        LOG_ERR("glfs_init", ret);

        /* This does not block, but enables caching of events. Real
         * applications like NFS-Ganesha run this in a thread before activity
         * on the fs (through this instance) happens. */
        ret = glfs_h_poll_upcall(fs_tmp, &cbk);
        LOG_ERR ("glfs_h_poll_upcall", ret);

        fs2 = glfs_new (volname);
        if (!fs2) {
                fprintf (stderr, "glfs_new fs2: returned NULL\n");
                return 1;
        }

        ret = glfs_set_volfile_server (fs2, "tcp", hostname, 24007);
        LOG_ERR("glfs_set_volfile_server-fs2", ret);

        ret = glfs_set_logging (fs2, logfile, 7);
        LOG_ERR("glfs_set_logging-fs2", ret);

        ret = glfs_init (fs2);
        LOG_ERR("glfs_init-fs2", ret);

        fd = glfs_creat(fs, filename, O_RDWR|O_SYNC, 0644);
        if (fd <= 0) {
                ret = -1;
                LOG_ERR ("glfs_creat", ret);
        }
        fprintf (stderr, "glfs-create fd - %d\n", fd);

        fd2 = glfs_open(fs2, filename, O_SYNC|O_RDWR|O_CREAT);
        if (fd2 <= 0) {
                ret = -1;
                LOG_ERR ("glfs_open-fs2", ret);
        }
        fprintf (stderr, "glfs-open fd2 - %d\n", fd2);

        do {
                if (cnt%2) {
                        fd_tmp = fd;
                        fs_tmp = fs;
                        fd_tmp2 = fd2;
                        fs_tmp2 = fs2;
                } else {
                        fd_tmp = fd2;
                        fs_tmp = fs2;
                        fd_tmp2 = fd;
                        fs_tmp2 = fs;
                }

                /* WRITE on fd_tmp */
                writebuf = malloc(10);
                if (writebuf) {
                        memcpy (writebuf, "abcd", 4);
                        ret = glfs_write (fd_tmp, writebuf, 4, 0);
                        if (ret <= 0)   {
                                ret = -1;
                                LOG_ERR ("glfs_write", ret);
                        } else {
                                fprintf (stderr,
                                         "glfs_write suceeded\n");
                        }
                        free(writebuf);
                } else {
                        fprintf (stderr,
                                 "Could not allocate writebuf\n");
                        return -1;
                }

                /* READ on fd_tmp2 */
                ret = glfs_lseek (fd_tmp2, 0, SEEK_SET);
                LOG_ERR ("glfs_lseek", ret);

                memset (readbuf, 0, sizeof(readbuf));
                ret = glfs_pread (fd_tmp2, readbuf, 4, 0, 0, NULL);

                if (ret <= 0) {
                        ret = -1;
                        LOG_ERR ("glfs_pread", ret);
                } else {
                        fprintf (stderr, "glfs_read: %s\n", readbuf);
                }

                /* Open() fops seem to be not performed on server side until
                 * there are I/Os on that fd
                 */
                if (cnt > 2) {
                        struct glfs_upcall_inode *in_arg = NULL;
                        enum glfs_upcall_reason   reason = 0;
                        struct glfs_object       *object = NULL;
                        uint64_t                  flags = 0;
                        uint64_t                  expire = 0;

                        ret = glfs_h_poll_upcall(fs_tmp, &cbk);
                        LOG_ERR ("glfs_h_poll_upcall", ret);

                        reason = glfs_upcall_get_reason (cbk);

                        /* Expect 'GLFS_INODE_INVALIDATE' upcall event. */
                        if (reason == GLFS_UPCALL_INODE_INVALIDATE) {
                                in_arg = glfs_upcall_get_event (cbk);

                                object = glfs_upcall_inode_get_object (in_arg);
                                flags = glfs_upcall_inode_get_flags (in_arg);
                                expire = glfs_upcall_inode_get_expire (in_arg);

                                fprintf (stderr, " upcall event type - %d,"
                                         " object(%p), flags(%d), "
                                         " expire_time_attr(%d)\n" ,
                                         reason, object, flags, expire);
                        } else {
                                fprintf (stderr,
                                         "Didnt receive upcall notify event");
                                ret = -1;
                                goto err;
                        }

                        glfs_free (cbk);
                }

                sleep(5);
        } while (++cnt < 5);

err:
        glfs_close(fd);
        LOG_ERR ("glfs_close", ret);

        glfs_close(fd2);
        LOG_ERR ("glfs_close-fd2", ret);

out:
        if (fs) {
                ret = glfs_fini(fs);
                fprintf (stderr, "glfs_fini(fs) returned %d \n", ret);
        }

        if (fs2) {
                ret = glfs_fini(fs2);
                fprintf (stderr, "glfs_fini(fs2) returned %d \n", ret);
        }

        if (ret)
                exit(1);
        exit(0);
}
Пример #3
0
/*
 * Return scsi status or TCMU_NOT_HANDLED
 */
int tcmu_glfs_handle_cmd(
	struct tcmu_device *dev,
	struct tcmulib_cmd *tcmulib_cmd)
{
	uint8_t *cdb = tcmulib_cmd->cdb;
	struct iovec *iovec = tcmulib_cmd->iovec;
	size_t iov_cnt = tcmulib_cmd->iov_cnt;
	uint8_t *sense = tcmulib_cmd->sense_buf;
	struct glfs_state *state = tcmu_get_dev_private(dev);
	uint8_t cmd;

	glfs_fd_t *gfd = state->gfd;
	int ret;
	uint32_t length;
	int result = SAM_STAT_GOOD;
	char *tmpbuf;
	uint64_t offset = state->block_size * tcmu_get_lba(cdb);
	uint32_t tl     = state->block_size * tcmu_get_xfer_length(cdb);
	int do_verify = 0;
	uint32_t cmp_offset;
	ret = length = 0;

	cmd = cdb[0];

	switch (cmd) {
	case INQUIRY:
		return tcmu_emulate_inquiry(dev, cdb, iovec, iov_cnt, sense);
		break;
	case TEST_UNIT_READY:
		return tcmu_emulate_test_unit_ready(cdb, iovec, iov_cnt, sense);
		break;
	case SERVICE_ACTION_IN_16:
		if (cdb[1] == READ_CAPACITY_16) {
			long long size;
			unsigned long long num_lbas;

			size = tcmu_get_device_size(dev);
			if (size == -1) {
				errp("Could not get device size\n");
				return TCMU_NOT_HANDLED;
			}

			num_lbas = size / state->block_size;

			return tcmu_emulate_read_capacity_16(num_lbas, state->block_size,
							     cdb, iovec, iov_cnt, sense);
		} else {
			return TCMU_NOT_HANDLED;
		}
		break;
	case MODE_SENSE:
	case MODE_SENSE_10:
		return tcmu_emulate_mode_sense(cdb, iovec, iov_cnt, sense);
		break;
	case MODE_SELECT:
	case MODE_SELECT_10:
		return tcmu_emulate_mode_select(cdb, iovec, iov_cnt, sense);
		break;
	case COMPARE_AND_WRITE:
		/* Blocks are transferred twice, first the set that
		 * we compare to the existing data, and second the set
		 * to write if the compare was successful.
		 */
		length = tl / 2;

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = tcmu_set_sense_data(sense, HARDWARE_ERROR,
						     ASC_INTERNAL_TARGET_FAILURE, NULL);
			break;
		}

		ret = glfs_pread(gfd, tmpbuf, length, offset, SEEK_SET);

		if (ret != length) {
			result = set_medium_error(sense);
			free(tmpbuf);
			break;
		}

		cmp_offset = tcmu_compare_with_iovec(tmpbuf, iovec, length);
		if (cmp_offset != -1) {
			result = tcmu_set_sense_data(sense, MISCOMPARE,
						     ASC_MISCOMPARE_DURING_VERIFY_OPERATION,
						     &cmp_offset);
			free(tmpbuf);
			break;
		}

		free(tmpbuf);

		tcmu_seek_in_iovec(iovec, length);
		goto write;
	case SYNCHRONIZE_CACHE:
	case SYNCHRONIZE_CACHE_16:
		if (cdb[1] & 0x2)
			result = tcmu_set_sense_data(sense, ILLEGAL_REQUEST,
						     ASC_INVALID_FIELD_IN_CDB, NULL);
		else
			glfs_fdatasync(gfd);
		break;
	case WRITE_VERIFY:
	case WRITE_VERIFY_12:
	case WRITE_VERIFY_16:
		do_verify = 1;
	case WRITE_6:
	case WRITE_10:
	case WRITE_12:
	case WRITE_16:
		length = tl;
write:
		ret = glfs_pwritev(gfd, iovec, iov_cnt, offset, ALLOWED_BSOFLAGS);

		if (ret == length) {
			/* Sync if FUA */
			if ((cmd != WRITE_6) && (cdb[1] & 0x8))
				glfs_fdatasync(gfd);
		} else {
			errp("Error on write %x %x\n", ret, length);
			result = set_medium_error(sense);
			break;
		}

		if (!do_verify)
			break;

		tmpbuf = malloc(length);
		if (!tmpbuf) {
			result = tcmu_set_sense_data(sense, HARDWARE_ERROR,
						     ASC_INTERNAL_TARGET_FAILURE, NULL);
			break;
		}

		ret = glfs_pread(gfd, tmpbuf, length, offset, ALLOWED_BSOFLAGS);

		if (ret != length) {
			result = set_medium_error(sense);
			free(tmpbuf);
			break;
		}

		cmp_offset = tcmu_compare_with_iovec(tmpbuf, iovec, length);
		if (cmp_offset != -1)
			result = tcmu_set_sense_data(sense, MISCOMPARE,
					    ASC_MISCOMPARE_DURING_VERIFY_OPERATION,
					    &cmp_offset);
		free(tmpbuf);
		break;

	case WRITE_SAME:
	case WRITE_SAME_16:
		errp("WRITE_SAME called, but has vpd b2 been implemented?\n");
		result = tcmu_set_sense_data(sense, ILLEGAL_REQUEST,
					     ASC_INVALID_FIELD_IN_CDB, NULL);
		break;

#if 0
		/* WRITE_SAME used to punch hole in file */
		if (cdb[1] & 0x08) {
			ret = glfs_discard(gfd, offset, tl);
			if (ret != 0) {
				result = tcmu_set_sense_data(sense, HARDWARE_ERROR,
						    ASC_INTERNAL_TARGET_FAILURE, NULL);
			}
			break;
		}
		while (tl > 0) {
			size_t blocksize = state->block_size;
			uint32_t val32;
			uint64_t val64;

			assert(iovec->iov_len >= 8);

			switch (cdb[1] & 0x06) {
			case 0x02: /* PBDATA==0 LBDATA==1 */
				val32 = htobe32(offset);
				memcpy(iovec->iov_base, &val32, 4);
				break;
			case 0x04: /* PBDATA==1 LBDATA==0 */
				/* physical sector format */
				/* hey this is wrong val! But how to fix? */
				val64 = htobe64(offset);
				memcpy(iovec->iov_base, &val64, 8);
				break;
			default:
				/* FIXME */
				errp("PBDATA and LBDATA set!!!\n");
			}

			ret = glfs_pwritev(gfd, iovec, blocksize,
					offset, ALLOWED_BSOFLAGS);

			if (ret != blocksize)
				result = set_medium_error(sense);

			offset += blocksize;
			tl     -= blocksize;
		}
		break;
#endif
	case READ_6:
	case READ_10:
	case READ_12:
	case READ_16:
		length = tcmu_iovec_length(iovec, iov_cnt);
		ret = glfs_preadv(gfd, iovec, iov_cnt, offset, SEEK_SET);

		if (ret != length) {
			errp("Error on read %x %x\n", ret, length);
			result = set_medium_error(sense);
		}
		break;
	case UNMAP:
		/* TODO: implement UNMAP */
		result = tcmu_set_sense_data(sense, ILLEGAL_REQUEST,
					     ASC_INVALID_FIELD_IN_CDB, NULL);
		break;
	default:
		result = TCMU_NOT_HANDLED;
		break;
	}

	dbgp("io done %p %x %d %u\n", cdb, cmd, result, length);

	if (result == TCMU_NOT_HANDLED)
		dbgp("io not handled %p %x %x %d %d %llu\n",
		     cdb, result, cmd, ret, length, (unsigned long long)offset);
	else if (result != SAM_STAT_GOOD) {
		errp("io error %p %x %x %d %d %llu\n",
		     cdb, result, cmd, ret, length, (unsigned long long)offset);
	}

	return result;
}
Пример #4
0
int
main (int argc, char *argv[])
{
        int        ret         = 0;
        glfs_t    *fs          = NULL;
        struct glfs_fd *fd     = NULL;
        char      *volname     = NULL;
        char      *log_file    = NULL;
        char      *hostname    = NULL;
        char      *buf = NULL;
        struct stat stat;

        if (argc != 4) {
                fprintf (stderr,
                                "Expect following args %s <hostname> <Vol> <log file location>\n"
                                , argv[0]);
                return -1;
        }

        hostname = argv[1];
        volname = argv[2];
        log_file = argv[3];

        fs = setup_new_client (hostname, volname, log_file, 0);
        if (!fs) {
                fprintf (stderr, "\nsetup_new_client: returned NULL (%s)\n",
                                 strerror (errno));
                goto error;
        }

        fd = glfs_opendir (fs, "/");
        if (!fd) {
                fprintf (stderr, "/: %s\n", strerror (errno));
                return -1;
        }

        glfs_readdirplus (fd, &stat);

        fd = glfs_open (fs, "/test", O_RDWR);
        if (fd == NULL) {
                fprintf (stderr, "glfs_open: returned NULL\n");
                goto error;
        }

        buf = (char *) malloc (5);

        ret = glfs_pread (fd, buf, 5, 0, 0);
        if (ret < 0) {
                fprintf (stderr, "Read(%s): %d (%s)\n", "test", ret,
                         strerror (errno));
                return ret;
        }

        free (buf);
        glfs_close (fd);

        ret = glfs_fini (fs);
        if (ret < 0) {
                fprintf (stderr, "glfs_fini failed with ret: %d (%s)\n",
                         ret, strerror (errno));
                return -1;
        }

        return 0;
error:
        return -1;
}
Пример #5
0
bool GlusterBackend::get(const SyncEvent* _getEvent) {
  if(_getEvent == nullptr || _getEvent->fullPathBuffer.empty())
    return false;

  //Try to find file
  /**
   * RETURN VALUES
   * NULL   : Failure. @errno will be set with the type of failure.
   * Others : Pointer to the opened glfs_fd_t.
   */
  glfs_fd_t *fd = glfs_open((glfs_t*)fs, _getEvent->fullPathBuffer.c_str(), O_RDONLY);
  if(!fd){
    LOG(ERROR)<<"Error while openeing a handle to:"<<_getEvent->fullPathBuffer;
    return false;
  }

  FileNode* fileNode = FileSystem::getInstance().findAndOpenNode(_getEvent->fullPathBuffer);
  //If File exist then we won't download it!
  if(fileNode!=nullptr){
    LOG(DEBUG)<<"File "<<fileNode->getFullPath()<<" already exist! no need to download.";
    //Close it! so it can be removed if needed
    uint64_t inodeNum = FileSystem::getInstance().assignINodeNum((intptr_t)fileNode);
    fileNode->close(inodeNum);
    glfs_close(fd);
    return false;
  }

  //Now create a file in FS
  //handle directories
  //FileSystem::getInstance().createHierarchy(_getEvent->fullPathBuffer,false);
  //FileNode *newFile = FileSystem::getInstance().mkFile(_getEvent->fullPathBuffer,false,true);//open
  string name = FileSystem::getInstance().getFileNameFromPath(_getEvent->fullPathBuffer);
  FileNode* newFile = new FileNode(name,_getEvent->fullPathBuffer, false,false);
  if(newFile == nullptr){
    LOG(ERROR)<<"Failed to create a newNode:"<<_getEvent->fullPathBuffer;
    glfs_close(fd);
    return false;
  }

  //and write the content
  uint64_t bufSize = 64ll*1024ll*1024ll;
  char *buff = new char[bufSize];//64MB buffer
  size_t offset = 0;
  int64_t read = 0;
  do {

    //No need to download it anymore.
    if(newFile->mustBeDeleted()){
      delete newFile;
      glfs_close(fd);
      return true;
    }

    read = glfs_pread(fd,buff,bufSize,offset,0);

    if(read < 0){
      LOG(ERROR)<<"Error while reading: "<<_getEvent->fullPathBuffer;
      glfs_close(fd);
      return false;
    }

    if(read>0){
      FileNode* afterMove = nullptr;
      long retCode = newFile->writeHandler(buff,offset,read,afterMove,true);

      while(retCode == -1)//-1 means moving
        retCode = newFile->writeHandler(buff,offset,read,afterMove,true);

      if(afterMove){
        newFile = afterMove;
        FileSystem::getInstance().replaceAllInodesByNewNode((intptr_t)newFile,(intptr_t)afterMove);
      }
      //Check space availability
      if(retCode < 0) {
        LOG(ERROR)<<"Error in writing file:"<<newFile->getFullPath()<<", probably no diskspace, Code:"<<retCode;
        delete newFile;
        glfs_close(fd);
        delete []buff;
        return false;
      }
    }

    offset += read;
  }while(read);

  newFile->setNeedSync(false);//We have just created this file so it's upload flag false
  glfs_close(fd);
  delete []buff;
  //Add it to File system
  if(FileSystem::getInstance().createHierarchy(_getEvent->fullPathBuffer,false)==nullptr){
    LOG(ERROR)<<"Error in creating hierarchy for newly downloaded file:"<<newFile->getFullPath();
    delete newFile;
    return false;
  }
  if(!FileSystem::getInstance().addFile(newFile)){
    LOG(ERROR)<<"Error in adding newly downloaded file:"<<newFile->getFullPath();
    delete newFile;
    return false;
  }
  //Gone well
  return true;
}
int
main (int argc, char *argv[])
{
        glfs_t    *fs = NULL;
        glfs_t    *fs2 = NULL;
        glfs_t    *fs_tmp = NULL;
        glfs_t    *fs_tmp2 = NULL;
        int        ret = 0, i;
        glfs_fd_t *fd = NULL;
        glfs_fd_t *fd2 = NULL;
        glfs_fd_t *fd_tmp = NULL;
        glfs_fd_t *fd_tmp2 = NULL;
        char       readbuf[32];
        char      *filename = "file_tmp";
        char      *writebuf = NULL;
        char      *vol_id  = NULL;
        unsigned int       cnt = 1;
        struct    callback_arg cbk;
        char      *logfile = NULL;
        char      *volname = NULL;

        cbk.object = NULL;

        if (argc != 3) {
                fprintf (stderr, "Invalid argument\n");
                exit(1);
        }

        volname = argv[1];
        logfile = argv[2];

        fs = glfs_new (volname);
        if (!fs) {
                fprintf (stderr, "glfs_new: returned NULL\n");
                return -1;
        }

        ret = glfs_set_volfile_server (fs, "tcp", "localhost", 24007);
        LOG_ERR("glfs_set_volfile_server", ret);

        ret = glfs_set_logging (fs, logfile, 7);
        LOG_ERR("glfs_set_logging", ret);

        ret = glfs_init (fs);
        LOG_ERR("glfs_init", ret);

        fs2 = glfs_new (volname);
        if (!fs2) {
                fprintf (stderr, "glfs_new fs2: returned NULL\n");
                return 1;
        }

        ret = glfs_set_volfile_server (fs2, "tcp", "localhost", 24007);
        LOG_ERR("glfs_set_volfile_server-fs2", ret);

        ret = glfs_set_logging (fs2, logfile, 7);
        LOG_ERR("glfs_set_logging-fs2", ret);

        ret = glfs_init (fs2);
        LOG_ERR("glfs_init-fs2", ret);

        fd = glfs_creat(fs, filename, O_RDWR|O_SYNC, 0644);
        if (fd <= 0) {
                ret = -1;
                LOG_ERR ("glfs_creat", ret);
        }
        fprintf (stderr, "glfs-create fd - %d\n", fd);

        fd2 = glfs_open(fs2, filename, O_SYNC|O_RDWR|O_CREAT);
        if (fd2 <= 0) {
                ret = -1;
                LOG_ERR ("glfs_open-fs2", ret);
        }
        fprintf (stderr, "glfs-open fd2 - %d\n", fd2);

        do {
                if (cnt%2) {
                        fd_tmp = fd;
                        fs_tmp = fs;
                        fd_tmp2 = fd2;
                        fs_tmp2 = fs2;
                } else {
                        fd_tmp = fd2;
                        fs_tmp = fs2;
                        fd_tmp2 = fd;
                        fs_tmp2 = fs;
                }

                /* WRITE on fd_tmp */
                writebuf = malloc(10);
                if (writebuf) {
                        memcpy (writebuf, "abcd", 4);
                        ret = glfs_write (fd_tmp, writebuf, 4, 0);
                        if (ret <= 0)   {
                                ret = -1;
                                LOG_ERR ("glfs_write", ret);
                        } else {
                                fprintf (stderr,
                                         "glfs_write suceeded\n");
                        }
                        free(writebuf);
                } else {
                        fprintf (stderr,
                                 "Could not allocate writebuf\n");
                        return -1;
                }

                /* READ on fd_tmp2 */
                ret = glfs_lseek (fd_tmp2, 0, SEEK_SET);
                LOG_ERR ("glfs_lseek", ret);

                ret = glfs_pread (fd_tmp2, readbuf, 4, 0, 0);

                if (ret <= 0) {
                        ret = -1;
                        LOG_ERR ("glfs_pread", ret);
                } else {
                        fprintf (stderr, "glfs_read: %s\n", readbuf);
                }

                /* Open() fops seem to be not performed on server side until
                 * there are I/Os on that fd
                 */
                if (cnt > 2) {
                        ret = glfs_h_poll_upcall(fs_tmp, &cbk);
                        LOG_ERR ("glfs_h_poll_upcall", ret);
                        if (cbk.object) {
                                fprintf (stderr, " upcall event type - %d,"
                                                 " flags - %d, expire_time_attr - %d\n" ,
                                         cbk.reason, cbk.flags, cbk.expire_time_attr);
                        } else {
                                fprintf (stderr,
                                         "Dint receive upcall notify event");
                                ret = -1;
                                goto err;
                        }
                }

                sleep(5);
        } while (++cnt < 5);

err:
        glfs_close(fd);
        LOG_ERR ("glfs_close", ret);

        glfs_close(fd2);
        LOG_ERR ("glfs_close-fd2", ret);

out:
        if (fs) {
                ret = glfs_fini(fs);
                fprintf (stderr, "glfs_fini(fs) returned %d \n", ret);
        }

        if (fs2) {
                ret = glfs_fini(fs2);
                fprintf (stderr, "glfs_fini(fs2) returned %d \n", ret);
        }

        if (ret)
                exit(1);
        exit(0);
}