aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 13:26:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-08-01 13:26:23 -0400
commita0e881b7c189fa2bd76c024dbff91e79511c971d (patch)
tree0c801918565b08921d21aceee5b326f64d998f5f /fs/xfs
parenteff0d13f3823f35d70228cd151d2a2c89288ff32 (diff)
parentdbc6e0222d79e78925fe20733844a796a4b72cf9 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull second vfs pile from Al Viro: "The stuff in there: fsfreeze deadlock fixes by Jan (essentially, the deadlock reproduced by xfstests 068), symlink and hardlink restriction patches, plus assorted cleanups and fixes. Note that another fsfreeze deadlock (emergency thaw one) is *not* dealt with - the series by Fernando conflicts a lot with Jan's, breaks userland ABI (FIFREEZE semantics gets changed) and trades the deadlock for massive vfsmount leak; this is going to be handled next cycle. There probably will be another pull request, but that stuff won't be in it." Fix up trivial conflicts due to unrelated changes next to each other in drivers/{staging/gdm72xx/usb_boot.c, usb/gadget/storage_common.c} * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (54 commits) delousing target_core_file a bit Documentation: Correct s_umount state for freeze_fs/unfreeze_fs fs: Remove old freezing mechanism ext2: Implement freezing btrfs: Convert to new freezing mechanism nilfs2: Convert to new freezing mechanism ntfs: Convert to new freezing mechanism fuse: Convert to new freezing mechanism gfs2: Convert to new freezing mechanism ocfs2: Convert to new freezing mechanism xfs: Convert to new freezing code ext4: Convert to new freezing mechanism fs: Protect write paths by sb_start_write - sb_end_write fs: Skip atime update on frozen filesystem fs: Add freezing handling to mnt_want_write() / mnt_drop_write() fs: Improve filesystem freezing handling switch the protection of percpu_counter list to spinlock nfsd: Push mnt_want_write() outside of i_mutex btrfs: Push mnt_want_write() outside of i_mutex fat: Push mnt_want_write() outside of i_mutex ...
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_aops.c18
-rw-r--r--fs/xfs/xfs_file.c10
-rw-r--r--fs/xfs/xfs_ioctl.c55
-rw-r--r--fs/xfs/xfs_ioctl32.c12
-rw-r--r--fs/xfs/xfs_iomap.c4
-rw-r--r--fs/xfs/xfs_mount.c2
-rw-r--r--fs/xfs/xfs_mount.h3
-rw-r--r--fs/xfs/xfs_sync.c2
-rw-r--r--fs/xfs/xfs_trans.c17
-rw-r--r--fs/xfs/xfs_trans.h2
10 files changed, 109 insertions, 16 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 15052ff916e..e562dd43f41 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -124,6 +124,12 @@ xfs_setfilesize_trans_alloc(
124 ioend->io_append_trans = tp; 124 ioend->io_append_trans = tp;
125 125
126 /* 126 /*
127 * We will pass freeze protection with a transaction. So tell lockdep
128 * we released it.
129 */
130 rwsem_release(&ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
131 1, _THIS_IP_);
132 /*
127 * We hand off the transaction to the completion thread now, so 133 * We hand off the transaction to the completion thread now, so
128 * clear the flag here. 134 * clear the flag here.
129 */ 135 */
@@ -199,6 +205,15 @@ xfs_end_io(
199 struct xfs_inode *ip = XFS_I(ioend->io_inode); 205 struct xfs_inode *ip = XFS_I(ioend->io_inode);
200 int error = 0; 206 int error = 0;
201 207
208 if (ioend->io_append_trans) {
209 /*
210 * We've got freeze protection passed with the transaction.
211 * Tell lockdep about it.
212 */
213 rwsem_acquire_read(
214 &ioend->io_inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
215 0, 1, _THIS_IP_);
216 }
202 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { 217 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
203 ioend->io_error = -EIO; 218 ioend->io_error = -EIO;
204 goto done; 219 goto done;
@@ -1425,6 +1440,9 @@ out_trans_cancel:
1425 if (ioend->io_append_trans) { 1440 if (ioend->io_append_trans) {
1426 current_set_flags_nested(&ioend->io_append_trans->t_pflags, 1441 current_set_flags_nested(&ioend->io_append_trans->t_pflags,
1427 PF_FSTRANS); 1442 PF_FSTRANS);
1443 rwsem_acquire_read(
1444 &inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1],
1445 0, 1, _THIS_IP_);
1428 xfs_trans_cancel(ioend->io_append_trans, 0); 1446 xfs_trans_cancel(ioend->io_append_trans, 0);
1429 } 1447 }
1430out_destroy_ioend: 1448out_destroy_ioend:
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index c4559c6e6f2..56afcdb2377 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -770,10 +770,12 @@ xfs_file_aio_write(
770 if (ocount == 0) 770 if (ocount == 0)
771 return 0; 771 return 0;
772 772
773 xfs_wait_for_freeze(ip->i_mount, SB_FREEZE_WRITE); 773 sb_start_write(inode->i_sb);
774 774
775 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) 775 if (XFS_FORCED_SHUTDOWN(ip->i_mount)) {
776 return -EIO; 776 ret = -EIO;
777 goto out;
778 }
777 779
778 if (unlikely(file->f_flags & O_DIRECT)) 780 if (unlikely(file->f_flags & O_DIRECT))
779 ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount); 781 ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount);
@@ -792,6 +794,8 @@ xfs_file_aio_write(
792 ret = err; 794 ret = err;
793 } 795 }
794 796
797out:
798 sb_end_write(inode->i_sb);
795 return ret; 799 return ret;
796} 800}
797 801
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 1f1535d25a9..0e0232c3b6d 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -364,9 +364,15 @@ xfs_fssetdm_by_handle(
364 if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t))) 364 if (copy_from_user(&dmhreq, arg, sizeof(xfs_fsop_setdm_handlereq_t)))
365 return -XFS_ERROR(EFAULT); 365 return -XFS_ERROR(EFAULT);
366 366
367 error = mnt_want_write_file(parfilp);
368 if (error)
369 return error;
370
367 dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq); 371 dentry = xfs_handlereq_to_dentry(parfilp, &dmhreq.hreq);
368 if (IS_ERR(dentry)) 372 if (IS_ERR(dentry)) {
373 mnt_drop_write_file(parfilp);
369 return PTR_ERR(dentry); 374 return PTR_ERR(dentry);
375 }
370 376
371 if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) { 377 if (IS_IMMUTABLE(dentry->d_inode) || IS_APPEND(dentry->d_inode)) {
372 error = -XFS_ERROR(EPERM); 378 error = -XFS_ERROR(EPERM);
@@ -382,6 +388,7 @@ xfs_fssetdm_by_handle(
382 fsd.fsd_dmstate); 388 fsd.fsd_dmstate);
383 389
384 out: 390 out:
391 mnt_drop_write_file(parfilp);
385 dput(dentry); 392 dput(dentry);
386 return error; 393 return error;
387} 394}
@@ -634,7 +641,11 @@ xfs_ioc_space(
634 if (ioflags & IO_INVIS) 641 if (ioflags & IO_INVIS)
635 attr_flags |= XFS_ATTR_DMI; 642 attr_flags |= XFS_ATTR_DMI;
636 643
644 error = mnt_want_write_file(filp);
645 if (error)
646 return error;
637 error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags); 647 error = xfs_change_file_space(ip, cmd, bf, filp->f_pos, attr_flags);
648 mnt_drop_write_file(filp);
638 return -error; 649 return -error;
639} 650}
640 651
@@ -1163,6 +1174,7 @@ xfs_ioc_fssetxattr(
1163{ 1174{
1164 struct fsxattr fa; 1175 struct fsxattr fa;
1165 unsigned int mask; 1176 unsigned int mask;
1177 int error;
1166 1178
1167 if (copy_from_user(&fa, arg, sizeof(fa))) 1179 if (copy_from_user(&fa, arg, sizeof(fa)))
1168 return -EFAULT; 1180 return -EFAULT;
@@ -1171,7 +1183,12 @@ xfs_ioc_fssetxattr(
1171 if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) 1183 if (filp->f_flags & (O_NDELAY|O_NONBLOCK))
1172 mask |= FSX_NONBLOCK; 1184 mask |= FSX_NONBLOCK;
1173 1185
1174 return -xfs_ioctl_setattr(ip, &fa, mask); 1186 error = mnt_want_write_file(filp);
1187 if (error)
1188 return error;
1189 error = xfs_ioctl_setattr(ip, &fa, mask);
1190 mnt_drop_write_file(filp);
1191 return -error;
1175} 1192}
1176 1193
1177STATIC int 1194STATIC int
@@ -1196,6 +1213,7 @@ xfs_ioc_setxflags(
1196 struct fsxattr fa; 1213 struct fsxattr fa;
1197 unsigned int flags; 1214 unsigned int flags;
1198 unsigned int mask; 1215 unsigned int mask;
1216 int error;
1199 1217
1200 if (copy_from_user(&flags, arg, sizeof(flags))) 1218 if (copy_from_user(&flags, arg, sizeof(flags)))
1201 return -EFAULT; 1219 return -EFAULT;
@@ -1210,7 +1228,12 @@ xfs_ioc_setxflags(
1210 mask |= FSX_NONBLOCK; 1228 mask |= FSX_NONBLOCK;
1211 fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip)); 1229 fa.fsx_xflags = xfs_merge_ioc_xflags(flags, xfs_ip2xflags(ip));
1212 1230
1213 return -xfs_ioctl_setattr(ip, &fa, mask); 1231 error = mnt_want_write_file(filp);
1232 if (error)
1233 return error;
1234 error = xfs_ioctl_setattr(ip, &fa, mask);
1235 mnt_drop_write_file(filp);
1236 return -error;
1214} 1237}
1215 1238
1216STATIC int 1239STATIC int
@@ -1385,8 +1408,13 @@ xfs_file_ioctl(
1385 if (copy_from_user(&dmi, arg, sizeof(dmi))) 1408 if (copy_from_user(&dmi, arg, sizeof(dmi)))
1386 return -XFS_ERROR(EFAULT); 1409 return -XFS_ERROR(EFAULT);
1387 1410
1411 error = mnt_want_write_file(filp);
1412 if (error)
1413 return error;
1414
1388 error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask, 1415 error = xfs_set_dmattrs(ip, dmi.fsd_dmevmask,
1389 dmi.fsd_dmstate); 1416 dmi.fsd_dmstate);
1417 mnt_drop_write_file(filp);
1390 return -error; 1418 return -error;
1391 } 1419 }
1392 1420
@@ -1434,7 +1462,11 @@ xfs_file_ioctl(
1434 1462
1435 if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t))) 1463 if (copy_from_user(&sxp, arg, sizeof(xfs_swapext_t)))
1436 return -XFS_ERROR(EFAULT); 1464 return -XFS_ERROR(EFAULT);
1465 error = mnt_want_write_file(filp);
1466 if (error)
1467 return error;
1437 error = xfs_swapext(&sxp); 1468 error = xfs_swapext(&sxp);
1469 mnt_drop_write_file(filp);
1438 return -error; 1470 return -error;
1439 } 1471 }
1440 1472
@@ -1463,9 +1495,14 @@ xfs_file_ioctl(
1463 if (copy_from_user(&inout, arg, sizeof(inout))) 1495 if (copy_from_user(&inout, arg, sizeof(inout)))
1464 return -XFS_ERROR(EFAULT); 1496 return -XFS_ERROR(EFAULT);
1465 1497
1498 error = mnt_want_write_file(filp);
1499 if (error)
1500 return error;
1501
1466 /* input parameter is passed in resblks field of structure */ 1502 /* input parameter is passed in resblks field of structure */
1467 in = inout.resblks; 1503 in = inout.resblks;
1468 error = xfs_reserve_blocks(mp, &in, &inout); 1504 error = xfs_reserve_blocks(mp, &in, &inout);
1505 mnt_drop_write_file(filp);
1469 if (error) 1506 if (error)
1470 return -error; 1507 return -error;
1471 1508
@@ -1496,7 +1533,11 @@ xfs_file_ioctl(
1496 if (copy_from_user(&in, arg, sizeof(in))) 1533 if (copy_from_user(&in, arg, sizeof(in)))
1497 return -XFS_ERROR(EFAULT); 1534 return -XFS_ERROR(EFAULT);
1498 1535
1536 error = mnt_want_write_file(filp);
1537 if (error)
1538 return error;
1499 error = xfs_growfs_data(mp, &in); 1539 error = xfs_growfs_data(mp, &in);
1540 mnt_drop_write_file(filp);
1500 return -error; 1541 return -error;
1501 } 1542 }
1502 1543
@@ -1506,7 +1547,11 @@ xfs_file_ioctl(
1506 if (copy_from_user(&in, arg, sizeof(in))) 1547 if (copy_from_user(&in, arg, sizeof(in)))
1507 return -XFS_ERROR(EFAULT); 1548 return -XFS_ERROR(EFAULT);
1508 1549
1550 error = mnt_want_write_file(filp);
1551 if (error)
1552 return error;
1509 error = xfs_growfs_log(mp, &in); 1553 error = xfs_growfs_log(mp, &in);
1554 mnt_drop_write_file(filp);
1510 return -error; 1555 return -error;
1511 } 1556 }
1512 1557
@@ -1516,7 +1561,11 @@ xfs_file_ioctl(
1516 if (copy_from_user(&in, arg, sizeof(in))) 1561 if (copy_from_user(&in, arg, sizeof(in)))
1517 return -XFS_ERROR(EFAULT); 1562 return -XFS_ERROR(EFAULT);
1518 1563
1564 error = mnt_want_write_file(filp);
1565 if (error)
1566 return error;
1519 error = xfs_growfs_rt(mp, &in); 1567 error = xfs_growfs_rt(mp, &in);
1568 mnt_drop_write_file(filp);
1520 return -error; 1569 return -error;
1521 } 1570 }
1522 1571
diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c
index c4f2da0d2bf..1244274a567 100644
--- a/fs/xfs/xfs_ioctl32.c
+++ b/fs/xfs/xfs_ioctl32.c
@@ -600,7 +600,11 @@ xfs_file_compat_ioctl(
600 600
601 if (xfs_compat_growfs_data_copyin(&in, arg)) 601 if (xfs_compat_growfs_data_copyin(&in, arg))
602 return -XFS_ERROR(EFAULT); 602 return -XFS_ERROR(EFAULT);
603 error = mnt_want_write_file(filp);
604 if (error)
605 return error;
603 error = xfs_growfs_data(mp, &in); 606 error = xfs_growfs_data(mp, &in);
607 mnt_drop_write_file(filp);
604 return -error; 608 return -error;
605 } 609 }
606 case XFS_IOC_FSGROWFSRT_32: { 610 case XFS_IOC_FSGROWFSRT_32: {
@@ -608,7 +612,11 @@ xfs_file_compat_ioctl(
608 612
609 if (xfs_compat_growfs_rt_copyin(&in, arg)) 613 if (xfs_compat_growfs_rt_copyin(&in, arg))
610 return -XFS_ERROR(EFAULT); 614 return -XFS_ERROR(EFAULT);
615 error = mnt_want_write_file(filp);
616 if (error)
617 return error;
611 error = xfs_growfs_rt(mp, &in); 618 error = xfs_growfs_rt(mp, &in);
619 mnt_drop_write_file(filp);
612 return -error; 620 return -error;
613 } 621 }
614#endif 622#endif
@@ -627,7 +635,11 @@ xfs_file_compat_ioctl(
627 offsetof(struct xfs_swapext, sx_stat)) || 635 offsetof(struct xfs_swapext, sx_stat)) ||
628 xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat)) 636 xfs_ioctl32_bstat_copyin(&sxp.sx_stat, &sxu->sx_stat))
629 return -XFS_ERROR(EFAULT); 637 return -XFS_ERROR(EFAULT);
638 error = mnt_want_write_file(filp);
639 if (error)
640 return error;
630 error = xfs_swapext(&sxp); 641 error = xfs_swapext(&sxp);
642 mnt_drop_write_file(filp);
631 return -error; 643 return -error;
632 } 644 }
633 case XFS_IOC_FSBULKSTAT_32: 645 case XFS_IOC_FSBULKSTAT_32:
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index 915edf6639f..973dff6ad93 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -680,9 +680,9 @@ xfs_iomap_write_unwritten(
680 * the same inode that we complete here and might deadlock 680 * the same inode that we complete here and might deadlock
681 * on the iolock. 681 * on the iolock.
682 */ 682 */
683 xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); 683 sb_start_intwrite(mp->m_super);
684 tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS); 684 tp = _xfs_trans_alloc(mp, XFS_TRANS_STRAT_WRITE, KM_NOFS);
685 tp->t_flags |= XFS_TRANS_RESERVE; 685 tp->t_flags |= XFS_TRANS_RESERVE | XFS_TRANS_FREEZE_PROT;
686 error = xfs_trans_reserve(tp, resblks, 686 error = xfs_trans_reserve(tp, resblks,
687 XFS_WRITE_LOG_RES(mp), 0, 687 XFS_WRITE_LOG_RES(mp), 0,
688 XFS_TRANS_PERM_LOG_RES, 688 XFS_TRANS_PERM_LOG_RES,
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 711ca51ca3d..29c2f83d414 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -1551,7 +1551,7 @@ xfs_unmountfs(
1551int 1551int
1552xfs_fs_writable(xfs_mount_t *mp) 1552xfs_fs_writable(xfs_mount_t *mp)
1553{ 1553{
1554 return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) || 1554 return !(mp->m_super->s_writers.frozen || XFS_FORCED_SHUTDOWN(mp) ||
1555 (mp->m_flags & XFS_MOUNT_RDONLY)); 1555 (mp->m_flags & XFS_MOUNT_RDONLY));
1556} 1556}
1557 1557
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index 8724336a9a0..05a05a7b611 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -311,9 +311,6 @@ void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname,
311#define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ 311#define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */
312#define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ 312#define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */
313 313
314#define xfs_test_for_freeze(mp) ((mp)->m_super->s_frozen)
315#define xfs_wait_for_freeze(mp,l) vfs_check_frozen((mp)->m_super, (l))
316
317/* 314/*
318 * Flags for xfs_mountfs 315 * Flags for xfs_mountfs
319 */ 316 */
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c
index 97304f10e78..96548176db8 100644
--- a/fs/xfs/xfs_sync.c
+++ b/fs/xfs/xfs_sync.c
@@ -403,7 +403,7 @@ xfs_sync_worker(
403 if (!(mp->m_super->s_flags & MS_ACTIVE) && 403 if (!(mp->m_super->s_flags & MS_ACTIVE) &&
404 !(mp->m_flags & XFS_MOUNT_RDONLY)) { 404 !(mp->m_flags & XFS_MOUNT_RDONLY)) {
405 /* dgc: errors ignored here */ 405 /* dgc: errors ignored here */
406 if (mp->m_super->s_frozen == SB_UNFROZEN && 406 if (mp->m_super->s_writers.frozen == SB_UNFROZEN &&
407 xfs_log_need_covered(mp)) 407 xfs_log_need_covered(mp))
408 error = xfs_fs_log_dummy(mp); 408 error = xfs_fs_log_dummy(mp);
409 else 409 else
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index fdf324508c5..06ed520a767 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -576,8 +576,12 @@ xfs_trans_alloc(
576 xfs_mount_t *mp, 576 xfs_mount_t *mp,
577 uint type) 577 uint type)
578{ 578{
579 xfs_wait_for_freeze(mp, SB_FREEZE_TRANS); 579 xfs_trans_t *tp;
580 return _xfs_trans_alloc(mp, type, KM_SLEEP); 580
581 sb_start_intwrite(mp->m_super);
582 tp = _xfs_trans_alloc(mp, type, KM_SLEEP);
583 tp->t_flags |= XFS_TRANS_FREEZE_PROT;
584 return tp;
581} 585}
582 586
583xfs_trans_t * 587xfs_trans_t *
@@ -588,6 +592,7 @@ _xfs_trans_alloc(
588{ 592{
589 xfs_trans_t *tp; 593 xfs_trans_t *tp;
590 594
595 WARN_ON(mp->m_super->s_writers.frozen == SB_FREEZE_COMPLETE);
591 atomic_inc(&mp->m_active_trans); 596 atomic_inc(&mp->m_active_trans);
592 597
593 tp = kmem_zone_zalloc(xfs_trans_zone, memflags); 598 tp = kmem_zone_zalloc(xfs_trans_zone, memflags);
@@ -611,6 +616,8 @@ xfs_trans_free(
611 xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false); 616 xfs_extent_busy_clear(tp->t_mountp, &tp->t_busy, false);
612 617
613 atomic_dec(&tp->t_mountp->m_active_trans); 618 atomic_dec(&tp->t_mountp->m_active_trans);
619 if (tp->t_flags & XFS_TRANS_FREEZE_PROT)
620 sb_end_intwrite(tp->t_mountp->m_super);
614 xfs_trans_free_dqinfo(tp); 621 xfs_trans_free_dqinfo(tp);
615 kmem_zone_free(xfs_trans_zone, tp); 622 kmem_zone_free(xfs_trans_zone, tp);
616} 623}
@@ -643,7 +650,11 @@ xfs_trans_dup(
643 ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES); 650 ASSERT(tp->t_flags & XFS_TRANS_PERM_LOG_RES);
644 ASSERT(tp->t_ticket != NULL); 651 ASSERT(tp->t_ticket != NULL);
645 652
646 ntp->t_flags = XFS_TRANS_PERM_LOG_RES | (tp->t_flags & XFS_TRANS_RESERVE); 653 ntp->t_flags = XFS_TRANS_PERM_LOG_RES |
654 (tp->t_flags & XFS_TRANS_RESERVE) |
655 (tp->t_flags & XFS_TRANS_FREEZE_PROT);
656 /* We gave our writer reference to the new transaction */
657 tp->t_flags &= ~XFS_TRANS_FREEZE_PROT;
647 ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket); 658 ntp->t_ticket = xfs_log_ticket_get(tp->t_ticket);
648 ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used; 659 ntp->t_blk_res = tp->t_blk_res - tp->t_blk_res_used;
649 tp->t_blk_res = tp->t_blk_res_used; 660 tp->t_blk_res = tp->t_blk_res_used;
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h
index bc2afd52a0b..db056544cbb 100644
--- a/fs/xfs/xfs_trans.h
+++ b/fs/xfs/xfs_trans.h
@@ -179,6 +179,8 @@ struct xfs_log_item_desc {
179#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */ 179#define XFS_TRANS_SYNC 0x08 /* make commit synchronous */
180#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */ 180#define XFS_TRANS_DQ_DIRTY 0x10 /* at least one dquot in trx dirty */
181#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */ 181#define XFS_TRANS_RESERVE 0x20 /* OK to use reserved data blocks */
182#define XFS_TRANS_FREEZE_PROT 0x40 /* Transaction has elevated writer
183 count in superblock */
182 184
183/* 185/*
184 * Values for call flags parameter. 186 * Values for call flags parameter.