Beispiel #1
0
int keydiv_dtable::create(int dfd, const char * name, const params & config, dtype::ctype key_type)
{
	int r, kdd_dfd, meta;
	divider_list dividers;
	const dtable_factory * base;
	params base_config;
	
	kddtable_header header;
	header.magic = KDDTABLE_MAGIC;
	header.version = KDDTABLE_VERSION;
	switch(key_type)
	{
		case dtype::UINT32:
			header.key_type = 1;
			r = load_dividers<int, uint32_t>(config, 0, &dividers);
			break;
		case dtype::DOUBLE:
			header.key_type = 2;
			r = load_dividers<float, double>(config, 0, &dividers);
			break;
		case dtype::STRING:
			header.key_type = 3;
			r = load_dividers<istr, istr>(config, 0, &dividers);
			break;
		case dtype::BLOB:
			header.key_type = 4;
			r = load_dividers<blob, blob>(config, 0, &dividers, true);
			break;
		default:
			return -EINVAL;
	}
	header.dt_count = dividers.size() + 1;
	/* make sure we don't overflow the header field */
	if(header.dt_count != dividers.size() + 1)
		return -EINVAL;
	
	base = dtable_factory::lookup(config, "base");
	if(!base)
		return -EINVAL;
	if(!config.get("base_config", &base_config, params()))
		return -EINVAL;
	
	r = mkdirat(dfd, name, 0755);
	if(r < 0)
		return r;
	kdd_dfd = openat(dfd, name, O_RDONLY);
	if(kdd_dfd < 0)
	{
		unlinkat(dfd, name, AT_REMOVEDIR);
		return kdd_dfd;
	}
	
	for(uint32_t i = 0; i < header.dt_count; i++)
	{
		char name[32];
		sprintf(name, "kdd_data.%u", i);
		r = base->create(kdd_dfd, name, base_config, key_type);
		if(r < 0)
			goto fail;
	}
	
	meta = openat(kdd_dfd, "kdd_meta", O_WRONLY | O_CREAT, 0644);
	if(meta < 0)
	{
		r = meta;
		goto fail;
	}
	r = pwrite(meta, &header, sizeof(header), 0);
	close(meta);
	if(r != sizeof(header))
		goto fail;
	close(kdd_dfd);
	return 0;
	
fail:
	close(kdd_dfd);
	util::rm_r(dfd, name);
	return (r < 0) ? r : -1;
}
Beispiel #2
0
void
runtime·badsignal(void)
{
	runtime·pwrite(2, badsignal, sizeof badsignal - 1, -1LL);
	runtime·exits(badsignal);
}
Beispiel #3
0
int
write_filemarks(uint32_t count, uint8_t *sam_stat)
{
	uint32_t blk_number;
	uint64_t data_offset;
	ssize_t nwrite;

	if (!tape_loaded(sam_stat)) {
		return -1;
	}

	/* Applications assume that writing a filemark (even writing zero
	   filemarks) will force-flush any data buffered in the drive to media
	   so that after the write-filemarks call returns there is no
	   possibility that any data previously written could be lost due
	   to a power hit.  Provide a similar guarantee here.
	*/

	if (count == 0) {
		MHVTL_DBG(2, "Flushing data - 0 filemarks written");
		fsync(datafile);
		fsync(indxfile);
		fsync(metafile);

		return 0;
	}

	if (check_for_overwrite(sam_stat)) {
		return -1;
	}

	/* Preserve existing raw_pos data we need, then clear raw_pos and
	   fill it in with new data.
	*/

	blk_number = raw_pos.hdr.blk_number;
	data_offset = raw_pos.data_offset;

	memset(&raw_pos, 0, sizeof(raw_pos));

	raw_pos.data_offset = data_offset;

	raw_pos.hdr.blk_type = B_FILEMARK;	/* Header type */
	raw_pos.hdr.blk_flags = 0;
	raw_pos.hdr.blk_number = blk_number;
	raw_pos.hdr.blk_size = 0;
	raw_pos.hdr.disk_blk_size = 0;

	/* Now write out one header per filemark. */

	for ( ; count > 0; count--, blk_number++) {
		raw_pos.hdr.blk_number = blk_number;

		MHVTL_DBG(3, "Writing filemark: block %d", blk_number);

		nwrite = pwrite(indxfile, &raw_pos, sizeof(raw_pos),
			blk_number * sizeof(raw_pos));
		if (nwrite != sizeof(raw_pos)) {
			mkSenseBuf(MEDIUM_ERROR, E_WRITE_ERROR, sam_stat);
			MHVTL_ERR("Index file write failure,"
					" pos: %" PRId64 ": %s",
				(uint64_t)blk_number * sizeof(raw_pos),
				strerror(errno));
			return -1;
		}
		add_filemark(blk_number);
	}

	/* Provide the force-flush guarantee. */

	fsync(datafile);
	fsync(indxfile);
	fsync(metafile);

	return mkEODHeader(blk_number, data_offset);
}
Beispiel #4
0
int journal::init_crfd(const istr & commit_name)
{
	int r;
	off_t filesize, nextcr = 0;
	struct timeval settime[2] = {{0, 0}, {0, 0}};
	commit_record zero = {0, 0}, cr;
	
	/* Only append more empy records to the commit file if it is already open
	 * otherwise create a new commit record file. */
	if(crfd < 0)
	{
		istr cname = commit_name;
		if(!cname)
		{
			char commit_number[16];
			snprintf(commit_number, sizeof(commit_number), "%d", commits);
			cname = path + J_COMMIT_EXT + commit_number;
		}
		crfd = openat(dfd, cname, O_CREAT | O_RDWR, 0644);
		if(crfd < 0)
			return -1;
	}

	filesize = lseek(crfd, 0, SEEK_END);
	util::memset(zero.checksum, 0, sizeof(zero.checksum));
	/* find out where the last good commit record is */
	while((r = pread(crfd, &cr, sizeof(cr), nextcr)))
	{
		if(r < (int) sizeof(cr))
			break;
		if(!cr.offset && !cr.length && !memcmp(&cr.checksum, &zero.checksum, J_CHECKSUM_LEN))
			break;
		nextcr += r;
	}
	
	/* We set the mtime for the commit record file in the future to prevent
	 * the inode metadata being updated with every write - this uses a hack
	 * in Featherstitch to optimize for patchgroups. */
	
	/* atime */
	settime[0].tv_sec = time(NULL);
	/* mtime is current time plus 10 years, or the end of 31-bit time, whichever is later */
	settime[1].tv_sec = settime[0].tv_sec + 315360000;
	if(settime[1].tv_sec < 2147483647)
		settime[1].tv_sec = 2147483647;
	if((r = futimes(crfd, settime)) < 0)
		goto error;
	
	if(filesize < (nextcr + (int) sizeof(cr)))
	{
		/* zero out the rest of the file J_ADD_N_COMMITS records at a time */
		uint8_t zbuffer[1000 * sizeof(zero)];
		util::memset(zbuffer, 0, sizeof(zbuffer));
		while((filesize - nextcr) < J_ADD_N_COMMITS * (int) sizeof(zbuffer))
		{
			r = pwrite(crfd, zbuffer, sizeof(zbuffer), filesize);
			if(r <= 0)
				goto error;
			filesize += r;
		}
		/* necessary? */
		fsync(crfd);
	}
	
	return nextcr;
	
error:
	if(crfd > 0)
	{
		close(crfd);
		crfd = -1;
	}
	return r < 0 ? r : -1;
}
Beispiel #5
0
int32
runtime·write(int32 fd, void *buf, int32 nbytes)
{
	return runtime·pwrite(fd, buf, nbytes, -1LL);
}
Beispiel #6
0
void masterconn_download_data(masterconn *eptr,const uint8_t *data,uint32_t length) {
    uint64_t offset;
    uint32_t leng;
    uint32_t crc;
    ssize_t ret;
    if (eptr->metafd<0) {
        syslog(LOG_NOTICE,"MATOML_DOWNLOAD_DATA - file not opened");
        eptr->mode = KILL;
        return;
    }
    if (length<16) {
        syslog(LOG_NOTICE,"MATOML_DOWNLOAD_DATA - wrong size (%"PRIu32"/16+data)",length);
        eptr->mode = KILL;
        return;
    }
    passert(data);
    offset = get64bit(&data);
    leng = get32bit(&data);
    crc = get32bit(&data);
    if (leng+16!=length) {
        syslog(LOG_NOTICE,"MATOML_DOWNLOAD_DATA - wrong size (%"PRIu32"/16+%"PRIu32")",length,leng);
        eptr->mode = KILL;
        return;
    }
    if (offset!=eptr->dloffset) {
        syslog(LOG_NOTICE,"MATOML_DOWNLOAD_DATA - unexpected file offset (%"PRIu64"/%"PRIu64")",offset,eptr->dloffset);
        eptr->mode = KILL;
        return;
    }
    if (offset+leng>eptr->filesize) {
        syslog(LOG_NOTICE,"MATOML_DOWNLOAD_DATA - unexpected file size (%"PRIu64"/%"PRIu64")",offset+leng,eptr->filesize);
        eptr->mode = KILL;
        return;
    }
#ifdef HAVE_PWRITE
    ret = pwrite(eptr->metafd,data,leng,offset);
#else /* HAVE_PWRITE */
    lseek(eptr->metafd,offset,SEEK_SET);
    ret = write(eptr->metafd,data,leng);
#endif /* HAVE_PWRITE */
    if (ret!=(ssize_t)leng) {
        mfs_errlog_silent(LOG_NOTICE,"error writing metafile");
        if (eptr->downloadretrycnt>=5) {
            masterconn_download_end(eptr);
        } else {
            eptr->downloadretrycnt++;
            masterconn_download_next(eptr);
        }
        return;
    }
    if (crc!=mycrc32(0,data,leng)) {
        syslog(LOG_NOTICE,"metafile data crc error");
        if (eptr->downloadretrycnt>=5) {
            masterconn_download_end(eptr);
        } else {
            eptr->downloadretrycnt++;
            masterconn_download_next(eptr);
        }
        return;
    }
    /*if (fsync(eptr->metafd)<0) {
      mfs_errlog_silent(LOG_NOTICE,"error syncing metafile");
      if (eptr->downloadretrycnt>=5) {
      masterconn_download_end(eptr);
      } else {
      eptr->downloadretrycnt++;
      masterconn_download_next(eptr);
      }
      return;
      }*/
    eptr->dloffset+=leng;
    eptr->downloadretrycnt=0;
    masterconn_download_next(eptr);
}
Beispiel #7
0
int nandwrite_mlc(char *image_path, int dev, loff_t mtdoffset,
                  struct mtd_info_user *meminfo)
{
    int cnt = 0;
    int image = -1;
    int imglen = 0, pagesize, blocksize, badblocks = 0;
    unsigned int offs;
    int ret;
    bool read_next = true;
    unsigned char *writebuf = NULL;
    int retCode = 0;

    uint32_t nblock, npage, skip;

    int total_blocks, pagesperblock, blockskip;

    image = open(image_path, O_RDONLY);
    if (image == -1) {
        perror("open error");
        return -1;
    }

    imglen = lseek(image, 0, SEEK_END);
    lseek (image, 0, SEEK_SET);

    pagesize = meminfo->writesize;
    blocksize = meminfo->erasesize;
    // Check, if length fits into device
    total_blocks = meminfo->size / blocksize;
    pagesperblock = blocksize / pagesize;
    blockskip = (MLC_MAX_IMG_SIZ / pagesize + 1) * CONFIG_PAGE_REPLICATION * CONFIG_BLOCK_REPLICATION / pagesperblock;

    if ((blockskip * 2) > total_blocks || imglen > MLC_MAX_IMG_SIZ) {
        show_nand_info(stderr, meminfo);
        perror("Assigned max image size does not fit into device");
        retCode = -2;
        goto closeall;
    }

    // Allocate a buffer big enough to contain all the data for one page
    writebuf = (unsigned char*)MALLOC(pagesize);
    erase_buffer(writebuf, pagesize);

