diff options
author | Jan Kara <jack@suse.cz> | 2012-06-12 10:20:39 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-07-31 01:45:48 -0400 |
commit | d9457dc056249913a7abe8b71dc09e427e590e35 (patch) | |
tree | 8f0c6681d4c5802a6f5a124111b9d3958f0b281b | |
parent | 8e8ad8a57c75f3bda2d03a4c4396a9a7024ad275 (diff) |
xfs: Convert to new freezing code
Generic code now blocks all writers from standard write paths. So we add
blocking of all writers coming from ioctl (we get a protection of ioctl against
racing remount read-only as a bonus) and convert xfs_file_aio_write() to a
non-racy freeze protection. We also keep freeze protection on transaction
start to block internal filesystem writes such as removal of preallocated
blocks.
CC: Ben Myers <bpm@sgi.com>
CC: Alex Elder <elder@kernel.org>
CC: xfs@oss.sgi.com
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/xfs/xfs_aops.c | 18 | ||||
-rw-r--r-- | fs/xfs/xfs_file.c | 10 | ||||
-rw-r--r-- | fs/xfs/xfs_ioctl.c | 55 | ||||
-rw-r--r-- | fs/xfs/xfs_ioctl32.c | 12 | ||||
-rw-r--r-- | fs/xfs/xfs_iomap.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_mount.h | 3 | ||||
-rw-r--r-- | fs/xfs/xfs_sync.c | 2 | ||||
-rw-r--r-- | fs/xfs/xfs_trans.c | 17 | ||||
-rw-r--r-- | fs/xfs/xfs_trans.h | 2 |
10 files changed, 109 insertions, 16 deletions
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c index 8dad722c0041..daa42383ebd9 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; |
@@ -1410,6 +1425,9 @@ out_trans_cancel: | |||
1410 | if (ioend->io_append_trans) { | 1425 | if (ioend->io_append_trans) { |
1411 | current_set_flags_nested(&ioend->io_append_trans->t_pflags, | 1426 | current_set_flags_nested(&ioend->io_append_trans->t_pflags, |
1412 | PF_FSTRANS); | 1427 | PF_FSTRANS); |
1428 | rwsem_acquire_read( | ||
1429 | &inode->i_sb->s_writers.lock_map[SB_FREEZE_FS-1], | ||
1430 | 0, 1, _THIS_IP_); | ||
1413 | xfs_trans_cancel(ioend->io_append_trans, 0); | 1431 | xfs_trans_cancel(ioend->io_append_trans, 0); |
1414 | } | 1432 | } |
1415 | out_destroy_ioend: | 1433 | out_destroy_ioend: |
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 9f7ec15a6522..f0081f20e5c0 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
@@ -781,10 +781,12 @@ xfs_file_aio_write( | |||
781 | if (ocount == 0) | 781 | if (ocount == 0) |
782 | return 0; | 782 | return 0; |
783 | 783 | ||
784 | xfs_wait_for_freeze(ip->i_mount, SB_FREEZE_WRITE); | 784 | sb_start_write(inode->i_sb); |
785 | 785 | ||
786 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 786 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) { |
787 | return -EIO; | 787 | ret = -EIO; |
788 | goto out; | ||
789 | } | ||
788 | 790 | ||
789 | if (unlikely(file->f_flags & O_DIRECT)) | 791 | if (unlikely(file->f_flags & O_DIRECT)) |
790 | ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount); | 792 | ret = xfs_file_dio_aio_write(iocb, iovp, nr_segs, pos, ocount); |
@@ -803,6 +805,8 @@ xfs_file_aio_write( | |||
803 | ret = err; | 805 | ret = err; |
804 | } | 806 | } |
805 | 807 | ||
808 | out: | ||
809 | sb_end_write(inode->i_sb); | ||
806 | return ret; | 810 | return ret; |
807 | } | 811 | } |
808 | 812 | ||
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 1f1535d25a9b..0e0232c3b6d9 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 | ||
1177 | STATIC int | 1194 | STATIC 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 | ||
1216 | STATIC int | 1239 | STATIC 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 c4f2da0d2bf5..1244274a5674 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 aadfce6681ee..b3b9b26091a3 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 536021fb3d4e..b09a4a7eb640 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -1544,7 +1544,7 @@ xfs_unmountfs( | |||
1544 | int | 1544 | int |
1545 | xfs_fs_writable(xfs_mount_t *mp) | 1545 | xfs_fs_writable(xfs_mount_t *mp) |
1546 | { | 1546 | { |
1547 | return !(xfs_test_for_freeze(mp) || XFS_FORCED_SHUTDOWN(mp) || | 1547 | return !(mp->m_super->s_writers.frozen || XFS_FORCED_SHUTDOWN(mp) || |
1548 | (mp->m_flags & XFS_MOUNT_RDONLY)); | 1548 | (mp->m_flags & XFS_MOUNT_RDONLY)); |
1549 | } | 1549 | } |
1550 | 1550 | ||
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 90c1fc9eaea4..c6bca0d92cb1 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -314,9 +314,6 @@ void xfs_do_force_shutdown(struct xfs_mount *mp, int flags, char *fname, | |||
314 | #define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ | 314 | #define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ |
315 | #define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ | 315 | #define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ |
316 | 316 | ||
317 | #define xfs_test_for_freeze(mp) ((mp)->m_super->s_frozen) | ||
318 | #define xfs_wait_for_freeze(mp,l) vfs_check_frozen((mp)->m_super, (l)) | ||
319 | |||
320 | /* | 317 | /* |
321 | * Flags for xfs_mountfs | 318 | * Flags for xfs_mountfs |
322 | */ | 319 | */ |
diff --git a/fs/xfs/xfs_sync.c b/fs/xfs/xfs_sync.c index 1e9ee064dbb2..0b9feacdcd1f 100644 --- a/fs/xfs/xfs_sync.c +++ b/fs/xfs/xfs_sync.c | |||
@@ -394,7 +394,7 @@ xfs_sync_worker( | |||
394 | if (!(mp->m_super->s_flags & MS_ACTIVE) && | 394 | if (!(mp->m_super->s_flags & MS_ACTIVE) && |
395 | !(mp->m_flags & XFS_MOUNT_RDONLY)) { | 395 | !(mp->m_flags & XFS_MOUNT_RDONLY)) { |
396 | /* dgc: errors ignored here */ | 396 | /* dgc: errors ignored here */ |
397 | if (mp->m_super->s_frozen == SB_UNFROZEN && | 397 | if (mp->m_super->s_writers.frozen == SB_UNFROZEN && |
398 | xfs_log_need_covered(mp)) | 398 | xfs_log_need_covered(mp)) |
399 | error = xfs_fs_log_dummy(mp); | 399 | error = xfs_fs_log_dummy(mp); |
400 | else | 400 | else |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index fdf324508c5e..06ed520a767f 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 | ||
583 | xfs_trans_t * | 587 | xfs_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 7c37b533aa8e..19c174282878 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. |