History

Merge tag 'xfs-for-linus-v3.13-rc5' of git://oss.sgi.com/xfs/xfs

Pull xfs bugfixes from Ben Myers: "This contains fixes for some asserts related to project quotas, a memory leak, a hang when disabling group or project quotas before disabling user quotas, Dave's email address, several fixes for the alignment of file allocation to stripe unit/width geometry, a fix for an assertion with xfs_zero_remaining_bytes, and the behavior of metadata writeback in the face of IO errors. Details: - fix memory leak in xfs_dir2_node_removename - fix quota assertion in xfs_setattr_size - fix quota assertions in xfs_qm_vop_create_dqattach - fix for hang when disabling group and project quotas before disabling user quotas - fix Dave Chinner's email address in MAINTAINERS - fix for file allocation alignment - fix for assertion in xfs_buf_stale by removing xfsbdstrat - fix for alignment with swalloc mount option - fix for "retry forever" semantics on IO errors" * tag 'xfs-for-linus-v3.13-rc5' of git://oss.sgi.com/xfs/xfs: xfs: abort metadata writeback on permanent errors xfs: swalloc doesn't align allocations properly xfs: remove xfsbdstrat error xfs: align initial file allocations correctly MAINTAINERS: fix incorrect mail address of XFS maintainer xfs: fix infinite loop by detaching the group/project hints from user dquot xfs: fix assertion failure at xfs_setattr_nonsize xfs: fix false assertion at xfs_qm_vop_create_dqattach xfs: fix memory leak in xfs_dir2_node_removename

Linus Torvalds committed 12 years ago

Commit a6ddeee2 parents 40b64ac ac8809f11 files · +168 −84Browse files

Unified · Split

11 files
  1. MAINTAINERS +1 −1
  2. fs/xfs/xfs_bmap.c +24 −8
  3. fs/xfs/xfs_bmap_util.c +12 −2
  4. fs/xfs/xfs_buf.c +14 −23
  5. fs/xfs/xfs_buf.h +7 −4
  6. fs/xfs/xfs_buf_item.c +19 −2
  7. fs/xfs/xfs_dir2_node.c +13 −13
  8. fs/xfs/xfs_iops.c +2 −1
  9. fs/xfs/xfs_log_recover.c +11 −2
  10. fs/xfs/xfs_qm.c +53 −27
  11. fs/xfs/xfs_trans_buf.c +12 −1
