void ADIOI_XFS_Resize(ADIO_File fd, ADIO_Offset size, int *error_code) { int err; static char myname[] = "ADIOI_XFS_RESIZE"; err = ftruncate64(fd->fd_sys, size); 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; }
ARTtrie *ARTnew (int fd) { int flag = PROT_READ | PROT_WRITE; ARTnode256 *radix256, *root256; ARTtrie *trie; ulong offset; uint i, j; #ifdef PERSIST if( !(offset = lseek64 (fd, 0L, 2)) ) ftruncate64 (fd, offset = ArenaInit); Arena = mmap (0, ArenaVM, flag, MAP_SHARED, fd, 0); #else offset = ArenaVM; Arena = mmap(NULL, offset, flag, MAP_ANONYMOUS | MAP_SHARED, -1, 0); #endif ArenaFd = fd; trie = (ARTtrie *)Arena; trie->arena_size = offset; // is this a new file? // if so, fill out the first two levels // of the trie with radix256 nodes. if( !trie->arena_next ) { trie->arena_next = sizeof(ARTtrie); root256 = (ARTnode256 *)(Arena + trie->arena_next); trie->root->off = trie->arena_next >> 3; trie->root->type = Array256; trie->arena_next += sizeof(ARTnode256); for( i = 0; i < 256; i++ ) { radix256 = (ARTnode256 *)(Arena + trie->arena_next); root256->radix[i].off = trie->arena_next >> 3; root256->radix[i].type = Array256; trie->arena_next += sizeof(ARTnode256); // for( j = 0; j < 256; j++ ) { // fill in 3rd level // radix256[i].radix[j].off = trie->arena_next >> 3; // radix256[i].radix[j].type = Array256; // trie->arena_next += sizeof(ARTnode256); // } } // round up to complete the first chunks trie->arena_next |= ARENA_chunk - 1; trie->arena_next++; }
int32_t SystemNative_FTruncate(intptr_t fd, int64_t length) { int32_t result; while (( result = #if HAVE_FTRUNCATE64 ftruncate64( #else ftruncate( #endif ToFileDescriptor(fd), (off_t)length)) < 0 && errno == EINTR); return result; }
exception_t* file_free(file_t* file) { char* function_name = "file_free()"; exception_t* exception; // Validate parameters. if ( file == NULL ) { return exception_throw("file was NULL.", function_name); } // Write metadata or truncate file. // Note that file->flag reflects the file when it was opened, // and the file is now the _opposite_ of what the flag states. if ( file->flag == UNENCRYPTED ) { // Write padding to the end of the file. exception = file_write_metadata(file); if ( exception != NULL ) { return exception_append(exception, function_name); } } else if ( file->flag == ENCRYPTED ) { // Truncate the file padding. if ( ftruncate64(file->fd, (off64_t)(file->size - (off64_t)file->padding)) == -1 ) { return exception_throw("Unable to truncate file.", function_name); } } else { return exception_throw("Unexpected flag.", function_name); } // Free file name, free(file->name); // Close the file. if ( close(file->fd) == -1 ) { perror("Unable to close file."); return exception_throw("Unable to close file.", function_name); } // Set structure defaults. file->blocks = NULL; file->name = NULL; file->block_count = 0; file->size = 0; file->padding = 0; file->fd = 0; file->flag = 0; // Return success. return NULL; }
extern "C" int32_t SystemNative_FTruncate(intptr_t fd, int64_t length) { int32_t result; while (CheckInterrupted( result = #if HAVE_FTRUNCATE64 ftruncate64( #else ftruncate( #endif ToFileDescriptor(fd), length))); return result; }
static void do_trunc(int fd) { off_t roffset = 0; roffset = random() % fsize; if (ftruncate64(fd, (offset + roffset)) < 0) { perror("truncate"); exit(7); } if (vflag) { (void) fprintf(stderr, "Truncated at offset %" PRId64 "\n", (offset + roffset)); } }
int main(int argc, char **argv) { int fd, fd1, ret; char *buf; char wbuf[8192]; unsigned long long offset = 0xffffff000ULL; char *p=wbuf; fd = open(FILENAME, O_RDWR|O_CREAT|O_LARGEFILE/*|O_TRUNC*/, 0644); if (fd < 0) { perror(FILENAME); return -1; } ftruncate64(fd, offset + 4096*4); buf = mmap64(NULL, 4096*4, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset); if (buf == MAP_FAILED) { perror("mmap"); return -1; } fd1 = open(FILENAME, O_RDWR|O_DIRECT|O_LARGEFILE, 0644); if (fd < 0) { perror(FILENAME); return -1; } p = (char *)((unsigned long) p | 4095)+1; if (fork()) { while(1) { /* map in the page */ buf[10] = 1; } } else { ret = pwrite64(fd1, p, 4096, offset); if (ret < 4096) { printf("write: %d %p\n", ret, p); perror("write"); return -1; } } return 0; }
static int truncate_f( int argc, char **argv) { off64_t offset; size_t blocksize, sectsize; init_cvtnum(&blocksize, §size); offset = cvtnum(blocksize, sectsize, argv[1]); if (offset < 0) { printf(_("non-numeric truncate argument -- %s\n"), argv[1]); return 0; } if (ftruncate64(file->fd, offset) < 0) { perror("ftruncate"); return 0; } return 0; }
exception_t* file_read_metadata(file_t* file) { char* function_name = "file_read_metadata()"; long long temp; // Validate parameters. if ( file == NULL ) { return exception_throw("file was NULL.", function_name); } // Seek to end of the file. temp = lseek64(file->fd, 0, SEEK_END); if ( temp == -1 ) { perror(NULL); return exception_throw("Unable to lseek to file end.", function_name); } // Move back by the size of the metadata. temp = lseek64(file->fd, (int)(-sizeof(file->padding)), SEEK_CUR); if ( temp == -1 ) { perror(NULL); return exception_throw("Unable to lseek to metadata.", function_name); } // Read in metadata. temp = read(file->fd, &file->padding, sizeof(file->padding)); if ( temp == -1 ) { perror(NULL); return exception_throw("Unable to read in metadata.", function_name); } // Delete the metadata. file->size -= sizeof(file->padding); if ( ftruncate64(file->fd, (off64_t)(file->size)) == -1 ) { perror(NULL); return exception_throw("Unable to truncate metadata.", function_name); } // Return success. return NULL; }
static int FileTruncateProc( ClientData instanceData, Tcl_WideInt length) { FileState *fsPtr = instanceData; int result; #ifdef HAVE_TYPE_OFF64_T /* * We assume this goes with the type for now... */ result = ftruncate64(fsPtr->fd, (off64_t) length); #else result = ftruncate(fsPtr->fd, (off_t) length); #endif if (result) { return errno; } return 0; }
void xftruncate (int fd, long long length) { if (ftruncate64 (fd, length) != 0) FAIL_EXIT1 ("ftruncate64 (%d, %lld): %m", fd, length); }
int __real_ftruncate64(int fildes, long long length) { return ftruncate64(fildes, length); }
int padding_decoder(char *file_name, unsigned long long content_length) { int fp_in; unsigned long long f_size; #ifdef _MSC_VER struct __stat64 file_stats; #else struct stat64 file_stats; #endif char file_name_in[256] = ""; char file_name_out[256] = ""; char *ptr; int retval; strcpy(file_name_in, file_name); ptr = strstr(file_name_in, PAD_SUFFIX); memcpy(file_name_out, file_name_in, (ptr - file_name_in)); #ifdef _MSC_VER fp_in = open((const char*)file_name_in, _O_RDWR | _O_CREAT | _O_BINARY, _S_IREAD | _S_IWRITE); #else fp_in = open64(file_name_in, O_RDWR | O_CREAT, S_IRWXU); #endif if(fp_in == -1) { printf("open error: %s\n", file_name_in); return -1; } #ifdef _MSC_VER _fstat64(fp_in, &file_stats); #else fstat64(fp_in, &file_stats); #endif f_size = file_stats.st_size; if(f_size > content_length) { #ifdef _MSC_VER retval = _chsize(fp_in, (long)content_length); /* TODO: 64 bits, how ??? */ #else retval = ftruncate64(fp_in, content_length); #endif if(retval != 0) { printf("Problem in padding decoding.\n" ); close(fp_in); return -1; } } close(fp_in); if(rename(file_name_in, file_name_out) < 0) { if(errno == EEXIST) { retval = remove(file_name_out); if(retval == -1) { printf("errno: %i\n", errno); fflush(stdout); close(fp_in); return -1; } if(rename(file_name_in, file_name_out) < 0) { printf("rename() error1: %s\n", file_name_in); fflush(stdout); close(fp_in); return -1; } } else { printf("rename() error2: %s\n", file_name_in); fflush(stdout); close(fp_in); return -1; } } return 0; }
int main(int argc, char **argv) { int i, j; int howfar = 0; int open_flags; xfs_off_t pos, end_pos; size_t length; int c, first_residue, tmp_residue; __uint64_t size, sizeb; __uint64_t numblocks = 0; int wblocks = 0; int num_threads = 0; struct dioattr d; int wbuf_size; int wbuf_align; int wbuf_miniosize; int source_is_file = 0; int buffered_output = 0; int duplicate = 0; uint btree_levels, current_level; ag_header_t ag_hdr; xfs_mount_t *mp; xfs_mount_t mbuf; xfs_buf_t *sbp; xfs_sb_t *sb; xfs_agnumber_t num_ags, agno; xfs_agblock_t bno; xfs_daddr_t begin, next_begin, ag_begin, new_begin, ag_end; struct xfs_btree_block *block; xfs_alloc_ptr_t *ptr; xfs_alloc_rec_t *rec_ptr; extern char *optarg; extern int optind; libxfs_init_t xargs; thread_args *tcarg; struct stat64 statbuf; progname = basename(argv[0]); setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); while ((c = getopt(argc, argv, "bdL:V")) != EOF) { switch (c) { case 'b': buffered_output = 1; break; case 'd': duplicate = 1; break; case 'L': logfile_name = optarg; break; case 'V': printf(_("%s version %s\n"), progname, VERSION); exit(0); case '?': usage(); } } if (argc - optind < 2) usage(); if (logfile_name) { logfd = open(logfile_name, O_CREAT|O_WRONLY|O_EXCL, 0600); } else { logfile_name = LOGFILE_NAME; logfd = mkstemp(logfile_name); } if (logfd < 0) { fprintf(stderr, _("%s: couldn't open log file \"%s\"\n"), progname, logfile_name); perror(_("Aborting XFS copy - reason")); exit(1); } if ((logerr = fdopen(logfd, "w")) == NULL) { fprintf(stderr, _("%s: couldn't set up logfile stream\n"), progname); perror(_("Aborting XFS copy - reason")); exit(1); } source_name = argv[optind]; source_fd = -1; optind++; num_targets = argc - optind; if ((target = malloc(sizeof(target_control) * num_targets)) == NULL) { do_log(_("Couldn't allocate target array\n")); die_perror(); } for (i = 0; optind < argc; i++, optind++) { target[i].name = argv[optind]; target[i].fd = -1; target[i].position = -1; target[i].state = INACTIVE; target[i].error = 0; target[i].err_type = 0; } parent_pid = getpid(); if (atexit(killall)) { do_log(_("%s: couldn't register atexit function.\n"), progname); die_perror(); } /* open up source -- is it a file? */ open_flags = O_RDONLY; if ((source_fd = open(source_name, open_flags)) < 0) { do_log(_("%s: couldn't open source \"%s\"\n"), progname, source_name); die_perror(); } if (fstat64(source_fd, &statbuf) < 0) { do_log(_("%s: couldn't stat source \"%s\"\n"), progname, source_name); die_perror(); } if (S_ISREG(statbuf.st_mode)) source_is_file = 1; if (source_is_file && platform_test_xfs_fd(source_fd)) { if (fcntl(source_fd, F_SETFL, open_flags | O_DIRECT) < 0) { do_log(_("%s: Cannot set direct I/O flag on \"%s\".\n"), progname, source_name); die_perror(); } if (xfsctl(source_name, source_fd, XFS_IOC_DIOINFO, &d) < 0) { do_log(_("%s: xfsctl on file \"%s\" failed.\n"), progname, source_name); die_perror(); } wbuf_align = d.d_mem; wbuf_size = MIN(d.d_maxiosz, 1 * 1024 * 1024); wbuf_miniosize = d.d_miniosz; } else { /* set arbitrary I/O params, miniosize at least 1 disk block */ wbuf_align = getpagesize(); wbuf_size = 1 * 1024 * 1024; wbuf_miniosize = -1; /* set after mounting source fs */ } if (!source_is_file) { /* * check to make sure a filesystem isn't mounted * on the device */ if (platform_check_ismounted(source_name, NULL, &statbuf, 0)) { do_log( _("%s: Warning -- a filesystem is mounted on the source device.\n"), progname); do_log( _("\t\tGenerated copies may be corrupt unless the source is\n")); do_log( _("\t\tunmounted or mounted read-only. Copy proceeding...\n")); } } /* prepare the libxfs_init structure */ memset(&xargs, 0, sizeof(xargs)); xargs.isdirect = LIBXFS_DIRECT; xargs.isreadonly = LIBXFS_ISREADONLY; if (source_is_file) { xargs.dname = source_name; xargs.disfile = 1; } else xargs.volname = source_name; if (!libxfs_init(&xargs)) { do_log(_("%s: couldn't initialize XFS library\n" "%s: Aborting.\n"), progname, progname); exit(1); } /* prepare the mount structure */ sbp = libxfs_readbuf(xargs.ddev, XFS_SB_DADDR, 1, 0); memset(&mbuf, 0, sizeof(xfs_mount_t)); sb = &mbuf.m_sb; libxfs_sb_from_disk(sb, XFS_BUF_TO_SBP(sbp)); mp = libxfs_mount(&mbuf, sb, xargs.ddev, xargs.logdev, xargs.rtdev, 1); if (mp == NULL) { do_log(_("%s: %s filesystem failed to initialize\n" "%s: Aborting.\n"), progname, source_name, progname); exit(1); } else if (mp->m_sb.sb_inprogress) { do_log(_("%s %s filesystem failed to initialize\n" "%s: Aborting.\n"), progname, source_name, progname); exit(1); } else if (mp->m_sb.sb_logstart == 0) { do_log(_("%s: %s has an external log.\n%s: Aborting.\n"), progname, source_name, progname); exit(1); } else if (mp->m_sb.sb_rextents != 0) { do_log(_("%s: %s has a real-time section.\n" "%s: Aborting.\n"), progname, source_name, progname); exit(1); } source_blocksize = mp->m_sb.sb_blocksize; source_sectorsize = mp->m_sb.sb_sectsize; if (wbuf_miniosize == -1) wbuf_miniosize = source_sectorsize; ASSERT(source_blocksize % source_sectorsize == 0); ASSERT(source_sectorsize % BBSIZE == 0); if (source_blocksize > source_sectorsize) { /* get number of leftover sectors in last block of ag header */ tmp_residue = ((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize) % source_blocksize; first_residue = (tmp_residue == 0) ? 0 : source_blocksize - tmp_residue; ASSERT(first_residue % source_sectorsize == 0); } else if (source_blocksize == source_sectorsize) { first_residue = 0; } else { do_log(_("Error: filesystem block size is smaller than the" " disk sectorsize.\nAborting XFS copy now.\n")); exit(1); } first_agbno = (((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize) + first_residue) / source_blocksize; ASSERT(first_agbno != 0); ASSERT( ((((XFS_AGFL_DADDR(mp) + 1) * source_sectorsize) + first_residue) % source_blocksize) == 0); /* now open targets */ open_flags = O_RDWR; for (i = 0; i < num_targets; i++) { int write_last_block = 0; if (stat64(target[i].name, &statbuf) < 0) { /* ok, assume it's a file and create it */ do_out(_("Creating file %s\n"), target[i].name); open_flags |= O_CREAT; if (!buffered_output) open_flags |= O_DIRECT; write_last_block = 1; } else if (S_ISREG(statbuf.st_mode)) { open_flags |= O_TRUNC; if (!buffered_output) open_flags |= O_DIRECT; write_last_block = 1; } else { /* * check to make sure a filesystem isn't mounted * on the device */ if (platform_check_ismounted(target[i].name, NULL, &statbuf, 0)) { do_log(_("%s: a filesystem is mounted " "on target device \"%s\".\n" "%s cannot copy to mounted filesystems." " Aborting\n"), progname, target[i].name, progname); exit(1); } } target[i].fd = open(target[i].name, open_flags, 0644); if (target[i].fd < 0) { do_log(_("%s: couldn't open target \"%s\"\n"), progname, target[i].name); die_perror(); } if (write_last_block) { /* ensure regular files are correctly sized */ if (ftruncate64(target[i].fd, mp->m_sb.sb_dblocks * source_blocksize)) { do_log(_("%s: cannot grow data section.\n"), progname); die_perror(); } if (platform_test_xfs_fd(target[i].fd)) { if (xfsctl(target[i].name, target[i].fd, XFS_IOC_DIOINFO, &d) < 0) { do_log( _("%s: xfsctl on \"%s\" failed.\n"), progname, target[i].name); die_perror(); } else { wbuf_align = MAX(wbuf_align, d.d_mem); wbuf_size = MIN(d.d_maxiosz, wbuf_size); wbuf_miniosize = MAX(d.d_miniosz, wbuf_miniosize); } } } else { char *lb[XFS_MAX_SECTORSIZE] = { NULL }; off64_t off; /* ensure device files are sufficiently large */ off = mp->m_sb.sb_dblocks * source_blocksize; off -= sizeof(lb); if (pwrite64(target[i].fd, lb, sizeof(lb), off) < 0) { do_log(_("%s: failed to write last block\n"), progname); do_log(_("\tIs target \"%s\" too small?\n"), target[i].name); die_perror(); } } } /* initialize locks and bufs */ if (pthread_mutex_init(&glob_masks.mutex, NULL) != 0) { do_log(_("Couldn't initialize global thread mask\n")); die_perror(); } glob_masks.num_working = 0; if (wbuf_init(&w_buf, wbuf_size, wbuf_align, wbuf_miniosize, 0) == NULL) { do_log(_("Error initializing wbuf 0\n")); die_perror(); } wblocks = wbuf_size / BBSIZE; if (wbuf_init(&btree_buf, MAX(source_blocksize, wbuf_miniosize), wbuf_align, wbuf_miniosize, 1) == NULL) { do_log(_("Error initializing btree buf 1\n")); die_perror(); } if (pthread_mutex_init(&mainwait,NULL) != 0) { do_log(_("Error creating first semaphore.\n")); die_perror(); exit(1); } /* need to start out blocking */ pthread_mutex_lock(&mainwait); /* set up sigchild signal handler */ signal(SIGCHLD, handler); signal_maskfunc(SIGCHLD, SIG_BLOCK); /* make children */ if ((targ = malloc(num_targets * sizeof(thread_args))) == NULL) { do_log(_("Couldn't malloc space for thread args\n")); die_perror(); exit(1); } for (i = 0, tcarg = targ; i < num_targets; i++, tcarg++) { if (!duplicate) platform_uuid_generate(&tcarg->uuid); else platform_uuid_copy(&tcarg->uuid, &mp->m_sb.sb_uuid); if (pthread_mutex_init(&tcarg->wait, NULL) != 0) { do_log(_("Error creating thread mutex %d\n"), i); die_perror(); exit(1); } /* need to start out blocking */ pthread_mutex_lock(&tcarg->wait); } for (i = 0, tcarg = targ; i < num_targets; i++, tcarg++) { tcarg->id = i; tcarg->fd = target[i].fd; target[i].state = ACTIVE; num_threads++; if (pthread_create(&target[i].pid, NULL, begin_reader, (void *)tcarg)) { do_log(_("Error creating thread for target %d\n"), i); die_perror(); } } ASSERT(num_targets == num_threads); /* set up statistics */ num_ags = mp->m_sb.sb_agcount; init_bar(mp->m_sb.sb_blocksize / BBSIZE * ((__uint64_t)mp->m_sb.sb_dblocks - (__uint64_t)mp->m_sb.sb_fdblocks + 10 * num_ags)); kids = num_targets; block = (struct xfs_btree_block *) btree_buf.data; for (agno = 0; agno < num_ags && kids > 0; agno++) { /* read in first blocks of the ag */ read_ag_header(source_fd, agno, &w_buf, &ag_hdr, mp, source_blocksize, source_sectorsize); /* set the in_progress bit for the first AG */ if (agno == 0) ag_hdr.xfs_sb->sb_inprogress = 1; /* save what we need (agf) in the btree buffer */ memmove(btree_buf.data, ag_hdr.xfs_agf, source_sectorsize); ag_hdr.xfs_agf = (xfs_agf_t *) btree_buf.data; btree_buf.length = source_blocksize; /* write the ag header out */ write_wbuf(); /* traverse btree until we get to the leftmost leaf node */ bno = be32_to_cpu(ag_hdr.xfs_agf->agf_roots[XFS_BTNUM_BNOi]); current_level = 0; btree_levels = be32_to_cpu(ag_hdr.xfs_agf-> agf_levels[XFS_BTNUM_BNOi]); ag_end = XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(ag_hdr.xfs_agf->agf_length) - 1) + source_blocksize / BBSIZE; for (;;) { /* none of this touches the w_buf buffer */ ASSERT(current_level < btree_levels); current_level++; btree_buf.position = pos = (xfs_off_t) XFS_AGB_TO_DADDR(mp,agno,bno) << BBSHIFT; btree_buf.length = source_blocksize; read_wbuf(source_fd, &btree_buf, mp); block = (struct xfs_btree_block *) ((char *)btree_buf.data + pos - btree_buf.position); ASSERT(be32_to_cpu(block->bb_magic) == XFS_ABTB_MAGIC); if (be16_to_cpu(block->bb_level) == 0) break; ptr = XFS_ALLOC_PTR_ADDR(mp, block, 1, mp->m_alloc_mxr[1]); bno = be32_to_cpu(ptr[0]); } /* align first data copy but don't overwrite ag header */ pos = w_buf.position >> BBSHIFT; length = w_buf.length >> BBSHIFT; next_begin = pos + length; ag_begin = next_begin; ASSERT(w_buf.position % source_sectorsize == 0); /* handle the rest of the ag */ for (;;) { if (be16_to_cpu(block->bb_level) != 0) { do_log( _("WARNING: source filesystem inconsistent.\n")); do_log( _(" A leaf btree rec isn't a leaf. Aborting now.\n")); exit(1); } rec_ptr = XFS_ALLOC_REC_ADDR(mp, block, 1); for (i = 0; i < be16_to_cpu(block->bb_numrecs); i++, rec_ptr++) { /* calculate in daddr's */ begin = next_begin; /* * protect against pathological case of a * hole right after the ag header in a * mis-aligned case */ if (begin < ag_begin) begin = ag_begin; /* * round size up to ensure we copy a * range bigger than required */ sizeb = XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(rec_ptr->ar_startblock)) - begin; size = roundup(sizeb <<BBSHIFT, wbuf_miniosize); if (size > 0) { /* copy extent */ w_buf.position = (xfs_off_t) begin << BBSHIFT; while (size > 0) { /* * let lower layer do alignment */ if (size > w_buf.size) { w_buf.length = w_buf.size; size -= w_buf.size; sizeb -= wblocks; numblocks += wblocks; } else { w_buf.length = size; numblocks += sizeb; size = 0; } read_wbuf(source_fd, &w_buf, mp); write_wbuf(); w_buf.position += w_buf.length; howfar = bump_bar( howfar, numblocks); } } /* round next starting point down */ new_begin = XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu(rec_ptr->ar_startblock) + be32_to_cpu(rec_ptr->ar_blockcount)); next_begin = rounddown(new_begin, w_buf.min_io_size >> BBSHIFT); } if (be32_to_cpu(block->bb_u.s.bb_rightsib) == NULLAGBLOCK) break; /* read in next btree record block */ btree_buf.position = pos = (xfs_off_t) XFS_AGB_TO_DADDR(mp, agno, be32_to_cpu( block->bb_u.s.bb_rightsib)) << BBSHIFT; btree_buf.length = source_blocksize; /* let read_wbuf handle alignment */ read_wbuf(source_fd, &btree_buf, mp); block = (struct xfs_btree_block *) ((char *) btree_buf.data + pos - btree_buf.position); ASSERT(be32_to_cpu(block->bb_magic) == XFS_ABTB_MAGIC); } /* * write out range of used blocks after last range * of free blocks in AG */ if (next_begin < ag_end) { begin = next_begin; sizeb = ag_end - begin; size = roundup(sizeb << BBSHIFT, wbuf_miniosize); if (size > 0) { /* copy extent */ w_buf.position = (xfs_off_t) begin << BBSHIFT; while (size > 0) { /* * let lower layer do alignment */ if (size > w_buf.size) { w_buf.length = w_buf.size; size -= w_buf.size; sizeb -= wblocks; numblocks += wblocks; } else { w_buf.length = size; numblocks += sizeb; size = 0; } read_wbuf(source_fd, &w_buf, mp); write_wbuf(); w_buf.position += w_buf.length; howfar = bump_bar(howfar, numblocks); } } } } if (kids > 0) { if (!duplicate) { /* write a clean log using the specified UUID */ for (j = 0, tcarg = targ; j < num_targets; j++) { w_buf.owner = tcarg; w_buf.length = rounddown(w_buf.size, w_buf.min_io_size); pos = write_log_header( source_fd, &w_buf, mp); end_pos = write_log_trailer( source_fd, &w_buf, mp); w_buf.position = pos; memset(w_buf.data, 0, w_buf.length); while (w_buf.position < end_pos) { do_write(tcarg); w_buf.position += w_buf.length; } tcarg++; } } else { num_ags = 1; } /* reread and rewrite superblocks (UUID and in-progress) */ /* [backwards, so inprogress bit only updated when done] */ for (i = num_ags - 1; i >= 0; i--) { read_ag_header(source_fd, i, &w_buf, &ag_hdr, mp, source_blocksize, source_sectorsize); if (i == 0) ag_hdr.xfs_sb->sb_inprogress = 0; /* do each thread in turn, each has its own UUID */ for (j = 0, tcarg = targ; j < num_targets; j++) { platform_uuid_copy(&ag_hdr.xfs_sb->sb_uuid, &tcarg->uuid); do_write(tcarg); tcarg++; } } bump_bar(100, 0); } check_errors(); killall(); pthread_exit(NULL); /*NOTREACHED*/ return 0; }
/* ARGSUSED */ bool_t node_init( intgen_t fd, off64_t off, size_t usrnodesz, ix_t nodehkix, size_t nodealignsz, size64_t vmsz, size64_t dirs_nondirs_cnt ) { size64_t nodesz; size64_t winmap_mem; size64_t segsz; size64_t segtablesz; size64_t nodesperseg; size64_t minsegsz; size64_t winmapmax; intgen_t rval; /* sanity checks */ ASSERT( sizeof( node_hdr_t ) <= NODE_HDRSZ ); ASSERT( sizeof( nh_t ) < sizeof( off64_t )); ASSERT( nodehkix < usrnodesz ); ASSERT( usrnodesz >= sizeof( char * ) + 1 ); /* so node is at least big enough to hold * the free list linkage and the housekeeping byte */ ASSERT( nodehkix > sizeof( char * )); /* since beginning of each node is used to * link it in the free list. */ /* adjust the user's node size to meet user's alignment constraint */ nodesz = ( usrnodesz + nodealignsz - 1 ) & ~( nodealignsz - 1 ); #define WINMAP_MAX 20 /* maximum number of windows to use */ #define WINMAP_MIN 4 /* minimum number of windows to use */ #define HARDLINK_FUDGE 1.2 /* approx 1.2 hard links per file */ /* Calculate the expected size of the segment table using the number * of dirs and non-dirs. Since we don't know how many hard-links * there will be, scale the size upward using HARDLINK_FUDGE. */ segtablesz = ( (size64_t)(HARDLINK_FUDGE * (double)dirs_nondirs_cnt) * nodesz); /* Figure out how much memory is available for use by winmaps, and * use that to pick an appropriate winmapmax, segsz, and nodesperseg, * the goal being that if at all possible we want the entire segment * table to be mapped so that we aren't constantly mapping and * unmapping winmaps. There must be at least WINMAP_MIN winmaps * because references can be held on more than one winmap at the * same time. More winmaps are generally better to reduce the * number of nodes that are unmapped if unmapping does occur. */ minsegsz = pgsz * nodesz; /* must be pgsz and nodesz multiple */ winmap_mem = min(vmsz, segtablesz); segsz = (((winmap_mem / WINMAP_MAX) + minsegsz - 1) / minsegsz) * minsegsz; segsz = max(segsz, minsegsz); nodesperseg = segsz / nodesz; winmapmax = min(WINMAP_MAX, vmsz / segsz); winmapmax = max(winmapmax, WINMAP_MIN); /* map the abstraction header */ ASSERT( ( NODE_HDRSZ & pgmask ) == 0 ); ASSERT( ! ( NODE_HDRSZ % pgsz )); ASSERT( off <= OFF64MAX ); ASSERT( ! ( off % ( off64_t )pgsz )); node_hdrp = ( node_hdr_t * )mmap_autogrow( NODE_HDRSZ, fd, off ); if ( node_hdrp == (node_hdr_t *)-1 ) { mlog( MLOG_NORMAL | MLOG_ERROR, _( "unable to map node hdr of size %d: %s\n"), NODE_HDRSZ, strerror( errno )); return BOOL_FALSE; } /* initialize and save persistent context. */ node_hdrp->nh_nodesz = nodesz; node_hdrp->nh_nodehkix = nodehkix; node_hdrp->nh_segsz = segsz; node_hdrp->nh_segtblsz = segtablesz; node_hdrp->nh_winmapmax = winmapmax; node_hdrp->nh_nodesperseg = nodesperseg; node_hdrp->nh_nodealignsz = nodealignsz; node_hdrp->nh_freenix = NIX_NULL; node_hdrp->nh_firstsegoff = off + ( off64_t )NODE_HDRSZ; node_hdrp->nh_virgsegreloff = 0; node_hdrp->nh_virgrelnix = 0; /* save transient context */ node_fd = fd; /* autogrow the first segment */ mlog( MLOG_DEBUG, "pre-growing new node array segment at %lld " "size %lld\n", node_hdrp->nh_firstsegoff, ( off64_t )node_hdrp->nh_segsz ); rval = ftruncate64( node_fd, node_hdrp->nh_firstsegoff + ( off64_t )node_hdrp->nh_segsz ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_ERROR | MLOG_TREE, _( "unable to autogrow first node segment: %s (%d)\n"), strerror( errno ), errno ); return BOOL_FALSE; } /* initialize the window abstraction */ win_init( fd, node_hdrp->nh_firstsegoff, segsz, segtablesz, winmapmax ); /* announce the results */ mlog( MLOG_DEBUG | MLOG_TREE, "node_init:" " vmsz = %llu (0x%llx)" " segsz = %u (0x%x)" " segtblsz = %llu (0x%llx)" " nodesperseg = %u (0x%x)" " winmapmax = %llu (0x%llx)" "\n", vmsz, vmsz, segsz, segsz, segtablesz, segtablesz, nodesperseg, nodesperseg, winmapmax, winmapmax ); return BOOL_TRUE; }
int writePREHASHES(int file, HashList *hashes_list) { uint32_t i; uint_least32_t qty = 0; #ifndef _POSIX_MAPPED_FILES int writecheck; #else struct stat st; int64_t mmap_offset = 0, size; char *address; #endif #ifdef _POSIX_MAPPED_FILES i = ftruncate64(file, (hashes_list->used * PREHASH_SIZE) + PREHASH_COUNT_SIZE); fstat(file, &st); size = st.st_size; address = mmap(0, size, PROT_WRITE, MAP_SHARED, file, 0); if(address == MAP_FAILED) { ci_debug_printf(3, " writePREHASHES: Failed to mmap with error: %s\n", strerror(errno)); return -1; } #endif if(hashes_list->used) // check before we write { qty = hashes_list->used; #ifdef _POSIX_MAPPED_FILES binary2char((char *) &qty, address, PREHASH_COUNT_SIZE); mmap_offset += PREHASH_COUNT_SIZE; #else do { writecheck = write(file, &qty, PREHASH_COUNT_SIZE); if(writecheck < PREHASH_COUNT_SIZE) lseek64(file, -writecheck, SEEK_CUR); } while (writecheck >=0 && writecheck < PREHASH_COUNT_SIZE); #endif for(i = 0; i < hashes_list->used; i++) { #ifdef _POSIX_MAPPED_FILES binary2char((char *) &hashes_list->hashes[i], address + mmap_offset, PREHASH_SIZE); mmap_offset += PREHASH_SIZE; #else do { // write hash writecheck = write(file, &hashes_list->hashes[i], PREHASH_SIZE); if(writecheck < PREHASH_SIZE) lseek64(file, -writecheck, SEEK_CUR); } while (writecheck >=0 && writecheck < PREHASH_SIZE); #endif } #ifdef _POSIX_MAPPED_FILES // wrap up mmap /* if(msync(address, size, MS_SYNC) < 0) { ci_debug_printf(3, "writeFBCHashes: msync failed with error: %s\n", strerror(errno)); strerror(errno); } */ if(munmap(address, size) < 0) { ci_debug_printf(3, " writePREHASHES: munmap failed with error: %s\n", strerror(errno)); } i = ftruncate64(file, (qty * PREHASH_SIZE) + PREHASH_COUNT_SIZE); #else ftruncate(file, lseek64(file, 0, SEEK_CUR)); #endif /* Ok, have written hashes, now save new count */ // ci_debug_printf(10, "%"PRIu32" hashes, wrote %"PRIu32" hashes\n", hashes_list->used, qty); return 0; } return -1; }
int do_test (int argc, char *argv[]) { struct aiocb64 cbs[10]; struct aiocb64 cbs_fsync; struct aiocb64 *cbp[10]; struct aiocb64 *cbp_fsync[1]; char buf[1000]; size_t cnt; int result = 0; /* Preparation. */ for (cnt = 0; cnt < 10; ++cnt) { cbs[cnt].aio_fildes = fd; cbs[cnt].aio_reqprio = 0; cbs[cnt].aio_buf = memset (&buf[cnt * 100], '0' + cnt, 100); cbs[cnt].aio_nbytes = 100; cbs[cnt].aio_offset = cnt * 100; cbs[cnt].aio_sigevent.sigev_notify = SIGEV_NONE; cbp[cnt] = &cbs[cnt]; } /* First a simple test. */ for (cnt = 10; cnt > 0; ) if (aio_write64 (cbp[--cnt]) < 0 && errno == ENOSYS) { error (0, 0, "no aio support in this configuration"); return 0; } /* Wait 'til the results are there. */ result |= do_wait (cbp, 10, 0); /* Test this. */ result |= test_file (buf, sizeof (buf), fd, "aio_write"); /* Read now as we've written it. */ memset (buf, '\0', sizeof (buf)); /* Issue the commands. */ for (cnt = 10; cnt > 0; ) { --cnt; cbp[cnt] = &cbs[cnt]; aio_read64 (cbp[cnt]); } /* Wait 'til the results are there. */ result |= do_wait (cbp, 10, 0); /* Test this. */ for (cnt = 0; cnt < 1000; ++cnt) if (buf[cnt] != '0' + (cnt / 100)) { result = 1; error (0, 0, "comparison failed for aio_read test"); break; } if (cnt == 1000) puts ("aio_read test ok"); /* Remove the test file contents. */ if (ftruncate64 (fd, 0) < 0) { error (0, errno, "ftruncate failed\n"); result = 1; } /* Test lio_listio. */ for (cnt = 0; cnt < 10; ++cnt) { cbs[cnt].aio_lio_opcode = LIO_WRITE; cbp[cnt] = &cbs[cnt]; } /* Issue the command. */ lio_listio64 (LIO_WAIT, cbp, 10, NULL); /* ...and immediately test it since we started it in wait mode. */ result |= test_file (buf, sizeof (buf), fd, "lio_listio (write)"); /* Test aio_fsync. */ cbs_fsync.aio_fildes = fd; cbs_fsync.aio_sigevent.sigev_notify = SIGEV_NONE; cbp_fsync[0] = &cbs_fsync; /* Remove the test file contents first. */ if (ftruncate64 (fd, 0) < 0) { error (0, errno, "ftruncate failed\n"); result = 1; } /* Write again. */ for (cnt = 10; cnt > 0; ) aio_write64 (cbp[--cnt]); if (aio_fsync64 (O_SYNC, &cbs_fsync) < 0) { error (0, errno, "aio_fsync failed\n"); result = 1; } result |= do_wait (cbp_fsync, 1, 0); /* ...and test since all data should be on disk now. */ result |= test_file (buf, sizeof (buf), fd, "aio_fsync (aio_write)"); /* Test aio_cancel. */ /* Remove the test file contents first. */ if (ftruncate64 (fd, 0) < 0) { error (0, errno, "ftruncate failed\n"); result = 1; } /* Write again. */ for (cnt = 10; cnt > 0; ) aio_write64 (cbp[--cnt]); /* Cancel all requests. */ if (aio_cancel64 (fd, NULL) == -1) printf ("aio_cancel64 (fd, NULL) cannot cancel anything\n"); result |= do_wait (cbp, 10, ECANCELED); /* Another test for aio_cancel. */ /* Remove the test file contents first. */ if (ftruncate64 (fd, 0) < 0) { error (0, errno, "ftruncate failed\n"); result = 1; } /* Write again. */ for (cnt = 10; cnt > 0; ) { --cnt; cbp[cnt] = &cbs[cnt]; aio_write64 (cbp[cnt]); } puts ("finished3"); /* Cancel all requests. */ for (cnt = 10; cnt > 0; ) if (aio_cancel64 (fd, cbp[--cnt]) == -1) /* This is not an error. The request can simply be finished. */ printf ("aio_cancel64 (fd, cbp[%Zd]) cannot be canceled\n", cnt); puts ("finished2"); result |= do_wait (cbp, 10, ECANCELED); puts ("finished"); return result; }
int capfs_ftruncate64(int fd, int64_t length) { int i; ireq req; memset(&req, 0, sizeof(req)); /* check for badness */ if (fd < 0 || fd >= CAPFS_NR_OPEN || (pfds[fd] && pfds[fd]->fs == FS_RESV)) { errno = EBADF; return(-1); } /* check for UNIX */ if (!pfds[fd] || pfds[fd]->fs==FS_UNIX) { #ifndef LARGE_FILE_SUPPORT if ((off_t) length == length) { return ftruncate(fd, (off_t) length); } else { errno = EINVAL; return(-1); } #else return ftruncate64(fd, length); #endif } if (pfds[fd]->fs == FS_PDIR) { errno = EISDIR; return(-1); } if (capfs_mode == 0) { req.majik_nr = IOD_MAJIK_NR; req.release_nr = CAPFS_RELEASE_NR; req.type = IOD_FTRUNCATE; req.dsize = 0; req.req.ftruncate.f_ino = FINO; req.req.ftruncate.cap = pfds[fd]->fd.cap; req.req.ftruncate.length = length; /* build job to send reqs and recv acks */ if (build_simple_jobs(pfds[fd], &req) < 0) { LOG(stderr, WARNING_MSG, SUBSYS_LIB, "capfs_ftruncate: build_simple_jobs failed\n"); return(-1); } /* call do_job */ while (!jlist_empty(active_p)) { if (do_jobs(active_p, &socks, -1) < 0) { LOG(stderr, WARNING_MSG, SUBSYS_LIB, "capfs_ftruncate: do_jobs failed\n"); return(-1); } } /* check acks from iods */ for (i=0; i < PCNT; i++) { if (pfds[fd]->fd.iod[i].ack.status) { LOG(stderr, WARNING_MSG, SUBSYS_LIB, "capfs_ftruncate: non-zero status returned from iod %d\n", i); errno = pfds[fd]->fd.iod[i].ack.eno; return(-1); } } } return(0); }
static unsigned int call_syscall(struct syscall_desc *scall, char *argv[]) { struct stat64 sb; struct utimbuf ut; long long flags; unsigned int i; char *endp; int rval; int more; union { char *str; long long num; } args[MAX_ARGS]; more = 0; /* * Verify correctness of the arguments. */ for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) { if (scall->sd_args[i] == TYPE_NONE) { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) break; fprintf(stderr, "too many arguments [%s]\n", argv[i]); exit(1); } else { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) { if (scall->sd_args[i] & TYPE_OPTIONAL) { args[i].str = NULL; break; } fprintf(stderr, "too few arguments\n"); exit(1); } if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) { if (strcmp(argv[i], "NULL") == 0) args[i].str = NULL; else if (strcmp(argv[i], "DEADCODE") == 0) args[i].str = (void *)0xdeadc0de; else args[i].str = argv[i]; } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_NUMBER) { args[i].num = strtoll(argv[i], &endp, 0); if (*endp != '\0' && !isspace((unsigned char)*endp)) { fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); exit(1); } } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_DESCRIPTOR) { if (strcmp(argv[i], "AT_FDCWD") == 0) { args[i].num = AT_FDCWD; } else if (strcmp(argv[i], "BADFD") == 0) { /* In case AT_FDCWD is -1 on some systems... */ if (AT_FDCWD == -1) args[i].num = -2; else args[i].num = -1; } else { int pos; pos = strtoll(argv[i], &endp, 0); if (*endp != '\0' && !isspace((unsigned char)*endp)) { fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); exit(1); } args[i].num = descriptor_get(pos); } } } } /* * Call the given syscall. */ #define NUM(n) (args[(n)].num) #define STR(n) (args[(n)].str) switch (scall->sd_action) { case ACTION_OPEN: flags = str2flags(open_flags, STR(1)); if (flags & O_CREAT) { if (i == 2) { fprintf(stderr, "too few arguments\n"); exit(1); } rval = open(STR(0), flags, (mode_t)NUM(2)); } else { if (i == 3) { fprintf(stderr, "too many arguments\n"); exit(1); } rval = open(STR(0), flags); } if (rval >= 0) { more = argv[i] && !strcmp(argv[i], ":"); descriptor_add(rval); } break; case ACTION_CREATE: rval = open(STR(0), O_CREAT | O_EXCL, NUM(1)); if (rval >= 0) { more = argv[i] && !strcmp(argv[i], ":"); descriptor_add(rval); } break; case ACTION_UNLINK: rval = unlink(STR(0)); break; case ACTION_MKDIR: rval = mkdir(STR(0), NUM(1)); break; case ACTION_RMDIR: rval = rmdir(STR(0)); break; case ACTION_LINK: rval = link(STR(0), STR(1)); break; case ACTION_SYMLINK: rval = symlink(STR(0), STR(1)); break; case ACTION_RENAME: rval = rename(STR(0), STR(1)); break; case ACTION_MKFIFO: rval = mkfifo(STR(0), NUM(1)); break; case ACTION_CHMOD: rval = chmod(STR(0), NUM(1)); break; #ifdef HAS_LCHMOD case ACTION_LCHMOD: rval = lchmod(STR(0), NUM(1)); break; #endif case ACTION_CHOWN: rval = chown(STR(0), NUM(1), NUM(2)); break; case ACTION_LCHOWN: rval = lchown(STR(0), NUM(1), NUM(2)); break; #ifdef HAS_CHFLAGS case ACTION_CHFLAGS: rval = chflags(STR(0), str2flags(chflags_flags, STR(1))); break; #endif #ifdef HAS_LCHFLAGS case ACTION_LCHFLAGS: rval = lchflags(STR(0), str2flags(chflags_flags, STR(1))); break; #endif case ACTION_TRUNCATE: rval = truncate64(STR(0), NUM(1)); break; case ACTION_FTRUNCATE: rval = ftruncate64(NUM(0), NUM(1)); break; case ACTION_STAT: rval = stat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_LSTAT: rval = lstat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_UTIME : switch (i) { case 1 : rval = utime(STR(0), (struct utimbuf*)NULL); break; case 3: ut.actime = NUM(1); ut.modtime = NUM(2); rval = utime(STR(0), &ut); break; default : fprintf(stderr,"utime() requires 1 or 3 arguments\n"); exit(1); } break; case ACTION_BIND: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } case ACTION_MKNOD: case ACTION_MKNODAT: { mode_t ntype; dev_t dev; int fa; switch (scall->sd_action) { case ACTION_MKNOD: fa = 0; break; case ACTION_MKNODAT: fa = 1; break; default: abort(); } dev = makedev(NUM(fa + 3), NUM(fa + 4)); if (strcmp(STR(fa + 1), "c") == 0) /* character device */ ntype = S_IFCHR; else if (strcmp(STR(fa + 1), "b") == 0) /* block device */ ntype = S_IFBLK; else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */ ntype = S_IFIFO; else if (strcmp(STR(fa + 1), "d") == 0) /* directory */ ntype = S_IFDIR; else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */ ntype = S_IFREG; else { fprintf(stderr, "wrong argument 1\n"); exit(1); } switch (scall->sd_action) { case ACTION_MKNOD: rval = mknod(STR(0), ntype | NUM(2), dev); break; case ACTION_MKNODAT: rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev); break; default: abort(); } break; } #ifdef HAS_ACL case ACTION_GETFACL : rval = do_getfacl(STR(0), STR(1)); if (rval == 0) return (i); break; case ACTION_SETFACL : rval = do_setfacl(STR(0), STR(1), STR(2)); break; #endif default: fprintf(stderr, "unsupported syscall\n"); exit(1); } #undef STR #undef NUM if (rval < 0) { const char *serrno; serrno = err2str(errno); fprintf(stderr, "%s returned %d\n", scall->sd_name, rval); printf("%s\n", serrno); exit(1); } /* Do not output a "0" when more syscalls to come */ if (!more) printf("0\n"); return (i); }
void ADIOI_XFS_Fcntl(ADIO_File fd, int flag, ADIO_Fcntl_t *fcntl_struct, int *error_code) { MPI_Datatype copy_etype, copy_filetype; int combiner, i, j, k, filetype_is_contig, err; ADIOI_Flatlist_node *flat_file; struct flock64 fl; #ifndef PRINT_ERR_MSG static char myname[] = "ADIOI_XFS_FCNTL"; #endif switch(flag) { case ADIO_FCNTL_SET_VIEW: /* free copies of old etypes and filetypes and delete flattened version of filetype if necessary */ MPI_Type_get_envelope(fd->etype, &i, &j, &k, &combiner); if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->etype)); ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); if (!filetype_is_contig) ADIOI_Delete_flattened(fd->filetype); MPI_Type_get_envelope(fd->filetype, &i, &j, &k, &combiner); if (combiner != MPI_COMBINER_NAMED) MPI_Type_free(&(fd->filetype)); /* set new info */ ADIO_SetInfo(fd, fcntl_struct->info, &err); /* set new etypes and filetypes */ MPI_Type_get_envelope(fcntl_struct->etype, &i, &j, &k, &combiner); if (combiner == MPI_COMBINER_NAMED) fd->etype = fcntl_struct->etype; else { MPI_Type_contiguous(1, fcntl_struct->etype, ©_etype); MPI_Type_commit(©_etype); fd->etype = copy_etype; } MPI_Type_get_envelope(fcntl_struct->filetype, &i, &j, &k, &combiner); if (combiner == MPI_COMBINER_NAMED) fd->filetype = fcntl_struct->filetype; else { MPI_Type_contiguous(1, fcntl_struct->filetype, ©_filetype); MPI_Type_commit(©_filetype); fd->filetype = copy_filetype; ADIOI_Flatten_datatype(fd->filetype); /* this function will not flatten the filetype if it turns out to be all contiguous. */ } MPI_Type_size(fd->etype, &(fd->etype_size)); fd->disp = fcntl_struct->disp; /* reset MPI-IO file pointer to point to the first byte that can be accessed in this view. */ ADIOI_Datatype_iscontig(fd->filetype, &filetype_is_contig); if (filetype_is_contig) fd->fp_ind = fcntl_struct->disp; else { flat_file = ADIOI_Flatlist; while (flat_file->type != fd->filetype) flat_file = flat_file->next; for (i=0; i<flat_file->count; i++) { if (flat_file->blocklens[i]) { fd->fp_ind = fcntl_struct->disp + flat_file->indices[i]; break; } } } *error_code = MPI_SUCCESS; break; case ADIO_FCNTL_GET_FSIZE: fcntl_struct->fsize = lseek64(fd->fd_sys, 0, SEEK_END); #ifdef PRINT_ERR_MSG *error_code = (fcntl_struct->fsize == -1) ? MPI_ERR_UNKNOWN : MPI_SUCCESS; #else if (fcntl_struct->fsize == -1) { *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, myname, "I/O Error", "%s", strerror(errno)); ADIOI_Error(fd, *error_code, myname); } else *error_code = MPI_SUCCESS; #endif break; case ADIO_FCNTL_SET_DISKSPACE: i = 0; fl.l_start = 0; fl.l_whence = SEEK_SET; fl.l_len = fcntl_struct->diskspace; err = fcntl(fd->fd_sys, F_RESVSP64, &fl); if (err) i = 1; if (fcntl_struct->diskspace > lseek64(fd->fd_sys, 0, SEEK_END)) { /* also need to set the file size */ err = ftruncate64(fd->fd_sys, fcntl_struct->diskspace); if (err) i = 1; } #ifdef PRINT_ERR_MSG *error_code = (i == 0) ? MPI_SUCCESS : MPI_ERR_UNKNOWN; #else if (i == 1) { *error_code = MPIR_Err_setmsg(MPI_ERR_IO, MPIR_ADIO_ERROR, myname, "I/O Error", "%s", strerror(errno)); ADIOI_Error(fd, *error_code, myname); } else *error_code = MPI_SUCCESS; #endif break; case ADIO_FCNTL_SET_IOMODE: /* for implementing PFS I/O modes. will not occur in MPI-IO implementation.*/ if (fd->iomode != fcntl_struct->iomode) { fd->iomode = fcntl_struct->iomode; MPI_Barrier(MPI_COMM_WORLD); } *error_code = MPI_SUCCESS; break; case ADIO_FCNTL_SET_ATOMICITY: fd->atomicity = (fcntl_struct->atomicity == 0) ? 0 : 1; *error_code = MPI_SUCCESS; break; default: FPRINTF(stderr, "Unknown flag passed to ADIOI_XFS_Fcntl\n"); MPI_Abort(MPI_COMM_WORLD, 1); } }
/* * Do the defragmentation of a single file. * We already are pretty sure we can and want to * defragment the file. Create the tmp file, copy * the data (maintaining holes) and call the kernel * extent swap routinte. */ static int packfile(char *fname, char *tname, int fd, xfs_bstat_t *statp, int do_rt) { int tfd; int srval; int nextents, extent, cur_nextents, new_nextents; unsigned blksz_dio; unsigned dio_min; struct dioattr dio; static xfs_swapext_t sx; struct xfs_flock64 space; off64_t cnt, pos; void *fbuf; int ct, wc, wc_b4; struct fsxattr tfsx; char ffname[SMBUFSZ]; int ffd = 0; /* * Work out the extent map - nextents will be set to the * minimum number of extents needed for the file (taking * into account holes), cur_nextents is the current number * of extents. */ nextents = read_fd_bmap(fd, statp, &cur_nextents); if ( cur_nextents == 1 || cur_nextents <= nextents ) { if (vflag) fsrprintf("%s already fully defragmented.\n", fname); return 1; /* indicates no change/no error */ } if (dflag) fsrprintf("%s extents=%d can_save=%d tmp=%s\n", fname, cur_nextents, (cur_nextents - nextents), tname); if ((tfd = open(tname, openopts, 0666)) < 0) { if (vflag) fsrprintf("could not open tmp as uid %d: %s: %s\n", statp->bs_uid,tname, strerror(errno)); return -1; } unlink(tname); /* Setup extended attributes */ if( statp->bs_xflags & XFS_XFLAG_HASATTR ) { if (attr_setf(tfd, "X", "X", 1, ATTR_CREATE) != 0) { fsrprintf("could not set ATTR on tmp: %s:\n", tname); close(tfd); return -1; } if (dflag) fsrprintf("%s set temp attr\n", tname); } if ((ioctl(tfd, XFS_IOC_DIOINFO, &dio)) < 0 ) { fsrprintf("could not get I/O info on tmp: %s\n", tname); close(tfd); return -1; } if (do_rt) { int rt_textsize = fsgeom.rtextsize * fsgeom.blocksize; tfsx.fsx_xflags = XFS_XFLAG_REALTIME; if ((tfsx.fsx_extsize = rt_textsize) <= 0 ) { fsrprintf("realtime geom not avail for tmp: %s\n", fname); close(tfd); return -1; } if (ioctl( tfd, XFS_IOC_FSSETXATTR, &tfsx) < 0) { fsrprintf("could not set rt on tmp: %s\n", tname); close(tfd); return -1; } } dio_min = dio.d_miniosz; if (statp->bs_size <= dio_min) blksz_dio = dio_min; else { blksz_dio = min(dio.d_maxiosz, BUFFER_MAX - pagesize); if (argv_blksz_dio != 0) blksz_dio = min(argv_blksz_dio, blksz_dio); blksz_dio = (min(statp->bs_size, blksz_dio) / dio_min) * dio_min; } if (dflag) { fsrprintf("DEBUG: fsize=%lld blsz_dio=%d d_min=%d d_max=%d pgsz=%d\n", statp->bs_size, blksz_dio, dio.d_miniosz, dio.d_maxiosz, pagesize); } /* Malloc a buffer */ if (! (fbuf = (char *)memalign(dio.d_mem, blksz_dio))) { fsrprintf("could not allocate buf: %s\n", tname); close(tfd); return -1; } if (nfrags) { /* Create new tmp file in same AG as first */ sprintf(ffname, "%s.frag", tname); /* Open the new file for sync writes */ if ((ffd = open(ffname, openopts, 0666)) < 0) { fsrprintf("could not open fragfile: %s : %s\n", ffname, strerror(errno)); return -1; } unlink(ffname); } /* Loop through block map copying the file. */ for (extent = 0; extent < nextents; extent++) { pos = outmap[extent].bmv_offset; if (outmap[extent].bmv_block == -1) { space.l_whence = 0; space.l_start = pos; space.l_len = outmap[extent].bmv_length; if (ioctl(tfd, XFS_IOC_UNRESVSP64, &space) < 0) { fsrprintf("could not trunc tmp %s\n", tname); } lseek64(tfd, outmap[extent].bmv_length, SEEK_CUR); lseek64(fd, outmap[extent].bmv_length, SEEK_CUR); continue; } else if (outmap[extent].bmv_length == 0) { /* to catch holes at the beginning of the file */ continue; } if (! nfrags) { space.l_whence = SEEK_CUR; space.l_start = 0; space.l_len = outmap[extent].bmv_length; if (ioctl(tfd, XFS_IOC_RESVSP64, &space) < 0) { fsrprintf("could not pre-alloc tmp space: %s\n", tname); close(tfd); free(fbuf); return -1; } } for (cnt = outmap[extent].bmv_length; cnt > 0; cnt -= ct, pos += ct) { if (nfrags && --nfrags) { ct = min(cnt, dio_min); } else if (cnt % dio_min == 0) { ct = min(cnt, blksz_dio); } else { ct = min(cnt + dio_min - (cnt % dio_min), blksz_dio); } ct = read(fd, fbuf, ct); if (ct == 0) { /* EOF, stop trying to read */ extent = nextents; break; } /* Ensure we do direct I/O to correct block * boundaries. */ if (ct % dio_min != 0) { wc = ct + dio_min - (ct % dio_min); } else { wc = ct; } wc_b4 = wc; if (ct < 0 || ((wc = write(tfd, fbuf, wc)) != wc_b4)) { if (ct < 0) fsrprintf("bad read of %d bytes from %s:%s\n", wc_b4, fname, strerror(errno)); else if (wc < 0) fsrprintf("bad write of %d bytes to %s: %s\n", wc_b4, tname, strerror(errno)); else { /* * Might be out of space * * Try to finish write */ int resid = ct-wc; if ((wc = write(tfd, ((char *)fbuf)+wc, resid)) == resid) { /* worked on second attempt? */ continue; } else if (wc < 0) { fsrprintf("bad write2 of %d bytes to %s: %s\n", resid, tname, strerror(errno)); } else { fsrprintf("bad copy to %s\n", tname); } } free(fbuf); return -1; } if (nfrags) { /* Do a matching write to the tmp file */ wc = wc_b4; if (((wc = write(ffd, fbuf, wc)) != wc_b4)) { fsrprintf("bad write of %d bytes " "to %s: %s\n", wc_b4, ffname, strerror(errno)); } } } } ftruncate64(tfd, statp->bs_size); if (ffd) close(ffd); fsync(tfd); free(fbuf); sx.sx_stat = *statp; /* struct copy */ sx.sx_version = XFS_SX_VERSION; sx.sx_fdtarget = fd; sx.sx_fdtmp = tfd; sx.sx_offset = 0; sx.sx_length = statp->bs_size; /* Check if the extent count improved */ new_nextents = getnextents(tfd); if (cur_nextents <= new_nextents) { if (vflag) fsrprintf("No improvement made: %s\n", fname); close(tfd); return 1; /* no change/no error */ } /* Swap the extents */ srval = xfs_swapext(fd, &sx); if (srval < 0) { if (errno == ENOTSUP) { if (vflag || dflag) fsrprintf("%s: file type not supported\n", fname); } else if (errno == EFAULT) { /* The file has changed since we started the copy */ if (vflag || dflag) fsrprintf("%s:file modified defrag aborted\n", fname); } else if (errno == EBUSY) { /* Timestamp has changed or mmap'ed file */ if (vflag || dflag) fsrprintf("%s: file busy \n", fname); } else { fsrprintf("XFS_IOC_SWAPEXT failed: %s: %s\n", fname, strerror(errno)); } close(tfd); return -1; } /* Report progress */ if (vflag) fsrprintf("extents before:%d after:%d %s %s\n", cur_nextents, new_nextents, (new_nextents <= nextents ? "DONE" : " " ), fname); close(tfd); return 0; }
/* * given a fileset entry, determines if the associated file * needs to be allocated or not, and if so does the allocation. */ static int fileset_alloc_file(filesetentry_t *entry) { char path[MAXPATHLEN]; char *buf; struct stat64 sb; char *pathtmp; off64_t seek; int fd; *path = 0; (void) strcpy(path, *entry->fse_fileset->fs_path); (void) strcat(path, "/"); (void) strcat(path, entry->fse_fileset->fs_name); pathtmp = fileset_resolvepath(entry); (void) strcat(path, pathtmp); filebench_log(LOG_DEBUG_IMPL, "Populated %s", entry->fse_path); /* see if reusing and this file exists */ if ((entry->fse_flags & FSE_REUSING) && (stat64(path, &sb) == 0)) { if ((fd = open64(path, O_RDWR)) < 0) { filebench_log(LOG_INFO, "Attempted but failed to Re-use file %s", path); return (-1); } if (sb.st_size == (off64_t)entry->fse_size) { filebench_log(LOG_INFO, "Re-using file %s", path); if (!integer_isset(entry->fse_fileset->fs_cached)) (void) fileset_freemem(fd, entry->fse_size); entry->fse_flags |= FSE_EXISTS; (void) close(fd); return (0); } else if (sb.st_size > (off64_t)entry->fse_size) { /* reuse, but too large */ filebench_log(LOG_INFO, "Truncating & re-using file %s", path); (void) ftruncate64(fd, (off64_t)entry->fse_size); if (!integer_isset(entry->fse_fileset->fs_cached)) (void) fileset_freemem(fd, entry->fse_size); entry->fse_flags |= FSE_EXISTS; (void) close(fd); return (0); } } else { /* No file or not reusing, so create */ if ((fd = open64(path, O_RDWR | O_CREAT, 0644)) < 0) { filebench_log(LOG_ERROR, "Failed to pre-allocate file %s: %s", path, strerror(errno)); return (-1); } } if ((buf = (char *)malloc(FILE_ALLOC_BLOCK)) == NULL) return (-1); entry->fse_flags |= FSE_EXISTS; for (seek = 0; seek < entry->fse_size; ) { off64_t wsize; int ret = 0; /* * Write FILE_ALLOC_BLOCK's worth, * except on last write */ wsize = MIN(entry->fse_size - seek, FILE_ALLOC_BLOCK); ret = write(fd, buf, wsize); if (ret != wsize) { filebench_log(LOG_ERROR, "Failed to pre-allocate file %s: %s", path, strerror(errno)); (void) close(fd); free(buf); return (-1); } seek += wsize; } if (!integer_isset(entry->fse_fileset->fs_cached)) (void) fileset_freemem(fd, entry->fse_size); (void) close(fd); free(buf); filebench_log(LOG_DEBUG_IMPL, "Pre-allocated file %s size %lld", path, entry->fse_size); return (0); }
static void enlarge_archive (struct locarhandle *ah, const struct locarhead *head) { struct stat64 st; int fd; struct locarhead newhead; size_t total; void *p; unsigned int cnt, loccnt; struct namehashent *oldnamehashtab; struct locrecent *oldlocrectab; struct locarhandle new_ah; struct oldlocrecent *oldlocrecarray; size_t prefix_len = output_prefix ? strlen (output_prefix) : 0; char archivefname[prefix_len + sizeof (ARCHIVE_NAME)]; char fname[prefix_len + sizeof (ARCHIVE_NAME) + sizeof (".XXXXXX") - 1]; if (output_prefix) memcpy (archivefname, output_prefix, prefix_len); strcpy (archivefname + prefix_len, ARCHIVE_NAME); strcpy (stpcpy (fname, archivefname), ".XXXXXX"); /* Not all of the old file has to be mapped. Change this now this we will have to access the whole content. */ if (fstat64 (ah->fd, &st) != 0) enomap: error (EXIT_FAILURE, errno, _("cannot map locale archive file")); if (st.st_size < ah->reserved) ah->addr = mmap64 (ah->addr, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, ah->fd, 0); else { munmap (ah->addr, ah->reserved); ah->addr = mmap64 (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, ah->fd, 0); ah->reserved = st.st_size; head = ah->addr; } if (ah->addr == MAP_FAILED) goto enomap; ah->mmaped = st.st_size; /* Create a temporary file in the correct directory. */ fd = mkstemp (fname); if (fd == -1) error (EXIT_FAILURE, errno, _("cannot create temporary file")); /* Copy the existing head information. */ newhead = *head; /* Create the new archive header. The sizes of the various tables should be double from what is currently used. */ newhead.namehash_size = MAX (next_prime (2 * newhead.namehash_used), newhead.namehash_size); if (verbose) printf ("name: size: %u, used: %d, new: size: %u\n", head->namehash_size, head->namehash_used, newhead.namehash_size); newhead.string_offset = (newhead.namehash_offset + (newhead.namehash_size * sizeof (struct namehashent))); /* Keep the string table size aligned to 4 bytes, so that all the struct { uint32_t } types following are happy. */ newhead.string_size = MAX ((2 * newhead.string_used + 3) & -4, newhead.string_size); newhead.locrectab_offset = newhead.string_offset + newhead.string_size; newhead.locrectab_size = MAX (2 * newhead.locrectab_used, newhead.locrectab_size); newhead.sumhash_offset = (newhead.locrectab_offset + (newhead.locrectab_size * sizeof (struct locrecent))); newhead.sumhash_size = MAX (next_prime (2 * newhead.sumhash_used), newhead.sumhash_size); total = (newhead.sumhash_offset + newhead.sumhash_size * sizeof (struct sumhashent)); /* The new file is empty now. */ newhead.namehash_used = 0; newhead.string_used = 0; newhead.locrectab_used = 0; newhead.sumhash_used = 0; /* Write out the header and create room for the other data structures. */ if (TEMP_FAILURE_RETRY (write (fd, &newhead, sizeof (newhead))) != sizeof (newhead)) { int errval = errno; unlink (fname); error (EXIT_FAILURE, errval, _("cannot initialize archive file")); } if (ftruncate64 (fd, total) != 0) { int errval = errno; unlink (fname); error (EXIT_FAILURE, errval, _("cannot resize archive file")); } /* To prepare for enlargements of the mmaped area reserve some address space. */ size_t reserved = RESERVE_MMAP_SIZE; int xflags = 0; if (total < reserved && ((p = mmap64 (NULL, reserved, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0)) != MAP_FAILED)) xflags = MAP_FIXED; else { p = NULL; reserved = total; } /* Map the header and all the administration data structures. */ p = mmap64 (p, total, PROT_READ | PROT_WRITE, MAP_SHARED | xflags, fd, 0); if (p == MAP_FAILED) { int errval = errno; unlink (fname); error (EXIT_FAILURE, errval, _("cannot map archive header")); } /* Lock the new file. */ if (lockf64 (fd, F_LOCK, total) != 0) { int errval = errno; unlink (fname); error (EXIT_FAILURE, errval, _("cannot lock new archive")); } new_ah.mmaped = total; new_ah.addr = p; new_ah.fd = fd; new_ah.reserved = reserved; /* Walk through the hash name hash table to find out what data is still referenced and transfer it into the new file. */ oldnamehashtab = (struct namehashent *) ((char *) ah->addr + head->namehash_offset); oldlocrectab = (struct locrecent *) ((char *) ah->addr + head->locrectab_offset); /* Sort the old locrec table in order of data position. */ oldlocrecarray = alloca (sizeof (*oldlocrecarray) * head->namehash_size); for (cnt = 0, loccnt = 0; cnt < head->namehash_size; ++cnt) if (oldnamehashtab[cnt].locrec_offset != 0) { oldlocrecarray[loccnt].cnt = cnt; oldlocrecarray[loccnt++].locrec = (struct locrecent *) ((char *) ah->addr + oldnamehashtab[cnt].locrec_offset); } qsort (oldlocrecarray, loccnt, sizeof (struct oldlocrecent), oldlocrecentcmp); uint32_t last_locrec_offset = 0; for (cnt = 0; cnt < loccnt; ++cnt) { /* Insert this entry in the new hash table. */ locale_data_t old_data; unsigned int idx; struct locrecent *oldlocrec = oldlocrecarray[cnt].locrec; for (idx = 0; idx < __LC_LAST; ++idx) if (idx != LC_ALL) { old_data[idx].size = oldlocrec->record[idx].len; old_data[idx].addr = ((char *) ah->addr + oldlocrec->record[idx].offset); __md5_buffer (old_data[idx].addr, old_data[idx].size, old_data[idx].sum); } if (cnt > 0 && oldlocrecarray[cnt - 1].locrec == oldlocrec) { const char *oldname = ((char *) ah->addr + oldnamehashtab[oldlocrecarray[cnt - 1].cnt].name_offset); add_alias (&new_ah, ((char *) ah->addr + oldnamehashtab[oldlocrecarray[cnt].cnt].name_offset), 0, oldname, &last_locrec_offset); continue; } last_locrec_offset = add_locale (&new_ah, ((char *) ah->addr + oldnamehashtab[oldlocrecarray[cnt].cnt].name_offset), old_data, 0); if (last_locrec_offset == 0) error (EXIT_FAILURE, 0, _("cannot extend locale archive file")); } /* Make the file globally readable. */ if (fchmod (fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) { int errval = errno; unlink (fname); error (EXIT_FAILURE, errval, _("cannot change mode of resized locale archive")); } /* Rename the new file. */ if (rename (fname, archivefname) != 0) { int errval = errno; unlink (fname); error (EXIT_FAILURE, errval, _("cannot rename new archive")); } /* Close the old file. */ close_archive (ah); /* Add the information for the new one. */ *ah = new_ah; }
static unsigned int call_syscall(struct syscall_desc *scall, char *argv[]) { struct stat64 sb; long long flags; unsigned int i; char *endp; int name, rval; union { char *str; long long num; } args[MAX_ARGS]; #ifdef HAS_FREEBSD_ACL int entry_id = ACL_FIRST_ENTRY; acl_t acl, newacl; acl_entry_t entry, newentry; #endif /* * Verify correctness of the arguments. */ for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) { if (scall->sd_args[i] == TYPE_NONE) { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) break; fprintf(stderr, "too many arguments [%s]\n", argv[i]); exit(1); } else { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) { if (scall->sd_args[i] & TYPE_OPTIONAL) break; fprintf(stderr, "too few arguments\n"); exit(1); } if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) { if (strcmp(argv[i], "NULL") == 0) args[i].str = NULL; else if (strcmp(argv[i], "DEADCODE") == 0) args[i].str = (void *)0xdeadc0de; else args[i].str = argv[i]; } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_NUMBER) { args[i].num = strtoll(argv[i], &endp, 0); if (*endp != '\0' && !isspace((unsigned char)*endp)) { fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); exit(1); } } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_DESCRIPTOR) { if (strcmp(argv[i], "AT_FDCWD") == 0) { args[i].num = AT_FDCWD; } else if (strcmp(argv[i], "BADFD") == 0) { /* In case AT_FDCWD is -1 on some systems... */ if (AT_FDCWD == -1) args[i].num = -2; else args[i].num = -1; } else { int pos; pos = strtoll(argv[i], &endp, 0); if (*endp != '\0' && !isspace((unsigned char)*endp)) { fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); exit(1); } args[i].num = descriptor_get(pos); } } } } /* * Call the given syscall. */ #define NUM(n) (args[(n)].num) #define STR(n) (args[(n)].str) switch (scall->sd_action) { case ACTION_OPEN: flags = str2flags(open_flags, STR(1)); if (flags & O_CREAT) { if (i == 2) { fprintf(stderr, "too few arguments\n"); exit(1); } rval = open(STR(0), (int)flags, (mode_t)NUM(2)); } else { if (i == 3) { fprintf(stderr, "too many arguments\n"); exit(1); } rval = open(STR(0), (int)flags); } if (rval >= 0) descriptor_add(rval); break; case ACTION_OPENAT: flags = str2flags(open_flags, STR(2)); if (flags & O_CREAT) { if (i == 3) { fprintf(stderr, "too few arguments\n"); exit(1); } rval = openat(NUM(0), STR(1), (int)flags, (mode_t)NUM(3)); } else { if (i == 4) { fprintf(stderr, "too many arguments\n"); exit(1); } rval = openat(NUM(0), STR(1), (int)flags); } if (rval >= 0) descriptor_add(rval); break; case ACTION_CREATE: rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1)); if (rval >= 0) close(rval); break; case ACTION_UNLINK: rval = unlink(STR(0)); break; case ACTION_UNLINKAT: rval = unlinkat(NUM(0), STR(1), (int)str2flags(unlinkat_flags, STR(2))); break; case ACTION_MKDIR: rval = mkdir(STR(0), (mode_t)NUM(1)); break; case ACTION_MKDIRAT: rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2)); break; case ACTION_RMDIR: rval = rmdir(STR(0)); break; case ACTION_LINK: rval = link(STR(0), STR(1)); break; case ACTION_LINKAT: rval = linkat(NUM(0), STR(1), NUM(2), STR(3), (int)str2flags(linkat_flags, STR(4))); break; case ACTION_SYMLINK: rval = symlink(STR(0), STR(1)); break; case ACTION_SYMLINKAT: rval = symlinkat(STR(0), NUM(1), STR(2)); break; case ACTION_RENAME: rval = rename(STR(0), STR(1)); break; case ACTION_RENAMEAT: rval = renameat(NUM(0), STR(1), NUM(2), STR(3)); break; case ACTION_MKFIFO: rval = mkfifo(STR(0), (mode_t)NUM(1)); break; case ACTION_MKFIFOAT: rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2)); break; case ACTION_MKNOD: case ACTION_MKNODAT: { mode_t ntype; dev_t dev; int fa; switch (scall->sd_action) { case ACTION_MKNOD: fa = 0; break; case ACTION_MKNODAT: fa = 1; break; default: abort(); } dev = makedev(NUM(fa + 3), NUM(fa + 4)); if (strcmp(STR(fa + 1), "c") == 0) /* character device */ ntype = S_IFCHR; else if (strcmp(STR(fa + 1), "b") == 0) /* block device */ ntype = S_IFBLK; else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */ ntype = S_IFIFO; else if (strcmp(STR(fa + 1), "d") == 0) /* directory */ ntype = S_IFDIR; else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */ ntype = S_IFREG; else { fprintf(stderr, "wrong argument 1\n"); exit(1); } switch (scall->sd_action) { case ACTION_MKNOD: rval = mknod(STR(0), ntype | NUM(2), dev); break; case ACTION_MKNODAT: rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev); break; default: abort(); } break; } case ACTION_BIND: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } #ifdef HAS_BINDAT case ACTION_BINDAT: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } #endif case ACTION_CONNECT: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } #ifdef HAS_CONNECTAT case ACTION_CONNECTAT: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } #endif case ACTION_CHMOD: rval = chmod(STR(0), (mode_t)NUM(1)); break; case ACTION_FCHMOD: rval = fchmod(NUM(0), (mode_t)NUM(1)); break; #ifdef HAS_LCHMOD case ACTION_LCHMOD: rval = lchmod(STR(0), (mode_t)NUM(1)); break; #endif case ACTION_FCHMODAT: rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2), str2flags(fchmodat_flags, STR(3))); break; case ACTION_CHOWN: rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); break; case ACTION_FCHOWN: rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2)); break; case ACTION_LCHOWN: rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); break; case ACTION_FCHOWNAT: rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3), (int)str2flags(fchownat_flags, STR(4))); break; #ifdef HAS_CHFLAGS case ACTION_CHFLAGS: rval = chflags(STR(0), (unsigned long)str2flags(chflags_flags, STR(1))); break; #endif #ifdef HAS_FCHFLAGS case ACTION_FCHFLAGS: rval = fchflags(NUM(0), (unsigned long)str2flags(chflags_flags, STR(1))); break; #endif #ifdef HAS_CHFLAGSAT case ACTION_CHFLAGSAT: rval = chflagsat(NUM(0), STR(1), (unsigned long)str2flags(chflags_flags, STR(2)), (int)str2flags(chflagsat_flags, STR(3))); break; #endif #ifdef HAS_LCHFLAGS case ACTION_LCHFLAGS: rval = lchflags(STR(0), (unsigned long)str2flags(chflags_flags, STR(1))); break; #endif case ACTION_TRUNCATE: rval = truncate64(STR(0), NUM(1)); break; case ACTION_FTRUNCATE: rval = ftruncate64(NUM(0), NUM(1)); break; case ACTION_STAT: rval = stat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_FSTAT: rval = fstat64(NUM(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_LSTAT: rval = lstat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_FSTATAT: rval = fstatat(NUM(0), STR(1), &sb, (int)str2flags(fstatat_flags, STR(2))); if (rval == 0) { show_stats(&sb, STR(3)); return (i); } break; case ACTION_PATHCONF: case ACTION_FPATHCONF: case ACTION_LPATHCONF: { long lrval; name = str2name(pathconf_names, STR(1)); if (name == -1) { fprintf(stderr, "unknown name %s", STR(1)); exit(1); } errno = 0; switch (scall->sd_action) { case ACTION_PATHCONF: lrval = pathconf(STR(0), name); break; case ACTION_FPATHCONF: lrval = fpathconf(NUM(0), name); break; case ACTION_LPATHCONF: lrval = lpathconf(STR(0), name); break; default: abort(); } if (lrval == -1 && errno == 0) { printf("unlimited\n"); return (i); } else if (lrval >= 0) { printf("%ld\n", lrval); return (i); } rval = -1; break; } #ifdef HAS_FREEBSD_ACL case ACTION_PREPENDACL: rval = -1; acl = acl_get_file(STR(0), ACL_TYPE_NFS4); if (acl == NULL) break; newacl = acl_from_text(STR(1)); if (acl == NULL) break; while (acl_get_entry(newacl, entry_id, &newentry) == 1) { entry_id = ACL_NEXT_ENTRY; if (acl_create_entry_np(&acl, &entry, 0)) break; if (acl_copy_entry(entry, newentry)) break; } rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl); break; case ACTION_READACL: acl = acl_get_file(STR(0), ACL_TYPE_NFS4); if (acl == NULL) rval = -1; else rval = 0; break; #endif case ACTION_WRITE: rval = write(NUM(0), STR(1), strlen(STR(1))); break; default: fprintf(stderr, "unsupported syscall\n"); exit(1); } #undef STR #undef NUM if (rval < 0) { const char *serrno; serrno = err2str(errno); fprintf(stderr, "%s returned %d\n", scall->sd_name, rval); printf("%s\n", serrno); exit(1); } printf("0\n"); return (i); }
static void create_archive (const char *archivefname, struct locarhandle *ah) { int fd; char fname[strlen (archivefname) + sizeof (".XXXXXX")]; struct locarhead head; void *p; size_t total; strcpy (stpcpy (fname, archivefname), ".XXXXXX"); /* Create a temporary file in the correct directory. */ fd = mkstemp (fname); if (fd == -1) error (EXIT_FAILURE, errno, _("cannot create temporary file")); /* Create the initial content of the archive. */ head.magic = AR_MAGIC; head.serial = 0; head.namehash_offset = sizeof (struct locarhead); head.namehash_used = 0; head.namehash_size = next_prime (INITIAL_NUM_NAMES); head.string_offset = (head.namehash_offset + head.namehash_size * sizeof (struct namehashent)); head.string_used = 0; head.string_size = INITIAL_SIZE_STRINGS; head.locrectab_offset = head.string_offset + head.string_size; head.locrectab_used = 0; head.locrectab_size = INITIAL_NUM_LOCREC; head.sumhash_offset = (head.locrectab_offset + head.locrectab_size * sizeof (struct locrecent)); head.sumhash_used = 0; head.sumhash_size = next_prime (INITIAL_NUM_SUMS); total = head.sumhash_offset + head.sumhash_size * sizeof (struct sumhashent); /* Write out the header and create room for the other data structures. */ if (TEMP_FAILURE_RETRY (write (fd, &head, sizeof (head))) != sizeof (head)) { int errval = errno; unlink (fname); error (EXIT_FAILURE, errval, _("cannot initialize archive file")); } if (ftruncate64 (fd, total) != 0) { int errval = errno; unlink (fname); error (EXIT_FAILURE, errval, _("cannot resize archive file")); } /* To prepare for enlargements of the mmaped area reserve some address space. */ size_t reserved = RESERVE_MMAP_SIZE; int xflags = 0; if (total < reserved && ((p = mmap64 (NULL, reserved, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0)) != MAP_FAILED)) xflags = MAP_FIXED; else { p = NULL; reserved = total; } /* Map the header and all the administration data structures. */ p = mmap64 (p, total, PROT_READ | PROT_WRITE, MAP_SHARED | xflags, fd, 0); if (p == MAP_FAILED) { int errval = errno; unlink (fname); error (EXIT_FAILURE, errval, _("cannot map archive header")); } /* Now try to rename it. We don't use the rename function since this would overwrite a file which has been created in parallel. */ if (link (fname, archivefname) == -1) { int errval = errno; /* We cannot use the just created file. */ close (fd); unlink (fname); if (errval == EEXIST) { /* There is already an archive. Must have been a localedef run which happened in parallel. Simply open this file then. */ open_archive (ah, false); return; } error (EXIT_FAILURE, errval, _("failed to create new locale archive")); } /* Remove the temporary name. */ unlink (fname); /* Make the file globally readable. */ if (fchmod (fd, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) { int errval = errno; unlink (archivefname); error (EXIT_FAILURE, errval, _("cannot change mode of new locale archive")); } ah->fd = fd; ah->addr = p; ah->mmaped = total; ah->reserved = reserved; }
static int usd_FileIoctl(usd_handle_t usd, int req, void *arg) { int fd = (intptr_t)(usd->handle); #ifdef O_LARGEFILE struct stat64 info; #else /* O_LARGEFILE */ struct stat info; #endif /* O_LARGEFILE */ #ifdef AFS_AIX_ENV struct statfs fsinfo; /* AIX stat structure doesn't have st_blksize */ #endif /* AFS_AIX_ENV */ afs_int64 size; int code = 0; switch (req) { case USD_IOCTL_GETBLKSIZE: #ifdef AFS_AIX_ENV code = fstatfs(fd, &fsinfo); if (code) { *((long *)arg) = (long)4096; return 0; } break; #endif /* AFS_AIX_ENV */ case USD_IOCTL_GETTYPE: case USD_IOCTL_GETDEV: case USD_IOCTL_GETSIZE: #ifdef O_LARGEFILE code = fstat64(fd, &info); #else /* O_LARGEFILE */ code = fstat(fd, &info); #endif /* O_LARGEFILE */ if (code) return errno; break; } switch (req) { case USD_IOCTL_GETTYPE: *(int *)arg = info.st_mode & S_IFMT; break; case USD_IOCTL_GETDEV: if (!(S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode))) return ENODEV; /* not a device */ *(dev_t *) arg = info.st_rdev; break; case USD_IOCTL_GETSIZE: if (S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode)) return ENOTTY; /* shouldn't be a device */ *(afs_int64 *)arg = info.st_size; break; case USD_IOCTL_GETFULLNAME: *(char **)arg = usd->fullPathName; break; case USD_IOCTL_SETSIZE: /* We could just use ftruncate in all cases. (This even works on AIX; * I tried it). -blake 931118 */ /* However, I'm pretty sure this doesn't work on Ultrix so I am * unsure about OSF/1 and HP/UX. 931118 */ size = *(afs_int64 *) arg; if (!osi_hFitsInOff(size)) return EFBIG; #ifdef O_LARGEFILE code = ftruncate64(fd, size); #else /* O_LARGEFILE */ code = ftruncate(fd, size); #endif /* O_LARGEFILE */ if (code == -1) code = errno; return code; case USD_IOCTL_TAPEOPERATION: { #ifdef AFS_DARWIN100_ENV code = EOPNOTSUPP; #else usd_tapeop_t *tapeOpp = (usd_tapeop_t *) arg; #if defined(AFS_AIX_ENV) struct stop os_tapeop; if (tapeOpp->tp_op == USDTAPE_WEOF) { os_tapeop.st_op = STWEOF; } else if (tapeOpp->tp_op == USDTAPE_REW) { os_tapeop.st_op = STREW; } else if (tapeOpp->tp_op == USDTAPE_FSF) { os_tapeop.st_op = STFSF; } else if (tapeOpp->tp_op == USDTAPE_BSF) { os_tapeop.st_op = STRSF; } else if (tapeOpp->tp_op == USDTAPE_PREPARE) { return 0; } else if (tapeOpp->tp_op == USDTAPE_SHUTDOWN) { return 0; } else { /* unsupported tape operation */ return EINVAL; } os_tapeop.st_count = tapeOpp->tp_count; code = ioctl(fd, STIOCTOP, &os_tapeop); #else struct mtop os_tapeop; if (tapeOpp->tp_op == USDTAPE_WEOF) { os_tapeop.mt_op = MTWEOF; } else if (tapeOpp->tp_op == USDTAPE_REW) { os_tapeop.mt_op = MTREW; } else if (tapeOpp->tp_op == USDTAPE_FSF) { os_tapeop.mt_op = MTFSF; } else if (tapeOpp->tp_op == USDTAPE_BSF) { os_tapeop.mt_op = MTBSF; } else if (tapeOpp->tp_op == USDTAPE_PREPARE) { return 0; } else if (tapeOpp->tp_op == USDTAPE_SHUTDOWN) { return 0; } else { /* unsupported tape operation */ return EINVAL; } os_tapeop.mt_count = tapeOpp->tp_count; code = ioctl(fd, MTIOCTOP, &os_tapeop); #endif /* AFS_AIX_ENV */ #endif if (code == -1) { code = errno; } else { code = 0; } return code; } case USD_IOCTL_GETBLKSIZE: if (S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode)) { *((long *)arg) = (long)4096; return 0; } #ifdef AFS_AIX_ENV *((long *)arg) = (long)fsinfo.f_bsize; #else /* AFS_AIX_ENV */ *((long *)arg) = (long)info.st_blksize; #endif /* AFS_AIX_ENV */ break; default: return EINVAL; } return code; }
int main (int argc, char ** argv) { errcode_t retval; ext2_filsys fs; int c; int flags = 0; int flush = 0; int force = 0; int io_flags = 0; int force_min_size = 0; int print_min_size = 0; int fd, ret; blk64_t new_size = 0; blk64_t max_size = 0; blk64_t min_size = 0; io_manager io_ptr; char *new_size_str = 0; int use_stride = -1; ext2fs_struct_stat st_buf; __s64 new_file_size; unsigned int sys_page_size = 4096; long sysval; int len, mount_flags; char *mtpt; #ifdef ENABLE_NLS setlocale(LC_MESSAGES, ""); setlocale(LC_CTYPE, ""); bindtextdomain(NLS_CAT_NAME, LOCALEDIR); textdomain(NLS_CAT_NAME); set_com_err_gettext(gettext); #endif add_error_table(&et_ext2_error_table); fprintf (stderr, "resize2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); if (argc && *argv) program_name = *argv; while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) { switch (c) { case 'h': usage(program_name); break; case 'f': force = 1; break; case 'F': flush = 1; break; case 'M': force_min_size = 1; break; case 'P': print_min_size = 1; break; case 'd': flags |= atoi(optarg); break; case 'p': flags |= RESIZE_PERCENT_COMPLETE; break; case 'S': use_stride = atoi(optarg); break; default: usage(program_name); } } if (optind == argc) usage(program_name); device_name = argv[optind++]; if (optind < argc) new_size_str = argv[optind++]; if (optind < argc) usage(program_name); io_options = strchr(device_name, '?'); if (io_options) *io_options++ = 0; /* * Figure out whether or not the device is mounted, and if it is * where it is mounted. */ len=80; while (1) { mtpt = malloc(len); if (!mtpt) return ENOMEM; mtpt[len-1] = 0; retval = ext2fs_check_mount_point(device_name, &mount_flags, mtpt, len); if (retval) { com_err("ext2fs_check_mount_point", retval, _("while determining whether %s is mounted."), device_name); exit(1); } if (!(mount_flags & EXT2_MF_MOUNTED) || (mtpt[len-1] == 0)) break; free(mtpt); len = 2 * len; } fd = ext2fs_open_file(device_name, O_RDWR, 0); if (fd < 0) { com_err("open", errno, _("while opening %s"), device_name); exit(1); } ret = ext2fs_fstat(fd, &st_buf); if (ret < 0) { com_err("open", errno, _("while getting stat information for %s"), device_name); exit(1); } if (flush) { retval = ext2fs_sync_device(fd, 1); if (retval) { com_err(argv[0], retval, _("while trying to flush %s"), device_name); exit(1); } } if (!S_ISREG(st_buf.st_mode )) { close(fd); fd = -1; } #ifdef CONFIG_TESTIO_DEBUG if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { io_ptr = test_io_manager; test_io_backing_manager = unix_io_manager; } else #endif io_ptr = unix_io_manager; if (!(mount_flags & EXT2_MF_MOUNTED)) io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE; io_flags |= EXT2_FLAG_64BITS; retval = ext2fs_open2(device_name, io_options, io_flags, 0, 0, io_ptr, &fs); if (retval) { com_err (program_name, retval, _("while trying to open %s"), device_name); printf (_("Couldn't find valid filesystem superblock.\n")); exit (1); } /* * Check for compatibility with the feature sets. We need to * be more stringent than ext2fs_open(). */ if (fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) { com_err(program_name, EXT2_ET_UNSUPP_FEATURE, "(%s)", device_name); exit(1); } min_size = calculate_minimum_resize_size(fs); if (print_min_size) { if (!force && ((fs->super->s_state & EXT2_ERROR_FS) || ((fs->super->s_state & EXT2_VALID_FS) == 0))) { fprintf(stderr, _("Please run 'e2fsck -f %s' first.\n\n"), device_name); exit(1); } printf(_("Estimated minimum size of the filesystem: %llu\n"), min_size); exit(0); } /* Determine the system page size if possible */ #ifdef HAVE_SYSCONF #if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE)) #define _SC_PAGESIZE _SC_PAGE_SIZE #endif #ifdef _SC_PAGESIZE sysval = sysconf(_SC_PAGESIZE); if (sysval > 0) sys_page_size = sysval; #endif /* _SC_PAGESIZE */ #endif /* HAVE_SYSCONF */ /* * Get the size of the containing partition, and use this for * defaults and for making sure the new filesystem doesn't * exceed the partition size. */ retval = ext2fs_get_device_size2(device_name, fs->blocksize, &max_size); if (retval) { com_err(program_name, retval, _("while trying to determine filesystem size")); exit(1); } if (force_min_size) new_size = min_size; else if (new_size_str) { new_size = parse_num_blocks2(new_size_str, fs->super->s_log_block_size); if (new_size == 0) { com_err(program_name, 0, _("Invalid new size: %s\n"), new_size_str); exit(1); } } else { new_size = max_size; /* Round down to an even multiple of a pagesize */ if (sys_page_size > fs->blocksize) new_size &= ~((sys_page_size / fs->blocksize)-1); } if (!EXT2_HAS_INCOMPAT_FEATURE(fs->super, EXT4_FEATURE_INCOMPAT_64BIT)) { /* Take 16T down to 2^32-1 blocks */ if (new_size == (1ULL << 32)) new_size--; else if (new_size > (1ULL << 32)) { com_err(program_name, 0, _("New size too large to be " "expressed in 32 bits\n")); exit(1); } } if (!force && new_size < min_size) { com_err(program_name, 0, _("New size smaller than minimum (%llu)\n"), min_size); exit(1); } if (use_stride >= 0) { if (use_stride >= (int) fs->super->s_blocks_per_group) { com_err(program_name, 0, _("Invalid stride length")); exit(1); } fs->stride = fs->super->s_raid_stride = use_stride; ext2fs_mark_super_dirty(fs); } else determine_fs_stride(fs); /* * If we are resizing a plain file, and it's not big enough, * automatically extend it in a sparse fashion by writing the * last requested block. */ new_file_size = ((__u64) new_size) * fs->blocksize; if ((__u64) new_file_size > (((__u64) 1) << (sizeof(st_buf.st_size)*8 - 1)) - 1) fd = -1; if ((new_file_size > st_buf.st_size) && (fd > 0)) { if ((ext2fs_llseek(fd, new_file_size-1, SEEK_SET) >= 0) && (write(fd, "0", 1) == 1)) max_size = new_size; } if (!force && (new_size > max_size)) { fprintf(stderr, _("The containing partition (or device)" " is only %llu (%dk) blocks.\nYou requested a new size" " of %llu blocks.\n\n"), max_size, fs->blocksize / 1024, new_size); exit(1); } if (new_size == ext2fs_blocks_count(fs->super)) { fprintf(stderr, _("The filesystem is already %llu blocks " "long. Nothing to do!\n\n"), new_size); exit(0); } if (mount_flags & EXT2_MF_MOUNTED) { retval = online_resize_fs(fs, mtpt, &new_size, flags); } else { if (!force && ((fs->super->s_lastcheck < fs->super->s_mtime) || (fs->super->s_state & EXT2_ERROR_FS) || ((fs->super->s_state & EXT2_VALID_FS) == 0))) { fprintf(stderr, _("Please run 'e2fsck -f %s' first.\n\n"), device_name); exit(1); } /* * XXXX The combination of flex_bg and !resize_inode * causes major problems for resize2fs, since when the * group descriptors grow in size this can potentially * require multiple inode tables to be moved aside to * make room, and resize2fs chokes rather badly in * this scenario. It's a rare combination, except * when a filesystem is expanded more than a certain * size, so for now, we'll just prohibit that * combination. This is something we should fix * eventually, though. */ if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) && !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE)) { com_err(program_name, 0, _("%s: The combination of " "flex_bg and\n\t!resize_inode features " "is not supported by resize2fs.\n"), device_name); exit(1); } printf(_("Resizing the filesystem on " "%s to %llu (%dk) blocks.\n"), device_name, new_size, fs->blocksize / 1024); retval = resize_fs(fs, &new_size, flags, ((flags & RESIZE_PERCENT_COMPLETE) ? resize_progress_func : 0)); } free(mtpt); if (retval) { com_err(program_name, retval, _("while trying to resize %s"), device_name); fprintf(stderr, _("Please run 'e2fsck -fy %s' to fix the filesystem\n" "after the aborted resize operation.\n"), device_name); ext2fs_close(fs); exit(1); } printf(_("The filesystem on %s is now %llu blocks long.\n\n"), device_name, new_size); if ((st_buf.st_size > new_file_size) && (fd > 0)) { #ifdef HAVE_FTRUNCATE64 retval = ftruncate64(fd, new_file_size); #else retval = 0; /* Only truncate if new_file_size doesn't overflow off_t */ if (((off_t) new_file_size) == new_file_size) retval = ftruncate(fd, (off_t) new_file_size); #endif if (retval) com_err(program_name, retval, _("while trying to truncate %s"), device_name); } if (fd > 0) close(fd); remove_error_table(&et_ext2_error_table); return (0); }
nh_t node_alloc( void ) { nix_t nix; u_char_t *p; nh_t nh; register nix_t *linkagep; #ifdef NODECHK register u_char_t *hkpp; register u_char_t gen; register u_char_t unq; #endif /* NODECHK */ /* if free list is depleted, map in a new window at the * end of backing store. put all nodes on free list. * initialize the gen count to the node index, and the unique * pattern to the free pattern. */ if ( node_hdrp->nh_freenix == NIX_NULL ) { nix_t virgbegnix; /* abs. nix of first node in virg seg */ nix_t virgendnix; /* abs. nix of next node after last */ nix_t sacrcnt; /* how many virgins to put on free list */ nix_t sacrnix; ASSERT( node_hdrp->nh_virgrelnix < ( nix_t )node_hdrp->nh_nodesperseg ); virgbegnix = OFF2NIX( node_hdrp->nh_virgsegreloff ) + node_hdrp->nh_virgrelnix; virgendnix = OFF2NIX( ( node_hdrp->nh_virgsegreloff + ( off64_t )node_hdrp->nh_segsz ) ); #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "node_alloc(): create freelist - " "virg_begin=%lld virg_end=%lld\n", virgbegnix, virgendnix); #endif ASSERT( virgendnix > virgbegnix ); sacrcnt = min( VIRGSACRMAX, virgendnix - virgbegnix ); ASSERT( sacrcnt >= 1 ); p = 0; /* keep lint happy */ win_map( NIX2OFF( virgbegnix ), ( void ** )&p ); if (p == NULL) return NH_NULL; node_hdrp->nh_freenix = virgbegnix; for ( sacrnix = virgbegnix ; sacrnix < virgbegnix + sacrcnt - 1 ; p += node_hdrp->nh_nodesz, sacrnix++ ) { linkagep = ( nix_t * )p; *linkagep = sacrnix + 1; #ifdef NODECHK hkpp = p + node_hdrp->nh_nodehkix; gen = ( u_char_t )sacrnix; *hkpp = ( u_char_t )HKPMKHKP( ( size_t )gen, NODEUNQFREE ); #endif /* NODECHK */ } linkagep = ( nix_t * )p; *linkagep = NIX_NULL; #ifdef NODECHK hkpp = p + node_hdrp->nh_nodehkix; gen = ( u_char_t )sacrnix; *hkpp = HKPMKHKP( gen, NODEUNQFREE ); #endif /* NODECHK */ node_hdrp->nh_virgrelnix += sacrcnt; win_unmap( node_hdrp->nh_virgsegreloff, ( void ** )&p ); if ( node_hdrp->nh_virgrelnix >= ( nix_t )node_hdrp->nh_nodesperseg ) { intgen_t rval; ASSERT( node_hdrp->nh_virgrelnix == ( nix_t )node_hdrp->nh_nodesperseg ); ASSERT( node_hdrp->nh_virgsegreloff <= OFF64MAX - ( off64_t )node_hdrp->nh_segsz ); #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "node_alloc(): runout of nodes for freelist in " "this segment - nodes used = %lld\n", node_hdrp->nh_virgrelnix); #endif node_hdrp->nh_virgsegreloff += ( off64_t )node_hdrp->nh_segsz; node_hdrp->nh_virgrelnix = 0; mlog( MLOG_DEBUG, "pre-growing new node array segment at %lld " "size %lld\n", node_hdrp->nh_firstsegoff + node_hdrp->nh_virgsegreloff + ( off64_t )node_hdrp->nh_segsz, ( off64_t )node_hdrp->nh_segsz ); rval = ftruncate64( node_fd, node_hdrp->nh_firstsegoff + node_hdrp->nh_virgsegreloff + ( off64_t )node_hdrp->nh_segsz ); if ( rval ) { mlog( MLOG_NORMAL | MLOG_WARNING | MLOG_TREE, _( "unable to autogrow node segment %llu: " "%s (%d)\n"), node_hdrp->nh_virgsegreloff / ( off64_t )node_hdrp->nh_segsz, strerror( errno ), errno ); } } } /* map in window containing node at top of free list, * and adjust free list. */ nix = node_hdrp->nh_freenix; #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "node_alloc(): win_map(%llu) and get head from node freelist\n", NIX2OFF(nix)); #endif win_map( NIX2OFF( nix ), ( void ** )&p ); if (p == NULL) return NH_NULL; #ifdef NODECHK hkpp = p + node_hdrp->nh_nodehkix; unq = HKPGETUNQ( *hkpp ); ASSERT( unq != NODEUNQALCD ); ASSERT( unq == NODEUNQFREE ); #endif /* NODECHK */ linkagep = ( nix_t * )p; node_hdrp->nh_freenix = *linkagep; /* clean the node */ memset( ( void * )p, 0, node_hdrp->nh_nodesz ); /* build a handle for node */ ASSERT( nix <= NIX_MAX ); #ifdef NODECHK hkpp = p + ( int )node_hdrp->nh_nodehkix; gen = ( u_char_t )( HKPGETGEN( *p ) + ( u_char_t )1 ); nh = HDLMKHDL( gen, nix ); *hkpp = HKPMKHKP( gen, NODEUNQALCD ); #else /* NODECHK */ nh = ( nh_t )nix; #endif /* NODECHK */ /* unmap window */ #ifdef TREE_DEBUG mlog(MLOG_DEBUG | MLOG_TREE, "node_alloc(): win_unmap(%llu)\n", NIX2OFF(nix)); #endif win_unmap( NIX2OFF( nix ), ( void ** )&p ); return nh; }
sem_t * sem_open(const char *path, int oflag, /* mode_t mode, int value */ ...) { va_list ap; mode_t crmode = 0; sem_t *sem = NULL; struct stat64 statbuf; semaddr_t *next = NULL; int fd = 0; int error = 0; int cr_flag = 0; uint_t value = 0; if (__pos4obj_check(path) == -1) return (SEM_FAILED); /* acquire semaphore lock to have atomic operation */ if (__pos4obj_lock(path, SEM_LOCK_TYPE) < 0) return (SEM_FAILED); /* modify oflag to have RDWR and filter CREATE mode only */ oflag = (oflag & (O_CREAT|O_EXCL)) | (O_RDWR); if (oflag & O_CREAT) { if (semvaluemax == 0 && (semvaluemax = _sysconf(_SC_SEM_VALUE_MAX)) <= 0) semvaluemax = -1; va_start(ap, oflag); crmode = va_arg(ap, mode_t); value = va_arg(ap, uint_t); va_end(ap); /* check value < the max for a named semaphore */ if (semvaluemax < 0 || (ulong_t)value > (ulong_t)semvaluemax) { errno = EINVAL; goto out; } } errno = 0; if ((fd = __pos4obj_open(path, SEM_DATA_TYPE, oflag, crmode, &cr_flag)) < 0) goto out; if (cr_flag) cr_flag = DFILE_CREATE | DFILE_OPEN; else cr_flag = DFILE_OPEN; /* find out inode # for the opened file */ if (fstat64(fd, &statbuf) < 0) goto out; /* if created, acquire total_size in the file */ if ((cr_flag & DFILE_CREATE) != 0) { if (ftruncate64(fd, (off64_t)sizeof (sem_t)) < 0) goto out; } else { /* * if this semaphore has already been opened, inode * will indicate then return the same semaphore address */ lmutex_lock(&semlock); for (next = semheadp; next != NULL; next = next->sad_next) { if (statbuf.st_ino == next->sad_inode && strcmp(path, next->sad_name) == 0) { (void) __close_nc(fd); lmutex_unlock(&semlock); (void) __pos4obj_unlock(path, SEM_LOCK_TYPE); return (next->sad_addr); } } lmutex_unlock(&semlock); } /* new sem descriptor to be allocated and new address to be mapped */ if ((next = malloc(sizeof (semaddr_t))) == NULL) { errno = ENOMEM; goto out; } cr_flag |= ALLOC_MEM; /* LINTED */ sem = (sem_t *)mmap64(NULL, sizeof (sem_t), PROT_READ|PROT_WRITE, MAP_SHARED, fd, (off64_t)0); (void) __close_nc(fd); cr_flag &= ~DFILE_OPEN; if (sem == MAP_FAILED) goto out; cr_flag |= DFILE_MMAP; /* if created, initialize */ if (cr_flag & DFILE_CREATE) { error = sema_init((sema_t *)sem, value, USYNC_PROCESS, 0); if (error) { errno = error; goto out; } } if (__pos4obj_unlock(path, SEM_LOCK_TYPE) == 0) { /* add to the list pointed by semheadp */ lmutex_lock(&semlock); next->sad_next = semheadp; semheadp = next; next->sad_addr = sem; next->sad_inode = statbuf.st_ino; (void) strcpy(next->sad_name, path); lmutex_unlock(&semlock); return (sem); } /* fall into the error case */ out: error = errno; if ((cr_flag & DFILE_OPEN) != 0) (void) __close_nc(fd); if ((cr_flag & DFILE_CREATE) != 0) (void) __pos4obj_unlink(path, SEM_DATA_TYPE); if ((cr_flag & ALLOC_MEM) != 0) free(next); if ((cr_flag & DFILE_MMAP) != 0) (void) munmap((caddr_t)sem, sizeof (sem_t)); (void) __pos4obj_unlock(path, SEM_LOCK_TYPE); errno = error; return (SEM_FAILED); }
int main (int argc, char ** argv) { errcode_t retval; ext2_filsys fs; int c; int flags = 0; int flush = 0; int force = 0; int io_flags = 0; int force_min_size = 0; int print_min_size = 0; int fd, ret; blk64_t new_size = 0; blk64_t max_size = 0; blk64_t min_size = 0; io_manager io_ptr; char *new_size_str = 0; int use_stride = -1; ext2fs_struct_stat st_buf; __s64 new_file_size; unsigned int sys_page_size = 4096; unsigned int blocksize; long sysval; int len, mount_flags; char *mtpt, *undo_file = NULL; #ifdef ENABLE_NLS setlocale(LC_MESSAGES, ""); setlocale(LC_CTYPE, ""); bindtextdomain(NLS_CAT_NAME, LOCALEDIR); textdomain(NLS_CAT_NAME); set_com_err_gettext(gettext); #endif add_error_table(&et_ext2_error_table); fprintf (stderr, "resize2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); if (argc && *argv) program_name = *argv; while ((c = getopt(argc, argv, "d:fFhMPpS:bsz:")) != EOF) { switch (c) { case 'h': usage(program_name); break; case 'f': force = 1; break; case 'F': flush = 1; break; case 'M': force_min_size = 1; break; case 'P': print_min_size = 1; break; case 'd': flags |= atoi(optarg); break; case 'p': flags |= RESIZE_PERCENT_COMPLETE; break; case 'S': use_stride = atoi(optarg); break; case 'b': flags |= RESIZE_ENABLE_64BIT; break; case 's': flags |= RESIZE_DISABLE_64BIT; break; case 'z': undo_file = optarg; break; default: usage(program_name); } } if (optind == argc) usage(program_name); device_name = argv[optind++]; if (optind < argc) new_size_str = argv[optind++]; if (optind < argc) usage(program_name); io_options = strchr(device_name, '?'); if (io_options) *io_options++ = 0; /* * Figure out whether or not the device is mounted, and if it is * where it is mounted. */ len=80; while (1) { mtpt = malloc(len); if (!mtpt) return ENOMEM; mtpt[len-1] = 0; retval = ext2fs_check_mount_point(device_name, &mount_flags, mtpt, len); if (retval) { com_err("ext2fs_check_mount_point", retval, _("while determining whether %s is mounted."), device_name); exit(1); } if (!(mount_flags & EXT2_MF_MOUNTED) || (mtpt[len-1] == 0)) break; free(mtpt); len = 2 * len; } fd = ext2fs_open_file(device_name, O_RDWR, 0); if (fd < 0) { com_err("open", errno, _("while opening %s"), device_name); exit(1); } ret = ext2fs_fstat(fd, &st_buf); if (ret < 0) { com_err("open", errno, _("while getting stat information for %s"), device_name); exit(1); } if (flush) { retval = ext2fs_sync_device(fd, 1); if (retval) { com_err(argv[0], retval, _("while trying to flush %s"), device_name); exit(1); } } if (!S_ISREG(st_buf.st_mode )) { close(fd); fd = -1; } #ifdef CONFIG_TESTIO_DEBUG if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { io_ptr = test_io_manager; test_io_backing_manager = unix_io_manager; } else #endif io_ptr = unix_io_manager; if (!(mount_flags & EXT2_MF_MOUNTED)) io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE; io_flags |= EXT2_FLAG_64BITS; if (undo_file) { retval = resize2fs_setup_tdb(device_name, undo_file, &io_ptr); if (retval) exit(1); } retval = ext2fs_open2(device_name, io_options, io_flags, 0, 0, io_ptr, &fs); if (retval) { com_err(program_name, retval, _("while trying to open %s"), device_name); printf("%s", _("Couldn't find valid filesystem superblock.\n")); exit (1); } fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE; /* * Before acting on an unmounted filesystem, make sure it's ok, * unless the user is forcing it. * * We do ERROR and VALID checks even if we're only printing the * minimimum size, because traversal of a badly damaged filesystem * can cause issues as well. We don't require it to be fscked after * the last mount time in this case, though, as this is a bit less * risky. */ if (!force && !(mount_flags & EXT2_MF_MOUNTED)) { int checkit = 0; if (fs->super->s_state & EXT2_ERROR_FS) checkit = 1; if ((fs->super->s_state & EXT2_VALID_FS) == 0) checkit = 1; if ((fs->super->s_lastcheck < fs->super->s_mtime) && !print_min_size) checkit = 1; if (checkit) { fprintf(stderr, _("Please run 'e2fsck -f %s' first.\n\n"), device_name); exit(1); } } /* * Check for compatibility with the feature sets. We need to * be more stringent than ext2fs_open(). */ if (fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) { com_err(program_name, EXT2_ET_UNSUPP_FEATURE, "(%s)", device_name); exit(1); } min_size = calculate_minimum_resize_size(fs, flags); if (print_min_size) { printf(_("Estimated minimum size of the filesystem: %llu\n"), min_size); exit(0); } /* Determine the system page size if possible */ #ifdef HAVE_SYSCONF #if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE)) #define _SC_PAGESIZE _SC_PAGE_SIZE #endif #ifdef _SC_PAGESIZE sysval = sysconf(_SC_PAGESIZE); if (sysval > 0) sys_page_size = sysval; #endif /* _SC_PAGESIZE */ #endif /* HAVE_SYSCONF */ /* * Get the size of the containing partition, and use this for * defaults and for making sure the new filesystem doesn't * exceed the partition size. */ blocksize = fs->blocksize; retval = ext2fs_get_device_size2(device_name, blocksize, &max_size); if (retval) { com_err(program_name, retval, "%s", _("while trying to determine filesystem size")); exit(1); } if (force_min_size) new_size = min_size; else if (new_size_str) { new_size = parse_num_blocks2(new_size_str, fs->super->s_log_block_size); if (new_size == 0) { com_err(program_name, 0, _("Invalid new size: %s\n"), new_size_str); exit(1); } } else { new_size = max_size; /* Round down to an even multiple of a pagesize */ if (sys_page_size > blocksize) new_size &= ~((sys_page_size / blocksize)-1); } /* If changing 64bit, don't change the filesystem size. */ if (flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)) { new_size = ext2fs_blocks_count(fs->super); } if (!ext2fs_has_feature_64bit(fs->super)) { /* Take 16T down to 2^32-1 blocks */ if (new_size == (1ULL << 32)) new_size--; else if (new_size > (1ULL << 32)) { com_err(program_name, 0, "%s", _("New size too large to be " "expressed in 32 bits\n")); exit(1); } } if (!force && new_size < min_size) { com_err(program_name, 0, _("New size smaller than minimum (%llu)\n"), min_size); exit(1); } if (use_stride >= 0) { if (use_stride >= (int) fs->super->s_blocks_per_group) { com_err(program_name, 0, "%s", _("Invalid stride length")); exit(1); } fs->stride = fs->super->s_raid_stride = use_stride; ext2fs_mark_super_dirty(fs); } else determine_fs_stride(fs); /* * If we are resizing a plain file, and it's not big enough, * automatically extend it in a sparse fashion by writing the * last requested block. */ new_file_size = ((__u64) new_size) * blocksize; if ((__u64) new_file_size > (((__u64) 1) << (sizeof(st_buf.st_size)*8 - 1)) - 1) fd = -1; if ((new_file_size > st_buf.st_size) && (fd > 0)) { if ((ext2fs_llseek(fd, new_file_size-1, SEEK_SET) >= 0) && (write(fd, "0", 1) == 1)) max_size = new_size; } if (!force && (new_size > max_size)) { fprintf(stderr, _("The containing partition (or device)" " is only %llu (%dk) blocks.\nYou requested a new size" " of %llu blocks.\n\n"), max_size, blocksize / 1024, new_size); exit(1); } if ((flags & RESIZE_DISABLE_64BIT) && (flags & RESIZE_ENABLE_64BIT)) { fprintf(stderr, _("Cannot set and unset 64bit feature.\n")); exit(1); } else if (flags & (RESIZE_DISABLE_64BIT | RESIZE_ENABLE_64BIT)) { if (new_size >= (1ULL << 32)) { fprintf(stderr, _("Cannot change the 64bit feature " "on a filesystem that is larger than " "2^32 blocks.\n")); exit(1); } if (mount_flags & EXT2_MF_MOUNTED) { fprintf(stderr, _("Cannot change the 64bit feature " "while the filesystem is mounted.\n")); exit(1); } if (flags & RESIZE_ENABLE_64BIT && !ext2fs_has_feature_extents(fs->super)) { fprintf(stderr, _("Please enable the extents feature " "with tune2fs before enabling the 64bit " "feature.\n")); exit(1); } } else if (new_size == ext2fs_blocks_count(fs->super)) { fprintf(stderr, _("The filesystem is already %llu (%dk) " "blocks long. Nothing to do!\n\n"), new_size, blocksize / 1024); exit(0); } if ((flags & RESIZE_ENABLE_64BIT) && ext2fs_has_feature_64bit(fs->super)) { fprintf(stderr, _("The filesystem is already 64-bit.\n")); exit(0); } if ((flags & RESIZE_DISABLE_64BIT) && !ext2fs_has_feature_64bit(fs->super)) { fprintf(stderr, _("The filesystem is already 32-bit.\n")); exit(0); } if (mount_flags & EXT2_MF_MOUNTED) { bigalloc_check(fs, force); retval = online_resize_fs(fs, mtpt, &new_size, flags); } else { bigalloc_check(fs, force); if (flags & RESIZE_ENABLE_64BIT) printf(_("Converting the filesystem to 64-bit.\n")); else if (flags & RESIZE_DISABLE_64BIT) printf(_("Converting the filesystem to 32-bit.\n")); else printf(_("Resizing the filesystem on " "%s to %llu (%dk) blocks.\n"), device_name, new_size, blocksize / 1024); retval = resize_fs(fs, &new_size, flags, ((flags & RESIZE_PERCENT_COMPLETE) ? resize_progress_func : 0)); } free(mtpt); if (retval) { com_err(program_name, retval, _("while trying to resize %s"), device_name); fprintf(stderr, _("Please run 'e2fsck -fy %s' to fix the filesystem\n" "after the aborted resize operation.\n"), device_name); ext2fs_close_free(&fs); exit(1); } printf(_("The filesystem on %s is now %llu (%dk) blocks long.\n\n"), device_name, new_size, blocksize / 1024); if ((st_buf.st_size > new_file_size) && (fd > 0)) { #ifdef HAVE_FTRUNCATE64 retval = ftruncate64(fd, new_file_size); #else retval = 0; /* Only truncate if new_file_size doesn't overflow off_t */ if (((off_t) new_file_size) == new_file_size) retval = ftruncate(fd, (off_t) new_file_size); #endif if (retval) com_err(program_name, retval, _("while trying to truncate %s"), device_name); } if (fd > 0) close(fd); remove_error_table(&et_ext2_error_table); return (0); }