xfs: misc. fixes
cover xfs: misc. fixes
Hi all,
This series includes a few miscellaneous patches I came across while doing some local branch housekeeping. These have been posted previously and appear to have fallen through the cracks.
Note that there was an alternative version of patch 3 floating around somewhere. It doesn't matter much to me which one we take.
Brian
Brian Foster (3):
xfs: replace on-stack xfs_trans_res with pointer in xfs_create()
xfs: fix error handling in xfs_qm_log_quotaoff()
xfs: allow lazy sb counter sync during filesystem freeze sequence
fs/xfs/xfs_inode.c | 15 ++++++--------- fs/xfs/xfs_log.c | 2 +- fs/xfs/xfs_mount.c | 29 +++++++++++++++++++++-------- fs/xfs/xfs_mount.h | 2 +- fs/xfs/xfs_qm_syscalls.c | 26 ++++++++++---------------- 5 files changed, 39 insertions(+), 35 deletions(-)
Signature · 6 lines
1.8.3.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 1/3 xfs: replace on-stack xfs_trans_res with pointer in xfs_create()
There's no need to store a full struct xfs_trans_res on the stack in xfs_create() and copy the fields. Use a pointer to the appropriate structures embedded in the xfs_mount.
--- fs/xfs/xfs_inode.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
fs/xfs/xfs_inode.c +6 -9
@@ -1082,7 +1082,7 @@ xfs_create(struct xfs_dquot *udqp =NULL ;struct xfs_dquot *gdqp =NULL ;struct xfs_dquot *pdqp =NULL ; -struct xfs_trans_res tres; +struct xfs_trans_res *tres;uint resblks;trace_xfs_create (dp, name);
@@ -1105,13 +1105,11 @@ xfs_create(if (is_dir) { rdev =0 ; resblks =XFS_MKDIR_SPACE_RES (mp, name->len); - tres.tr_logres =M_RES (mp)->tr_mkdir.tr_logres; - tres.tr_logcount =XFS_MKDIR_LOG_COUNT ; + tres = &M_RES (mp)->tr_mkdir; tp =xfs_trans_alloc (mp,XFS_TRANS_MKDIR ); }else { resblks =XFS_CREATE_SPACE_RES (mp, name->len); - tres.tr_logres =M_RES (mp)->tr_create.tr_logres; - tres.tr_logcount =XFS_CREATE_LOG_COUNT ; + tres = &M_RES (mp)->tr_create; tp =xfs_trans_alloc (mp,XFS_TRANS_CREATE ); }
@@ -1123,17 +1121,16 @@ xfs_create(* the case we'll drop the one we have and get a more * appropriate transaction later. */ - tres.tr_logflags =XFS_TRANS_PERM_LOG_RES ; - error =xfs_trans_reserve (tp, &tres, resblks,0 ); + error =xfs_trans_reserve (tp, tres, resblks,0 );if (error == -ENOSPC ) {/* flush outstanding delalloc blocks and retry */ xfs_flush_inodes (mp); - error =xfs_trans_reserve (tp, &tres, resblks,0 ); + error =xfs_trans_reserve (tp, tres, resblks,0 ); }if (error == -ENOSPC ) {/* No space at all so try a "no-allocation" reservation */ resblks =0 ; - error =xfs_trans_reserve (tp, &tres,0 ,0 ); + error =xfs_trans_reserve (tp, tres,0 ,0 ); }if (error) { cancel_flags =0 ;
Signature · 6 lines
1.8.3.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 2/3 xfs: fix error handling in xfs_qm_log_quotaoff()
In reply to Brian FosterThe error handling in xfs_qm_log_quotaoff() has a couple problems. If xfs_trans_commit() fails, we fall through to the error block and call xfs_trans_cancel(). This is incorrect on commit failure. If xfs_trans_reserve() fails, we jump to the error block, cancel the tp and restore the superblock qflags to oldsbqflag. However, oldsbqflag has been initialized to zero and not yet updated from the original flags so we set the flags to zero.
Fix up the error handling in xfs_qm_log_quotaoff() to not restore flags if they haven't been modified and not cancel the tp on commit failure. Remove the flag restore code altogether because commit error is the only failure condition and we don't know whether the transaction made it to disk.
--- fs/xfs/xfs_qm_syscalls.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-)
fs/xfs/xfs_qm_syscalls.c +10 -16
@@ -784,19 +784,21 @@ xfs_qm_log_quotaoff( {xfs_trans_t *tp;int error; -xfs_qoff_logitem_t *qoffi=NULL ; -uint oldsbqflag=0 ; +xfs_qoff_logitem_t *qoffi; + + *qoffstartp =NULL ; tp =xfs_trans_alloc (mp,XFS_TRANS_QM_QUOTAOFF ); error =xfs_trans_reserve (tp, &M_RES (mp)->tr_qm_quotaoff,0 ,0 ); -if (error) - goto error0; +if (error) { +xfs_trans_cancel (tp,0 ); + goto out; + } qoffi =xfs_trans_get_qoff_item (tp,NULL , flags &XFS_ALL_QUOTA_ACCT );xfs_trans_log_quotaoff_item (tp, qoffi);spin_lock (&mp->m_sb_lock); - oldsbqflag = mp->m_sb.sb_qflags; mp->m_sb.sb_qflags = (mp->m_qflags & ~(flags)) &XFS_MOUNT_QUOTA_ALL ;spin_unlock (&mp->m_sb_lock);
@@ -809,19 +811,11 @@ xfs_qm_log_quotaoff(*/ xfs_trans_set_sync (tp); error =xfs_trans_commit (tp,0 ); +if (error) + goto out; -error0: -if (error) { -xfs_trans_cancel (tp,0 ); -/* -* No one else is modifying sb_qflags, so this is OK. -* We still hold the quotaofflock. -*/ -spin_lock (&mp->m_sb_lock); - mp->m_sb.sb_qflags = oldsbqflag; -spin_unlock (&mp->m_sb_lock); - } *qoffstartp = qoffi; +out:return error; }
Signature · 6 lines
1.8.3.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs
PATCH 3/3 xfs: allow lazy sb counter sync during filesystem freeze sequence
In reply to Brian FosterThe expectation since the introduction the lazy superblock counters is that the counters are synced and superblock logged appropriately as part of the filesystem freeze sequence. This does not occur, however, due to the logic in xfs_fs_writable() that prevents progress when the fs is in any state other than SB_UNFROZEN.
While this is a bug, it has not been exposed to date because the last thing XFS does during freeze is dirty the log. The log recovery process recalculates the counters from AGI/AGF metadata to ensure everything is correct. Therefore should a crash occur while an fs is frozen, the subsequent log recovery puts everything back in order. See the following commit for reference:
92821e2b [XFS] Lazy Superblock Counters
We might not always want to rely on dirtying the log on a frozen fs. Modify xfs_log_sbcount() to proceed when the filesystem is freezing but not once the freeze process has completed. Modify xfs_fs_writable() to accept the minimum freeze level for which modifications should be blocked to support various codepaths.
--- fs/xfs/xfs_log.c | 2 +- fs/xfs/xfs_mount.c | 29 +++++++++++++++++++++-------- fs/xfs/xfs_mount.h | 2 +- 3 files changed, 23 insertions(+), 10 deletions(-)
fs/xfs/xfs_log.c +1 -1
@@ -1031,7 +1031,7 @@ xfs_log_need_covered(xfs_mount_t *mp)struct xlog *log = mp->m_log;int needed =0 ; -if (!xfs_fs_writable (mp)) +if (!xfs_fs_writable (mp,SB_FREEZE_WRITE ))return 0 ;if (!xlog_cil_empty (log))
fs/xfs/xfs_mount.c +21 -8
@@ -1074,11 +1074,23 @@ xfs_unmountfs(xfs_sysfs_del (&mp->m_kobj); } -int -xfs_fs_writable (xfs_mount_t *mp) +/* +* Determine whether modifications can proceed. The caller specifies the minimum +* freeze level for which modifications should not be allowed. This allows +* certain operations to proceed while the freeze sequence is in progress, if +* necessary. +*/ +bool +xfs_fs_writable ( +struct xfs_mount *mp, +int level) { -return !(mp->m_super->s_writers.frozen ||XFS_FORCED_SHUTDOWN (mp) || - (mp->m_flags &XFS_MOUNT_RDONLY )); +ASSERT (level >SB_UNFROZEN ); +if ((mp->m_super->s_writers.frozen >= level) || +XFS_FORCED_SHUTDOWN (mp) || (mp->m_flags &XFS_MOUNT_RDONLY )) +return false; + +return true; }/*
@@ -1086,9 +1098,9 @@ xfs_fs_writable(xfs_mount_t *mp)* * Sync the superblock counters to disk. * -* Note this code can be called during the process of freezing, so -* we may need to use the transaction allocator which does not -* block when the transaction subsystem is in its frozen state. +* Note this code can be called during the process of freezing, so we use the +* transaction allocator that does not block when the transaction subsystem is +* in its frozen state. */ int xfs_log_sbcount (xfs_mount_t *mp)
@@ -1096,7 +1108,8 @@ xfs_log_sbcount(xfs_mount_t *mp)xfs_trans_t *tp;int error; -if (!xfs_fs_writable (mp)) +/* allow this to proceed during the freeze sequence... */ +if (!xfs_fs_writable (mp,SB_FREEZE_COMPLETE ))return 0 ;xfs_icsb_sync_counters (mp,0 );
fs/xfs/xfs_mount.h +1 -1
@@ -384,7 +384,7 @@ extern int xfs_mount_log_sb(xfs_mount_t *, __int64_t);extern struct xfs_buf *xfs_getsb (xfs_mount_t *,int );extern int xfs_readsb (xfs_mount_t *,int );extern void xfs_freesb (xfs_mount_t *); -extern int xfs_fs_writable (xfs_mount_t *); +extern bool xfs_fs_writable (struct xfs_mount *mp,int level);extern int xfs_sb_validate_fsb_count (struct xfs_sb *,__uint64_t );extern int xfs_dev_is_read_only (struct xfs_mount *,char *);
Signature · 6 lines
1.8.3.1 _______________________________________________ xfs mailing list [email protected] http://oss.sgi.com/mailman/listinfo/xfs