/* * Set the he range [start, stop) in the directory freemap. * * Returns 1 if there is a conflict or 0 if everything's good. * * Within a char, the lowest bit of the char represents the byte with * the smallest address */ static int set_da_freemap(xfs_mount_t *mp, da_freemap_t *map, int start, int stop) { const da_freemap_t mask = 0x1; int i; if (start > stop) { /* * allow == relation since [x, x) claims 1 byte */ do_warn(_("bad range claimed [%d, %d) in da block\n"), start, stop); return(1); } if (stop > mp->m_sb.sb_blocksize) { do_warn( _("byte range end [%d %d) in da block larger than blocksize %d\n"), start, stop, mp->m_sb.sb_blocksize); return(1); } for (i = start; i < stop; i ++) { if (map[i / NBBY] & (mask << i % NBBY)) { do_warn(_("multiply claimed byte %d in da block\n"), i); return(1); } map[i / NBBY] |= (mask << i % NBBY); } return(0); }
void no_sb(void) { do_warn(_("Sorry, could not find valid secondary superblock\n")); do_warn(_("Exiting now.\n")); exit(1); }
void read_wbuf(int fd, wbuf *buf, xfs_mount_t *mp) { int res = 0; xfs_off_t lres = 0; xfs_off_t newpos; size_t diff; newpos = rounddown(buf->position, (xfs_off_t) buf->min_io_size); if (newpos != buf->position) { diff = buf->position - newpos; buf->position = newpos; buf->length += diff; } if (source_position != buf->position) { lres = lseek64(fd, buf->position, SEEK_SET); if (lres < 0LL) { do_warn(_("%s: lseek64 failure at offset %lld\n"), progname, source_position); die_perror(); } source_position = buf->position; } ASSERT(source_position % source_sectorsize == 0); /* round up length for direct I/O if necessary */ if (buf->length % buf->min_io_size != 0) buf->length = roundup(buf->length, buf->min_io_size); if (buf->length > buf->size) { do_warn(_("assert error: buf->length = %d, buf->size = %d\n"), buf->length, buf->size); killall(); abort(); } if ((res = read(fd, buf->data, buf->length)) < 0) { do_warn(_("%s: read failure at offset %lld\n"), progname, source_position); die_perror(); } if (res < buf->length && source_position + res == mp->m_sb.sb_dblocks * source_blocksize) res = buf->length; else ASSERT(res == buf->length); source_position += res; buf->length = res; }
static int process_leaf_attr_local( struct xfs_mount *mp, xfs_attr_leafblock_t *leaf, int i, xfs_attr_leaf_entry_t *entry, xfs_dahash_t last_hashval, xfs_dablk_t da_bno, xfs_ino_t ino) { xfs_attr_leaf_name_local_t *local; local = xfs_attr3_leaf_name_local(leaf, i); if (local->namelen == 0 || namecheck((char *)&local->nameval[0], local->namelen)) { do_warn( _("attribute entry %d in attr block %u, inode %" PRIu64 " has bad name (namelen = %d)\n"), i, da_bno, ino, local->namelen); return -1; } /* Check on the hash value. Checking order of values * is not necessary, since one wrong clears the whole * fork. If the ordering's wrong, it's caught here or * the kernel code has a bug with transaction logging * or attributes itself. Being paranoid, let's check * ordering anyway in case both the name value and the * hashvalue were wrong but matched. Unlikely, however. */ if (be32_to_cpu(entry->hashval) != libxfs_da_hashname( &local->nameval[0], local->namelen) || be32_to_cpu(entry->hashval) < last_hashval) { do_warn( _("bad hashvalue for attribute entry %d in attr block %u, inode %" PRIu64 "\n"), i, da_bno, ino); return -1; } /* Only check values for root security attributes */ if (entry->flags & XFS_ATTR_ROOT) { if (valuecheck(mp, (char *)&local->nameval[0], NULL, local->namelen, be16_to_cpu(local->valuelen))) { do_warn( _("bad security value for attribute entry %d in attr block %u, inode %" PRIu64 "\n"), i, da_bno, ino); return -1; } } return xfs_attr_leaf_entsize_local(local->namelen, be16_to_cpu(local->valuelen)); }
/* This routine brings in blocks from disk one by one and assembles them * in the value buffer. If get_bmapi gets smarter later to return an extent * or list of extents, that would be great. For now, we don't expect too * many blocks per remote value, so one by one is sufficient. */ static int rmtval_get(xfs_mount_t *mp, xfs_ino_t ino, blkmap_t *blkmap, xfs_dablk_t blocknum, int valuelen, char* value) { xfs_fsblock_t bno; xfs_buf_t *bp; int clearit = 0, i = 0, length = 0, amountdone = 0; int hdrsize = 0; if (xfs_sb_version_hascrc(&mp->m_sb)) hdrsize = sizeof(struct xfs_attr3_rmt_hdr); /* ASSUMPTION: valuelen is a valid number, so use it for looping */ /* Note that valuelen is not a multiple of blocksize */ while (amountdone < valuelen) { bno = blkmap_get(blkmap, blocknum + i); if (bno == NULLFSBLOCK) { do_warn( _("remote block for attributes of inode %" PRIu64 " is missing\n"), ino); clearit = 1; break; } bp = libxfs_readbuf(mp->m_dev, XFS_FSB_TO_DADDR(mp, bno), XFS_FSB_TO_BB(mp, 1), 0, &xfs_attr3_rmt_buf_ops); if (!bp) { do_warn( _("can't read remote block for attributes of inode %" PRIu64 "\n"), ino); clearit = 1; break; } if (bp->b_error == -EFSBADCRC || bp->b_error == -EFSCORRUPTED) { do_warn( _("Corrupt remote block for attributes of inode %" PRIu64 "\n"), ino); clearit = 1; break; } ASSERT(mp->m_sb.sb_blocksize == XFS_BUF_COUNT(bp)); length = MIN(XFS_BUF_COUNT(bp) - hdrsize, valuelen - amountdone); memmove(value, bp->b_addr + hdrsize, length); amountdone += length; value += length; i++; libxfs_putbuf(bp); } return (clearit); }
int verify_set_agheader(xfs_mount_t *mp, xfs_buf_t *sbuf, xfs_sb_t *sb, xfs_agf_t *agf, xfs_agi_t *agi, xfs_agnumber_t i) { int rval = 0; int status = XR_OK; int status_sb = XR_OK; status = verify_sb(sb, (i == 0)); if (status != XR_OK) { do_warn(_("bad on-disk superblock %d - %s\n"), i, err_string(status)); } status_sb = compare_sb(mp, sb); if (status_sb != XR_OK) { do_warn(_("primary/secondary superblock %d conflict - %s\n"), i, err_string(status_sb)); } if (status != XR_OK || status_sb != XR_OK) { if (!no_modify) { *sb = mp->m_sb; /* * clear the more transient fields */ sb->sb_inprogress = 1; sb->sb_icount = 0; sb->sb_ifree = 0; sb->sb_fdblocks = 0; sb->sb_frextents = 0; sb->sb_qflags = 0; } rval |= XR_AG_SB; } rval |= secondary_sb_wack(mp, sbuf, sb, i); rval |= verify_set_agf(mp, agf, i); rval |= verify_set_agi(mp, agi, i); return(rval); }
/* * returns 1 if attributes got cleared * and 0 if things are ok. */ int process_attributes( xfs_mount_t *mp, xfs_ino_t ino, xfs_dinode_t *dip, blkmap_t *blkmap, int *repair) /* returned if we did repair */ { int err; __u8 aformat = dip->di_aformat; #ifdef DEBUG xfs_attr_shortform_t *asf; asf = (xfs_attr_shortform_t *) XFS_DFORK_APTR(dip); #endif if (aformat == XFS_DINODE_FMT_LOCAL) { ASSERT(be16_to_cpu(asf->hdr.totsize) <= XFS_DFORK_ASIZE(dip, mp)); err = process_shortform_attr(mp, ino, dip, repair); } else if (aformat == XFS_DINODE_FMT_EXTENTS || aformat == XFS_DINODE_FMT_BTREE) { err = process_longform_attr(mp, ino, dip, blkmap, repair); /* if err, convert this to shortform and clear it */ /* if repair and no error, it's taken care of */ } else { do_warn(_("illegal attribute format %d, ino %" PRIu64 "\n"), aformat, ino); err = 1; } return (err); /* and repair */ }
void warn(const char *file,int line,const char *fmt, ...) { va_list args; va_start(args, fmt); do_warn("WARNINGS", file, line, fmt, args); va_end(args); }
void warning(struct position pos, const char * fmt, ...) { va_list args; if (Wsparse_error) { va_start(args, fmt); do_error(pos, fmt, args); va_end(args); return; } if (!max_warnings) { show_info = 0; return; } if (!--max_warnings) { show_info = 0; fmt = "too many warnings"; } va_start(args, fmt); do_warn("warning: ", pos, fmt, args); va_end(args); }
void warn_doc_error(const char *file,int line,const char *fmt, ...) { va_list args; va_start(args, fmt); do_warn("WARN_IF_DOC_ERROR", file, line, fmt, args); va_end(args); }
void warn_undoc(const char *file,int line,const char *fmt, ...) { va_list args; va_start(args, fmt); do_warn("WARN_IF_UNDOCUMENTED", file, line, fmt, args); va_end(args); }
void error_die(struct position pos, const char * fmt, ...) { va_list args; va_start(args, fmt); do_warn("error: ", pos, fmt, args); va_end(args); exit(1); }
void info(struct position pos, const char * fmt, ...) { va_list args; if (!show_info) return; va_start(args, fmt); do_warn("", pos, fmt, args); va_end(args); }
static PyObject * warnings_warn_impl(PyObject *module, PyObject *message, PyObject *category, Py_ssize_t stacklevel, PyObject *source) /*[clinic end generated code: output=31ed5ab7d8d760b2 input=bfdf5cf99f6c4edd]*/ { category = get_category(message, category); if (category == NULL) return NULL; return do_warn(message, category, stacklevel, source); }
static int xfs_acl_from_disk( struct xfs_mount *mp, struct xfs_icacl **aclp, struct xfs_acl *dacl) { struct xfs_icacl *acl; struct xfs_icacl_entry *ace; struct xfs_acl_entry *dace; int count; int i; count = be32_to_cpu(dacl->acl_cnt); if (count > XFS_ACL_MAX_ENTRIES(mp)) { do_warn(_("Too many ACL entries, count %d\n"), count); *aclp = NULL; return EINVAL; } acl = malloc(sizeof(struct xfs_icacl) + count * sizeof(struct xfs_icacl_entry)); if (!acl) { do_warn(_("cannot malloc enough for ACL attribute\n")); do_warn(_("SKIPPING this ACL\n")); *aclp = NULL; return ENOMEM; } acl->acl_cnt = count; for (i = 0; i < count; i++) { ace = &acl->acl_entry[i]; dace = &dacl->acl_entry[i]; ace->ae_tag = be32_to_cpu(dace->ae_tag); ace->ae_id = be32_to_cpu(dace->ae_id); ace->ae_perm = be16_to_cpu(dace->ae_perm); } *aclp = acl; return 0; }
/* * Set up an inode tree record for a group of inodes that will include the * requested inode. * * This does NOT do error-check for duplicate records. The caller is * responsible for checking that. Ino must be the start of an * XFS_INODES_PER_CHUNK (64) inode chunk * * Each inode resides in a 64-inode chunk which can be part one or more chunks * (MAX(64, inodes-per-block). The fs allocates in chunks (as opposed to 1 * chunk) when a block can hold more than one chunk (inodes per block > 64). * Allocating in one chunk pieces causes us problems when it takes more than * one fs block to contain an inode chunk because the chunks can start on * *any* block boundary. So we assume that the caller has a clue because at * this level, we don't. */ static struct ino_tree_node * add_inode( struct xfs_mount *mp, xfs_agnumber_t agno, xfs_agino_t agino) { struct ino_tree_node *irec; irec = alloc_ino_node(mp, agino); if (!avl_insert(inode_tree_ptrs[agno], &irec->avl_node)) do_warn(_("add_inode - duplicate inode range\n")); return irec; }
/* * get a possible superblock -- don't check for internal consistency */ int get_sb(xfs_sb_t *sbp, xfs_off_t off, int size, xfs_agnumber_t agno) { int error, rval; xfs_dsb_t *buf; buf = memalign(libxfs_device_alignment(), size); if (buf == NULL) { do_error( _("error reading superblock %u -- failed to memalign buffer\n"), agno); exit(1); } memset(buf, 0, size); /* try and read it first */ if (lseek64(x.dfd, off, SEEK_SET) != off) { do_warn( _("error reading superblock %u -- seek to offset %" PRId64 " failed\n"), agno, off); return(XR_EOF); } if ((rval = read(x.dfd, buf, size)) != size) { error = errno; do_warn( _("superblock read failed, offset %" PRId64 ", size %d, ag %u, rval %d\n"), off, size, agno, rval); do_error("%s\n", strerror(error)); } libxfs_sb_from_disk(sbp, buf); free(buf); return (verify_sb(sbp, 0)); }
/* check v5 metadata */ static int __check_attr_header( struct xfs_mount *mp, struct xfs_buf *bp, xfs_ino_t ino) { struct xfs_da3_blkinfo *info = bp->b_addr; if (info->hdr.magic != cpu_to_be16(XFS_ATTR3_LEAF_MAGIC) && info->hdr.magic != cpu_to_be16(XFS_DA3_NODE_MAGIC)) return 0; /* verify owner */ if (be64_to_cpu(info->owner) != ino) { do_warn( _("expected owner inode %" PRIu64 ", got %llu, attr block %" PRIu64 "\n"), ino, be64_to_cpu(info->owner), bp->b_bn); return 1; } /* verify block number */ if (be64_to_cpu(info->blkno) != bp->b_bn) { do_warn( _("expected block %" PRIu64 ", got %llu, inode %" PRIu64 "attr block\n"), bp->b_bn, be64_to_cpu(info->blkno), ino); return 1; } /* verify uuid */ if (platform_uuid_compare(&info->uuid, &mp->m_sb.sb_meta_uuid) != 0) { do_warn( _("wrong FS UUID, inode %" PRIu64 " attr block %" PRIu64 "\n"), ino, bp->b_bn); return 1; } return 0; }
static int warn_unicode(PyObject *category, PyObject *message, Py_ssize_t stack_level, PyObject *source) { PyObject *res; if (category == NULL) category = PyExc_RuntimeWarning; res = do_warn(message, category, stack_level, source); if (res == NULL) return -1; Py_DECREF(res); return 0; }
static PyObject * warnings_warn(PyObject *self, PyObject *args, PyObject *kwds) { static char *kw_list[] = { "message", "category", "stacklevel", 0 }; PyObject *message, *category = NULL; Py_ssize_t stack_level = 1; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|On:warn", kw_list, &message, &category, &stack_level)) return NULL; category = get_category(message, category); if (category == NULL) return NULL; return do_warn(message, category, stack_level); }
/* Function to issue a warning message; may raise an exception. */ int PyErr_WarnEx(PyObject *category, const char *text, Py_ssize_t stack_level) { PyObject *res; PyObject *message = PyString_FromString(text); if (message == NULL) return -1; if (category == NULL) category = PyExc_RuntimeWarning; res = do_warn(message, category, stack_level); Py_DECREF(message); if (res == NULL) return -1; Py_DECREF(res); return 0; }
static void do_error(struct position pos, const char * fmt, va_list args) { static int errors = 0; die_if_error = 1; show_info = 1; /* Shut up warnings after an error */ max_warnings = 0; if (errors > 100) { static int once = 0; show_info = 0; if (once) return; fmt = "too many errors"; once = 1; } do_warn("error: ", pos, fmt, args); errors++; }
static void zero_log(xfs_mount_t *mp) { int error; xlog_t log; xfs_daddr_t head_blk, tail_blk; dev_t logdev = (mp->m_sb.sb_logstart == 0) ? x.logdev : x.ddev; memset(&log, 0, sizeof(log)); if (!x.logdev) x.logdev = x.ddev; x.logBBsize = XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks); x.logBBstart = XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart); log.l_dev = logdev; log.l_logsize = BBTOB(x.logBBsize); log.l_logBBsize = x.logBBsize; log.l_logBBstart = x.logBBstart; log.l_mp = mp; if (xfs_sb_version_hassector(&mp->m_sb)) { log.l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; ASSERT(log.l_sectbb_log <= mp->m_sectbb_log); /* for larger sector sizes, must have v2 or external log */ ASSERT(log.l_sectbb_log == 0 || log.l_logBBstart == 0 || xfs_sb_version_haslogv2(&mp->m_sb)); ASSERT(mp->m_sb.sb_logsectlog >= BBSHIFT); } log.l_sectbb_mask = (1 << log.l_sectbb_log) - 1; if ((error = xlog_find_tail(&log, &head_blk, &tail_blk))) { do_warn(_("zero_log: cannot find log head/tail " "(xlog_find_tail=%d), zeroing it anyway\n"), error); } else { if (verbose) { do_warn(_("zero_log: head block %lld tail block %lld\n"), head_blk, tail_blk); } if (head_blk != tail_blk) { if (zap_log) { do_warn(_( "ALERT: The filesystem has valuable metadata changes in a log which is being\n" "destroyed because the -L option was used.\n")); } else { do_warn(_( "ERROR: The filesystem has valuable metadata changes in a log which needs to\n" "be replayed. Mount the filesystem to replay the log, and unmount it before\n" "re-running xfs_repair. If you are unable to mount the filesystem, then use\n" "the -L option to destroy the log and attempt a repair.\n" "Note that destroying the log may cause corruption -- please attempt a mount\n" "of the filesystem before doing this.\n")); exit(2); } } } libxfs_log_clear(logdev, XFS_FSB_TO_DADDR(mp, mp->m_sb.sb_logstart), (xfs_extlen_t)XFS_FSB_TO_BB(mp, mp->m_sb.sb_logblocks), &mp->m_sb.sb_uuid, xfs_sb_version_haslogv2(&mp->m_sb) ? 2 : 1, mp->m_sb.sb_logsunit, XLOG_FMT); }
void phase2( struct xfs_mount *mp, int scan_threads) { int j; ino_tree_node_t *ino_rec; /* now we can start using the buffer cache routines */ set_mp(mp); /* Check whether this fs has internal or external log */ if (mp->m_sb.sb_logstart == 0) { if (!x.logname) do_error(_("This filesystem has an external log. " "Specify log device with the -l option.\n")); do_log(_("Phase 2 - using external log on %s\n"), x.logname); } else do_log(_("Phase 2 - using internal log\n")); /* Zero log if applicable */ if (!no_modify) { do_log(_(" - zero log...\n")); zero_log(mp); } do_log(_(" - scan filesystem freespace and inode maps...\n")); bad_ino_btree = 0; set_progress_msg(PROG_FMT_SCAN_AG, (__uint64_t) glob_agcount); scan_ags(mp, scan_threads); print_final_rpt(); /* * make sure we know about the root inode chunk */ if ((ino_rec = find_inode_rec(0, mp->m_sb.sb_rootino)) == NULL) { ASSERT(mp->m_sb.sb_rbmino == mp->m_sb.sb_rootino + 1 && mp->m_sb.sb_rsumino == mp->m_sb.sb_rootino + 2); do_warn(_("root inode chunk not found\n")); /* * mark the first 3 used, the rest are free */ ino_rec = set_inode_used_alloc(0, (xfs_agino_t) mp->m_sb.sb_rootino); set_inode_used(ino_rec, 1); set_inode_used(ino_rec, 2); for (j = 3; j < XFS_INODES_PER_CHUNK; j++) set_inode_free(ino_rec, j); /* * also mark blocks */ set_bmap_ext(0, XFS_INO_TO_AGBNO(mp, mp->m_sb.sb_rootino), mp->m_ialloc_blks, XR_E_INO); } else { do_log(_(" - found root inode chunk\n")); /* * blocks are marked, just make sure they're in use */ if (is_inode_free(ino_rec, 0)) { do_warn(_("root inode marked free, ")); set_inode_used(ino_rec, 0); if (!no_modify) do_warn(_("correcting\n")); else do_warn(_("would correct\n")); } if (is_inode_free(ino_rec, 1)) { do_warn(_("realtime bitmap inode marked free, ")); set_inode_used(ino_rec, 1); if (!no_modify) do_warn(_("correcting\n")); else do_warn(_("would correct\n")); } if (is_inode_free(ino_rec, 2)) { do_warn(_("realtime summary inode marked free, ")); set_inode_used(ino_rec, 2); if (!no_modify) do_warn(_("correcting\n")); else do_warn(_("would correct\n")); } } }
void phase2(xfs_mount_t *mp, libxfs_init_t *args) { xfs_agnumber_t i; xfs_agblock_t b; int j; ino_tree_node_t *ino_rec; /* now we can start using the buffer cache routines */ set_mp(mp); /* Check whether this fs has internal or external log */ if (mp->m_sb.sb_logstart == 0) { if (!args->logname) { fprintf (stderr, "This filesystem has an external log. " "Specify log device with the -l option.\n"); exit (1); } fprintf (stderr, "Phase 2 - using external log on %s\n", args->logname); } else fprintf (stderr, "Phase 2 - using internal log\n"); /* Zero log if applicable */ if (!no_modify) { do_log(" - zero log...\n"); zero_log(mp, args); } do_log(" - scan filesystem freespace and inode maps...\n"); /* * account for space used by ag headers and log if internal */ set_bmap_log(mp); set_bmap_fs(mp); bad_ino_btree = 0; for (i = 0; i < mp->m_sb.sb_agcount; i++) { scan_ag(i); #ifdef XR_INODE_TRACE print_inode_list(i); #endif } /* * make sure we know about the root inode chunk */ if ((ino_rec = find_inode_rec(0, mp->m_sb.sb_rootino)) == NULL) { ASSERT(mp->m_sb.sb_rbmino == mp->m_sb.sb_rootino + 1 && mp->m_sb.sb_rsumino == mp->m_sb.sb_rootino + 2); do_warn("root inode chunk not found\n"); /* * mark the first 3 used, the rest are free */ ino_rec = set_inode_used_alloc(0, (xfs_agino_t) mp->m_sb.sb_rootino); set_inode_used(ino_rec, 1); set_inode_used(ino_rec, 2); for (j = 3; j < XFS_INODES_PER_CHUNK; j++) set_inode_free(ino_rec, j); /* * also mark blocks */ for (b = 0; b < mp->m_ialloc_blks; b++) { set_agbno_state(mp, 0, b + XFS_INO_TO_AGBNO(mp, mp->m_sb.sb_rootino), XR_E_INO); } } else { do_log(" - found root inode chunk\n"); /* * blocks are marked, just make sure they're in use */ if (is_inode_free(ino_rec, 0)) { do_warn("root inode marked free, "); set_inode_used(ino_rec, 0); if (!no_modify) do_warn("correcting\n"); else do_warn("would correct\n"); } if (is_inode_free(ino_rec, 1)) { do_warn("realtime bitmap inode marked free, "); set_inode_used(ino_rec, 1); if (!no_modify) do_warn("correcting\n"); else do_warn("would correct\n"); } if (is_inode_free(ino_rec, 2)) { do_warn("realtime summary inode marked free, "); set_inode_used(ino_rec, 2); if (!no_modify) do_warn("correcting\n"); else do_warn("would correct\n"); } } }
void handler(int sig) { pid_t pid = getpid(); int status, i; pid = wait(&status); kids--; for (i = 0; i < num_targets; i++) { if (target[i].pid == pid) { if (target[i].state == INACTIVE) { /* thread got an I/O error */ if (target[i].err_type == 0) { do_warn( _("%s: write error on target %d \"%s\" at offset %lld\n"), progname, i, target[i].name, target[i].position); } else { do_warn( _("%s: lseek64 error on target %d \"%s\" at offset %lld\n"), progname, i, target[i].name, target[i].position); } do_vfatal(target[i].error, _("Aborting target %d - reason"), i); if (kids == 0) { do_log( _("Aborting XFS copy - no more targets.\n")); check_errors(); pthread_exit(NULL); } signal(SIGCHLD, handler); return; } else { /* it just croaked it bigtime, log it */ do_warn( _("%s: thread %d died unexpectedly, target \"%s\" incomplete\n"), progname, i, target[i].name); do_warn(_("%s: offset was probably %lld\n"), progname, target[i].position); do_fatal(target[i].error, _("Aborting XFS copy - reason")); pthread_exit(NULL); } } } /* unknown child -- something very wrong */ do_warn(_("%s: Unknown child died (should never happen!)\n"), progname); die_perror(); pthread_exit(NULL); signal(SIGCHLD, handler); }
void update_sb_version(xfs_mount_t *mp) { xfs_sb_t *sb; __uint16_t vn; sb = &mp->m_sb; if (fs_attributes && !xfs_sb_version_hasattr(sb)) { ASSERT(fs_attributes_allowed); xfs_sb_version_addattr(sb); } if (fs_attributes2 && !xfs_sb_version_hasattr2(sb)) { ASSERT(fs_attributes2_allowed); xfs_sb_version_addattr2(sb); } if (fs_inode_nlink && !xfs_sb_version_hasnlink(sb)) { ASSERT(fs_inode_nlink_allowed); xfs_sb_version_addnlink(sb); } /* * fix up the superblock version number and feature bits, * turn off quota bits and flags if the filesystem doesn't * have quotas. */ if (fs_quotas) { if (!xfs_sb_version_hasquota(sb)) { ASSERT(fs_quotas_allowed); xfs_sb_version_addquota(sb); } /* * protect against stray bits in the quota flag field */ if (sb->sb_qflags & ~XFS_MOUNT_QUOTA_ALL) { /* * update the incore superblock, if we're in * no_modify mode, it'll never get flushed out * so this is ok. */ do_warn(_("bogus quota flags 0x%x set in superblock"), sb->sb_qflags & ~XFS_MOUNT_QUOTA_ALL); sb->sb_qflags &= XFS_MOUNT_QUOTA_ALL; if (!no_modify) do_warn(_(", bogus flags will be cleared\n")); else do_warn(_(", bogus flags would be cleared\n")); } } else { sb->sb_qflags = 0; if (xfs_sb_version_hasquota(sb)) { lost_quotas = 1; vn = sb->sb_versionnum; vn &= ~XFS_SB_VERSION_QUOTABIT; if (!(vn & XFS_SB_VERSION_ALLFBITS)) vn = xfs_sb_version_toold(vn); ASSERT(vn != 0); sb->sb_versionnum = vn; } } if (!fs_aligned_inodes && xfs_sb_version_hasalign(sb)) sb->sb_versionnum &= ~XFS_SB_VERSION_ALIGNBIT; }
/* * returns 0 if things are fine, 1 if we don't understand * this superblock version. Sets superblock geometry-dependent * global variables. */ int parse_sb_version(xfs_sb_t *sb) { int issue_warning; fs_attributes = 0; fs_attributes2 = 0; fs_inode_nlink = 0; fs_quotas = 0; fs_aligned_inodes = 0; fs_sb_feature_bits = 0; fs_ino_alignment = 0; fs_has_extflgbit = 0; have_uquotino = 0; have_gquotino = 0; have_pquotino = 0; issue_warning = 0; /* * ok, check to make sure that the sb isn't newer * than we are */ if (xfs_sb_version_hasextflgbit(sb)) { fs_has_extflgbit = 1; if (!fs_has_extflgbit_allowed) { issue_warning = 1; do_warn( _("This filesystem has uninitialized extent flags.\n")); } } if (xfs_sb_version_hasshared(sb)) { fs_shared = 1; if (!fs_shared_allowed) { issue_warning = 1; do_warn(_("This filesystem is marked shared.\n")); } } if (issue_warning) { do_warn( _("This filesystem uses feature(s) not yet supported in this release.\n" "Please run a more recent version of xfs_repair.\n")); return(1); } if (!xfs_sb_good_version(sb)) { do_warn(_("WARNING: unknown superblock version %d\n"), XFS_SB_VERSION_NUM(sb)); do_warn( _("This filesystem contains features not understood by this program.\n")); return(1); } if (XFS_SB_VERSION_NUM(sb) >= XFS_SB_VERSION_4) { if (!fs_sb_feature_bits_allowed) { if (!no_modify) { do_warn( _("WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twill be downgraded. This may cause loss of filesystem meta-data\n")); } else { do_warn( _("WARNING: you have disallowed superblock-feature-bits-allowed\n" "\tbut this superblock has feature bits. The superblock\n" "\twould be downgraded. This might cause loss of filesystem\n" "\tmeta-data.\n")); } } else { fs_sb_feature_bits = 1; } } if (xfs_sb_version_hasattr(sb)) { if (!fs_attributes_allowed) { if (!no_modify) { do_warn( _("WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attributes will be removed.\n")); } else { do_warn( _("WARNING: you have disallowed attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attributes would be removed.\n")); } } else { fs_attributes = 1; } } if (xfs_sb_version_hasattr2(sb)) { if (!fs_attributes2_allowed) { if (!no_modify) { do_warn( _("WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem will be downgraded and\n" "\tall attr2 attributes will be removed.\n")); } else { do_warn( _("WARNING: you have disallowed attr2 attributes but this filesystem\n" "\thas attributes. The filesystem would be downgraded and\n" "\tall attr2 attributes would be removed.\n")); } } else { fs_attributes2 = 1; } } if (xfs_sb_version_hasnlink(sb)) { if (!fs_inode_nlink_allowed) { if (!no_modify) { do_warn( _("WARNING: you have disallowed version 2 inodes but this filesystem\n" "\thas version 2 inodes. The filesystem will be downgraded and\n" "\tall version 2 inodes will be converted to version 1 inodes.\n" "\tThis may cause some hard links to files to be destroyed\n")); } else { do_warn( _("WARNING: you have disallowed version 2 inodes but this filesystem\n" "\thas version 2 inodes. The filesystem would be downgraded and\n" "\tall version 2 inodes would be converted to version 1 inodes.\n" "\tThis might cause some hard links to files to be destroyed\n")); } } else { fs_inode_nlink = 1; } } if (xfs_sb_version_hasquota(sb)) { if (!fs_quotas_allowed) { if (!no_modify) { do_warn( _("WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem will be downgraded and\n" "\tall quota information will be removed.\n")); } else { do_warn( _("WARNING: you have disallowed quotas but this filesystem\n" "\thas quotas. The filesystem would be downgraded and\n" "\tall quota information would be removed.\n")); } } else { fs_quotas = 1; if (sb->sb_uquotino != 0 && sb->sb_uquotino != NULLFSINO) have_uquotino = 1; if (sb->sb_gquotino != 0 && sb->sb_gquotino != NULLFSINO) have_gquotino = 1; if (sb->sb_pquotino != 0 && sb->sb_pquotino != NULLFSINO) have_pquotino = 1; } } if (xfs_sb_version_hasalign(sb)) { if (fs_aligned_inodes_allowed) { fs_aligned_inodes = 1; fs_ino_alignment = sb->sb_inoalignmt; } else { if (!no_modify) { do_warn( _("WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem will be downgraded.\n" "\tThis will permanently degrade the performance of this filesystem.\n")); } else { do_warn( _("WARNING: you have disallowed aligned inodes but this filesystem\n" "\thas aligned inodes. The filesystem would be downgraded.\n" "\tThis would permanently degrade the performance of this filesystem.\n")); } } } /* * calculate maximum file offset for this geometry */ fs_max_file_offset = 0x7fffffffffffffffLL >> sb->sb_blocklog; return(0); }
/* * find a secondary superblock, copy it into the sb buffer */ int find_secondary_sb(xfs_sb_t *rsb) { xfs_off_t off; xfs_sb_t *sb; xfs_sb_t bufsb; char *c_bufsb; int done; int i; int dirty; int retval; int bsize; do_warn(_("\nattempting to find secondary superblock...\n")); sb = (xfs_sb_t *)memalign(libxfs_device_alignment(), BSIZE); if (!sb) { do_error( _("error finding secondary superblock -- failed to memalign buffer\n")); exit(1); } memset(&bufsb, 0, sizeof(xfs_sb_t)); retval = 0; dirty = 0; bsize = 0; /* * skip first sector since we know that's bad */ for (done = 0, off = XFS_AG_MIN_BYTES; !done ; off += bsize) { /* * read disk 1 MByte at a time. */ if (lseek64(x.dfd, off, SEEK_SET) != off) { done = 1; } if (!done && (bsize = read(x.dfd, sb, BSIZE)) <= 0) { done = 1; } do_warn("."); /* * check the buffer 512 bytes at a time since * we don't know how big the sectors really are. */ for (i = 0; !done && i < bsize; i += BBSIZE) { c_bufsb = (char *)sb + i; libxfs_sb_from_disk(&bufsb, (xfs_dsb_t *)c_bufsb); if (verify_sb(&bufsb, 0) != XR_OK) continue; do_warn(_("found candidate secondary superblock...\n")); /* * found one. now verify it by looking * for other secondaries. */ memmove(rsb, &bufsb, sizeof(xfs_sb_t)); rsb->sb_inprogress = 0; clear_sunit = 1; if (verify_set_primary_sb(rsb, 0, &dirty) == XR_OK) { do_warn( _("verified secondary superblock...\n")); done = 1; retval = 1; } else { do_warn( _("unable to verify superblock, continuing...\n")); } } } free(sb); return(retval); }
/* * the way to verify that a primary sb is consistent with the * filesystem is find the secondaries given the info in the * primary and compare the geometries in the secondaries against * the geometry indicated by the primary. * * returns 1 if bad, 0 if ok */ int verify_set_primary_sb(xfs_sb_t *rsb, int sb_index, int *sb_modified) { xfs_off_t off; fs_geometry_t geo; xfs_sb_t *sb; fs_geo_list_t *list; fs_geo_list_t *current; char *checked; xfs_agnumber_t agno; int num_sbs; int skip; int size; int num_ok; int retval; int round; /* * select the number of secondaries to try for */ num_sbs = MIN(NUM_SBS, rsb->sb_agcount); skip = howmany(num_sbs, rsb->sb_agcount); /* * We haven't been able to validate the sector size yet properly * (e.g. in the case of repairing an image in a file), so we need to * take into account sector mismatches and so use the maximum possible * sector size rather than the sector size in @rsb. */ size = NUM_AGH_SECTS * (1 << (XFS_MAX_SECTORSIZE_LOG)); retval = 0; list = NULL; num_ok = 0; *sb_modified = 0; sb = (xfs_sb_t *) alloc_ag_buf(size); checked = calloc(rsb->sb_agcount, sizeof(char)); if (!checked) { do_error(_("calloc failed in verify_set_primary_sb\n")); exit(1); } /* * put the primary sb geometry info onto the geometry list */ checked[sb_index] = 1; get_sb_geometry(&geo, rsb); list = add_geo(list, &geo, sb_index); /* * grab N secondaries. check them off as we get them * so we only process each one once */ for (round = 0; round < skip; round++) { for (agno = round; agno < rsb->sb_agcount; agno += skip) { if (checked[agno]) continue; off = (xfs_off_t)agno * rsb->sb_agblocks << rsb->sb_blocklog; checked[agno] = 1; if (get_sb(sb, off, size, agno) == XR_EOF) { retval = 1; goto out; } if (verify_sb(sb, 0) == XR_OK) { /* * save away geometry info. * don't bother checking the sb * against the agi/agf as the odds * of the sb being corrupted in a way * that it is internally consistent * but not consistent with the rest * of the filesystem is really really low. */ get_sb_geometry(&geo, sb); list = add_geo(list, &geo, agno); num_ok++; } } } /* * see if we have enough superblocks to bother with */ if (num_ok < num_sbs / 2) return(XR_INSUFF_SEC_SB); current = get_best_geo(list); /* * check that enough sbs agree that we're willing to * go with this geometry. if not, print out the * geometry and a message about the force option. */ switch (num_sbs) { case 2: /* * If we only have two allocation groups, and the superblock * in the second allocation group differs from the primary * superblock we can't verify the geometry information. * Warn the user about this situation and get out unless * explicitly overridden. */ if (current->refs != 2) { if (!force_geo) { do_warn( _("Only two AGs detected and they do not match - " "cannot validate filesystem geometry.\n" "Use the -o force_geometry option to proceed.\n")); exit(1); } } goto out_free_list; case 1: /* * If we only have a single allocation group there is no * secondary superblock that we can use to verify the geometry * information. Warn the user about this situation and get * out unless explicitly overridden. */ if (!force_geo) { do_warn( _("Only one AG detected - " "cannot validate filesystem geometry.\n" "Use the -o force_geometry option to proceed.\n")); exit(1); } goto out_free_list; default: /* * at least half of the probed superblocks have * to agree. if they don't, this fs is probably * too far gone anyway considering the fact that * XFS normally doesn't alter the secondary superblocks. */ if (current->refs < num_sbs / 2) { do_warn( _("Not enough matching superblocks - cannot proceed.\n")); exit(1); } } /* * set the geometry into primary superblock if necessary. */ if (current->index != sb_index) { *sb_modified = 1; off = (xfs_off_t)current->index * current->geo.sb_agblocks * current->geo.sb_blocksize; if (get_sb(sb, off, current->geo.sb_sectsize, current->index) != XR_OK) do_error(_("could not read superblock\n")); copy_sb(sb, rsb); /* * turn off inprogress bit since this is the primary. * also save away values that we need to ensure are * consistent in the other secondaries. */ rsb->sb_inprogress = 0; sb_inoalignmt = sb->sb_inoalignmt; sb_unit = sb->sb_unit; sb_width = sb->sb_width; } out_free_list: free_geo(list); out: free(sb); free(checked); return(retval); }