    while ((imglen > 0)	&& (mtdoffset < meminfo->size))
    {
        int readlen = pagesize;
        int tinycnt = 0;

        skip = 0;
        badblocks = 0;

        if (read_next) {
            erase_buffer(writebuf, readlen);
            /* Read up to one page data */
            while (tinycnt < readlen) {
                cnt = read(image, writebuf + tinycnt, readlen - tinycnt);
                if (cnt == 0) { /* EOF */
                    break;
                } else if (cnt < 0) {
                    perror ("File I/O error on input");
                    retCode = -3;
                    goto closeall;
                }
                tinycnt += cnt;
            }
            imglen -= tinycnt;
            read_next = false;
        }

        for (nblock = 0; nblock < CONFIG_BLOCK_REPLICATION; nblock++)
        {
//			offs = mtdoffset + nblock * blocksize + skip * blocksize;
            offs = mtdoffset + skip * blocksize;
            // skip bad blocks
            ret = nand_block_isbad(dev, offs);
            if (ret < 0) {
                retCode = -5;
                goto closeall;
            } else if (ret == 1) {
#if 0
                loff_t checkblock;
                char have_copy = 0;

                if (!quiet) {
                    fprintf(stderr, "Skip bad block at address 0x%x, (block %u)\n",
                            offs, offs / blocksize);
                }

                badblocks++;
                // make sure we have at least one copy
                for (checkblock = 0; checkblock < CONFIG_BLOCK_REPLICATION; checkblock++)
                {
                    offs = mtdoffset + checkblock * blocksize + skip * blocksize;
                    ret = nand_block_isbad(dev, offs);
                    if (ret < 0) goto closeall;
                    else if (ret == 0) {
                        have_copy = 1;
                        break;
                    }
                }
                if (!have_copy)
                {
                    printf("Too many bad blocks\n");
                    goto closeall;
                }
                skip += blockskip;
                continue;
#else
                if (!quiet) {
                    uint32_t block_mask = meminfo->erasesize - 1;
                    printf("Bad block 0x%x\n", (offs & (~block_mask)));
                }
                if (++badblocks >= CONFIG_BLOCK_REPLICATION) {
                    printf("Too many bad blocks\n");
                    retCode = -4;
                    goto closeall;
                }
                skip += blockskip;
                continue;
#endif
            }

            for (npage = 0; npage < CONFIG_PAGE_REPLICATION; npage++)
            {
                offs = mtdoffset + npage * pagesize + skip * blocksize;
                /* Write out the Page data */
                if (pwrite(dev, writebuf, pagesize, offs) != pagesize) {
                    fprintf(stderr, "Bad page for copy %u of block %x for address %x\n",
                            npage, nblock, offs);
                }
            }
            skip += blockskip;
            read_next = true;
        } // for nblock
        mtdoffset += pagesize * CONFIG_PAGE_REPLICATION;
    } // while (imglen > 0)

closeall:
    if (writebuf) {
        free(writebuf);
    }

    close(image);

    if (imglen > 0)
    {
        fprintf(stderr, "Data was only partially written due to error\n");
    }

    return retCode;
}
Beispiel #8
0
/* write data to a process memory space */
int write_process_memory( struct process *process, client_ptr_t ptr, data_size_t size, const char *src )
{
    struct thread *thread = get_ptrace_thread( process );
    int ret = 0;
    long data = 0;
    data_size_t len;
    long *addr;
    unsigned long first_mask, first_offset, last_mask, last_offset;

    if (!thread) return 0;

    if ((unsigned long)ptr != ptr)
    {
        set_error( STATUS_ACCESS_DENIED );
        return 0;
    }

    /* compute the mask for the first long */
    first_mask = ~0;
    first_offset = ptr % sizeof(long);
    memset( &first_mask, 0, first_offset );

    /* compute the mask for the last long */
    last_offset = (size + first_offset) % sizeof(long);
    if (!last_offset) last_offset = sizeof(long);
    last_mask = 0;
    memset( &last_mask, 0xff, last_offset );

    addr = (long *)(unsigned long)(ptr - first_offset);
    len = (size + first_offset + sizeof(long) - 1) / sizeof(long);

    if (suspend_for_ptrace( thread ))
    {
        if (!check_process_write_access( thread, addr, len ))
        {
            set_error( STATUS_ACCESS_DENIED );
            goto done;
        }

        if (len > 3)
        {
            char procmem[24];
            int fd;

            sprintf( procmem, "/proc/%u/mem", process->unix_pid );
            if ((fd = open( procmem, O_WRONLY )) != -1)
            {
                ssize_t r = pwrite( fd, src, size, ptr );
                close( fd );
                if (r == size)
                {
                    ret = 1;
                    goto done;
                }
            }
        }

        /* first word is special */
        if (len > 1)
        {
            memcpy( (char *)&data + first_offset, src, sizeof(long) - first_offset );
            src += sizeof(long) - first_offset;
            if (write_thread_long( thread, addr++, data, first_mask ) == -1) goto done;
            first_offset = 0;
            len--;
        }
        else last_mask &= first_mask;

        while (len > 1)
        {
            memcpy( &data, src, sizeof(long) );
            src += sizeof(long);
            if (write_thread_long( thread, addr++, data, ~0ul ) == -1) goto done;
            len--;
        }

        /* last word is special too */
        memcpy( (char *)&data + first_offset, src, last_offset - first_offset );
        if (write_thread_long( thread, addr, data, last_mask ) == -1) goto done;
        ret = 1;

    done:
        resume_after_ptrace( thread );
    }
    return ret;
}
Beispiel #9
0
static int xmp_write(const char *path, const char *buf, size_t size,
		     off_t offset, struct fuse_file_info *fi)
{
	(void) fi;
	(void) offset;

	int res=0;
	int action = COPY;

	ssize_t vsize = 0;
	char *tval = NULL;

	char fpath[PATH_MAX];
	xmp_getfullpath(fpath, path);

	vsize = getxattr(fpath, XATRR_ENCRYPTED_FLAG, NULL, 0);
	tval = malloc(sizeof(*tval)*(vsize));
	vsize = getxattr(fpath, XATRR_ENCRYPTED_FLAG, tval, vsize);

	if (vsize < 0 || memcmp(tval, "false", 5) == 0){
		if(errno == ENODATA){
			fprintf(stderr, "Encryption flag not set, file cannot be read.\n");
		}
		fprintf(stderr, "File unencrypted, reading...\n");
	}
	/* If the attribute exists and is true get size of decrypted file */
	else if (memcmp(tval, "true", 4) == 0){
		fprintf(stderr, "File encrypted, decrypting...\n");
		action = DECRYPT;
	}


	/* If the file to be written to is encrypted */
	if (action == DECRYPT){
		
		FILE *fd = fopen(fpath, "rb+");
		const char *tpath = ftemp(fpath, ".write");
		FILE *dfd = fopen(tpath, "wb+");

		fseek(fd, 0, SEEK_END);
		fseek(fd, 0, SEEK_SET);

		if(!do_crypt(fd, dfd, DECRYPT, ENCFS_DATA->passkey)){
			fprintf(stderr, "Decryption failed, error code: %d\n", res);
    	}

    	fseek(fd, 0, SEEK_SET);

    	res = fwrite(buf, 1, size, dfd);
    	if (res == -1)
		res = -errno;

		fseek(dfd, 0, SEEK_SET);

		if(!do_crypt(dfd, fd, ENCRYPT, ENCFS_DATA->passkey)){
			fprintf(stderr, "Encryption failed, error code: %d\n", res);
		}

		fclose(fd);
		fclose(dfd);
		remove(tpath);
	}
	/* If the file to be written to is unencrypted */
	else if (action == COPY){
		int fd1;
		fprintf(stderr, "File unencrypted, reading...\n");

		fd1 = open(fpath, O_WRONLY);
		if (fd1 == -1)
			return -errno;

		res = pwrite(fd1, buf, size, offset);
		if (res == -1)
			res = -errno;

		close(fd1);
   	}
   	
	free(tval);
	return res;
}
Beispiel #10
0
void ADIOI_XFS_WriteContig(ADIO_File fd, void *buf, int count, 
                     MPI_Datatype datatype, int file_ptr_type,
		     ADIO_Offset offset, ADIO_Status *status, int *error_code)
{
    int err=-1, datatype_size, len, diff, size, nbytes;
    void *newbuf;
    static char myname[] = "ADIOI_XFS_WRITECONTIG";

    MPI_Type_size(datatype, &datatype_size);
    len = datatype_size * count;

    fd->fp_sys_posn = -1; /* set it to null, since we are using pwrite */

    if (file_ptr_type == ADIO_INDIVIDUAL) offset = fd->fp_ind;

    if (!(fd->direct_write))     /* direct I/O not enabled */
	err = pwrite(fd->fd_sys, buf, len, offset);
    else {       /* direct I/O enabled */

	/* (1) if mem_aligned && file_aligned 
                    use direct I/O to write up to correct io_size
                    use buffered I/O for remaining  */

	if (!(((long) buf) % fd->d_mem) && !(offset % fd->d_miniosz)) 
	    ADIOI_XFS_Aligned_Mem_File_Write(fd, buf, len, offset, &err);

        /* (2) if !file_aligned
                    use buffered I/O to write up to file_aligned
                    At that point, if still mem_aligned, use (1)
   		        else copy into aligned buf and then use (1) */
	else if (offset % fd->d_miniosz) {
	    diff = fd->d_miniosz - (offset % fd->d_miniosz);
	    diff = ADIOI_MIN(diff, len);
	    nbytes = pwrite(fd->fd_sys, buf, diff, offset);

	    buf = ((char *) buf) + diff;
	    offset += diff;
	    size = len - diff;
	    if (!(((long) buf) % fd->d_mem)) {
		ADIOI_XFS_Aligned_Mem_File_Write(fd, buf, size, offset, &err);
		nbytes += err;
	    }
	    else {
		newbuf = (void *) memalign(XFS_MEMALIGN, size);
		if (newbuf) {
		    memcpy(newbuf, buf, size);
		    ADIOI_XFS_Aligned_Mem_File_Write(fd, newbuf, size, offset, &err);
		    nbytes += err;
		    free(newbuf);
		}
		else nbytes += pwrite(fd->fd_sys, buf, size, offset);
	    }
	    err = nbytes;
	}

        /* (3) if !mem_aligned && file_aligned
    	            copy into aligned buf, then use (1)  */
	else {
	    newbuf = (void *) memalign(XFS_MEMALIGN, len);
	    if (newbuf) {
		memcpy(newbuf, buf, len);
		ADIOI_XFS_Aligned_Mem_File_Write(fd, newbuf, len, offset, &err);
		free(newbuf);
	    }
	    else err = pwrite(fd->fd_sys, buf, len, offset);
	}
    }

    if (file_ptr_type == ADIO_INDIVIDUAL) fd->fp_ind += err;

#ifdef HAVE_STATUS_SET_BYTES
    if (err != -1) MPIR_Status_set_bytes(status, datatype, err);
#endif

    if (err == -1) {
	*error_code = MPIO_Err_create_code(MPI_SUCCESS, MPIR_ERR_RECOVERABLE,
					   myname, __LINE__, MPI_ERR_IO, "**io",
					   "**io %s", strerror(errno));
    }
    else *error_code = MPI_SUCCESS;
}
Beispiel #11
0
int main(int argc, char **argv)
{
	unsigned long startofs = 0, part_size = 0;
	unsigned long ezones = 0, ezone = 0, bad_zones = 0;
	unsigned char unit_factor = 0xFF;

	long MediaUnit1 = -1, MediaUnit2 = -1;
	unsigned char oobbuf[16];
	struct mtd_oob_buf oob = {0, 16, oobbuf};

	printf("$Id: nftl_format.c,v 1.1.1.1 2006-07-11 09:31:28 andy Exp $\n");

	if (argc < 2) {
		fprintf(stderr, "Usage: %s <mtddevice> [<start offset> [<size>]]\n",
			argv[0]);
		return 1;
	}

	if (argc > 2) {
		startofs = strtoul(argv[2], NULL, 0);
	}
	if (argc > 3) {
		part_size = strtoul(argv[3], NULL, 0);
	}

	// Open and size the device
	if ((fd = open(argv[1], O_RDWR)) < 0) {
		perror("Open flash device");
		return 1;
	}

	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
		perror("ioctl(MEMGETINFO)");
		close(fd);
		return 1;
	}

	switch (meminfo.erasesize) {
	case 0x1000:
	case 0x2000:
	case 0x4000:
		break;
	default:
		printf("Unrecognized Erase size, 0x%x - I'm confused\n", 
			meminfo.erasesize);
		close(fd);
		return 1;
	}
	writebuf[0] = malloc(meminfo.erasesize * 5);
	if (!writebuf[0]) {
		printf("Malloc failed\n");
		close(fd);
		return 1;
	}
	writebuf[1] = writebuf[0] + meminfo.erasesize;
	writebuf[2] = writebuf[1] + meminfo.erasesize;
	writebuf[3] = writebuf[2] + meminfo.erasesize;
	readbuf = writebuf[3] + meminfo.erasesize;
	memset(writebuf[0], 0xff, meminfo.erasesize);
	memset(writebuf[1], 0x00, meminfo.erasesize);
	memset(writebuf[2], 0x5a, meminfo.erasesize);
	memset(writebuf[3], 0xa5, meminfo.erasesize);
	memset(BadUnitTable, ZONE_GOOD, MAX_ERASE_ZONES);

	if (part_size == 0 || (part_size > meminfo.size - startofs))
		/* the user doest not or incorrectly specify NFTL partition size */ 
		part_size = meminfo.size - startofs;

	erase.length = meminfo.erasesize;
	ezones = part_size / meminfo.erasesize;

	if (ezones > MAX_ERASE_ZONES) {
		/* Ought to change the UnitSizeFactor. But later. */
		part_size = meminfo.erasesize * MAX_ERASE_ZONES;
		ezones = MAX_ERASE_ZONES;
		unit_factor = 0xFF;
	}

	/* Phase 1. Erasing and checking each erase zones in the NFTL partition.
	   N.B. Erase Zones not used by the NFTL partition are untouched and marked ZONE_GOOD */
	printf("Phase 1. Checking and erasing Erase Zones from 0x%08lx to 0x%08lx\n",
	       startofs, startofs + part_size);
	for (ezone = startofs / meminfo.erasesize;
	     ezone < (ezones + startofs / meminfo.erasesize); ezone++) {
		if ((BadUnitTable[ezone] = erase_block(ezone)) == ZONE_GOOD) {
			if (MediaUnit1 == -1) {
				MediaUnit1 = ezone;
			} else if (MediaUnit2 == -1) {
				MediaUnit2 = ezone;
			}
		} else {
			bad_zones++;
		}
	}
	printf("\n");

	/* N.B. from dump of M-System original chips, NumEraseUnits counts the 2 Erase Unit used
	   by MediaHeader and the FirstPhysicalEUN starts from the MediaHeader */
	NFTLhdr = (struct NFTLMediaHeader *) (writebuf[0]);
	strcpy(NFTLhdr->DataOrgID, "ANAND");
	NFTLhdr->NumEraseUnits = cpu_to_le16(part_size / meminfo.erasesize);
	NFTLhdr->FirstPhysicalEUN = cpu_to_le16(MediaUnit1);
	/* N.B. we reserve 2 more Erase Units for "folding" of Virtual Unit Chain */
	NFTLhdr->FormattedSize = cpu_to_le32(part_size - ( (5+bad_zones) * meminfo.erasesize));
	NFTLhdr->UnitSizeFactor = unit_factor;

	/* Phase 2. Writing NFTL Media Headers and Bad Unit Table */
	printf("Phase 2.a Writing NFTL Media Header and Bad Unit Table\n");
	pwrite(fd, writebuf[0], 512, MediaUnit1 * meminfo.erasesize);
	for (ezone = 0; ezone < (meminfo.size / meminfo.erasesize); ezone += 512) {
		pwrite(fd, BadUnitTable + ezone, 512,
		       (MediaUnit1 * meminfo.erasesize) + 512 * (1 + ezone / 512));
	}
