aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/libxfs/xfs_format.h10
-rw-r--r--fs/xfs/xfs_buf_item.c2
-rw-r--r--fs/xfs/xfs_inode.c134
-rw-r--r--fs/xfs/xfs_inode.h2
-rw-r--r--fs/xfs/xfs_iops.c21
-rw-r--r--fs/xfs/xfs_log.c10
-rw-r--r--fs/xfs/xfs_mount.c5
-rw-r--r--fs/xfs/xfs_super.c2
8 files changed, 163 insertions, 23 deletions
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index fbd6da263571..476273287aaf 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -304,8 +304,8 @@ typedef enum {
304#define XFS_SB_ICOUNT XFS_SB_MVAL(ICOUNT) 304#define XFS_SB_ICOUNT XFS_SB_MVAL(ICOUNT)
305#define XFS_SB_IFREE XFS_SB_MVAL(IFREE) 305#define XFS_SB_IFREE XFS_SB_MVAL(IFREE)
306#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS) 306#define XFS_SB_FDBLOCKS XFS_SB_MVAL(FDBLOCKS)
307#define XFS_SB_FEATURES2 XFS_SB_MVAL(FEATURES2) 307#define XFS_SB_FEATURES2 (XFS_SB_MVAL(FEATURES2) | \
308#define XFS_SB_BAD_FEATURES2 XFS_SB_MVAL(BAD_FEATURES2) 308 XFS_SB_MVAL(BAD_FEATURES2))
309#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT) 309#define XFS_SB_FEATURES_COMPAT XFS_SB_MVAL(FEATURES_COMPAT)
310#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT) 310#define XFS_SB_FEATURES_RO_COMPAT XFS_SB_MVAL(FEATURES_RO_COMPAT)
311#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT) 311#define XFS_SB_FEATURES_INCOMPAT XFS_SB_MVAL(FEATURES_INCOMPAT)
@@ -319,9 +319,9 @@ typedef enum {
319 XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \ 319 XFS_SB_VERSIONNUM | XFS_SB_UQUOTINO | XFS_SB_GQUOTINO | \
320 XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \ 320 XFS_SB_QFLAGS | XFS_SB_SHARED_VN | XFS_SB_UNIT | XFS_SB_WIDTH | \
321 XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \ 321 XFS_SB_ICOUNT | XFS_SB_IFREE | XFS_SB_FDBLOCKS | XFS_SB_FEATURES2 | \
322 XFS_SB_BAD_FEATURES2 | XFS_SB_FEATURES_COMPAT | \ 322 XFS_SB_FEATURES_COMPAT | XFS_SB_FEATURES_RO_COMPAT | \
323 XFS_SB_FEATURES_RO_COMPAT | XFS_SB_FEATURES_INCOMPAT | \ 323 XFS_SB_FEATURES_INCOMPAT | XFS_SB_FEATURES_LOG_INCOMPAT | \
324 XFS_SB_FEATURES_LOG_INCOMPAT | XFS_SB_PQUOTINO) 324 XFS_SB_PQUOTINO)
325 325
326 326
327/* 327/*
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index 3f9bd58edec7..925ead22803a 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -535,7 +535,7 @@ xfs_buf_item_push(
535 if ((bp->b_flags & XBF_WRITE_FAIL) && 535 if ((bp->b_flags & XBF_WRITE_FAIL) &&
536 ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) { 536 ___ratelimit(&xfs_buf_write_fail_rl_state, "XFS:")) {
537 xfs_warn(bp->b_target->bt_mount, 537 xfs_warn(bp->b_target->bt_mount,
538"Detected failing async write on buffer block 0x%llx. Retrying async write.\n", 538"Detected failing async write on buffer block 0x%llx. Retrying async write.",
539 (long long)bp->b_bn); 539 (long long)bp->b_bn);
540 } 540 }
541 541
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index 41f804e740d7..9916aef60997 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -2656,6 +2656,124 @@ xfs_sort_for_rename(
2656} 2656}
2657 2657
2658/* 2658/*
2659 * xfs_cross_rename()
2660 *
2661 * responsible for handling RENAME_EXCHANGE flag in renameat2() sytemcall
2662 */
2663STATIC int
2664xfs_cross_rename(
2665 struct xfs_trans *tp,
2666 struct xfs_inode *dp1,
2667 struct xfs_name *name1,
2668 struct xfs_inode *ip1,
2669 struct xfs_inode *dp2,
2670 struct xfs_name *name2,
2671 struct xfs_inode *ip2,
2672 struct xfs_bmap_free *free_list,
2673 xfs_fsblock_t *first_block,
2674 int spaceres)
2675{
2676 int error = 0;
2677 int ip1_flags = 0;
2678 int ip2_flags = 0;
2679 int dp2_flags = 0;
2680
2681 /* Swap inode number for dirent in first parent */
2682 error = xfs_dir_replace(tp, dp1, name1,
2683 ip2->i_ino,
2684 first_block, free_list, spaceres);
2685 if (error)
2686 goto out;
2687
2688 /* Swap inode number for dirent in second parent */
2689 error = xfs_dir_replace(tp, dp2, name2,
2690 ip1->i_ino,
2691 first_block, free_list, spaceres);
2692 if (error)
2693 goto out;
2694
2695 /*
2696 * If we're renaming one or more directories across different parents,
2697 * update the respective ".." entries (and link counts) to match the new
2698 * parents.
2699 */
2700 if (dp1 != dp2) {
2701 dp2_flags = XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
2702
2703 if (S_ISDIR(ip2->i_d.di_mode)) {
2704 error = xfs_dir_replace(tp, ip2, &xfs_name_dotdot,
2705 dp1->i_ino, first_block,
2706 free_list, spaceres);
2707 if (error)
2708 goto out;
2709
2710 /* transfer ip2 ".." reference to dp1 */
2711 if (!S_ISDIR(ip1->i_d.di_mode)) {
2712 error = xfs_droplink(tp, dp2);
2713 if (error)
2714 goto out;
2715 error = xfs_bumplink(tp, dp1);
2716 if (error)
2717 goto out;
2718 }
2719
2720 /*
2721 * Although ip1 isn't changed here, userspace needs
2722 * to be warned about the change, so that applications
2723 * relying on it (like backup ones), will properly
2724 * notify the change
2725 */
2726 ip1_flags |= XFS_ICHGTIME_CHG;
2727 ip2_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
2728 }
2729
2730 if (S_ISDIR(ip1->i_d.di_mode)) {
2731 error = xfs_dir_replace(tp, ip1, &xfs_name_dotdot,
2732 dp2->i_ino, first_block,
2733 free_list, spaceres);
2734 if (error)
2735 goto out;
2736
2737 /* transfer ip1 ".." reference to dp2 */
2738 if (!S_ISDIR(ip2->i_d.di_mode)) {
2739 error = xfs_droplink(tp, dp1);
2740 if (error)
2741 goto out;
2742 error = xfs_bumplink(tp, dp2);
2743 if (error)
2744 goto out;
2745 }
2746
2747 /*
2748 * Although ip2 isn't changed here, userspace needs
2749 * to be warned about the change, so that applications
2750 * relying on it (like backup ones), will properly
2751 * notify the change
2752 */
2753 ip1_flags |= XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG;
2754 ip2_flags |= XFS_ICHGTIME_CHG;
2755 }
2756 }
2757
2758 if (ip1_flags) {
2759 xfs_trans_ichgtime(tp, ip1, ip1_flags);
2760 xfs_trans_log_inode(tp, ip1, XFS_ILOG_CORE);
2761 }
2762 if (ip2_flags) {
2763 xfs_trans_ichgtime(tp, ip2, ip2_flags);
2764 xfs_trans_log_inode(tp, ip2, XFS_ILOG_CORE);
2765 }
2766 if (dp2_flags) {
2767 xfs_trans_ichgtime(tp, dp2, dp2_flags);
2768 xfs_trans_log_inode(tp, dp2, XFS_ILOG_CORE);
2769 }
2770 xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
2771 xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE);
2772out:
2773 return error;
2774}
2775
2776/*
2659 * xfs_rename 2777 * xfs_rename
2660 */ 2778 */
2661int 2779int
@@ -2665,7 +2783,8 @@ xfs_rename(
2665 xfs_inode_t *src_ip, 2783 xfs_inode_t *src_ip,
2666 xfs_inode_t *target_dp, 2784 xfs_inode_t *target_dp,
2667 struct xfs_name *target_name, 2785 struct xfs_name *target_name,
2668 xfs_inode_t *target_ip) 2786 xfs_inode_t *target_ip,
2787 unsigned int flags)
2669{ 2788{
2670 xfs_trans_t *tp = NULL; 2789 xfs_trans_t *tp = NULL;
2671 xfs_mount_t *mp = src_dp->i_mount; 2790 xfs_mount_t *mp = src_dp->i_mount;
@@ -2743,6 +2862,18 @@ xfs_rename(
2743 } 2862 }
2744 2863
2745 /* 2864 /*
2865 * Handle RENAME_EXCHANGE flags
2866 */
2867 if (flags & RENAME_EXCHANGE) {
2868 error = xfs_cross_rename(tp, src_dp, src_name, src_ip,
2869 target_dp, target_name, target_ip,
2870 &free_list, &first_block, spaceres);
2871 if (error)
2872 goto abort_return;
2873 goto finish_rename;
2874 }
2875
2876 /*
2746 * Set up the target. 2877 * Set up the target.
2747 */ 2878 */
2748 if (target_ip == NULL) { 2879 if (target_ip == NULL) {
@@ -2881,6 +3012,7 @@ xfs_rename(
2881 if (new_parent) 3012 if (new_parent)
2882 xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE); 3013 xfs_trans_log_inode(tp, target_dp, XFS_ILOG_CORE);
2883 3014
3015finish_rename:
2884 /* 3016 /*
2885 * If this is a synchronous mount, make sure that the 3017 * If this is a synchronous mount, make sure that the
2886 * rename transaction goes to disk before returning to 3018 * rename transaction goes to disk before returning to
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index 4ed2ba9342dc..f7722960b69c 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -338,7 +338,7 @@ int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip,
338int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name, 338int xfs_rename(struct xfs_inode *src_dp, struct xfs_name *src_name,
339 struct xfs_inode *src_ip, struct xfs_inode *target_dp, 339 struct xfs_inode *src_ip, struct xfs_inode *target_dp,
340 struct xfs_name *target_name, 340 struct xfs_name *target_name,
341 struct xfs_inode *target_ip); 341 struct xfs_inode *target_ip, unsigned int flags);
342 342
343void xfs_ilock(xfs_inode_t *, uint); 343void xfs_ilock(xfs_inode_t *, uint);
344int xfs_ilock_nowait(xfs_inode_t *, uint); 344int xfs_ilock_nowait(xfs_inode_t *, uint);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index c50311cae1b1..ce80eeb8faa4 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -380,18 +380,27 @@ xfs_vn_rename(
380 struct inode *odir, 380 struct inode *odir,
381 struct dentry *odentry, 381 struct dentry *odentry,
382 struct inode *ndir, 382 struct inode *ndir,
383 struct dentry *ndentry) 383 struct dentry *ndentry,
384 unsigned int flags)
384{ 385{
385 struct inode *new_inode = ndentry->d_inode; 386 struct inode *new_inode = ndentry->d_inode;
387 int omode = 0;
386 struct xfs_name oname; 388 struct xfs_name oname;
387 struct xfs_name nname; 389 struct xfs_name nname;
388 390
389 xfs_dentry_to_name(&oname, odentry, 0); 391 if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
392 return -EINVAL;
393
394 /* if we are exchanging files, we need to set i_mode of both files */
395 if (flags & RENAME_EXCHANGE)
396 omode = ndentry->d_inode->i_mode;
397
398 xfs_dentry_to_name(&oname, odentry, omode);
390 xfs_dentry_to_name(&nname, ndentry, odentry->d_inode->i_mode); 399 xfs_dentry_to_name(&nname, ndentry, odentry->d_inode->i_mode);
391 400
392 return xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode), 401 return xfs_rename(XFS_I(odir), &oname, XFS_I(odentry->d_inode),
393 XFS_I(ndir), &nname, new_inode ? 402 XFS_I(ndir), &nname,
394 XFS_I(new_inode) : NULL); 403 new_inode ? XFS_I(new_inode) : NULL, flags);
395} 404}
396 405
397/* 406/*
@@ -1144,7 +1153,7 @@ static const struct inode_operations xfs_dir_inode_operations = {
1144 */ 1153 */
1145 .rmdir = xfs_vn_unlink, 1154 .rmdir = xfs_vn_unlink,
1146 .mknod = xfs_vn_mknod, 1155 .mknod = xfs_vn_mknod,
1147 .rename = xfs_vn_rename, 1156 .rename2 = xfs_vn_rename,
1148 .get_acl = xfs_get_acl, 1157 .get_acl = xfs_get_acl,
1149 .set_acl = xfs_set_acl, 1158 .set_acl = xfs_set_acl,
1150 .getattr = xfs_vn_getattr, 1159 .getattr = xfs_vn_getattr,
@@ -1172,7 +1181,7 @@ static const struct inode_operations xfs_dir_ci_inode_operations = {
1172 */ 1181 */
1173 .rmdir = xfs_vn_unlink, 1182 .rmdir = xfs_vn_unlink,
1174 .mknod = xfs_vn_mknod, 1183 .mknod = xfs_vn_mknod,
1175 .rename = xfs_vn_rename, 1184 .rename2 = xfs_vn_rename,
1176 .get_acl = xfs_get_acl, 1185 .get_acl = xfs_get_acl,
1177 .set_acl = xfs_set_acl, 1186 .set_acl = xfs_set_acl,
1178 .getattr = xfs_vn_getattr, 1187 .getattr = xfs_vn_getattr,
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index e408bf5a3ff7..8fbbfb2d46e1 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -1395,6 +1395,8 @@ xlog_alloc_log(
1395 ASSERT(xfs_buf_islocked(bp)); 1395 ASSERT(xfs_buf_islocked(bp));
1396 xfs_buf_unlock(bp); 1396 xfs_buf_unlock(bp);
1397 1397
1398 /* use high priority wq for log I/O completion */
1399 bp->b_ioend_wq = mp->m_log_workqueue;
1398 bp->b_iodone = xlog_iodone; 1400 bp->b_iodone = xlog_iodone;
1399 log->l_xbuf = bp; 1401 log->l_xbuf = bp;
1400 1402
@@ -1427,6 +1429,8 @@ xlog_alloc_log(
1427 ASSERT(xfs_buf_islocked(bp)); 1429 ASSERT(xfs_buf_islocked(bp));
1428 xfs_buf_unlock(bp); 1430 xfs_buf_unlock(bp);
1429 1431
1432 /* use high priority wq for log I/O completion */
1433 bp->b_ioend_wq = mp->m_log_workqueue;
1430 bp->b_iodone = xlog_iodone; 1434 bp->b_iodone = xlog_iodone;
1431 iclog->ic_bp = bp; 1435 iclog->ic_bp = bp;
1432 iclog->ic_data = bp->b_addr; 1436 iclog->ic_data = bp->b_addr;
@@ -1806,8 +1810,6 @@ xlog_sync(
1806 XFS_BUF_ZEROFLAGS(bp); 1810 XFS_BUF_ZEROFLAGS(bp);
1807 XFS_BUF_ASYNC(bp); 1811 XFS_BUF_ASYNC(bp);
1808 bp->b_flags |= XBF_SYNCIO; 1812 bp->b_flags |= XBF_SYNCIO;
1809 /* use high priority completion wq */
1810 bp->b_ioend_wq = log->l_mp->m_log_workqueue;
1811 1813
1812 if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) { 1814 if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) {
1813 bp->b_flags |= XBF_FUA; 1815 bp->b_flags |= XBF_FUA;
@@ -1856,8 +1858,6 @@ xlog_sync(
1856 bp->b_flags |= XBF_SYNCIO; 1858 bp->b_flags |= XBF_SYNCIO;
1857 if (log->l_mp->m_flags & XFS_MOUNT_BARRIER) 1859 if (log->l_mp->m_flags & XFS_MOUNT_BARRIER)
1858 bp->b_flags |= XBF_FUA; 1860 bp->b_flags |= XBF_FUA;
1859 /* use high priority completion wq */
1860 bp->b_ioend_wq = log->l_mp->m_log_workqueue;
1861 1861
1862 ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1); 1862 ASSERT(XFS_BUF_ADDR(bp) <= log->l_logBBsize-1);
1863 ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize); 1863 ASSERT(XFS_BUF_ADDR(bp) + BTOBB(count) <= log->l_logBBsize);
@@ -2027,7 +2027,7 @@ xlog_print_tic_res(
2027 " total reg = %u bytes (o/flow = %u bytes)\n" 2027 " total reg = %u bytes (o/flow = %u bytes)\n"
2028 " ophdrs = %u (ophdr space = %u bytes)\n" 2028 " ophdrs = %u (ophdr space = %u bytes)\n"
2029 " ophdr + reg = %u bytes\n" 2029 " ophdr + reg = %u bytes\n"
2030 " num regions = %u\n", 2030 " num regions = %u",
2031 ((ticket->t_trans_type <= 0 || 2031 ((ticket->t_trans_type <= 0 ||
2032 ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ? 2032 ticket->t_trans_type > XFS_TRANS_TYPE_MAX) ?
2033 "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]), 2033 "bad-trans-type" : trans_type_str[ticket->t_trans_type-1]),
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index d3d38836f87f..71d2c97cf58a 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -678,7 +678,7 @@ xfs_mountfs(
678 xfs_warn(mp, "correcting sb_features alignment problem"); 678 xfs_warn(mp, "correcting sb_features alignment problem");
679 sbp->sb_features2 |= sbp->sb_bad_features2; 679 sbp->sb_features2 |= sbp->sb_bad_features2;
680 sbp->sb_bad_features2 = sbp->sb_features2; 680 sbp->sb_bad_features2 = sbp->sb_features2;
681 mp->m_update_flags |= XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2; 681 mp->m_update_flags |= XFS_SB_FEATURES2;
682 682
683 /* 683 /*
684 * Re-check for ATTR2 in case it was found in bad_features2 684 * Re-check for ATTR2 in case it was found in bad_features2
@@ -1436,8 +1436,7 @@ xfs_mount_log_sb(
1436 int error; 1436 int error;
1437 1437
1438 ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID | 1438 ASSERT(fields & (XFS_SB_UNIT | XFS_SB_WIDTH | XFS_SB_UUID |
1439 XFS_SB_FEATURES2 | XFS_SB_BAD_FEATURES2 | 1439 XFS_SB_FEATURES2 | XFS_SB_VERSIONNUM));
1440 XFS_SB_VERSIONNUM));
1441 1440
1442 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT); 1441 tp = xfs_trans_alloc(mp, XFS_TRANS_SB_UNIT);
1443 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_sb, 0, 0); 1442 error = xfs_trans_reserve(tp, &M_RES(mp)->tr_sb, 0, 0);
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 19cbda196369..22e6acaa0320 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -685,7 +685,7 @@ xfs_blkdev_get(
685 mp); 685 mp);
686 if (IS_ERR(*bdevp)) { 686 if (IS_ERR(*bdevp)) {
687 error = PTR_ERR(*bdevp); 687 error = PTR_ERR(*bdevp);
688 xfs_warn(mp, "Invalid device [%s], error=%d\n", name, error); 688 xfs_warn(mp, "Invalid device [%s], error=%d", name, error);
689 } 689 }
690 690
691 return error; 691 return error;