MAINTAINERS+1−1
@@ -9588,7 +9588,7 @@ F: drivers/xen/*swiotlb* · 9587 unmodified lines
95889588
95899589 XFS FILESYSTEM
95909590 P: Silicon Graphics Inc
9591−M: Dave Chinner <dchinner@fromorbit.com>
9591+M: Dave Chinner <david@fromorbit.com>
95929592 M: Ben Myers <bpm@sgi.com>
95939593 M: xfs@oss.sgi.com
95949594 L: xfs@oss.sgi.com
fs/xfs/xfs_bmap.c+24−8
@@ -1635,7 +1635,7 @@ xfs_bmap_last_extent( · 1634 unmodified lines
16351635 * blocks at the end of the file which do not start at the previous data block,
16361636 * we will try to align the new blocks at stripe unit boundaries.
16371637 *
1638− * Returns 0 in bma->aeof if the file (fork) is empty as any new write will be
1638+ * Returns 1 in bma->aeof if the file (fork) is empty as any new write will be
16391639 * at, or past the EOF.
16401640 */
16411641 STATIC int
@@ -1650,9 +1650,14 @@ xfs_bmap_isaeof( · 8 unmodified lines
16501650 bma->aeof = 0;
16511651 error = xfs_bmap_last_extent(NULL, bma->ip, whichfork, &rec,
16521652 &is_empty);
1653− if (error || is_empty)
1653+ if (error)
16541654 return error;
16551655
1656+ if (is_empty) {
1657+ bma->aeof = 1;
1658+ return 0;
1659+ }
1660+
16561661 /*
16571662 * Check if we are allocation or past the last extent, or at least into
16581663 * the last delayed allocated extent.
@@ -3643,10 +3648,19 @@ xfs_bmap_btalloc( · 1984 unmodified lines
36433648 int isaligned;
36443649 int tryagain;
36453650 int error;
3651+ int stripe_align;
36463652
36473653 ASSERT(ap->length);
36483654
36493655 mp = ap->ip->i_mount;
3656+
3657+ /* stripe alignment for allocation is determined by mount parameters */
3658+ stripe_align = 0;
3659+ if (mp->m_swidth && (mp->m_flags & XFS_MOUNT_SWALLOC))
3660+ stripe_align = mp->m_swidth;
3661+ else if (mp->m_dalign)
3662+ stripe_align = mp->m_dalign;
3663+
36503664 align = ap->userdata ? xfs_get_extsz_hint(ap->ip) : 0;
36513665 if (unlikely(align)) {
36523666 error = xfs_bmap_extsize_align(mp, &ap->got, &ap->prev,
@@ -3655,6 +3669,8 @@ xfs_bmap_btalloc( · 2 unmodified lines
36553669 ASSERT(!error);
36563670 ASSERT(ap->length);
36573671 }
3672+
3673+
36583674 nullfb = *ap->firstblock == NULLFSBLOCK;
36593675 fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, *ap->firstblock);
36603676 if (nullfb) {
@@ -3730,7 +3746,7 @@ xfs_bmap_btalloc( · 69 unmodified lines
37303746 */
37313747 if (!ap->flist->xbf_low && ap->aeof) {
37323748 if (!ap->offset) {
3733− args.alignment = mp->m_dalign;
3749+ args.alignment = stripe_align;
37343750 atype = args.type;
37353751 isaligned = 1;
37363752 /*
@@ -3755,13 +3771,13 @@ xfs_bmap_btalloc( · 18 unmodified lines
37553771 * of minlen+alignment+slop doesn't go up
37563772 * between the calls.
37573773 */
3758− if (blen > mp->m_dalign && blen <= args.maxlen)
3759− nextminlen = blen - mp->m_dalign;
3774+ if (blen > stripe_align && blen <= args.maxlen)
3775+ nextminlen = blen - stripe_align;
37603776 else
37613777 nextminlen = args.minlen;
3762− if (nextminlen + mp->m_dalign > args.minlen + 1)
3778+ if (nextminlen + stripe_align > args.minlen + 1)
37633779 args.minalignslop =
3764− nextminlen + mp->m_dalign -
3780+ nextminlen + stripe_align -
37653781 args.minlen - 1;
37663782 else
37673783 args.minalignslop = 0;
@@ -3783,7 +3799,7 @@ xfs_bmap_btalloc( · 15 unmodified lines
37833799 */
37843800 args.type = atype;
37853801 args.fsbno = ap->blkno;
3786− args.alignment = mp->m_dalign;
3802+ args.alignment = stripe_align;
37873803 args.minlen = nextminlen;
37883804 args.minalignslop = 0;
37893805 isaligned = 1;
fs/xfs/xfs_bmap_util.c+12−2
@@ -1187,7 +1187,12 @@ xfs_zero_remaining_bytes( · 1186 unmodified lines
11871187 XFS_BUF_UNWRITE(bp);
11881188 XFS_BUF_READ(bp);
11891189 XFS_BUF_SET_ADDR(bp, xfs_fsb_to_db(ip, imap.br_startblock));
1190− xfsbdstrat(mp, bp);
1190+
1191+ if (XFS_FORCED_SHUTDOWN(mp)) {
1192+ error = XFS_ERROR(EIO);
1193+ break;
1194+ }
1195+ xfs_buf_iorequest(bp);
11911196 error = xfs_buf_iowait(bp);
11921197 if (error) {
11931198 xfs_buf_ioerror_alert(bp,
@@ -1200,7 +1205,12 @@ xfs_zero_remaining_bytes( · 6 unmodified lines
12001205 XFS_BUF_UNDONE(bp);
12011206 XFS_BUF_UNREAD(bp);
12021207 XFS_BUF_WRITE(bp);
1203− xfsbdstrat(mp, bp);
1208+
1209+ if (XFS_FORCED_SHUTDOWN(mp)) {
1210+ error = XFS_ERROR(EIO);
1211+ break;
1212+ }
1213+ xfs_buf_iorequest(bp);
12041214 error = xfs_buf_iowait(bp);
12051215 if (error) {
12061216 xfs_buf_ioerror_alert(bp,
fs/xfs/xfs_buf.c+14−23
@@ -698,7 +698,11 @@ xfs_buf_read_uncached( · 697 unmodified lines
698698 bp->b_flags |= XBF_READ;
699699 bp->b_ops = ops;
700700
701− xfsbdstrat(target->bt_mount, bp);
701+ if (XFS_FORCED_SHUTDOWN(target->bt_mount)) {
702+ xfs_buf_relse(bp);
703+ return NULL;
704+ }
705+ xfs_buf_iorequest(bp);
702706 xfs_buf_iowait(bp);
703707 return bp;
704708 }
@@ -1089,7 +1093,7 @@ xfs_bioerror( · 384 unmodified lines
10891093 * This is meant for userdata errors; metadata bufs come with
10901094 * iodone functions attached, so that we can track down errors.
10911095 */
1092−STATIC int
1096+int
10931097 xfs_bioerror_relse(
10941098 struct xfs_buf *bp)
10951099 {
@@ -1152,7 +1156,7 @@ xfs_bwrite( · 56 unmodified lines
11521156 ASSERT(xfs_buf_islocked(bp));
11531157
11541158 bp->b_flags |= XBF_WRITE;
1155− bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q);
1159+ bp->b_flags &= ~(XBF_ASYNC | XBF_READ | _XBF_DELWRI_Q | XBF_WRITE_FAIL);
11561160
11571161 xfs_bdstrat_cb(bp);
11581162
@@ -1164,25 +1168,6 @@ xfs_bwrite( · 5 unmodified lines
11641168 return error;
11651169 }
11661170
1167−/*
1168− * Wrapper around bdstrat so that we can stop data from going to disk in case
1169− * we are shutting down the filesystem. Typically user data goes thru this
1170− * path; one of the exceptions is the superblock.
1171− */
1172−void
1173−xfsbdstrat(
1174− struct xfs_mount *mp,
1175− struct xfs_buf *bp)
1176−{
1177− if (XFS_FORCED_SHUTDOWN(mp)) {
1178− trace_xfs_bdstrat_shut(bp, _RET_IP_);
1179− xfs_bioerror_relse(bp);
1180− return;
1181− }
1182−
1183− xfs_buf_iorequest(bp);
1184−}
1185−
11861171 STATIC void
11871172 _xfs_buf_ioend(
11881173 xfs_buf_t *bp,
@@ -1516,6 +1501,12 @@ xfs_wait_buftarg( · 327 unmodified lines
15161501 struct xfs_buf *bp;
15171502 bp = list_first_entry(&dispose, struct xfs_buf, b_lru);
15181503 list_del_init(&bp->b_lru);
1504+ if (bp->b_flags & XBF_WRITE_FAIL) {
1505+ xfs_alert(btp->bt_mount,
1506+"Corruption Alert: Buffer at block 0x%llx had permanent write failures!\n"
1507+"Please run xfs_repair to determine the extent of the problem.",
1508+ (long long)bp->b_bn);
1509+ }
15191510 xfs_buf_rele(bp);
15201511 }
15211512 if (loop++ != 0)
@@ -1799,7 +1790,7 @@ __xfs_buf_delwri_submit( · 277 unmodified lines
17991790
18001791 blk_start_plug(&plug);
18011792 list_for_each_entry_safe(bp, n, io_list, b_list) {
1802− bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC);
1793+ bp->b_flags &= ~(_XBF_DELWRI_Q | XBF_ASYNC | XBF_WRITE_FAIL);
18031794 bp->b_flags |= XBF_WRITE;
18041795
18051796 if (!wait) {
fs/xfs/xfs_buf.h+7−4
@@ -45,6 +45,7 @@ typedef enum { · 44 unmodified lines
4545 #define XBF_ASYNC (1 << 4) /* initiator will not wait for completion */
4646 #define XBF_DONE (1 << 5) /* all pages in the buffer uptodate */
4747 #define XBF_STALE (1 << 6) /* buffer has been staled, do not find it */
48+#define XBF_WRITE_FAIL (1 << 24)/* async writes have failed on this buffer */
4849
4950 /* I/O hints for the BIO layer */
5051 #define XBF_SYNCIO (1 << 10)/* treat this buffer as synchronous I/O */
@@ -70,6 +71,7 @@ typedef unsigned int xfs_buf_flags_t; · 19 unmodified lines
7071 { XBF_ASYNC, "ASYNC" }, \
7172 { XBF_DONE, "DONE" }, \
7273 { XBF_STALE, "STALE" }, \
74+ { XBF_WRITE_FAIL, "WRITE_FAIL" }, \
7375 { XBF_SYNCIO, "SYNCIO" }, \
7476 { XBF_FUA, "FUA" }, \
7577 { XBF_FLUSH, "FLUSH" }, \
@@ -80,6 +82,7 @@ typedef unsigned int xfs_buf_flags_t; · 4 unmodified lines
8082 { _XBF_DELWRI_Q, "DELWRI_Q" }, \
8183 { _XBF_COMPOUND, "COMPOUND" }
8284
85+
8386 /*
8487 * Internal state flags.
8588 */
@@ -269,9 +272,6 @@ extern void xfs_buf_unlock(xfs_buf_t *); · 183 unmodified lines
269272
270273 /* Buffer Read and Write Routines */
271274 extern int xfs_bwrite(struct xfs_buf *bp);
272−
273−extern void xfsbdstrat(struct xfs_mount *, struct xfs_buf *);
274−
275275 extern void xfs_buf_ioend(xfs_buf_t *, int);
276276 extern void xfs_buf_ioerror(xfs_buf_t *, int);
277277 extern void xfs_buf_ioerror_alert(struct xfs_buf *, const char *func);
@@ -282,6 +282,8 @@ extern void xfs_buf_iomove(xfs_buf_t *, size_t, size_t, void *, · 4 unmodified lines
282282 #define xfs_buf_zero(bp, off, len) \
283283 xfs_buf_iomove((bp), (off), (len), NULL, XBRW_ZERO)
284284
285+extern int xfs_bioerror_relse(struct xfs_buf *);
286+
285287 static inline int xfs_buf_geterror(xfs_buf_t *bp)
286288 {
287289 return bp ? bp->b_error : ENOMEM;
@@ -301,7 +303,8 @@ extern void xfs_buf_terminate(void); · 13 unmodified lines
301303
302304 #define XFS_BUF_ZEROFLAGS(bp) \
303305 ((bp)->b_flags &= ~(XBF_READ|XBF_WRITE|XBF_ASYNC| \
304− XBF_SYNCIO|XBF_FUA|XBF_FLUSH))
306+ XBF_SYNCIO|XBF_FUA|XBF_FLUSH| \
307+ XBF_WRITE_FAIL))
305308
306309 void xfs_buf_stale(struct xfs_buf *bp);
307310 #define XFS_BUF_UNSTALE(bp) ((bp)->b_flags &= ~XBF_STALE)
fs/xfs/xfs_buf_item.c+19−2
@@ -496,6 +496,14 @@ xfs_buf_item_unpin( · 495 unmodified lines
496496 }
497497 }
498498
499+/*
500+ * Buffer IO error rate limiting. Limit it to no more than 10 messages per 30
501+ * seconds so as to not spam logs too much on repeated detection of the same
502+ * buffer being bad..
503+ */
504+
505+DEFINE_RATELIMIT_STATE(xfs_buf_write_fail_rl_state, 30 * HZ, 10);
506+
499507 STATIC uint
500508 xfs_buf_item_push(
501509 struct xfs_log_item *lip,
@@ -524,6 +532,14 @@ xfs_buf_item_push( · 22 unmodified lines
524532
525533 trace_xfs_buf_item_push(bip);
526534
535+ /* has a previous flush failed due to IO errors? */
536+ if ((bp->b_flags & XBF_WRITE_FAIL) &&
537+ ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) {
538+ xfs_warn(bp->b_target->bt_mount,
539+"Detected failing async write on buffer block 0x%llx. Retrying async write.\n",
540+ (long long)bp->b_bn);
541+ }
542+
527543 if (!xfs_buf_delwri_queue(bp, buffer_list))
528544 rval = XFS_ITEM_FLUSHING;
529545 xfs_buf_unlock(bp);
@@ -1096,8 +1112,9 @@ xfs_buf_iodone_callbacks( · 566 unmodified lines
10961112
10971113 xfs_buf_ioerror(bp, 0); /* errno of 0 unsets the flag */
10981114
1099− if (!XFS_BUF_ISSTALE(bp)) {
1100− bp->b_flags |= XBF_WRITE | XBF_ASYNC | XBF_DONE;
1115+ if (!(bp->b_flags & (XBF_STALE|XBF_WRITE_FAIL))) {
1116+ bp->b_flags |= XBF_WRITE | XBF_ASYNC |
1117+ XBF_DONE | XBF_WRITE_FAIL;
11011118 xfs_buf_iorequest(bp);
11021119 } else {
11031120 xfs_buf_relse(bp);
fs/xfs/xfs_dir2_node.c+13−13
@@ -2067,12 +2067,12 @@ xfs_dir2_node_lookup( · 2066 unmodified lines
20672067 */
20682068 int /* error */
20692069 xfs_dir2_node_removename(
2070− xfs_da_args_t *args) /* operation arguments */
2070+ struct xfs_da_args *args) /* operation arguments */
20712071 {
2072− xfs_da_state_blk_t *blk; /* leaf block */
2072+ struct xfs_da_state_blk *blk; /* leaf block */
20732073 int error; /* error return value */
20742074 int rval; /* operation return value */
2075− xfs_da_state_t *state; /* btree cursor */
2075+ struct xfs_da_state *state; /* btree cursor */
20762076
20772077 trace_xfs_dir2_node_removename(args);
20782078
@@ -2084,19 +2084,18 @@ xfs_dir2_node_removename( · 5 unmodified lines
20842084 state->mp = args->dp->i_mount;
20852085 state->blocksize = state->mp->m_dirblksize;
20862086 state->node_ents = state->mp->m_dir_node_ents;
2087− /*
2088− * Look up the entry we're deleting, set up the cursor.
2089− */
2087+
2088+ /* Look up the entry we're deleting, set up the cursor. */
20902089 error = xfs_da3_node_lookup_int(state, &rval);
20912090 if (error)
2092− rval = error;
2093− /*
2094− * Didn't find it, upper layer screwed up.
2095− */
2091+ goto out_free;
2092+
2093+ /* Didn't find it, upper layer screwed up. */
20962094 if (rval != EEXIST) {
2097− xfs_da_state_free(state);
2098− return rval;
2095+ error = rval;
2096+ goto out_free;
20992097 }
2098+
21002099 blk = &state->path.blk[state->path.active - 1];
21012100 ASSERT(blk->magic == XFS_DIR2_LEAFN_MAGIC);
21022101 ASSERT(state->extravalid);
@@ -2107,7 +2106,7 @@ xfs_dir2_node_removename( · 4 unmodified lines
21072106 error = xfs_dir2_leafn_remove(args, blk->bp, blk->index,
21082107 &state->extrablk, &rval);
21092108 if (error)
2110− return error;
2109+ goto out_free;
21112110 /*
21122111 * Fix the hash values up the btree.
21132112 */
@@ -2122,6 +2121,7 @@ xfs_dir2_node_removename( · 8 unmodified lines
21222121 */
21232122 if (!error)
21242123 error = xfs_dir2_node_to_leaf(state);
2124+out_free:
21252125 xfs_da_state_free(state);
21262126 return error;
21272127 }
fs/xfs/xfs_iops.c+2−1
@@ -618,7 +618,8 @@ xfs_setattr_nonsize( · 617 unmodified lines
618618 }
619619 if (!gid_eq(igid, gid)) {
620620 if (XFS_IS_QUOTA_RUNNING(mp) && XFS_IS_GQUOTA_ON(mp)) {
621− ASSERT(!XFS_IS_PQUOTA_ON(mp));
621+ ASSERT(xfs_sb_version_has_pquotino(&mp->m_sb) ||
622+ !XFS_IS_PQUOTA_ON(mp));
622623 ASSERT(mask & ATTR_GID);
623624 ASSERT(gdqp);
624625 olddquot2 = xfs_qm_vop_chown(tp, ip,
fs/xfs/xfs_log_recover.c+11−2
@@ -193,7 +193,10 @@ xlog_bread_noalign( · 192 unmodified lines
193193 bp->b_io_length = nbblks;
194194 bp->b_error = 0;
195195
196− xfsbdstrat(log->l_mp, bp);
196+ if (XFS_FORCED_SHUTDOWN(log->l_mp))
197+ return XFS_ERROR(EIO);
198+
199+ xfs_buf_iorequest(bp);
197200 error = xfs_buf_iowait(bp);
198201 if (error)
199202 xfs_buf_ioerror_alert(bp, __func__);
@@ -4397,7 +4400,13 @@ xlog_do_recover( · 4197 unmodified lines
43974400 XFS_BUF_READ(bp);
43984401 XFS_BUF_UNASYNC(bp);
43994402 bp->b_ops = &xfs_sb_buf_ops;
4400− xfsbdstrat(log->l_mp, bp);
4403+
4404+ if (XFS_FORCED_SHUTDOWN(log->l_mp)) {
4405+ xfs_buf_relse(bp);
4406+ return XFS_ERROR(EIO);
4407+ }
4408+
4409+ xfs_buf_iorequest(bp);
44014410 error = xfs_buf_iowait(bp);
44024411 if (error) {
44034412 xfs_buf_ioerror_alert(bp, __func__);
fs/xfs/xfs_qm.c+53−27
@@ -134,8 +134,6 @@ xfs_qm_dqpurge( · 133 unmodified lines
134134 {
135135 struct xfs_mount *mp = dqp->q_mount;
136136 struct xfs_quotainfo *qi = mp->m_quotainfo;
137− struct xfs_dquot *gdqp = NULL;
138− struct xfs_dquot *pdqp = NULL;
139137
140138 xfs_dqlock(dqp);
141139 if ((dqp->dq_flags & XFS_DQ_FREEING) || dqp->q_nrefs != 0) {
@@ -143,21 +141,6 @@ xfs_qm_dqpurge( · 1 unmodified line
143141 return EAGAIN;
144142 }
145143
146− /*
147− * If this quota has a hint attached, prepare for releasing it now.
148− */
149− gdqp = dqp->q_gdquot;
150− if (gdqp) {
151− xfs_dqlock(gdqp);
152− dqp->q_gdquot = NULL;
153− }
154−
155− pdqp = dqp->q_pdquot;
156− if (pdqp) {
157− xfs_dqlock(pdqp);
158− dqp->q_pdquot = NULL;
159− }
160−
161144 dqp->dq_flags |= XFS_DQ_FREEING;
162145
163146 xfs_dqflock(dqp);
@@ -206,11 +189,47 @@ xfs_qm_dqpurge( · 42 unmodified lines
206189 XFS_STATS_DEC(xs_qm_dquot_unused);
207190
208191 xfs_qm_dqdestroy(dqp);
192+ return 0;
193+}
194+
195+/*
196+ * Release the group or project dquot pointers the user dquots maybe carrying
197+ * around as a hint, and proceed to purge the user dquot cache if requested.
198+*/
199+STATIC int
200+xfs_qm_dqpurge_hints(
201+ struct xfs_dquot *dqp,
202+ void *data)
203+{
204+ struct xfs_dquot *gdqp = NULL;
205+ struct xfs_dquot *pdqp = NULL;
206+ uint flags = *((uint *)data);
207+
208+ xfs_dqlock(dqp);
209+ if (dqp->dq_flags & XFS_DQ_FREEING) {
210+ xfs_dqunlock(dqp);
211+ return EAGAIN;
212+ }
213+
214+ /* If this quota has a hint attached, prepare for releasing it now */
215+ gdqp = dqp->q_gdquot;
216+ if (gdqp)
217+ dqp->q_gdquot = NULL;
218+
219+ pdqp = dqp->q_pdquot;
220+ if (pdqp)
221+ dqp->q_pdquot = NULL;
222+
223+ xfs_dqunlock(dqp);
209224
210225 if (gdqp)
211− xfs_qm_dqput(gdqp);
226+ xfs_qm_dqrele(gdqp);
212227 if (pdqp)
213− xfs_qm_dqput(pdqp);
228+ xfs_qm_dqrele(pdqp);
229+
230+ if (flags & XFS_QMOPT_UQUOTA)
231+ return xfs_qm_dqpurge(dqp, NULL);
232+
214233 return 0;
215234 }
216235
@@ -222,8 +241,18 @@ xfs_qm_dqpurge_all( · 5 unmodified lines
222241 struct xfs_mount *mp,
223242 uint flags)
224243 {
225− if (flags & XFS_QMOPT_UQUOTA)
226− xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge, NULL);
244+ /*
245+ * We have to release group/project dquot hint(s) from the user dquot
246+ * at first if they are there, otherwise we would run into an infinite
247+ * loop while walking through radix tree to purge other type of dquots
248+ * since their refcount is not zero if the user dquot refers to them
249+ * as hint.
250+ *
251+ * Call the special xfs_qm_dqpurge_hints() will end up go through the
252+ * general xfs_qm_dqpurge() against user dquot cache if requested.
253+ */
254+ xfs_qm_dquot_walk(mp, XFS_DQ_USER, xfs_qm_dqpurge_hints, &flags);
255+
227256 if (flags & XFS_QMOPT_GQUOTA)
228257 xfs_qm_dquot_walk(mp, XFS_DQ_GROUP, xfs_qm_dqpurge, NULL);
229258 if (flags & XFS_QMOPT_PQUOTA)
@@ -2082,24 +2111,21 @@ xfs_qm_vop_create_dqattach( · 1852 unmodified lines
20822111 ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL));
20832112 ASSERT(XFS_IS_QUOTA_RUNNING(mp));
20842113
2085− if (udqp) {
2114+ if (udqp && XFS_IS_UQUOTA_ON(mp)) {
20862115 ASSERT(ip->i_udquot == NULL);
2087− ASSERT(XFS_IS_UQUOTA_ON(mp));
20882116 ASSERT(ip->i_d.di_uid == be32_to_cpu(udqp->q_core.d_id));
20892117
20902118 ip->i_udquot = xfs_qm_dqhold(udqp);
20912119 xfs_trans_mod_dquot(tp, udqp, XFS_TRANS_DQ_ICOUNT, 1);
20922120 }
2093− if (gdqp) {
2121+ if (gdqp && XFS_IS_GQUOTA_ON(mp)) {
20942122 ASSERT(ip->i_gdquot == NULL);
2095− ASSERT(XFS_IS_GQUOTA_ON(mp));
20962123 ASSERT(ip->i_d.di_gid == be32_to_cpu(gdqp->q_core.d_id));
20972124 ip->i_gdquot = xfs_qm_dqhold(gdqp);
20982125 xfs_trans_mod_dquot(tp, gdqp, XFS_TRANS_DQ_ICOUNT, 1);
20992126 }
2100− if (pdqp) {
2127+ if (pdqp && XFS_IS_PQUOTA_ON(mp)) {
21012128 ASSERT(ip->i_pdquot == NULL);
2102− ASSERT(XFS_IS_PQUOTA_ON(mp));
21032129 ASSERT(xfs_get_projid(ip) == be32_to_cpu(pdqp->q_core.d_id));
21042130
21052131 ip->i_pdquot = xfs_qm_dqhold(pdqp);
fs/xfs/xfs_trans_buf.c+12−1
@@ -314,7 +314,18 @@ xfs_trans_read_buf_map( · 313 unmodified lines
314314 ASSERT(bp->b_iodone == NULL);
315315 XFS_BUF_READ(bp);
316316 bp->b_ops = ops;
317− xfsbdstrat(tp->t_mountp, bp);
317+
318+ /*
319+ * XXX(hch): clean up the error handling here to be less
320+ * of a mess..
321+ */
322+ if (XFS_FORCED_SHUTDOWN(mp)) {
323+ trace_xfs_bdstrat_shut(bp, _RET_IP_);
324+ xfs_bioerror_relse(bp);
325+ } else {
326+ xfs_buf_iorequest(bp);
327+ }
328+
318329 error = xfs_buf_iowait(bp);
319330 if (error) {
320331 xfs_buf_ioerror_alert(bp, __func__);