#if 0
	printf("  MediaHeader contents:\n");
	printf("    NumEraseUnits: %d\n", le16_to_cpu(NFTLhdr->NumEraseUnits));
	printf("    FirstPhysicalEUN: %d\n", le16_to_cpu(NFTLhdr->FirstPhysicalEUN));
	printf("    FormattedSize: %d (%d sectors)\n", le32_to_cpu(NFTLhdr->FormattedSize),
	       le32_to_cpu(NFTLhdr->FormattedSize)/512);
#endif
	printf("Phase 2.b Writing Spare NFTL Media Header and Spare Bad Unit Table\n");
	pwrite(fd, writebuf[0], 512, MediaUnit2 * meminfo.erasesize);
	for (ezone = 0; ezone < (meminfo.size / meminfo.erasesize); ezone += 512) {
		pwrite(fd, BadUnitTable + ezone, 512,
		       (MediaUnit2 * meminfo.erasesize) + 512 * (1 + ezone / 512));
	}

	/* UCI #1 for newly erased Erase Unit */
	memset(oobbuf, 0xff, 16);
	oobbuf[11] = oobbuf[10] = oobbuf[9] = 0;
	oobbuf[8]  = 0x03;
	oobbuf[12] = oobbuf[14] = 0x69;
	oobbuf[13] = oobbuf[15] = 0x3c;

	/* N.B. The Media Header and Bad Erase Unit Table are considered as Free Erase Unit
	   by M-System i.e. their Virtual Unit Number == 0xFFFF in the Unit Control Information #0,
	   but their Block Status is BLOCK_USED (0x5555) in their Block Control Information */
	/* Phase 3. Writing Unit Control Information for each Erase Unit */
	printf("Phase 3. Writing Unit Control Information to each Erase Unit\n");
	for (ezone = cpu_to_le16(NFTLhdr->FirstPhysicalEUN);
	     ezone < (ezones + startofs / meminfo.erasesize); ezone++) {
		/* write UCI #1 to each Erase Unit */
		if (BadUnitTable[ezone] != ZONE_GOOD)
			continue;
		oob.start = (ezone * meminfo.erasesize) + 512;
		if (ioctl(fd, MEMWRITEOOB, &oob))
			printf("MEMWRITEOOB at %lx: %s\n", (unsigned long)oob.start, strerror(errno));
	}

	exit(0);
}
Beispiel #12
0
static int xmp_read(const char *path, char *buf, size_t size, off_t offset,
		    struct fuse_file_info *fi)
{
	int fd;
	ino_t ino;
	int res = 0;
	static int cnt = 0;

	struct loop_file_info *info
		= (struct loop_file_info *) (unsigned long) fi->fh;

	fd = info->fd;
	ino = info->ino;

	if (fd == -1)
		return -errno;

	if (size > max_block_size) {
		return -ENOMEM;
	}

	if (fp_sync) {
		fprintf(fp_sync, "cnt %d read %s inode %llu size %lu off %ld\n", cnt, path, (unsigned long long) ino, size, offset);
		fflush(fp_sync);
		cnt++;
	}

	/* fill in the request */
	sem_t sem;
	sem_init(&sem, 0, 0);
	struct cache_entry response;

	struct elm_read_req req = {
		.fd = fd,
		.ino = ino,
		.size = size,
		.offset = offset,
		.sem = &sem,
		.refcnt = 1,
		.p_response = &response
	};

	/* check for already cached */
	pthread_mutex_lock(&cache_lock);

	int get_rc;

	struct cache_entry *result;

	get_rc = cache->cache_lookup(cache,
				     &req,
				     &result);

	if (get_rc == 0 && result->rc > 0) {
		memcpy(buf, result->data, result->rc);

		fprintf(fp_sync,
			"Found record already cached "
			"ref = %d data = %p rc = %ld\n",
			*result->refcnt,
			result->data, 
			result->rc);

		fflush(fp_sync);

		if (result->rc > 0) {
			cache_hit_bytes += result->rc;
		}

		cache_report(fp_sync, cache_hit_bytes, cache_miss_bytes);

		res = result->rc;
		pthread_mutex_unlock(&cache_lock);
	}
	else if (get_rc == -1) {
		pthread_mutex_unlock(&cache_lock);
		return -EIO;
	}
	else {
		pthread_mutex_unlock(&cache_lock);
		pthread_mutex_lock(&req_queue_lock);

		if (circ_enq(&req_queue, &req)) {
			return -EBUSY;
		}
	}

	int i;

	struct elm_read_req prefetch_req = req;

	for (i=0; i<prefetch_aggressiveness; i++) {

		prefetch_req.offset += prefetch_req.size;
		prefetch_req.sem = NULL;
		prefetch_req.refcnt = 0;
		prefetch_req.p_response = NULL;

		if (prefetch_req.offset + prefetch_req.size
		    > info->st_buf.st_size)
		{
			/* XXX */
			break;
		}


		/* Prefetch requests are advisory only. 
		 * If the queue is full, it may not be an error.
		 */

		if (circ_enq(&req_queue, &prefetch_req)) {
			break;
		}
	}

	int q_cnt = circ_cnt(&req_queue);

	fprintf(fp_sync, "req_queue_cnt = %d\n", q_cnt);

	fflush(fp_sync);

	pthread_cond_signal(&req_condition);

	pthread_mutex_unlock(&req_queue_lock);

	if (get_rc == 0) {
		/* If it was already in cache no need to wait.
		 */
		return res;
	}

	/* Wait for the response */

	sem_wait(&sem);

	fprintf(fp_sync, "got response\n");
	fflush(fp_sync);

	pthread_mutex_lock(&cache_lock);

	/* Check the response */

	result = &response;

	if (result->rc >= 0) {
		memcpy(buf,
		       result->data,
		       result->rc);
	}

	res = result->rc;

	if (*result->refcnt > 0) {
		*result->refcnt -= 1;
	}

	cache_report(fp_sync, cache_hit_bytes, cache_miss_bytes);

	pthread_mutex_unlock(&cache_lock);

	sem_destroy(&sem);

	return res;
}

