···12211221 goto bmap_cancel;12221222 if (!xfs_sb_version_hasattr(&mp->m_sb) ||12231223 (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2)) {12241224- __int64_t sbfields = 0;12241224+ bool log_sb = false;1225122512261226 spin_lock(&mp->m_sb_lock);12271227 if (!xfs_sb_version_hasattr(&mp->m_sb)) {12281228 xfs_sb_version_addattr(&mp->m_sb);12291229- sbfields |= XFS_SB_VERSIONNUM;12291229+ log_sb = true;12301230 }12311231 if (!xfs_sb_version_hasattr2(&mp->m_sb) && version == 2) {12321232 xfs_sb_version_addattr2(&mp->m_sb);12331233- sbfields |= (XFS_SB_VERSIONNUM | XFS_SB_FEATURES2);12331233+ log_sb = true;12341234 }12351235- if (sbfields) {12361236- spin_unlock(&mp->m_sb_lock);12371237- xfs_mod_sb(tp, sbfields);12381238- } else12391239- spin_unlock(&mp->m_sb_lock);12351235+ spin_unlock(&mp->m_sb_lock);12361236+ if (log_sb)12371237+ xfs_log_sb(tp);12401238 }1241123912421240 error = xfs_bmap_finish(&tp, &flist, &committed);
+7-7
fs/xfs/libxfs/xfs_format.h
···151151 __uint32_t sb_features2; /* additional feature bits */152152153153 /*154154- * bad features2 field as a result of failing to pad the sb155155- * structure to 64 bits. Some machines will be using this field156156- * for features2 bits. Easiest just to mark it bad and not use157157- * it for anything else.154154+ * bad features2 field as a result of failing to pad the sb structure to155155+ * 64 bits. Some machines will be using this field for features2 bits.156156+ * Easiest just to mark it bad and not use it for anything else.157157+ *158158+ * This is not kept up to date in memory; it is always overwritten by159159+ * the value in sb_features2 when formatting the incore superblock to160160+ * the disk buffer.158161 */159162 __uint32_t sb_bad_features2;160163···456453{457454 sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;458455 sbp->sb_features2 |= XFS_SB_VERSION2_ATTR2BIT;459459- sbp->sb_bad_features2 |= XFS_SB_VERSION2_ATTR2BIT;460456}461457462458static inline void xfs_sb_version_removeattr2(struct xfs_sb *sbp)463459{464460 sbp->sb_features2 &= ~XFS_SB_VERSION2_ATTR2BIT;465465- sbp->sb_bad_features2 &= ~XFS_SB_VERSION2_ATTR2BIT;466461 if (!sbp->sb_features2)467462 sbp->sb_versionnum &= ~XFS_SB_VERSION_MOREBITSBIT;468463}···476475{477476 sbp->sb_versionnum |= XFS_SB_VERSION_MOREBITSBIT;478477 sbp->sb_features2 |= XFS_SB_VERSION2_PROJID32BIT;479479- sbp->sb_bad_features2 |= XFS_SB_VERSION2_PROJID32BIT;480478}481479482480/*
+138-186
fs/xfs/libxfs/xfs_sb.c
···4040 * Physical superblock buffer manipulations. Shared with libxfs in userspace.4141 */42424343-static const struct {4444- short offset;4545- short type; /* 0 = integer4646- * 1 = binary / string (no translation)4747- */4848-} xfs_sb_info[] = {4949- { offsetof(xfs_sb_t, sb_magicnum), 0 },5050- { offsetof(xfs_sb_t, sb_blocksize), 0 },5151- { offsetof(xfs_sb_t, sb_dblocks), 0 },5252- { offsetof(xfs_sb_t, sb_rblocks), 0 },5353- { offsetof(xfs_sb_t, sb_rextents), 0 },5454- { offsetof(xfs_sb_t, sb_uuid), 1 },5555- { offsetof(xfs_sb_t, sb_logstart), 0 },5656- { offsetof(xfs_sb_t, sb_rootino), 0 },5757- { offsetof(xfs_sb_t, sb_rbmino), 0 },5858- { offsetof(xfs_sb_t, sb_rsumino), 0 },5959- { offsetof(xfs_sb_t, sb_rextsize), 0 },6060- { offsetof(xfs_sb_t, sb_agblocks), 0 },6161- { offsetof(xfs_sb_t, sb_agcount), 0 },6262- { offsetof(xfs_sb_t, sb_rbmblocks), 0 },6363- { offsetof(xfs_sb_t, sb_logblocks), 0 },6464- { offsetof(xfs_sb_t, sb_versionnum), 0 },6565- { offsetof(xfs_sb_t, sb_sectsize), 0 },6666- { offsetof(xfs_sb_t, sb_inodesize), 0 },6767- { offsetof(xfs_sb_t, sb_inopblock), 0 },6868- { offsetof(xfs_sb_t, sb_fname[0]), 1 },6969- { offsetof(xfs_sb_t, sb_blocklog), 0 },7070- { offsetof(xfs_sb_t, sb_sectlog), 0 },7171- { offsetof(xfs_sb_t, sb_inodelog), 0 },7272- { offsetof(xfs_sb_t, sb_inopblog), 0 },7373- { offsetof(xfs_sb_t, sb_agblklog), 0 },7474- { offsetof(xfs_sb_t, sb_rextslog), 0 },7575- { offsetof(xfs_sb_t, sb_inprogress), 0 },7676- { offsetof(xfs_sb_t, sb_imax_pct), 0 },7777- { offsetof(xfs_sb_t, sb_icount), 0 },7878- { offsetof(xfs_sb_t, sb_ifree), 0 },7979- { offsetof(xfs_sb_t, sb_fdblocks), 0 },8080- { offsetof(xfs_sb_t, sb_frextents), 0 },8181- { offsetof(xfs_sb_t, sb_uquotino), 0 },8282- { offsetof(xfs_sb_t, sb_gquotino), 0 },8383- { offsetof(xfs_sb_t, sb_qflags), 0 },8484- { offsetof(xfs_sb_t, sb_flags), 0 },8585- { offsetof(xfs_sb_t, sb_shared_vn), 0 },8686- { offsetof(xfs_sb_t, sb_inoalignmt), 0 },8787- { offsetof(xfs_sb_t, sb_unit), 0 },8888- { offsetof(xfs_sb_t, sb_width), 0 },8989- { offsetof(xfs_sb_t, sb_dirblklog), 0 },9090- { offsetof(xfs_sb_t, sb_logsectlog), 0 },9191- { offsetof(xfs_sb_t, sb_logsectsize), 0 },9292- { offsetof(xfs_sb_t, sb_logsunit), 0 },9393- { offsetof(xfs_sb_t, sb_features2), 0 },9494- { offsetof(xfs_sb_t, sb_bad_features2), 0 },9595- { offsetof(xfs_sb_t, sb_features_compat), 0 },9696- { offsetof(xfs_sb_t, sb_features_ro_compat), 0 },9797- { offsetof(xfs_sb_t, sb_features_incompat), 0 },9898- { offsetof(xfs_sb_t, sb_features_log_incompat), 0 },9999- { offsetof(xfs_sb_t, sb_crc), 0 },100100- { offsetof(xfs_sb_t, sb_pad), 0 },101101- { offsetof(xfs_sb_t, sb_pquotino), 0 },102102- { offsetof(xfs_sb_t, sb_lsn), 0 },103103- { sizeof(xfs_sb_t), 0 }104104-};105105-10643/*10744 * Reference counting access wrappers to the perag structures.10845 * Because we never free per-ag structures, the only thing we···398461 __xfs_sb_from_disk(to, from, true);399462}400463401401-static inline void464464+static void402465xfs_sb_quota_to_disk(403403- xfs_dsb_t *to,404404- xfs_sb_t *from,405405- __int64_t *fields)466466+ struct xfs_dsb *to,467467+ struct xfs_sb *from)406468{407469 __uint16_t qflags = from->sb_qflags;408470409409- /*410410- * We need to do these manipilations only if we are working411411- * with an older version of on-disk superblock.412412- */413413- if (xfs_sb_version_has_pquotino(from))471471+ to->sb_uquotino = cpu_to_be64(from->sb_uquotino);472472+ if (xfs_sb_version_has_pquotino(from)) {473473+ to->sb_qflags = cpu_to_be16(from->sb_qflags);474474+ to->sb_gquotino = cpu_to_be64(from->sb_gquotino);475475+ to->sb_pquotino = cpu_to_be64(from->sb_pquotino);414476 return;415415-416416- if (*fields & XFS_SB_QFLAGS) {417417- /*418418- * The in-core version of sb_qflags do not have419419- * XFS_OQUOTA_* flags, whereas the on-disk version420420- * does. So, convert incore XFS_{PG}QUOTA_* flags421421- * to on-disk XFS_OQUOTA_* flags.422422- */423423- qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD |424424- XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD);425425-426426- if (from->sb_qflags &427427- (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD))428428- qflags |= XFS_OQUOTA_ENFD;429429- if (from->sb_qflags &430430- (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))431431- qflags |= XFS_OQUOTA_CHKD;432432- to->sb_qflags = cpu_to_be16(qflags);433433- *fields &= ~XFS_SB_QFLAGS;434477 }435478436479 /*437437- * GQUOTINO and PQUOTINO cannot be used together in versions of438438- * superblock that do not have pquotino. from->sb_flags tells us which439439- * quota is active and should be copied to disk. If neither are active,440440- * make sure we write NULLFSINO to the sb_gquotino field as a quota441441- * inode value of "0" is invalid when the XFS_SB_VERSION_QUOTA feature442442- * bit is set.443443- *444444- * Note that we don't need to handle the sb_uquotino or sb_pquotino here445445- * as they do not require any translation. Hence the main sb field loop446446- * will write them appropriately from the in-core superblock.480480+ * The in-core version of sb_qflags do not have XFS_OQUOTA_*481481+ * flags, whereas the on-disk version does. So, convert incore482482+ * XFS_{PG}QUOTA_* flags to on-disk XFS_OQUOTA_* flags.447483 */448448- if ((*fields & XFS_SB_GQUOTINO) &&449449- (from->sb_qflags & XFS_GQUOTA_ACCT))484484+ qflags &= ~(XFS_PQUOTA_ENFD | XFS_PQUOTA_CHKD |485485+ XFS_GQUOTA_ENFD | XFS_GQUOTA_CHKD);486486+487487+ if (from->sb_qflags &488488+ (XFS_PQUOTA_ENFD | XFS_GQUOTA_ENFD))489489+ qflags |= XFS_OQUOTA_ENFD;490490+ if (from->sb_qflags &491491+ (XFS_PQUOTA_CHKD | XFS_GQUOTA_CHKD))492492+ qflags |= XFS_OQUOTA_CHKD;493493+ to->sb_qflags = cpu_to_be16(qflags);494494+495495+ /*496496+ * GQUOTINO and PQUOTINO cannot be used together in versions497497+ * of superblock that do not have pquotino. from->sb_flags498498+ * tells us which quota is active and should be copied to499499+ * disk. If neither are active, we should NULL the inode.500500+ *501501+ * In all cases, the separate pquotino must remain 0 because it502502+ * it beyond the "end" of the valid non-pquotino superblock.503503+ */504504+ if (from->sb_qflags & XFS_GQUOTA_ACCT)450505 to->sb_gquotino = cpu_to_be64(from->sb_gquotino);451451- else if ((*fields & XFS_SB_PQUOTINO) &&452452- (from->sb_qflags & XFS_PQUOTA_ACCT))506506+ else if (from->sb_qflags & XFS_PQUOTA_ACCT)453507 to->sb_gquotino = cpu_to_be64(from->sb_pquotino);454508 else {455509 /*···454526 to->sb_gquotino = cpu_to_be64(NULLFSINO);455527 }456528457457- *fields &= ~(XFS_SB_PQUOTINO | XFS_SB_GQUOTINO);529529+ to->sb_pquotino = 0;458530}459531460460-/*461461- * Copy in core superblock to ondisk one.462462- *463463- * The fields argument is mask of superblock fields to copy.464464- */465532void466533xfs_sb_to_disk(467467- xfs_dsb_t *to,468468- xfs_sb_t *from,469469- __int64_t fields)534534+ struct xfs_dsb *to,535535+ struct xfs_sb *from)470536{471471- xfs_caddr_t to_ptr = (xfs_caddr_t)to;472472- xfs_caddr_t from_ptr = (xfs_caddr_t)from;473473- xfs_sb_field_t f;474474- int first;475475- int size;537537+ xfs_sb_quota_to_disk(to, from);476538477477- ASSERT(fields);478478- if (!fields)479479- return;539539+ to->sb_magicnum = cpu_to_be32(from->sb_magicnum);540540+ to->sb_blocksize = cpu_to_be32(from->sb_blocksize);541541+ to->sb_dblocks = cpu_to_be64(from->sb_dblocks);542542+ to->sb_rblocks = cpu_to_be64(from->sb_rblocks);543543+ to->sb_rextents = cpu_to_be64(from->sb_rextents);544544+ memcpy(&to->sb_uuid, &from->sb_uuid, sizeof(to->sb_uuid));545545+ to->sb_logstart = cpu_to_be64(from->sb_logstart);546546+ to->sb_rootino = cpu_to_be64(from->sb_rootino);547547+ to->sb_rbmino = cpu_to_be64(from->sb_rbmino);548548+ to->sb_rsumino = cpu_to_be64(from->sb_rsumino);549549+ to->sb_rextsize = cpu_to_be32(from->sb_rextsize);550550+ to->sb_agblocks = cpu_to_be32(from->sb_agblocks);551551+ to->sb_agcount = cpu_to_be32(from->sb_agcount);552552+ to->sb_rbmblocks = cpu_to_be32(from->sb_rbmblocks);553553+ to->sb_logblocks = cpu_to_be32(from->sb_logblocks);554554+ to->sb_versionnum = cpu_to_be16(from->sb_versionnum);555555+ to->sb_sectsize = cpu_to_be16(from->sb_sectsize);556556+ to->sb_inodesize = cpu_to_be16(from->sb_inodesize);557557+ to->sb_inopblock = cpu_to_be16(from->sb_inopblock);558558+ memcpy(&to->sb_fname, &from->sb_fname, sizeof(to->sb_fname));559559+ to->sb_blocklog = from->sb_blocklog;560560+ to->sb_sectlog = from->sb_sectlog;561561+ to->sb_inodelog = from->sb_inodelog;562562+ to->sb_inopblog = from->sb_inopblog;563563+ to->sb_agblklog = from->sb_agblklog;564564+ to->sb_rextslog = from->sb_rextslog;565565+ to->sb_inprogress = from->sb_inprogress;566566+ to->sb_imax_pct = from->sb_imax_pct;567567+ to->sb_icount = cpu_to_be64(from->sb_icount);568568+ to->sb_ifree = cpu_to_be64(from->sb_ifree);569569+ to->sb_fdblocks = cpu_to_be64(from->sb_fdblocks);570570+ to->sb_frextents = cpu_to_be64(from->sb_frextents);480571481481- /* We should never write the crc here, it's updated in the IO path */482482- fields &= ~XFS_SB_CRC;572572+ to->sb_flags = from->sb_flags;573573+ to->sb_shared_vn = from->sb_shared_vn;574574+ to->sb_inoalignmt = cpu_to_be32(from->sb_inoalignmt);575575+ to->sb_unit = cpu_to_be32(from->sb_unit);576576+ to->sb_width = cpu_to_be32(from->sb_width);577577+ to->sb_dirblklog = from->sb_dirblklog;578578+ to->sb_logsectlog = from->sb_logsectlog;579579+ to->sb_logsectsize = cpu_to_be16(from->sb_logsectsize);580580+ to->sb_logsunit = cpu_to_be32(from->sb_logsunit);483581484484- xfs_sb_quota_to_disk(to, from, &fields);485485- while (fields) {486486- f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);487487- first = xfs_sb_info[f].offset;488488- size = xfs_sb_info[f + 1].offset - first;582582+ /*583583+ * We need to ensure that bad_features2 always matches features2.584584+ * Hence we enforce that here rather than having to remember to do it585585+ * everywhere else that updates features2.586586+ */587587+ from->sb_bad_features2 = from->sb_features2;588588+ to->sb_features2 = cpu_to_be32(from->sb_features2);589589+ to->sb_bad_features2 = cpu_to_be32(from->sb_bad_features2);489590490490- ASSERT(xfs_sb_info[f].type == 0 || xfs_sb_info[f].type == 1);491491-492492- if (size == 1 || xfs_sb_info[f].type == 1) {493493- memcpy(to_ptr + first, from_ptr + first, size);494494- } else {495495- switch (size) {496496- case 2:497497- *(__be16 *)(to_ptr + first) =498498- cpu_to_be16(*(__u16 *)(from_ptr + first));499499- break;500500- case 4:501501- *(__be32 *)(to_ptr + first) =502502- cpu_to_be32(*(__u32 *)(from_ptr + first));503503- break;504504- case 8:505505- *(__be64 *)(to_ptr + first) =506506- cpu_to_be64(*(__u64 *)(from_ptr + first));507507- break;508508- default:509509- ASSERT(0);510510- }511511- }512512-513513- fields &= ~(1LL << f);591591+ if (xfs_sb_version_hascrc(from)) {592592+ to->sb_features_compat = cpu_to_be32(from->sb_features_compat);593593+ to->sb_features_ro_compat =594594+ cpu_to_be32(from->sb_features_ro_compat);595595+ to->sb_features_incompat =596596+ cpu_to_be32(from->sb_features_incompat);597597+ to->sb_features_log_incompat =598598+ cpu_to_be32(from->sb_features_log_incompat);599599+ to->sb_pad = 0;600600+ to->sb_lsn = cpu_to_be64(from->sb_lsn);514601 }515602}516603···759816}760817761818/*762762- * xfs_mod_sb() can be used to copy arbitrary changes to the763763- * in-core superblock into the superblock buffer to be logged.764764- * It does not provide the higher level of locking that is765765- * needed to protect the in-core superblock from concurrent766766- * access.819819+ * xfs_log_sb() can be used to copy arbitrary changes to the in-core superblock820820+ * into the superblock buffer to be logged. It does not provide the higher821821+ * level of locking that is needed to protect the in-core superblock from822822+ * concurrent access.767823 */768824void769769-xfs_mod_sb(xfs_trans_t *tp, __int64_t fields)825825+xfs_log_sb(826826+ struct xfs_trans *tp)770827{771771- xfs_buf_t *bp;772772- int first;773773- int last;774774- xfs_mount_t *mp;775775- xfs_sb_field_t f;828828+ struct xfs_mount *mp = tp->t_mountp;829829+ struct xfs_buf *bp = xfs_trans_getsb(tp, mp, 0);776830777777- ASSERT(fields);778778- if (!fields)779779- return;780780- mp = tp->t_mountp;781781- bp = xfs_trans_getsb(tp, mp, 0);782782- first = sizeof(xfs_sb_t);783783- last = 0;784784-785785- /* translate/copy */786786-787787- xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, fields);788788-789789- /* find modified range */790790- f = (xfs_sb_field_t)xfs_highbit64((__uint64_t)fields);791791- ASSERT((1LL << f) & XFS_SB_MOD_BITS);792792- last = xfs_sb_info[f + 1].offset - 1;793793-794794- f = (xfs_sb_field_t)xfs_lowbit64((__uint64_t)fields);795795- ASSERT((1LL << f) & XFS_SB_MOD_BITS);796796- first = xfs_sb_info[f].offset;797797-831831+ xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);798832 xfs_trans_buf_set_type(tp, bp, XFS_BLFT_SB_BUF);799799- xfs_trans_log_buf(tp, bp, first, last);833833+ xfs_trans_log_buf(tp, bp, 0, sizeof(struct xfs_dsb));834834+}835835+836836+/*837837+ * xfs_sync_sb838838+ *839839+ * Sync the superblock to disk.840840+ *841841+ * Note that the caller is responsible for checking the frozen state of the842842+ * filesystem. This procedure uses the non-blocking transaction allocator and843843+ * thus will allow modifications to a frozen fs. This is required because this844844+ * code can be called during the process of freezing where use of the high-level845845+ * allocator would deadlock.846846+ */847847+int848848+xfs_sync_sb(849849+ struct xfs_mount *mp,850850+ bool wait)851851+{852852+ struct xfs_trans *tp;853853+ int error;854854+855855+ tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_CHANGE, KM_SLEEP);856856+ error = xfs_trans_reserve(tp, &M_RES(mp)->tr_sb, 0, 0);857857+ if (error) {858858+ xfs_trans_cancel(tp, 0);859859+ return error;860860+ }861861+862862+ xfs_log_sb(tp);863863+ if (wait)864864+ xfs_trans_set_sync(tp);865865+ return xfs_trans_commit(tp, 0);800866}
···716716}717717718718/*719719- * Clearing the quotaflags in the superblock.720720- * the super block for changing quota flags: sector size721721- */722722-STATIC uint723723-xfs_calc_qm_sbchange_reservation(724724- struct xfs_mount *mp)725725-{726726- return xfs_calc_buf_res(1, mp->m_sb.sb_sectsize);727727-}728728-729729-/*730719 * Adjusting quota limits.731720 * the xfs_disk_dquot_t: sizeof(struct xfs_disk_dquot)732721 */···853864 * The following transactions are logged in logical format with854865 * a default log count.855866 */856856- resp->tr_qm_sbchange.tr_logres = xfs_calc_qm_sbchange_reservation(mp);857857- resp->tr_qm_sbchange.tr_logcount = XFS_DEFAULT_LOG_COUNT;858858-859867 resp->tr_qm_setqlim.tr_logres = xfs_calc_qm_setqlim_reservation(mp);860868 resp->tr_qm_setqlim.tr_logcount = XFS_DEFAULT_LOG_COUNT;861869
···541541 saved_error = error;542542 continue;543543 }544544- xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb, XFS_SB_ALL_BITS);544544+ xfs_sb_to_disk(XFS_BUF_TO_SBP(bp), &mp->m_sb);545545546546 error = xfs_bwrite(bp);547547 xfs_buf_relse(bp);···754754 goto retry;755755 }756756 return 0;757757-}758758-759759-/*760760- * Dump a transaction into the log that contains no real change. This is needed761761- * to be able to make the log dirty or stamp the current tail LSN into the log762762- * during the covering operation.763763- *764764- * We cannot use an inode here for this - that will push dirty state back up765765- * into the VFS and then periodic inode flushing will prevent log covering from766766- * making progress. Hence we log a field in the superblock instead and use a767767- * synchronous transaction to ensure the superblock is immediately unpinned768768- * and can be written back.769769- */770770-int771771-xfs_fs_log_dummy(772772- xfs_mount_t *mp)773773-{774774- xfs_trans_t *tp;775775- int error;776776-777777- tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1, KM_SLEEP);778778- error = xfs_trans_reserve(tp, &M_RES(mp)->tr_sb, 0, 0);779779- if (error) {780780- xfs_trans_cancel(tp, 0);781781- return error;782782- }783783-784784- /* log the UUID because it is an unchanging field */785785- xfs_mod_sb(tp, XFS_SB_UUID);786786- xfs_trans_set_sync(tp);787787- return xfs_trans_commit(tp, 0);788757}789758790759int
+15-3
fs/xfs/xfs_log.c
···3333#include "xfs_fsops.h"3434#include "xfs_cksum.h"3535#include "xfs_sysfs.h"3636+#include "xfs_sb.h"36373738kmem_zone_t *xfs_log_ticket_zone;3839···12911290 struct xfs_mount *mp = log->l_mp;1292129112931292 /* dgc: errors ignored - not fatal and nowhere to report them */12941294- if (xfs_log_need_covered(mp))12951295- xfs_fs_log_dummy(mp);12961296- else12931293+ if (xfs_log_need_covered(mp)) {12941294+ /*12951295+ * Dump a transaction into the log that contains no real change.12961296+ * This is needed to stamp the current tail LSN into the log12971297+ * during the covering operation.12981298+ *12991299+ * We cannot use an inode here for this - that will push dirty13001300+ * state back up into the VFS and then periodic inode flushing13011301+ * will prevent log covering from making progress. Hence we13021302+ * synchronously log the superblock instead to ensure the13031303+ * superblock is immediately unpinned and can be written back.13041304+ */13051305+ xfs_sync_sb(mp, true);13061306+ } else12971307 xfs_log_force(mp, 0);1298130812991309 /* start pushing all the metadata that is currently dirty */
+23-83
fs/xfs/xfs_mount.c
···408408 if (xfs_sb_version_hasdalign(sbp)) {409409 if (sbp->sb_unit != mp->m_dalign) {410410 sbp->sb_unit = mp->m_dalign;411411- mp->m_update_flags |= XFS_SB_UNIT;411411+ mp->m_update_sb = true;412412 }413413 if (sbp->sb_width != mp->m_swidth) {414414 sbp->sb_width = mp->m_swidth;415415- mp->m_update_flags |= XFS_SB_WIDTH;415415+ mp->m_update_sb = true;416416 }417417 } else {418418 xfs_warn(mp,···583583xfs_mount_reset_sbqflags(584584 struct xfs_mount *mp)585585{586586- int error;587587- struct xfs_trans *tp;588588-589586 mp->m_qflags = 0;590587591591- /*592592- * It is OK to look at sb_qflags here in mount path,593593- * without m_sb_lock.594594- */588588+ /* It is OK to look at sb_qflags in the mount path without m_sb_lock. */595589 if (mp->m_sb.sb_qflags == 0)596590 return 0;597591 spin_lock(&mp->m_sb_lock);598592 mp->m_sb.sb_qflags = 0;599593 spin_unlock(&mp->m_sb_lock);600594601601- /*602602- * If the fs is readonly, let the incore superblock run603603- * with quotas off but don't flush the update out to disk604604- */605605- if (mp->m_flags & XFS_MOUNT_RDONLY)595595+ if (!xfs_fs_writable(mp, SB_FREEZE_WRITE))606596 return 0;607597608608- tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);609609- error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_sbchange, 0, 0);610610- if (error) {611611- xfs_trans_cancel(tp, 0);612612- xfs_alert(mp, "%s: Superblock update failed!", __func__);613613- return error;614614- }615615-616616- xfs_mod_sb(tp, XFS_SB_QFLAGS);617617- return xfs_trans_commit(tp, 0);598598+ return xfs_sync_sb(mp, false);618599}619600620601__uint64_t···640659 xfs_sb_mount_common(mp, sbp);641660642661 /*643643- * Check for a mismatched features2 values. Older kernels644644- * read & wrote into the wrong sb offset for sb_features2645645- * on some platforms due to xfs_sb_t not being 64bit size aligned646646- * when sb_features2 was added, which made older superblock647647- * reading/writing routines swap it as a 64-bit value.662662+ * Check for a mismatched features2 values. Older kernels read & wrote663663+ * into the wrong sb offset for sb_features2 on some platforms due to664664+ * xfs_sb_t not being 64bit size aligned when sb_features2 was added,665665+ * which made older superblock reading/writing routines swap it as a666666+ * 64-bit value.648667 *649668 * For backwards compatibility, we make both slots equal.650669 *651651- * If we detect a mismatched field, we OR the set bits into the652652- * existing features2 field in case it has already been modified; we653653- * don't want to lose any features. We then update the bad location654654- * with the ORed value so that older kernels will see any features2655655- * flags, and mark the two fields as needing updates once the656656- * transaction subsystem is online.670670+ * If we detect a mismatched field, we OR the set bits into the existing671671+ * features2 field in case it has already been modified; we don't want672672+ * to lose any features. We then update the bad location with the ORed673673+ * value so that older kernels will see any features2 flags. The674674+ * superblock writeback code ensures the new sb_features2 is copied to675675+ * sb_bad_features2 before it is logged or written to disk.657676 */658677 if (xfs_sb_has_mismatched_features2(sbp)) {659678 xfs_warn(mp, "correcting sb_features alignment problem");660679 sbp->sb_features2 |= sbp->sb_bad_features2;661661- sbp->sb_bad_features2 = sbp->sb_features2;662662- mp->m_update_flags |= XFS_SB_FEATURES2;680680+ mp->m_update_sb = true;663681664682 /*665683 * Re-check for ATTR2 in case it was found in bad_features2···672692 if (xfs_sb_version_hasattr2(&mp->m_sb) &&673693 (mp->m_flags & XFS_MOUNT_NOATTR2)) {674694 xfs_sb_version_removeattr2(&mp->m_sb);675675- mp->m_update_flags |= XFS_SB_FEATURES2;695695+ mp->m_update_sb = true;676696677697 /* update sb_versionnum for the clearing of the morebits */678698 if (!sbp->sb_features2)679679- mp->m_update_flags |= XFS_SB_VERSIONNUM;699699+ mp->m_update_sb = true;680700 }681701682702 /* always use v2 inodes by default now */683703 if (!(mp->m_sb.sb_versionnum & XFS_SB_VERSION_NLINKBIT)) {684704 mp->m_sb.sb_versionnum |= XFS_SB_VERSION_NLINKBIT;685685- mp->m_update_flags |= XFS_SB_VERSIONNUM;705705+ mp->m_update_sb = true;686706 }687707688708 /*···875895 * the next remount into writeable mode. Otherwise we would never876896 * perform the update e.g. for the root filesystem.877897 */878878- if (mp->m_update_flags && !(mp->m_flags & XFS_MOUNT_RDONLY)) {879879- error = xfs_mount_log_sb(mp, mp->m_update_flags);898898+ if (mp->m_update_sb && !(mp->m_flags & XFS_MOUNT_RDONLY)) {899899+ error = xfs_sync_sb(mp, false);880900 if (error) {881901 xfs_warn(mp, "failed to write sb changes");882902 goto out_rtunmount;···10831103int10841104xfs_log_sbcount(xfs_mount_t *mp)10851105{10861086- xfs_trans_t *tp;10871087- int error;10881088-10891106 /* allow this to proceed during the freeze sequence... */10901107 if (!xfs_fs_writable(mp, SB_FREEZE_COMPLETE))10911108 return 0;···10961119 if (!xfs_sb_version_haslazysbcount(&mp->m_sb))10971120 return 0;1098112110991099- tp = _xfs_trans_alloc(mp, XFS_TRANS_SB_COUNT, KM_SLEEP);11001100- error = xfs_trans_reserve(tp, &M_RES(mp)->tr_sb, 0, 0);11011101- if (error) {11021102- xfs_trans_cancel(tp, 0);11031103- return error;11041104- }11051105-11061106- xfs_mod_sb(tp, XFS_SB_IFREE | XFS_SB_ICOUNT | XFS_SB_FDBLOCKS);11071107- xfs_trans_set_sync(tp);11081108- error = xfs_trans_commit(tp, 0);11091109- return error;11221122+ return xfs_sync_sb(mp, true);11101123}1111112411121125/*···13871420 xfs_buf_lock(bp);13881421 mp->m_sb_bp = NULL;13891422 xfs_buf_relse(bp);13901390-}13911391-13921392-/*13931393- * Used to log changes to the superblock unit and width fields which could13941394- * be altered by the mount options, as well as any potential sb_features213951395- * fixup. Only the first superblock is updated.13961396- */13971397-int13981398-xfs_mount_log_sb(13991399- xfs_mount_t *mp,14001400- __int64_t fields)14011401-{14021402- xfs_trans_t *tp;14031403- int error;14041404-14051405- ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |14061406- XFS_SB_FEATURES2 | XFS_SB_VERSIONNUM));14071407-14081408- tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);14091409- error = xfs_trans_reserve(tp, &M_RES(mp)->tr_sb, 0, 0);14101410- if (error) {14111411- xfs_trans_cancel(tp, 0);14121412- return error;14131413- }14141414- xfs_mod_sb(tp, fields);14151415- error = xfs_trans_commit(tp, 0);14161416- return error;14171423}1418142414191425/*
+2-3
fs/xfs/xfs_mount.h
···162162 struct delayed_work m_reclaim_work; /* background inode reclaim */163163 struct delayed_work m_eofblocks_work; /* background eof blocks164164 trimming */165165- __int64_t m_update_flags; /* sb flags we need to update166166- on the next remount,rw */165165+ bool m_update_sb; /* sb needs update in mount */167166 int64_t m_low_space[XFS_LOWSP_MAX];168167 /* low free space thresholds */169168 struct xfs_kobj m_kobj;···377378extern int xfs_mod_incore_sb(xfs_mount_t *, xfs_sb_field_t, int64_t, int);378379extern int xfs_mod_incore_sb_batch(xfs_mount_t *, xfs_mod_sb_t *,379380 uint, int);380380-extern int xfs_mount_log_sb(xfs_mount_t *, __int64_t);381381+extern int xfs_mount_log_sb(xfs_mount_t *);381382extern struct xfs_buf *xfs_getsb(xfs_mount_t *, int);382383extern int xfs_readsb(xfs_mount_t *, int);383384extern void xfs_freesb(xfs_mount_t *);
+2-41
fs/xfs/xfs_qm.c
···714714xfs_qm_qino_alloc(715715 xfs_mount_t *mp,716716 xfs_inode_t **ip,717717- __int64_t sbfields,718717 uint flags)719718{720719 xfs_trans_t *tp;···776777 spin_lock(&mp->m_sb_lock);777778 if (flags & XFS_QMOPT_SBVERSION) {778779 ASSERT(!xfs_sb_version_hasquota(&mp->m_sb));779779- ASSERT((sbfields & (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |780780- XFS_SB_GQUOTINO | XFS_SB_PQUOTINO | XFS_SB_QFLAGS)) ==781781- (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |782782- XFS_SB_GQUOTINO | XFS_SB_PQUOTINO |783783- XFS_SB_QFLAGS));784780785781 xfs_sb_version_addquota(&mp->m_sb);786782 mp->m_sb.sb_uquotino = NULLFSINO;···792798 else793799 mp->m_sb.sb_pquotino = (*ip)->i_ino;794800 spin_unlock(&mp->m_sb_lock);795795- xfs_mod_sb(tp, sbfields);801801+ xfs_log_sb(tp);796802797803 if ((error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES))) {798804 xfs_alert(mp, "%s failed (error %d)!", __func__, error);···14451451 spin_unlock(&mp->m_sb_lock);1446145214471453 if (sbf != (mp->m_qflags & XFS_MOUNT_QUOTA_ALL)) {14481448- if (xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS)) {14541454+ if (xfs_sync_sb(mp, false)) {14491455 /*14501456 * We could only have been turning quotas off.14511457 * We aren't in very good shape actually because···14761482 struct xfs_inode *gip = NULL;14771483 struct xfs_inode *pip = NULL;14781484 int error;14791479- __int64_t sbflags = 0;14801485 uint flags = 0;1481148614821487 ASSERT(mp->m_quotainfo);···15101517 }15111518 } else {15121519 flags |= XFS_QMOPT_SBVERSION;15131513- sbflags |= (XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO |15141514- XFS_SB_GQUOTINO | XFS_SB_PQUOTINO |15151515- XFS_SB_QFLAGS);15161520 }1517152115181522 /*···15201530 */15211531 if (XFS_IS_UQUOTA_ON(mp) && uip == NULL) {15221532 error = xfs_qm_qino_alloc(mp, &uip,15231523- sbflags | XFS_SB_UQUOTINO,15241533 flags | XFS_QMOPT_UQUOTA);15251534 if (error)15261535 goto error_rele;···15281539 }15291540 if (XFS_IS_GQUOTA_ON(mp) && gip == NULL) {15301541 error = xfs_qm_qino_alloc(mp, &gip,15311531- sbflags | XFS_SB_GQUOTINO,15321542 flags | XFS_QMOPT_GQUOTA);15331543 if (error)15341544 goto error_rele;···15361548 }15371549 if (XFS_IS_PQUOTA_ON(mp) && pip == NULL) {15381550 error = xfs_qm_qino_alloc(mp, &pip,15391539- sbflags | XFS_SB_PQUOTINO,15401551 flags | XFS_QMOPT_PQUOTA);15411552 if (error)15421553 goto error_rele;···1573158615741587 xfs_qm_dqdestroy(dqp);15751588}15761576-15771577-/*15781578- * Start a transaction and write the incore superblock changes to15791579- * disk. flags parameter indicates which fields have changed.15801580- */15811581-int15821582-xfs_qm_write_sb_changes(15831583- xfs_mount_t *mp,15841584- __int64_t flags)15851585-{15861586- xfs_trans_t *tp;15871587- int error;15881588-15891589- tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SBCHANGE);15901590- error = xfs_trans_reserve(tp, &M_RES(mp)->tr_qm_sbchange, 0, 0);15911591- if (error) {15921592- xfs_trans_cancel(tp, 0);15931593- return error;15941594- }15951595-15961596- xfs_mod_sb(tp, flags);15971597- error = xfs_trans_commit(tp, 0);15981598-15991599- return error;16001600-}16011601-1602158916031590/* --------------- utility functions for vnodeops ---------------- */16041591
···9292 mutex_unlock(&q->qi_quotaofflock);93939494 /* XXX what to do if error ? Revert back to old vals incore ? */9595- error = xfs_qm_write_sb_changes(mp, XFS_SB_QFLAGS);9696- return error;9595+ return xfs_sync_sb(mp, false);9796 }98979998 dqtype = 0;···313314{314315 int error;315316 uint qf;316316- __int64_t sbflags;317317318318 flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD);319319 /*320320 * Switching on quota accounting must be done at mount time.321321 */322322 flags &= ~(XFS_ALL_QUOTA_ACCT);323323-324324- sbflags = 0;325323326324 if (flags == 0) {327325 xfs_debug(mp, "%s: zero flags, m_qflags=%x",···366370 /*367371 * There's nothing to change if it's the same.368372 */369369- if ((qf & flags) == flags && sbflags == 0)373373+ if ((qf & flags) == flags)370374 return -EEXIST;371371- sbflags |= XFS_SB_QFLAGS;372375373373- if ((error = xfs_qm_write_sb_changes(mp, sbflags)))376376+ error = xfs_sync_sb(mp, false);377377+ if (error)374378 return error;375379 /*376380 * If we aren't trying to switch on quota enforcement, we are done.···797801 mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) & XFS_MOUNT_QUOTA_ALL;798802 spin_unlock(&mp->m_sb_lock);799803800800- xfs_mod_sb(tp, XFS_SB_QFLAGS);804804+ xfs_log_sb(tp);801805802806 /*803807 * We have to make sure that the transaction is secure on disk before we
+7-6
fs/xfs/xfs_super.c
···12571257 * If this is the first remount to writeable state we12581258 * might have some superblock changes to update.12591259 */12601260- if (mp->m_update_flags) {12611261- error = xfs_mount_log_sb(mp, mp->m_update_flags);12601260+ if (mp->m_update_sb) {12611261+ error = xfs_sync_sb(mp, false);12621262 if (error) {12631263 xfs_warn(mp, "failed to write sb changes");12641264 return error;12651265 }12661266- mp->m_update_flags = 0;12661266+ mp->m_update_sb = false;12671267 }1268126812691269 /*···1293129312941294/*12951295 * Second stage of a freeze. The data is already frozen so we only12961296- * need to take care of the metadata. Once that's done write a dummy12971297- * record to dirty the log in case of a crash while frozen.12961296+ * need to take care of the metadata. Once that's done sync the superblock12971297+ * to the log to dirty it in case of a crash while frozen. This ensures that we12981298+ * will recover the unlinked inode lists on the next mount.12981299 */12991300STATIC int13001301xfs_fs_freeze(···1305130413061305 xfs_save_resvblks(mp);13071306 xfs_quiesce_attr(mp);13081308- return xfs_fs_log_dummy(mp);13071307+ return xfs_sync_sb(mp, true);13091308}1310130913111310STATIC int