static int xmp_write(const char *path, const char *buf, size_t size,
		     off_t offset, struct fuse_file_info *fi)
{
	int fd;
	int res;

	(void) fi;
	fd = open(path, O_WRONLY);
	if (fd == -1)
		return -errno;

	res = pwrite(fd, buf, size, offset);
	if (res == -1)
		res = -errno;

	close(fd);
	return res;
}
Beispiel #13
0
static int cfs_write(const char *path, const char *buf, size_t length, off_t offset, struct fuse_file_info *info)
{
    update_dir_cache(path, offset + length, 0, 0);
    return pwrite(((openfile *)(uintptr_t)info->fh)->fd, buf, length, offset);
}
Beispiel #14
0
int resize_gpt_partition(const char *devname, __u64 new_size)
{
	unsigned char buf[SECTOR_SIZE*GPT_DATA_SIZE]; // LBA1 header, LBA2-34 partition entry
	int fd;
	int part, ret;
	struct GptHeader *pt;
	struct GptEntry *pe;
	__u32 pt_crc32, pe_crc32, orig_crc;
	off_t size;
	__u64 tmp;

	ret = has_partition(devname, &part);
	if (ret)
		return ret;

	if (!part)
		return 0;

	ret = ploop_get_size(devname, &size);
	if (ret)
		return ret;

	// Resize up to max available space
	if (new_size == 0)
		new_size = size;

	if (new_size > size) {
		ploop_err(0, "Unable to resize GPT partition:"
				" incorrect parameter new_size=%llu size=%lu",
				new_size, (long)size);
		return SYSEXIT_PARAM;
	}

	ploop_log(1, "Resizing GPT partition to %ld", (long)new_size);
	fd = open(devname, O_RDWR);
	if (fd == -1) {
		ploop_err(errno, "open %s", devname);
		return SYSEXIT_OPEN;
	}
	// skip LBA0 Protective MBR
	ret = pread(fd, buf, sizeof(buf), SECTOR_SIZE);
	if (ret == -1) {
		ploop_err(errno, "pread %s", devname);
		goto err;
	}
	pt = (struct GptHeader *)buf;
	pe = (struct GptEntry *)(&buf[SECTOR_SIZE * GPT_HEADER_SIZE]);

	// Validate crc
	orig_crc = pt->header_crc32;
	pt->header_crc32 = 0;
	pt_crc32 = ploop_crc32((unsigned char *)pt, pt->header_size);
	if (pt_crc32 != orig_crc) {
		ploop_err(0, "GPT validation failed orig crc %x != %x",
				orig_crc, pt_crc32);
		ret = -1;
		goto err;
	}
	// change GPT header
	pt->alternate_lba = new_size - 1;
	pt->last_usable_lba = new_size - GPT_DATA_SIZE - 1;
	pe->ending_lba = (pt->last_usable_lba >> 3 << 3) - 1;

	// Recalculate crc32
	pe_crc32 = ploop_crc32((unsigned char *)pe, SECTOR_SIZE * GPT_PT_ENTRY_SIZE);
	pt->partition_entry_array_crc32 = pe_crc32;

	pt->header_crc32 = 0;
	pt_crc32 = ploop_crc32((unsigned char *)pt, pt->header_size);
	pt->header_crc32 = pt_crc32;

	ploop_log(0, "Storing GPT");
	ret = pwrite(fd, pt, SECTOR_SIZE * GPT_DATA_SIZE, SECTOR_SIZE);
	if (ret == -1) {
		ploop_err(errno, "Failed to store primary GPT %s", devname);
		goto err;
	}
	ret = fsync(fd);
	if (ret) {
		ploop_err(errno, "Can't fsync %s", devname);
		ret = SYSEXIT_FSYNC;
		goto err;
	}

	// Store secondary GPT entries
	tmp = pt->my_lba;
	pt->my_lba = pt->alternate_lba;
	pt->alternate_lba = tmp;
	pt->partition_entry_lba = pt->last_usable_lba + 1;

	// Recalculate crc32
	pt->header_crc32 = 0;
	pt_crc32 = ploop_crc32((unsigned char *)pt, pt->header_size);
	pt->header_crc32 = pt_crc32;

	ret = pwrite(fd, pe, SECTOR_SIZE * GPT_PT_ENTRY_SIZE,
			(new_size - GPT_DATA_SIZE)*SECTOR_SIZE);
	if (ret == -1) {
		ploop_err(errno, "Failed to store secondary GPT %s", devname);
		goto err;
	}

	// Store Secondary GPT header
	ret = pwrite(fd, pt, SECTOR_SIZE, (new_size - GPT_HEADER_SIZE)*SECTOR_SIZE);
	if (ret == -1) {
		ploop_err(errno, "Failed to store secondary GPT header %s", devname);
		goto err;
	}
	if (fsync(fd)) {
		ploop_err(errno, "Can't fsync %s", devname);
		ret = SYSEXIT_FSYNC;
		goto err;
	}

	blkpg_resize_partition(fd, pe);
	ret = 0;
err:
	close(fd);
	if (ret < 0)
		ret = SYSEXIT_CHANGE_GPT;
	return ret;
}
Beispiel #15
0
static int
fifolog_write_output(struct fifolog_writer *f, int fl, time_t now)
{
	long h, l = f->ff->zs->next_out - f->obuf;
	ssize_t i, w;
	int retval = 0;

	h = 4;					/* seq */
	be32enc(f->obuf, f->seq);
	f->obuf[h] = f->flag;
	h += 1;					/* flag */
	if (f->flag & FIFOLOG_FLG_SYNC) {
		be32enc(f->obuf + h, now);
		h += 4;				/* timestamp */
	}

	assert(l <= (long)f->ff->recsize);	/* NB: l includes h */
	assert(l >= h);

	/* We will never write an entirely empty buffer */
	if (l == h)
		return (0);

	if (l < (long)f->ff->recsize && fl == Z_NO_FLUSH)
		return (0);

	w = f->ff->recsize - l;
	if (w >  255) {
		be32enc(f->obuf + f->ff->recsize - 4, w);
		f->obuf[4] |= FIFOLOG_FLG_4BYTE;
	} else if (w > 0) {
		f->obuf[f->ff->recsize - 1] = (uint8_t)w;
		f->obuf[4] |= FIFOLOG_FLG_1BYTE;
	}

	f->cnt[FIFOLOG_PT_BYTES_POST] += l - h;

	i = pwrite(f->ff->fd, f->obuf, f->ff->recsize,
	    (f->recno + 1) * f->ff->recsize);
	if (i != f->ff->recsize)
		retval = -1;
	else
		retval = 1;

	f->cnt[FIFOLOG_PT_WRITES]++;
	f->cnt[FIFOLOG_PT_RUNTIME] = now - f->starttime;

	f->lastwrite = now;
	/*
	 * We increment these even on error, so as to properly skip bad,
	 * sectors or other light trouble.
	 */
	f->seq++;
	f->recno++;
	f->flag = 0;

	memset(f->obuf, 0, f->obufsize);
	f->ff->zs->next_out = f->obuf + 5;
	f->ff->zs->avail_out = f->obufsize - 5;
	return (retval);
}
Beispiel #16
0
glio_arena_t *
_glio_arena_create(
	glio_group_t	*gg,		/* group of processes to share access */
	size_t		asize)		/* arena size (bytes per process) */
{
	char	*fname, *fncpy;
	int	fd;
	int	groupsz;
	int	namelen;
	int	myrank;
	size_t	arena_size;
	glio_arena_t	*arp;
	shmem_group_t	shg;
	void	*aret;
	MPI_Comm	comm;
	MPI_Status	mpistatus;

	groupsz	= gg->groupsz;
	myrank	= gg->myrank;

	arp	= malloc(sizeof(*arp));
	if (arp == NULL) {
                fprintf(stderr,"%s:\n\
    _glio_arena_create(a) could not allocate a memory object of size %lld bytes\n",
			GLOBERRMSG, (long long)sizeof(*arp));
		abort();
	}
	bzero(arp, sizeof(*arp));

	arp->grp	= *gg;		/* copy it */
	gg		= &arp->grp;	/* point to the new copy */

	/* 
	 * Process with rank 0 finds a unique new file name to use as
	 * a memory mapped file.
	 */
	if (myrank == 0) {

		fname	= NULL;

		do {
			if (fname != NULL)
				free(fname);
			fname	= tempnam(NULL, "glio_arena");
			assert(fname != NULL);
			fd	= open(fname, O_CREAT | O_EXCL | O_RDWR, 0700);
		} while (fd == -1 && errno == EEXIST);
	}
	

	/*
	 * Trivial groups of size 1 can be handled trivially.
	 */
	if (groupsz == 1)
		goto past_file_name_send;

	_glio_barrier(arp);

	/*
	 * Initialization
	 */
	switch (gg->grtype) {
	    case GR_SHMEM:
		if ( _shmem_group_inquire != NULL) {
			_shmem_group_inquire(arp->grp.u.shmem.group, &shg);
		} else {
		    /* Special case for pre-release versions of MPT 1.2 */
		    static int	*world_plist;
		    static int	*world_racom;

		    /* if pre-release version of MPT 1.2 is used, then all */
		    /* PEs are in the group */
		    assert (groupsz == _num_pes());

                    if (world_plist == NULL) {
			register short	ipe;

                        world_plist	= malloc(_num_pes() * sizeof(int));
			if (world_plist == NULL) {
                		fprintf(stderr,"%s:\n\
    _glio_arena_create(b) could not allocate a memory object of size %lld bytes\n",
					GLOBERRMSG, (long long)(_num_pes() *
					sizeof(int)));
				abort();
			}

			world_racom	= shmalloc(SHMEM_GROUP_COM_SIZE *
					sizeof(int));
                        assert(world_racom != NULL);
			bzero(world_racom, 10*sizeof(int));

                        for (ipe = 0; ipe < _num_pes(); ipe++)
                                world_plist[ipe]	= ipe;
                    }

                    shg.groupsz	= _num_pes();
                    shg.myrank	= _my_pe();
		    shg.plist	= world_plist;
		    shg.racom	= world_racom;

		}
		break;

	    case GR_MPI:
		comm	= arp->grp.u.MPI.comm;
		break;

	    default:
		break;
	}

	/*
	 * Process 0 now must communicate the file name to all other 
	 * processes in the group.
	 */

	switch (gg->grtype) {
	    case GR_SHMEM:
		if (myrank == 0) {
			void	*vp;

			fncpy	= _sma_global_heap_alloc(strlen(fname)+1);
			assert(fncpy != NULL);
			strcpy(fncpy, fname); 

			vp	= fncpy;
			
			/* racom[1] gets string length */
			shg.racom[1]	= strlen(fname);

			/* racom[2]  and racom[3] get the pointer */
			/* to the string.			    */
			memcpy(&shg.racom[2], &vp, sizeof(vp));
		}

		_glio_barrier(arp);
			
		/* 
		 * Other processes now get the file name.
		 */
		if (myrank != 0) {
			void	*vp;

			namelen	= _shmem_int_g( &shg.racom[1], shg.plist[0]);
			assert(namelen > 0);

			/* get pointer to the string */
			_shmem_getmem(&vp, &shg.racom[2], sizeof(vp),
				shg.plist[0]);

			fname	= malloc(namelen + 1);
			if (fname == NULL) {
                		fprintf(stderr,"%s:\n\
    _glio_arena_create(c) could not allocate a memory object of size %lld bytes\n",
				GLOBERRMSG, (long long)(namelen + 1));
				abort();
			}

			/* copy the string */
			_shmem_getmem(fname, vp, namelen, shg.plist[0]);
			fname[namelen]	= '\0';
		}

		_glio_barrier(arp);

		if (myrank == 0) {
			_sma_global_heap_free(fncpy);
		}

		break;

	    case GR_MPI:
		if (myrank == 0) {
			register int	rank;

			namelen	= strlen(fname);

			for (rank = 1; rank < groupsz; rank++) {
                		ckMPIerr( MPI_Send(&namelen, 1, MPI_INT, 
					rank, 1, comm) );
			}

			for (rank = 1; rank < groupsz; rank++) {
                		ckMPIerr( MPI_Send(fname, namelen, MPI_CHAR, 
					rank, 2, comm) );
			}
		} else {
                	ckMPIerr( MPI_Recv(&namelen, 1, MPI_INT, 
					0, 1, comm, &mpistatus) );

			fname	= malloc(namelen + 1);
			if (fname == NULL) {
                		fprintf(stderr,"%s:\n\
    _glio_arena_create(d) could not allocate a memory object of size %lld bytes\n",
				GLOBERRMSG, (long long)(namelen + 1));
				abort();
			}

                	ckMPIerr( MPI_Recv(fname, namelen, MPI_CHAR, 
					0, 2, comm, &mpistatus) );

			fname[namelen]	= '\0';
		}

		break;

	    default:
		assert(0);
	}


	_glio_barrier(arp);

	/* 
	 * Non-rank-0 processes now open the file.
	 */
	if (myrank != 0) {
		fd	= open(fname, O_RDWR, 0700);
		if (fd == -1) {
			fprintf(stderr, "%s:\n\
Global I/O failed to open mapped file.  Errno is %d\n",
				GLOBERRMSG, errno);
			abort();
		}
	}

	_glio_barrier(arp);

past_file_name_send:
	/*
 	 * All processes have opened the file, so rank 0 may now unlink it.
	 */
	if (myrank == 0) {
		unlink(fname);
	}

	_glio_barrier(arp);

	/*
	 * After the barrier process 0 may initialize the mapped
	 * file and unlink it because we know that all processes in the
	 * group have now opened this file.
	 */
	arena_size	= groupsz * CEILING(asize, 1024);

	if (myrank == 0) {
		ssize_t	wret;

		wret	= pwrite(fd, " ", 1, arena_size - 1);
		assert(wret != -1L);
	}

	_glio_barrier(arp);

	/*
	 * A barrier assures us that the file has been initialized
	 * to the right size.   Now map the file into every process'
	 * address space.
	 */

	aret	= mmap64(NULL, arena_size, PROT_READ | PROT_WRITE, MAP_SHARED,
                        fd, 0);
	if (aret == MAP_FAILED) {
                fprintf(stderr,"%s:\n\
    Cannot map internal file %s\n\
    for shared memory arena.  Error = %d\n",
			GLOBERRMSG, fname, errno);
		abort();
	}
Beispiel #17
0
/**
 * write() equivalent
 *
 * @param path the path of the file to be written
 * @param buf buffer holding write() data
 * @param size how many bytes should be written (size of *buf)
 * @param offset starting of the write
 * @param fi struct fuse_file_info used for open() flags
 * @return(0 on success, -errno otherwise)
 */
int tagsistant_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi)
{
    int res = 0, tagsistant_errno = 0, fh = 0;

	TAGSISTANT_START("WRITE on %s [size: %lu offset: %lu]", path, (unsigned long) size, (long unsigned int) offset);

	tagsistant_querytree *qtree = tagsistant_querytree_new(path, 0, 0, 1, 1);

	// -- malformed --
	if (QTREE_IS_MALFORMED(qtree))
		TAGSISTANT_ABORT_OPERATION(ENOENT);

	// -- alias --
	if (QTREE_IS_ALIAS(qtree) && qtree->alias) {
		res = size;

		gchar *_buf = g_strndup(buf, size);

		// end the string at the first carriage return or line feed character
		gchar *path_ptr = rindex(_buf, '\n');
		if (path_ptr) *path_ptr = '/';

		path_ptr = rindex(_buf, '\r');
		if (path_ptr) *path_ptr = '/';

		// remove double slashes
		GRegex *rx = g_regex_new("//", 0, 0, NULL);
		gchar *_buf2 = g_regex_replace(rx, _buf, -1, 0, "/", 0, NULL);
		g_regex_unref(rx);
		g_free(_buf);
		_buf = _buf2;

		// get the size of the buffer
		size_t max_size = MIN(size, TAGSISTANT_ALIAS_MAX_LENGTH - 1);
		size_t real_size = MIN(max_size, strlen(_buf));

		// copy the buffer to a temporary variable
		gchar *value = g_strndup(_buf, real_size);

		// save the buffer on disk
		tagsistant_sql_alias_set(qtree->dbi, qtree->alias, value);

		g_free(value);
		g_free(_buf);

	} else

	// -- object on disk --
	if (QTREE_POINTS_TO_OBJECT(qtree)) {
		if (!qtree->full_archive_path) {
			dbg('F', LOG_ERR, "Null qtree->full_archive_path");
			TAGSISTANT_ABORT_OPERATION(EFAULT);
		}

#if TAGSISTANT_ENABLE_FILE_HANDLE_CACHING
		if (fi->fh) {
			tagsistant_get_file_handle(fi, fh);
			res = pwrite(fh, buf, size, offset);
			tagsistant_errno = errno;
		}

		if ((-1 == res) || (0 == fh)) {
			if (fh) close(fh);
			fh = open(qtree->full_archive_path, fi->flags|O_WRONLY);
			if (fh)	res = pwrite(fh, buf, size, offset);
			else res = -1;
			tagsistant_errno = errno;
		}

		tagsistant_set_file_handle(fi, fh);
#else
		fh = open(qtree->full_archive_path, fi->flags|O_WRONLY);
		if (fh) {
			res = pwrite(fh, buf, size, offset);
			tagsistant_errno = errno;
			close(fh);
		} else {
			TAGSISTANT_ABORT_OPERATION(errno);
		}
#endif
	}

	// -- tags --
	// -- stats --
	// -- relations --
	else TAGSISTANT_ABORT_OPERATION(EROFS);

	// dbg('F', LOG_ERR, "Yeah!");

TAGSISTANT_EXIT_OPERATION:
	if ( res == -1 ) {
		TAGSISTANT_STOP_ERROR("WRITE %s (%s) (%s): %d %d: %s", path, qtree->full_archive_path, tagsistant_querytree_type(qtree), res, tagsistant_errno, strerror(tagsistant_errno));
		tagsistant_querytree_destroy(qtree, TAGSISTANT_ROLLBACK_TRANSACTION);
		return (-tagsistant_errno);
	} else {
		TAGSISTANT_STOP_OK("WRITE %s (%s): OK", path, tagsistant_querytree_type(qtree));
		tagsistant_querytree_destroy(qtree, TAGSISTANT_COMMIT_TRANSACTION);
		return (res);
	}
}
Beispiel #18
0
static void *
rtems_aio_handle (void *arg)
{

  rtems_aio_request_chain *r_chain = arg;
  rtems_aio_request *req;
  rtems_chain_control *chain;
  rtems_chain_node *node;
  int result, policy;
  struct sched_param param;

  AIO_printf ("Thread started\n");
 
  while (1) {
    
    /* acquire the mutex of the current fd chain.
       we don't need to lock the queue mutex since we can
       add requests to idle fd chains or even active ones
       if the working request has been extracted from the
       chain */
    result = pthread_mutex_lock (&r_chain->mutex);
    if (result != 0)
      return NULL;
    
    chain = &r_chain->perfd;    

    /* If the locked chain is not empty, take the first
       request extract it, unlock the chain and process 
       the request, in this way the user can supply more
       requests to this fd chain */
    if (!rtems_chain_is_empty (chain)) {

      AIO_printf ("Get new request from not empty chain\n");	
      node = rtems_chain_first (chain);
      req = (rtems_aio_request *) node;
      
      /* See _POSIX_PRIORITIZE_IO and _POSIX_PRIORITY_SCHEDULING
	 discussion in rtems_aio_enqueue () */
      pthread_getschedparam (pthread_self(), &policy, &param);
      param.sched_priority = req->priority;
      pthread_setschedparam (pthread_self(), req->policy, &param);

      rtems_chain_extract (node);

      pthread_mutex_unlock (&r_chain->mutex);

      switch (req->aiocbp->aio_lio_opcode) {
      case LIO_READ:
	AIO_printf ("read\n");
        result = pread (req->aiocbp->aio_fildes,
                        (void *) req->aiocbp->aio_buf,
                        req->aiocbp->aio_nbytes, req->aiocbp->aio_offset);
        break;

      case LIO_WRITE:
	AIO_printf ("write\n");
        result = pwrite (req->aiocbp->aio_fildes,
                         (void *) req->aiocbp->aio_buf,
                         req->aiocbp->aio_nbytes, req->aiocbp->aio_offset);
        break;
        
      case LIO_SYNC:
	AIO_printf ("sync\n");
      	result = fsync (req->aiocbp->aio_fildes);
      	break;

      default:
        result = -1;
      }
      if (result == -1) {
        req->aiocbp->return_value = -1;
	req->aiocbp->error_code = errno;
      } else {
        req->aiocbp->return_value = result;
        req->aiocbp->error_code = 0;
      }

      // notification needed for lio

    } else {
      /* If the fd chain is empty we unlock the fd chain
	 and we lock the queue chain, this will ensure that
	 we have at most one request comming to our fd chain
	 when we check. 
	 
	 If there was no request added sleep for 3 seconds and
	 wait for a signal on chain, this will unlock the queue.
	 The fd chain is already unlocked */

      struct timespec timeout;
      
      AIO_printf ("Chain is empty [WQ], wait for work\n");
     
      pthread_mutex_unlock (&r_chain->mutex);
      pthread_mutex_lock (&aio_request_queue.mutex);
      
      if (rtems_chain_is_empty (chain))
	{
	  clock_gettime (CLOCK_REALTIME, &timeout);
	  timeout.tv_sec += 3;
	  timeout.tv_nsec = 0;
	  result = pthread_cond_timedwait (&r_chain->cond,
					   &aio_request_queue.mutex,
					   &timeout);

	  /* If no requests were added to the chain we delete the fd chain from 
	     the queue and start working with idle fd chains */
	  if (result == ETIMEDOUT) {
	    rtems_chain_extract (&r_chain->next_fd);
	    pthread_mutex_destroy (&r_chain->mutex);
	    pthread_cond_destroy (&r_chain->cond);
	    free (r_chain);
	    
	    /* If the idle chain is empty sleep for 3 seconds and wait for a 
	       signal. The thread now becomes idle. */
	    if (rtems_chain_is_empty (&aio_request_queue.idle_req)) {
	      AIO_printf ("Chain is empty [IQ], wait for work\n");	      

	      ++aio_request_queue.idle_threads;
	      --aio_request_queue.active_threads;
	      clock_gettime (CLOCK_REALTIME, &timeout);
	      timeout.tv_sec += 3;
	      timeout.tv_nsec = 0;

	      result = pthread_cond_timedwait (&aio_request_queue.new_req,
					       &aio_request_queue.mutex,
					       &timeout);
	      
	      /* If no new fd chain was added in the idle requests
		 then this thread is finished */
	      if (result == ETIMEDOUT) {
		AIO_printf ("Etimeout\n");
		--aio_request_queue.idle_threads;
		pthread_mutex_unlock (&aio_request_queue.mutex);
		return NULL;
	      }
	    }
	    /* Otherwise move this chain to the working chain and 
	       start the loop all over again */
	    AIO_printf ("Work on idle\n");
	    --aio_request_queue.idle_threads;
	    ++aio_request_queue.active_threads;

	    node = rtems_chain_first (&aio_request_queue.idle_req);
	    rtems_chain_extract (node);

	    r_chain = (rtems_aio_request_chain *) node;
	    rtems_aio_move_to_work (r_chain);
	    
	  }
	}
      /* If there was a request added in the initial fd chain then release
	 the mutex and process it */
      pthread_mutex_unlock (&aio_request_queue.mutex);
      
    }
  }
  
  AIO_printf ("Thread finished\n");
  return NULL;
}
Beispiel #19
0
void
main(int argc, char *argv[])
{
	int fd, i;
	int n = 1000, m;
	int s = 1;
	double *t, t0, t1;
	unsigned char *buf;
	double a, d, max, min;

	m = OREAD;
	ARGBEGIN{
	case 'n':
		n = atoi(ARGF());
		break;
	case 's':
		s = unittoull(ARGF());
		if(s < 1 || s > 1024*1024)
			sysfatal("bad size");
		break;
	case 'r':
		m = OREAD;
		break;
	case 'w':
		m = OWRITE;
		break;
	}ARGEND

	fd = 0;
	if(argc == 1){
		fd = open(argv[0], m);
		if(fd < 0)
			sysfatal("could not open file: %s: %r", argv[0]);
	}

	buf = malloc(s);
	t = malloc(n*sizeof(double));

	t0 = nsec();
	for(i=0; i<n; i++){
		if(m == OREAD){
			if(pread(fd, buf, s, 0) < s)
				sysfatal("bad read: %r");
		}else{
			if(pwrite(fd, buf, s, 0) < s)
				sysfatal("bad write: %r");
		}
		t1 = nsec();
		t[i] = (t1 - t0)*1e-3;
		t0 = t1;
	}

	a = 0.;
	d = 0.;
	max = 0.;
	min = 1e12;

	for(i=0; i<n; i++){
		a += t[i];
		if(max < t[i])
			max = t[i];
		if(min > t[i])
			min = t[i];
	}

	a /= n;

	for(i=0; i<n; i++)
		d += (a - t[i]) * (a - t[i]);
	d /= n;
	d = sqrt(d);

	print("avg = %.0fµs min = %.0fµs max = %.0fµs dev = %.0fµs\n", a, min, max, d);

	exits(0);
}
Beispiel #20
0
static int copy_one_extent(struct btrfs_root *root, int fd,
			   struct extent_buffer *leaf,
			   struct btrfs_file_extent_item *fi, u64 pos)
{
	struct btrfs_multi_bio *multi = NULL;
	struct btrfs_device *device;
	char *inbuf, *outbuf = NULL;
	ssize_t done, total = 0;
	u64 bytenr;
	u64 ram_size;
	u64 disk_size;
	u64 num_bytes;
	u64 length;
	u64 size_left;
	u64 dev_bytenr;
	u64 offset;
	u64 count = 0;
	int compress;
	int ret;
	int dev_fd;
	int mirror_num = 1;
	int num_copies;

	compress = btrfs_file_extent_compression(leaf, fi);
	bytenr = btrfs_file_extent_disk_bytenr(leaf, fi);
	disk_size = btrfs_file_extent_disk_num_bytes(leaf, fi);
	ram_size = btrfs_file_extent_ram_bytes(leaf, fi);
	offset = btrfs_file_extent_offset(leaf, fi);
	num_bytes = btrfs_file_extent_num_bytes(leaf, fi);
	size_left = disk_size;
	if (compress == BTRFS_COMPRESS_NONE)
		bytenr += offset;

	if (verbose && offset)
		printf("offset is %Lu\n", offset);
	/* we found a hole */
	if (disk_size == 0)
		return 0;

	inbuf = malloc(size_left);
	if (!inbuf) {
		error("not enough memory");
		return -ENOMEM;
	}

	if (compress != BTRFS_COMPRESS_NONE) {
		outbuf = calloc(1, ram_size);
		if (!outbuf) {
			error("not enough memory");
			free(inbuf);
			return -ENOMEM;
		}
	}
again:
	length = size_left;
	ret = btrfs_map_block(root->fs_info, READ, bytenr, &length, &multi,
			      mirror_num, NULL);
	if (ret) {
		error("cannot map block logical %llu length %llu: %d",
				(unsigned long long)bytenr,
				(unsigned long long)length, ret);
		goto out;
	}
	device = multi->stripes[0].dev;
	dev_fd = device->fd;
	device->total_ios++;
	dev_bytenr = multi->stripes[0].physical;
	free(multi);

	if (size_left < length)
		length = size_left;

	done = pread(dev_fd, inbuf+count, length, dev_bytenr);
	/* Need both checks, or we miss negative values due to u64 conversion */
	if (done < 0 || done < length) {
		num_copies = btrfs_num_copies(root->fs_info, bytenr, length);
		mirror_num++;
		/* mirror_num is 1-indexed, so num_copies is a valid mirror. */
		if (mirror_num > num_copies) {
			ret = -1;
			error("exhausted mirrors trying to read (%d > %d)",
					mirror_num, num_copies);
			goto out;
		}
		fprintf(stderr, "Trying another mirror\n");
		goto again;
	}

	mirror_num = 1;
	size_left -= length;
	count += length;
	bytenr += length;
	if (size_left)
		goto again;

	if (compress == BTRFS_COMPRESS_NONE) {
		while (total < num_bytes) {
			done = pwrite(fd, inbuf+total, num_bytes-total,
				      pos+total);
			if (done < 0) {
				ret = -1;
				error("cannot write data: %d %m", errno);
				goto out;
			}
			total += done;
		}
		ret = 0;
		goto out;
	}

	ret = decompress(root, inbuf, outbuf, disk_size, &ram_size, compress);
	if (ret) {
		num_copies = btrfs_num_copies(root->fs_info, bytenr, length);
		mirror_num++;
		if (mirror_num >= num_copies) {
			ret = -1;
			goto out;
		}
		fprintf(stderr, "Trying another mirror\n");
		goto again;
	}

	while (total < num_bytes) {
		done = pwrite(fd, outbuf + offset + total,
			      num_bytes - total,
			      pos + total);
		if (done < 0) {
			ret = -1;
			goto out;
		}
		total += done;
	}
out:
	free(inbuf);
	free(outbuf);
	return ret;
}
Beispiel #21
0
int journal::commit()
{
	commit_record cr;
	
	if(erasure)
		return -EINVAL;
	if(commits > playbacks)
		/* must play back previous commit first */
		return -EINVAL;
	assert(playbacks == commits);
	
	if(!records)
		return 0;
	
	/* initialize crfd or if it is almost full add more empty records to it */
	if(crfd < 0 || !(commits % (J_ADD_N_COMMITS * 1000)))
		if(init_crfd(istr::null) < 0)
			return -1;

	cr.offset = prev_cr.offset + prev_cr.length;
	cr.length = data_file.end() - cr.offset;
	if(checksum(cr.offset, cr.offset + cr.length, cr.checksum) < 0)
		return -1;
#if HAVE_FSTITCH /* {{{ */
	patchgroup_id_t commit;
	commit = patchgroup_create(0);
	if(commit <= 0)
		return -1;
	patchgroup_label(commit, "commit");
	
	/* add the external dependency, if any */
	assert(!ext_count);
	if(external > 0)
	{
		if(ext_success && patchgroup_add_depend(commit, external) < 0)
			goto fail;
		patchgroup_abandon(external);
		external = 0;
	}
	
	if(patchgroup_add_depend(commit, records) < 0)
	{
	fail:
		patchgroup_release(commit);
		patchgroup_abandon(commit);
		return -1;
	}
	if(last_commit > 0 && patchgroup_add_depend(commit, last_commit) < 0)
		goto fail;
	if(prev && prev->last_commit && !commits && patchgroup_add_depend(commit, prev->last_commit) < 0)
		goto fail;
	patchgroup_release(commit);
	
	if(patchgroup_engage(commit) < 0)
	{
		/* this basically can't happen */
		patchgroup_abandon(commit);
		return -1;
	}
#endif /* }}} */
	data_file.flush();
	
	if(pwrite(crfd, &cr, sizeof(cr), commits * sizeof(cr)) != sizeof(cr))
	{
#if HAVE_FSTITCH /* {{{ */
		int save = errno;
		patchgroup_disengage(commit);
		/* the truncate() really should be part of records, but
		 * since commit depends on records, we'll substitute it */
		patchgroup_abandon(records);
		/* make sure the pointer is not past the end of the file */
		errno = save;
#endif /* }}} */
		return -1;
	}
#if HAVE_FSTITCH /* {{{ */
	patchgroup_disengage(commit);
	patchgroup_abandon(records);
	if(last_commit)
		patchgroup_abandon(last_commit);
	last_commit = commit;
#else /* }}} */
	char commit_number[16];
	istr old_commit, new_commit;
	last_commit = commits;
	snprintf(commit_number, sizeof(commit_number), "%d", last_commit);
	old_commit = path + J_COMMIT_EXT + commit_number;
	snprintf(commit_number, sizeof(commit_number), "%d", commits + 1);
	new_commit = path + J_COMMIT_EXT + commit_number;
	int r = renameat(dfd, old_commit, dfd, new_commit);
	if(r < 0)
		return r;
#endif
	records = 0;
	++commits;
	prev_cr = cr;
	return 0;
}
Beispiel #22
0
int file_set_size(int fd, off_t size)
{
#ifdef HAVE_POSIX_FALLOCATE
	static bool posix_fallocate_supported = TRUE;
#endif
	char block[IO_BLOCK_SIZE];
	off_t offset;
	ssize_t ret;
	struct stat st;

	i_assert(size >= 0);

	if (fstat(fd, &st) < 0) {
		i_error("fstat() failed: %m");
		return -1;
	}

	if (size < st.st_size) {
		if (ftruncate(fd, size) < 0) {
			i_error("ftruncate() failed: %m");
			return -1;
		}
		return 0;
	}
	if (size == st.st_size)
		return 0;

#ifdef HAVE_POSIX_FALLOCATE
	if (posix_fallocate_supported) {
		int err;

		err = posix_fallocate(fd, st.st_size, size - st.st_size);
		if (err == 0)
			return 0;

		if (err != EINVAL /* Solaris */ &&
		    err != EOPNOTSUPP /* AOX */) {
			if (!ENOSPACE(err))
				i_error("posix_fallocate() failed: %m");
			return -1;
		}
		/* Not supported by kernel, fallback to writing. */
		posix_fallocate_supported = FALSE;
	}
#endif
	/* start growing the file */
	offset = st.st_size;
	memset(block, 0, I_MIN((ssize_t)sizeof(block), size - offset));

	while (offset < size) {
		ret = pwrite(fd, block,
			     I_MIN((ssize_t)sizeof(block), size - offset),
			     offset);
		if (ret < 0) {
			if (!ENOSPACE(errno))
				i_error("pwrite() failed: %m");
			return -1;
		}
		offset += ret;
	}
	return 0;
}
Beispiel #23
0
/**
 * FSAL_write:
 * Perform a write operation on an opened file.
 *
 * \param file_descriptor (input):
 *        The file descriptor returned by FSAL_open.
 * \param p_context (input):
 *        Authentication context for the operation (user,...).
 * \param seek_descriptor (optional input):
 *        Specifies the position where data is to be written.
 *        If not specified, data will be written at the current position.
 * \param buffer_size (input):
 *        Amount (in bytes) of data to be written.
 * \param buffer (input):
 *        Address in memory of the data to write to file.
 * \param write_amount (output):
 *        Pointer to the amount of data (in bytes) that have been written
 *        during this call.
 *
 * \return Major error codes:
 *      - ERR_FSAL_NO_ERROR: no error.
 *      - Another error code if an error occured during this call.
 */
fsal_status_t XFSFSAL_write(fsal_file_t * p_file_descriptor, /* IN */
                            fsal_op_context_t * p_context,   /* IN */
                            fsal_seek_t * p_seek_descriptor,    /* IN */
                            fsal_size_t buffer_size,    /* IN */
                            caddr_t buffer,     /* IN */
                            fsal_size_t * p_write_amount        /* OUT */
    )
{

  ssize_t nb_written;
  size_t i_size;
  int rc, errsv;
  int pcall = FALSE;

  /* sanity checks. */
  if(!p_file_descriptor || !buffer || !p_write_amount)
    Return(ERR_FSAL_FAULT, 0, INDEX_FSAL_write);

  if(((xfsfsal_file_t *)p_file_descriptor)->ro)
    Return(ERR_FSAL_PERM, 0, INDEX_FSAL_write);

  /** @todo: manage fsal_size_t to size_t convertion */
  i_size = (size_t) buffer_size;

  *p_write_amount = 0;

  /* positioning */

  if(p_seek_descriptor)
    {

      switch (p_seek_descriptor->whence)
        {
        case FSAL_SEEK_CUR:
          /* set position plus offset */
          pcall = FALSE;

          TakeTokenFSCall();
          rc = lseek(((xfsfsal_file_t *)p_file_descriptor)->fd, p_seek_descriptor->offset, SEEK_CUR);
          errsv = errno;
          ReleaseTokenFSCall();
          break;

        case FSAL_SEEK_SET:
          /* set absolute position to offset */
          pcall = TRUE;
          rc = 0;
	  errsv = 0;
          break;

        case FSAL_SEEK_END:
          /* set end of file plus offset */
          pcall = FALSE;

          TakeTokenFSCall();
          rc = lseek(((xfsfsal_file_t *)p_file_descriptor)->fd, p_seek_descriptor->offset, SEEK_END);
          errsv = errno;
          ReleaseTokenFSCall();

          break;
	default:
	  rc = -1;
	  errsv = EINVAL;
	  break;
        }

      if(rc)
        {
	  LogEvent(COMPONENT_FSAL,
                            "Error in posix fseek operation (whence=%s, offset=%"PRId64")",
                            (p_seek_descriptor->whence == FSAL_SEEK_CUR ? "SEEK_CUR" :
                             (p_seek_descriptor->whence == FSAL_SEEK_SET ? "SEEK_SET" :
                              (p_seek_descriptor->whence ==
                               FSAL_SEEK_END ? "SEEK_END" : "ERROR"))),
                            p_seek_descriptor->offset);

          Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);

        }

      LogFullDebug(COMPONENT_FSAL,
                        "Write operation (whence=%s, offset=%"PRId64", size=%zu)",
                        (p_seek_descriptor->whence ==
                         FSAL_SEEK_CUR ? "SEEK_CUR" : (p_seek_descriptor->whence ==
                                                       FSAL_SEEK_SET ? "SEEK_SET"
                                                       : (p_seek_descriptor->whence ==
                                                          FSAL_SEEK_END ? "SEEK_END" :
                                                          "ERROR"))),
                        p_seek_descriptor->offset, buffer_size);

    }

  /* write operation */

  TakeTokenFSCall();

  if(pcall)
    nb_written = pwrite(((xfsfsal_file_t *)p_file_descriptor)->fd,
			buffer, i_size, p_seek_descriptor->offset);
  else
    nb_written = write(((xfsfsal_file_t *)p_file_descriptor)->fd, buffer, i_size);
  errsv = errno;

  ReleaseTokenFSCall();

  /** @todo: manage ssize_t to fsal_size_t convertion */
  if(nb_written <= 0)
    {
      LogDebug(COMPONENT_FSAL,
	       "Write operation of size %zu at offset %"PRId64" failed. fd=%d, errno=%d.",
	       i_size, p_seek_descriptor->offset,
	       ((xfsfsal_file_t *)p_file_descriptor)->fd, errsv);
      Return(posix2fsal_error(errsv), errsv, INDEX_FSAL_write);
    }

  /* set output vars */

  *p_write_amount = (fsal_size_t) nb_written;

  Return(ERR_FSAL_NO_ERROR, 0, INDEX_FSAL_write);

}
Beispiel #24
0
static ssize_t uv__fs_write(uv_fs_t* req) {
#if defined(__linux__)
    static int no_pwritev;
#endif
    ssize_t r;

    /* Serialize writes on OS X, concurrent write() and pwrite() calls result in
     * data loss. We can't use a per-file descriptor lock, the descriptor may be
     * a dup().
     */
#if defined(__APPLE__)
    static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
    pthread_mutex_lock(&lock);
#endif

    if (req->off < 0) {
        if (req->nbufs == 1)
            r = write(req->file, req->bufs[0].base, req->bufs[0].len);
        else
            r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
    } else {
        if (req->nbufs == 1) {
            r = pwrite(req->file, req->bufs[0].base, req->bufs[0].len, req->off);
            goto done;
        }
#if HAVE_PREADV
        r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
#else
# if defined(__linux__)
if (no_pwritev) retry:
# endif
        {
            off_t written;
            size_t index;

            written = 0;
            index = 0;
            r = 0;
            do {
                if (req->bufs[index].len > 0) {
                    r = pwrite(req->file,
                               req->bufs[index].base,
                               req->bufs[index].len,
                               req->off + written);
                    if (r > 0)
                        written += r;
                }
                index++;
            } while (index < req->nbufs && r >= 0);
            if (written > 0)
                r = written;
        }
# if defined(__linux__)
        else {
            r = uv__pwritev(req->file,
                            (struct iovec*) req->bufs,
                            req->nbufs,
                            req->off);
            if (r == -1 && errno == ENOSYS) {
                no_pwritev = 1;
                goto retry;
            }
        }
# endif
#endif
    }

done:
#if defined(__APPLE__)
    pthread_mutex_unlock(&lock);
#endif

    if (req->bufs != req->bufsml)
        uv__free(req->bufs);

    return r;
}
Beispiel #25
0
void
runtime·badcallback(void)
{
	runtime·pwrite(2, badcallback, sizeof badcallback - 1, -1LL);
}
Beispiel #26
0
/*
 * Main program
 */
int main(int argc, char **argv)
{
	int cnt, fd, ifd, imglen = 0, pagelen, baderaseblock, blockstart = -1;
	struct mtd_info_user meminfo;
	struct mtd_oob_buf oob;
	loff_mtd_t offs;
	int ret, readlen;
	int oobinfochanged = 0;
	struct nand_oobinfo old_oobinfo;

	printf("Warning: nandwrite_mlc instead of nandwrite is used for MLC NAND!\n");

	process_options(argc, argv);

	memset(oobbuf, 0xff, sizeof(oobbuf));

	if (pad && writeoob) {
		fprintf(stderr, "Can't pad when oob data is present.\n");
		exit(1);
	}

	/* Open the device */
	if ((fd = open(mtd_device, O_RDWR)) == -1) {
		perror("open flash");
		exit(1);
	}

	/* Fill in MTD device capability structure */
	if (ioctl(fd, MEMGETINFO, &meminfo) != 0) {
		perror("MEMGETINFO");
		close(fd);
		exit(1);
	}

	/* Set erasesize to specified number of blocks - to match jffs2
	 * (virtual) block size */
	meminfo.erasesize *= blockalign;

	/* Make sure device page sizes are valid */
	if (!(meminfo.oobsize == 16 && meminfo.writesize == 512) &&
			!(meminfo.oobsize == 8 && meminfo.writesize == 256) &&
			!(meminfo.oobsize == 64 && meminfo.writesize == 2048) &&
			!(meminfo.oobsize == 128 && meminfo.writesize == 4096)) {
		fprintf(stderr, "Unknown flash (not normal NAND)\n");
		close(fd);
		exit(1);
	}

	if (autoplace) {
		/* Read the current oob info */
		if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
			perror ("MEMGETOOBSEL");
			close (fd);
			exit (1);
		}

		// autoplace ECC ?
		if (autoplace && (old_oobinfo.useecc != MTD_NANDECC_AUTOPLACE)) {

			if (ioctl (fd, MEMSETOOBSEL, &autoplace_oobinfo) != 0) {
				perror ("MEMSETOOBSEL");
				close (fd);
				exit (1);
			}
			oobinfochanged = 1;
		}
	}

	if (noecc)  {
		ret = ioctl(fd, MTDFILEMODE, (void *) MTD_MODE_RAW);
		if (ret == 0) {
			oobinfochanged = 2;
		} else {
			switch (errno) {
			case ENOTTY:
				if (ioctl (fd, MEMGETOOBSEL, &old_oobinfo) != 0) {
					perror ("MEMGETOOBSEL");
					close (fd);
					exit (1);
				}
				if (ioctl (fd, MEMSETOOBSEL, &none_oobinfo) != 0) {
					perror ("MEMSETOOBSEL");
					close (fd);
					exit (1);
				}
				oobinfochanged = 1;
				break;
			default:
				perror ("MTDFILEMODE");
				close (fd);
				exit (1);
			}
		}
	}

	/*
	 * force oob layout for jffs2 or yaffs ?
	 * Legacy support
	 */
	if (forcejffs2 || forceyaffs) {
		struct nand_oobinfo *oobsel = forcejffs2 ? &jffs2_oobinfo : &yaffs_oobinfo;

		if (autoplace) {
			fprintf(stderr, "Autoplacement is not possible for legacy -j/-y options\n");
			goto restoreoob;
		}
		if ((old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE) && !forcelegacy) {
			fprintf(stderr, "Use -f option to enforce legacy placement on autoplacement enabled mtd device\n");
			goto restoreoob;
		}
		if (meminfo.oobsize == 8) {
			if (forceyaffs) {
				fprintf (stderr, "YAFSS cannot operate on 256 Byte page size");
				goto restoreoob;
			}
			/* Adjust number of ecc bytes */
			jffs2_oobinfo.eccbytes = 3;
		}

		if (ioctl (fd, MEMSETOOBSEL, oobsel) != 0) {
			perror ("MEMSETOOBSEL");
			goto restoreoob;
		}
	}

	oob.length = meminfo.oobsize;
	oob.ptr = noecc ? oobreadbuf : oobbuf;

	/* Open the input file */
	if ((ifd = open(img, O_RDONLY)) == -1) {
		perror("open input file");
		goto restoreoob;
	}

	// get image length
	imglen = lseek(ifd, 0, SEEK_END);
	lseek (ifd, 0, SEEK_SET);

	pagelen = meminfo.writesize + ((writeoob == 1) ? meminfo.oobsize : 0);

	// Check, if file is pagealigned
	if ((!pad) && ((imglen % pagelen) != 0)) {
		fprintf (stderr, "Input file is not page aligned\n");
		goto closeall;
	}

	// Check, if length fits into device
	if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) {
		fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %llu bytes\n",
				imglen, pagelen, meminfo.writesize, meminfo.size);
		perror ("Input file does not fit into device");
		goto closeall;
	}

	/* Get data from input and write to the device */
	while (imglen && (mtdoffset < meminfo.size)) {
		// new eraseblock , check for bad block(s)
		// Stay in the loop to be sure if the mtdoffset changes because
		// of a bad block, that the next block that will be written to
		// is also checked. Thus avoiding errors if the block(s) after the
		// skipped block(s) is also bad (number of blocks depending on
		// the blockalign
		while (blockstart != (mtdoffset & (~meminfo.erasesize + 1))) {
			blockstart = mtdoffset & (~meminfo.erasesize + 1);
			offs = blockstart;
			baderaseblock = 0;
			if (!quiet)
				fprintf (stdout, "Writing data to block %x\n", blockstart);

			/* Check all the blocks in an erase block for bad blocks */
			do {
				if ((ret = ioctl(fd, MEMGETBADBLOCK, &offs)) < 0) {
					perror("ioctl(MEMGETBADBLOCK)");
					goto closeall;
				}

				if (ret == 1) {
					baderaseblock = 1;
					if (!quiet)
						fprintf (stderr, "Bad block at %x, %u block(s) "
								"from %x will be skipped\n",
								(int) offs, blockalign, blockstart);
				}

				if (baderaseblock) {
					mtdoffset = blockstart + meminfo.erasesize;
				}
				offs +=  meminfo.erasesize / blockalign ;
			} while ( offs < blockstart + meminfo.erasesize );

		}

		readlen = meminfo.writesize;
		if (pad && (imglen < readlen))
		{
			readlen = imglen;
			memset(writebuf + readlen, 0xff, meminfo.writesize - readlen);
		}

		/* Read Page Data from input file */
		if ((cnt = read(ifd, writebuf, readlen)) != readlen) {
			if (cnt == 0)	// EOF
				break;
			perror ("File I/O error on input file");
			goto closeall;
		}

		if (writeoob) {
			/* Read OOB data from input file, exit on failure */
			if ((cnt = read(ifd, oobreadbuf, meminfo.oobsize)) != meminfo.oobsize) {
				perror ("File I/O error on input file");
				goto closeall;
			}
			if (!noecc) {
				int i, start, len;
				/*
				 *  We use autoplacement and have the oobinfo with the autoplacement
				 * information from the kernel available
				 *
				 * Modified to support out of order oobfree segments,
				 * such as the layout used by diskonchip.c
				 */
				if (!oobinfochanged && (old_oobinfo.useecc == MTD_NANDECC_AUTOPLACE)) {
					for (i = 0;old_oobinfo.oobfree[i][1]; i++) {
						/* Set the reserved bytes to 0xff */
						start = old_oobinfo.oobfree[i][0];
						len = old_oobinfo.oobfree[i][1];
						memcpy(oobbuf + start,
								oobreadbuf + start,
								len);
					}
				} else {
					/* Set at least the ecc byte positions to 0xff */
					start = old_oobinfo.eccbytes;
					len = meminfo.oobsize - start;
					memcpy(oobbuf + start,
							oobreadbuf + start,
							len);
				}
			}
			/* Write OOB data first, as ecc will be placed in there*/
			oob.start = mtdoffset;
			if (ioctl(fd, MEMWRITEOOB, &oob) != 0) {
				perror ("ioctl(MEMWRITEOOB)");
				goto closeall;
			}
			imglen -= meminfo.oobsize;
		}

		/* Write out the Page data */
		if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) != meminfo.writesize) {
			int rewind_blocks;
			off_t rewind_bytes;
			erase_info_t erase;

			perror ("pwrite");
			/* Must rewind to blockstart if we can */
			rewind_blocks = (mtdoffset - blockstart) / meminfo.writesize; /* Not including the one we just attempted */
			rewind_bytes = (rewind_blocks * meminfo.writesize) + readlen;
			if (writeoob)
				rewind_bytes += (rewind_blocks + 1) * meminfo.oobsize;
			if (lseek(ifd, -rewind_bytes, SEEK_CUR) == -1) {
				perror("lseek");
				fprintf(stderr, "Failed to seek backwards to recover from write error\n");
				goto closeall;
			}
			erase.start = blockstart;
			erase.length = meminfo.erasesize;
			fprintf(stderr, "Erasing failed write from 0x%09llx-0x%09llx\n",
				erase.start, erase.start+erase.length-1);
			if (ioctl(fd, MEMERASE, &erase) != 0) {
				perror("MEMERASE");
				goto closeall;
			}

			if (markbad) {
				loff_mtd_t bad_addr = mtdoffset & (~(meminfo.erasesize / blockalign) + 1);
				fprintf(stderr, "Marking block at %09llx bad\n", (long long)bad_addr);
				if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) {
					perror("MEMSETBADBLOCK");
					/* But continue anyway */
				}
			}
			mtdoffset = blockstart + meminfo.erasesize;
			imglen += rewind_blocks * meminfo.writesize;

			continue;
		}
		imglen -= readlen;
		mtdoffset += meminfo.writesize;
	}

closeall:
	close(ifd);

restoreoob:
	if (oobinfochanged == 1) {
		if (ioctl (fd, MEMSETOOBSEL, &old_oobinfo) != 0) {
			perror ("MEMSETOOBSEL");
			close (fd);
			exit (1);
		}
	}

	close(fd);

	if (imglen > 0) {
		perror ("Data was only partially written due to error\n");
		exit (1);
	}

	/* Return happy */
	return 0;
}
liHandlerResult li_filter_buffer_on_disk(liVRequest *vr, liChunkQueue *out, liChunkQueue *in, bod_state *state) {
	UNUSED(vr);

	if (out->is_closed) {
		in->is_closed = TRUE;
		li_chunkqueue_skip_all(in);
		bod_close(state);
		return LI_HANDLER_GO_ON;
	}

	while (in->length > 0) {
		liChunk *c = li_chunkqueue_first_chunk(in);
		liChunkIter ci;
		off_t length, data_len;
		char *data = NULL;
		GError *err;

		switch (c->type) {
		case UNUSED_CHUNK: return LI_HANDLER_ERROR;
		case FILE_CHUNK:
			bod_flush(out, state);
			if (state->split_on_file_chunks) {
				bod_close(state);
			}
			li_chunkqueue_steal_chunk(out, in);
			break;
		case STRING_CHUNK:
		case MEM_CHUNK:
		case BUFFER_CHUNK:
			if (!bod_open(vr, state)) return LI_HANDLER_ERROR;

			length = li_chunk_length(c);
			ci = li_chunkqueue_iter(in);

			err = NULL;
			if (LI_HANDLER_GO_ON != li_chunkiter_read(ci, 0, length, &data, &data_len, &err)) {
				if (NULL != err) {
					VR_ERROR(vr, "%s", err->message);
					g_error_free(err);
				}
				return LI_HANDLER_ERROR;
			}

			while ( data_len > 0 ) {
				ssize_t r;

				r = pwrite(state->tempfile->fd, data, data_len, state->write_pos);

				if (r < 0) {
					switch (errno) {
					case EINTR: continue;
					default: break;
					}

					VR_ERROR(vr, "pwrite failed: %s", g_strerror(errno));
					return LI_HANDLER_ERROR;
				}

				data += r;
				data_len -= r;
				state->write_pos += r;
			}

			li_chunkqueue_skip(in, length);

			break;
		}
	}

	bod_autoflush(out, state);

	if (in->is_closed) {
		bod_flush(out, state);
		out->is_closed = TRUE;
		bod_close(state);
		return LI_HANDLER_GO_ON;
	}
	return LI_HANDLER_GO_ON;
}
Beispiel #28
0
void
main(int argc, char *argv[])
{
	int fd, force;
	Header h;
	ulong bn;
	Entry e;
	char *label = "vfs";
	char *host = nil;
	char *score = nil;
	u32int root;
	Dir *d;

	force = 0;
	ARGBEGIN{
	default:
		usage();
	case 'b':
		bsize = unittoull(EARGF(usage()));
		if(bsize == ~0)
			usage();
		break;
	case 'h':
		host = EARGF(usage());
		break;
	case 'i':
		iso9660file = EARGF(usage());
		iso9660off = atoi(EARGF(usage()));
		break;
	case 'l':
		label = EARGF(usage());
		break;
	case 'v':
		score = EARGF(usage());
		break;

	/*
	 * This is -y instead of -f because flchk has a
	 * (frequently used) -f option.  I type flfmt instead
	 * of flchk all the time, and want to make it hard
	 * to reformat my file system accidentally.
	 */
	case 'y':
		force = 1;
		break;
	}ARGEND

	if(argc != 1)
		usage();

	if(iso9660file && score)
		vtFatal("cannot use -i with -v");

	vtAttach();

	fmtinstall('V', scoreFmt);
	fmtinstall('R', vtErrFmt);
	fmtinstall('L', labelFmt);

	fd = open(argv[0], ORDWR);
	if(fd < 0)
		vtFatal("could not open file: %s: %r", argv[0]);

	buf = vtMemAllocZ(bsize);
	if(pread(fd, buf, bsize, HeaderOffset) != bsize)
		vtFatal("could not read fs header block: %r");

	if(headerUnpack(&h, buf) && !force
	&& !confirm("fs header block already exists; are you sure?"))
		goto Out;

	if((d = dirfstat(fd)) == nil)
		vtFatal("dirfstat: %r");

	if(d->type == 'M' && !force
	&& !confirm("fs file is mounted via devmnt (is not a kernel device); are you sure?"))
		goto Out;

	partition(fd, bsize, &h);
	headerPack(&h, buf);
	if(pwrite(fd, buf, bsize, HeaderOffset) < bsize)
		vtFatal("could not write fs header: %r");

	disk = diskAlloc(fd);
	if(disk == nil)
		vtFatal("could not open disk: %r");

	if(iso9660file)
		iso9660init(fd, &h, iso9660file, iso9660off);

	/* zero labels */
	memset(buf, 0, bsize);
	for(bn = 0; bn < diskSize(disk, PartLabel); bn++)
		blockWrite(PartLabel, bn);

	if(iso9660file)
		iso9660labels(disk, buf, blockWrite);

	if(score)
		root = ventiRoot(host, score);
	else{
		rootMetaInit(&e);
		root = rootInit(&e);
	}

	superInit(label, root, vtZeroScore);
	diskFree(disk);

	if(score == nil)
		topLevel(argv[0]);

Out:
	vtDetach();
	exits(0);
}
Beispiel #29
0
int
write_tape_block(const uint8_t *buffer, uint32_t blk_size, uint32_t comp_size,
	const struct encryption *encryptp, uint8_t comp_type, uint8_t *sam_stat)
{
	uint32_t blk_number, disk_blk_size;
	uint64_t data_offset;
	ssize_t nwrite;

	if (!tape_loaded(sam_stat)) {
		return -1;
	}

	if (check_for_overwrite(sam_stat)) {
		return -1;
	}

	/* Preserve existing raw_pos data we need, then clear out raw_pos and
	   fill it in with new data.
	*/

	blk_number = raw_pos.hdr.blk_number;
	data_offset = raw_pos.data_offset;

	memset(&raw_pos, 0, sizeof(raw_pos));

	raw_pos.data_offset = data_offset;

	raw_pos.hdr.blk_type = B_DATA;	/* Header type */
	raw_pos.hdr.blk_flags = 0;
	raw_pos.hdr.blk_number = blk_number;
	raw_pos.hdr.blk_size = blk_size; /* Size of uncompressed data */

	if (comp_size) {
		if (comp_type == LZO)
			raw_pos.hdr.blk_flags |= BLKHDR_FLG_LZO_COMPRESSED;
		else
			raw_pos.hdr.blk_flags |= BLKHDR_FLG_ZLIB_COMPRESSED;
		raw_pos.hdr.disk_blk_size = disk_blk_size = comp_size;
	} else {
		raw_pos.hdr.disk_blk_size = disk_blk_size = blk_size;
	}

	if (encryptp != NULL) {
		unsigned int i;

		raw_pos.hdr.blk_flags |= BLKHDR_FLG_ENCRYPTED;
		raw_pos.hdr.encryption.ukad_length = encryptp->ukad_length;
		for (i = 0; i < encryptp->ukad_length; ++i) {
			raw_pos.hdr.encryption.ukad[i] = encryptp->ukad[i];
		}

		raw_pos.hdr.encryption.akad_length = encryptp->akad_length;
		for (i = 0; i < encryptp->akad_length; ++i) {
			raw_pos.hdr.encryption.akad[i] = encryptp->akad[i];
		}

		raw_pos.hdr.encryption.key_length = encryptp->key_length;
		for (i = 0; i < encryptp->key_length; ++i) {
			raw_pos.hdr.encryption.key[i] = encryptp->key[i];
		}
	}

	/* Now write out both the header and the data. */

	nwrite = pwrite(indxfile, &raw_pos, sizeof(raw_pos),
		blk_number * sizeof(raw_pos));
	if (nwrite != sizeof(raw_pos)) {
		mkSenseBuf(MEDIUM_ERROR, E_WRITE_ERROR, sam_stat);
		MHVTL_ERR("Index file write failure, pos: %" PRId64 ": %s",
			(uint64_t)blk_number * sizeof(raw_pos),
			strerror(errno));
		return -1;
	}

	nwrite = pwrite(datafile, buffer, disk_blk_size, data_offset);
	if (nwrite != disk_blk_size) {
		mkSenseBuf(MEDIUM_ERROR, E_WRITE_ERROR, sam_stat);
		MHVTL_ERR("Data file write failure, pos: %" PRId64 ": %s",
			data_offset, strerror(errno));
		return -1;
	}

	MHVTL_DBG(3, "Successfully wrote block: %u", blk_number);

	return mkEODHeader(blk_number + 1, data_offset + disk_blk_size);
}
Beispiel #30
0
/*
 * Perform data transfer on the selected device.
 */
static int
vnd_transfer(devminor_t minor, int do_write, u64_t position,
	endpoint_t endpt, iovec_t *iovt, unsigned int nr_req, int flags)
{
	struct device *dv;
	iovec_s_t *iov;
	size_t off, chunk, bytes, iov_off;
	ssize_t r;
	unsigned int i;

	iov = (iovec_s_t *) iovt;

	if (state.fd == -1 || (dv = vnd_part(minor)) == NULL)
		return ENXIO;

	/* Prevent write operations on devices opened as write-only. */
	if (do_write && state.rdonly)
		return EACCES;

	/* Determine the total number of bytes to transfer. */
	if (position >= dv->dv_size)
		return 0;

	bytes = 0;

	for (i = 0; i < nr_req; i++) {
		if (iov[i].iov_size == 0 || iov[i].iov_size > LONG_MAX)
			return EINVAL;
		bytes += iov[i].iov_size;
		if (bytes > LONG_MAX)
			return EINVAL;
	}

	if (bytes > dv->dv_size - position)
		bytes = dv->dv_size - position;

	position += dv->dv_base;

	/* Perform the actual transfer, in chunks if necessary. */
	iov_off = 0;

	for (off = 0; off < bytes; off += chunk) {
		chunk = MIN(bytes - off, VND_BUF_SIZE);

		assert((unsigned int) (iov - (iovec_s_t *) iovt) < nr_req);

		/* For reads, read in the data for the chunk; possibly less. */
		if (!do_write) {
			chunk = r = pread(state.fd, state.buf, chunk,
			    position);

			if (r < 0) {
				printf("VND%u: pread failed (%d)\n", instance,
				    -errno);
				return -errno;
			}
			if (r == 0)
				break;
		}

		/* Copy the data for this chunk from or to the caller. */
		if ((r = vnd_copy(iov, iov_off, chunk, endpt, do_write)) < 0) {
			printf("VND%u: data copy failed (%d)\n", instance, r);
			return r;
		}

		/* For writes, write the data to the file; possibly less. */
		if (do_write) {
			chunk = r = pwrite(state.fd, state.buf, chunk,
			    position);

			if (r <= 0) {
				if (r < 0)
					r = -errno;
				printf("VND%u: pwrite failed (%d)\n", instance,
				    r);
				return (r < 0) ? r : EIO;
			}
		}

		/* Move ahead on the I/O vector and the file position. */
		iov = vnd_advance(iov, &iov_off, chunk);

		position += chunk;
	}

	/* If force-write is requested, flush the underlying file to disk. */
	if (do_write && (flags & BDEV_FORCEWRITE))
		fsync(state.fd);

	/* Return the number of bytes transferred. */
	return off;
}