diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-31 17:50:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-31 17:50:16 -0400 |
commit | e8d256aca05b6de163605a04f86e5827ef77899f (patch) | |
tree | 05de636b72b3d96808daea2aba104e07d722f79d /fs | |
parent | 977b55cf988b86cdc929fef730a78aca98a8ebdb (diff) | |
parent | e400d27d1690d609f203f2d7d8efebc98cbc3089 (diff) |
Merge tag 'for-linus-v3.10-rc4' of git://oss.sgi.com/xfs/xfs
Pull xfs fixes from Ben Myers:
- Fix nested transactions in xfs_qm_scall_setqlim
- Clear suid/sgid bits when we truncate with size update
- Fix recovery for split buffers
- Fix block count on remote symlinks
- Add fsgeom flag for v5 superblock support
- Disable XFS_IOC_SWAPEXT for CRC enabled filesystems
- Fix dirv3 freespace block corruption
* tag 'for-linus-v3.10-rc4' of git://oss.sgi.com/xfs/xfs:
xfs: fix dir3 freespace block corruption
xfs: disable swap extents ioctl on CRC enabled filesystems
xfs: add fsgeom flag for v5 superblock support.
xfs: fix incorrect remote symlink block count
xfs: fix split buffer vector log recovery support
xfs: kill suid/sgid through the truncate path.
xfs: avoid nesting transactions in xfs_qm_scall_setqlim()
Diffstat (limited to 'fs')
-rw-r--r-- | fs/xfs/xfs_buf_item.c | 7 | ||||
-rw-r--r-- | fs/xfs/xfs_dfrag.c | 8 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_format.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_dir2_node.c | 13 | ||||
-rw-r--r-- | fs/xfs/xfs_fs.h | 1 | ||||
-rw-r--r-- | fs/xfs/xfs_fsops.c | 4 | ||||
-rw-r--r-- | fs/xfs/xfs_iops.c | 47 | ||||
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 11 | ||||
-rw-r--r-- | fs/xfs/xfs_qm_syscalls.c | 40 | ||||
-rw-r--r-- | fs/xfs/xfs_symlink.c | 20 |
10 files changed, 92 insertions, 60 deletions
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index cf263476d6b4..4ec431777048 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -262,12 +262,7 @@ xfs_buf_item_format_segment( | |||
262 | vecp->i_addr = xfs_buf_offset(bp, buffer_offset); | 262 | vecp->i_addr = xfs_buf_offset(bp, buffer_offset); |
263 | vecp->i_len = nbits * XFS_BLF_CHUNK; | 263 | vecp->i_len = nbits * XFS_BLF_CHUNK; |
264 | vecp->i_type = XLOG_REG_TYPE_BCHUNK; | 264 | vecp->i_type = XLOG_REG_TYPE_BCHUNK; |
265 | /* | 265 | nvecs++; |
266 | * You would think we need to bump the nvecs here too, but we do not | ||
267 | * this number is used by recovery, and it gets confused by the boundary | ||
268 | * split here | ||
269 | * nvecs++; | ||
270 | */ | ||
271 | vecp++; | 266 | vecp++; |
272 | first_bit = next_bit; | 267 | first_bit = next_bit; |
273 | last_bit = next_bit; | 268 | last_bit = next_bit; |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index f852b082a084..c407e1ccff43 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
@@ -219,6 +219,14 @@ xfs_swap_extents( | |||
219 | int taforkblks = 0; | 219 | int taforkblks = 0; |
220 | __uint64_t tmp; | 220 | __uint64_t tmp; |
221 | 221 | ||
222 | /* | ||
223 | * We have no way of updating owner information in the BMBT blocks for | ||
224 | * each inode on CRC enabled filesystems, so to avoid corrupting the | ||
225 | * this metadata we simply don't allow extent swaps to occur. | ||
226 | */ | ||
227 | if (xfs_sb_version_hascrc(&mp->m_sb)) | ||
228 | return XFS_ERROR(EINVAL); | ||
229 | |||
222 | tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); | 230 | tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); |
223 | if (!tempifp) { | 231 | if (!tempifp) { |
224 | error = XFS_ERROR(ENOMEM); | 232 | error = XFS_ERROR(ENOMEM); |
diff --git a/fs/xfs/xfs_dir2_format.h b/fs/xfs/xfs_dir2_format.h index a3b1bd841a80..995f1f505a52 100644 --- a/fs/xfs/xfs_dir2_format.h +++ b/fs/xfs/xfs_dir2_format.h | |||
@@ -715,6 +715,7 @@ struct xfs_dir3_free_hdr { | |||
715 | __be32 firstdb; /* db of first entry */ | 715 | __be32 firstdb; /* db of first entry */ |
716 | __be32 nvalid; /* count of valid entries */ | 716 | __be32 nvalid; /* count of valid entries */ |
717 | __be32 nused; /* count of used entries */ | 717 | __be32 nused; /* count of used entries */ |
718 | __be32 pad; /* 64 bit alignment. */ | ||
718 | }; | 719 | }; |
719 | 720 | ||
720 | struct xfs_dir3_free { | 721 | struct xfs_dir3_free { |
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index 5246de4912d4..2226a00acd15 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -263,18 +263,19 @@ xfs_dir3_free_get_buf( | |||
263 | * Initialize the new block to be empty, and remember | 263 | * Initialize the new block to be empty, and remember |
264 | * its first slot as our empty slot. | 264 | * its first slot as our empty slot. |
265 | */ | 265 | */ |
266 | hdr.magic = XFS_DIR2_FREE_MAGIC; | 266 | memset(bp->b_addr, 0, sizeof(struct xfs_dir3_free_hdr)); |
267 | hdr.firstdb = 0; | 267 | memset(&hdr, 0, sizeof(hdr)); |
268 | hdr.nused = 0; | 268 | |
269 | hdr.nvalid = 0; | ||
270 | if (xfs_sb_version_hascrc(&mp->m_sb)) { | 269 | if (xfs_sb_version_hascrc(&mp->m_sb)) { |
271 | struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; | 270 | struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; |
272 | 271 | ||
273 | hdr.magic = XFS_DIR3_FREE_MAGIC; | 272 | hdr.magic = XFS_DIR3_FREE_MAGIC; |
273 | |||
274 | hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); | 274 | hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); |
275 | hdr3->hdr.owner = cpu_to_be64(dp->i_ino); | 275 | hdr3->hdr.owner = cpu_to_be64(dp->i_ino); |
276 | uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); | 276 | uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); |
277 | } | 277 | } else |
278 | hdr.magic = XFS_DIR2_FREE_MAGIC; | ||
278 | xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr); | 279 | xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr); |
279 | *bpp = bp; | 280 | *bpp = bp; |
280 | return 0; | 281 | return 0; |
@@ -1921,8 +1922,6 @@ xfs_dir2_node_addname_int( | |||
1921 | */ | 1922 | */ |
1922 | freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * | 1923 | freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * |
1923 | xfs_dir3_free_max_bests(mp); | 1924 | xfs_dir3_free_max_bests(mp); |
1924 | free->hdr.nvalid = 0; | ||
1925 | free->hdr.nused = 0; | ||
1926 | } else { | 1925 | } else { |
1927 | free = fbp->b_addr; | 1926 | free = fbp->b_addr; |
1928 | bests = xfs_dir3_free_bests_p(mp, free); | 1927 | bests = xfs_dir3_free_bests_p(mp, free); |
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index 6dda3f949b04..d04695545397 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h | |||
@@ -236,6 +236,7 @@ typedef struct xfs_fsop_resblks { | |||
236 | #define XFS_FSOP_GEOM_FLAGS_PROJID32 0x0800 /* 32-bit project IDs */ | 236 | #define XFS_FSOP_GEOM_FLAGS_PROJID32 0x0800 /* 32-bit project IDs */ |
237 | #define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */ | 237 | #define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */ |
238 | #define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */ | 238 | #define XFS_FSOP_GEOM_FLAGS_LAZYSB 0x4000 /* lazy superblock counters */ |
239 | #define XFS_FSOP_GEOM_FLAGS_V5SB 0x8000 /* version 5 superblock */ | ||
239 | 240 | ||
240 | 241 | ||
241 | /* | 242 | /* |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 87595b211da1..3c3644ea825b 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -99,7 +99,9 @@ xfs_fs_geometry( | |||
99 | (xfs_sb_version_hasattr2(&mp->m_sb) ? | 99 | (xfs_sb_version_hasattr2(&mp->m_sb) ? |
100 | XFS_FSOP_GEOM_FLAGS_ATTR2 : 0) | | 100 | XFS_FSOP_GEOM_FLAGS_ATTR2 : 0) | |
101 | (xfs_sb_version_hasprojid32bit(&mp->m_sb) ? | 101 | (xfs_sb_version_hasprojid32bit(&mp->m_sb) ? |
102 | XFS_FSOP_GEOM_FLAGS_PROJID32 : 0); | 102 | XFS_FSOP_GEOM_FLAGS_PROJID32 : 0) | |
103 | (xfs_sb_version_hascrc(&mp->m_sb) ? | ||
104 | XFS_FSOP_GEOM_FLAGS_V5SB : 0); | ||
103 | geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? | 105 | geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? |
104 | mp->m_sb.sb_logsectsize : BBSIZE; | 106 | mp->m_sb.sb_logsectsize : BBSIZE; |
105 | geo->rtsectsize = mp->m_sb.sb_blocksize; | 107 | geo->rtsectsize = mp->m_sb.sb_blocksize; |
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c index d82efaa2ac73..ca9ecaa81112 100644 --- a/fs/xfs/xfs_iops.c +++ b/fs/xfs/xfs_iops.c | |||
@@ -455,6 +455,28 @@ xfs_vn_getattr( | |||
455 | return 0; | 455 | return 0; |
456 | } | 456 | } |
457 | 457 | ||
458 | static void | ||
459 | xfs_setattr_mode( | ||
460 | struct xfs_trans *tp, | ||
461 | struct xfs_inode *ip, | ||
462 | struct iattr *iattr) | ||
463 | { | ||
464 | struct inode *inode = VFS_I(ip); | ||
465 | umode_t mode = iattr->ia_mode; | ||
466 | |||
467 | ASSERT(tp); | ||
468 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | ||
469 | |||
470 | if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) | ||
471 | mode &= ~S_ISGID; | ||
472 | |||
473 | ip->i_d.di_mode &= S_IFMT; | ||
474 | ip->i_d.di_mode |= mode & ~S_IFMT; | ||
475 | |||
476 | inode->i_mode &= S_IFMT; | ||
477 | inode->i_mode |= mode & ~S_IFMT; | ||
478 | } | ||
479 | |||
458 | int | 480 | int |
459 | xfs_setattr_nonsize( | 481 | xfs_setattr_nonsize( |
460 | struct xfs_inode *ip, | 482 | struct xfs_inode *ip, |
@@ -606,18 +628,8 @@ xfs_setattr_nonsize( | |||
606 | /* | 628 | /* |
607 | * Change file access modes. | 629 | * Change file access modes. |
608 | */ | 630 | */ |
609 | if (mask & ATTR_MODE) { | 631 | if (mask & ATTR_MODE) |
610 | umode_t mode = iattr->ia_mode; | 632 | xfs_setattr_mode(tp, ip, iattr); |
611 | |||
612 | if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) | ||
613 | mode &= ~S_ISGID; | ||
614 | |||
615 | ip->i_d.di_mode &= S_IFMT; | ||
616 | ip->i_d.di_mode |= mode & ~S_IFMT; | ||
617 | |||
618 | inode->i_mode &= S_IFMT; | ||
619 | inode->i_mode |= mode & ~S_IFMT; | ||
620 | } | ||
621 | 633 | ||
622 | /* | 634 | /* |
623 | * Change file access or modified times. | 635 | * Change file access or modified times. |
@@ -714,9 +726,8 @@ xfs_setattr_size( | |||
714 | return XFS_ERROR(error); | 726 | return XFS_ERROR(error); |
715 | 727 | ||
716 | ASSERT(S_ISREG(ip->i_d.di_mode)); | 728 | ASSERT(S_ISREG(ip->i_d.di_mode)); |
717 | ASSERT((mask & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| | 729 | ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| |
718 | ATTR_MTIME_SET|ATTR_KILL_SUID|ATTR_KILL_SGID| | 730 | ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); |
719 | ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); | ||
720 | 731 | ||
721 | if (!(flags & XFS_ATTR_NOLOCK)) { | 732 | if (!(flags & XFS_ATTR_NOLOCK)) { |
722 | lock_flags |= XFS_IOLOCK_EXCL; | 733 | lock_flags |= XFS_IOLOCK_EXCL; |
@@ -860,6 +871,12 @@ xfs_setattr_size( | |||
860 | xfs_inode_clear_eofblocks_tag(ip); | 871 | xfs_inode_clear_eofblocks_tag(ip); |
861 | } | 872 | } |
862 | 873 | ||
874 | /* | ||
875 | * Change file access modes. | ||
876 | */ | ||
877 | if (mask & ATTR_MODE) | ||
878 | xfs_setattr_mode(tp, ip, iattr); | ||
879 | |||
863 | if (mask & ATTR_CTIME) { | 880 | if (mask & ATTR_CTIME) { |
864 | inode->i_ctime = iattr->ia_ctime; | 881 | inode->i_ctime = iattr->ia_ctime; |
865 | ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec; | 882 | ip->i_d.di_ctime.t_sec = iattr->ia_ctime.tv_sec; |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 93f03ec17eec..d9e4d3c3991a 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -2097,6 +2097,17 @@ xlog_recover_do_reg_buffer( | |||
2097 | ((uint)bit << XFS_BLF_SHIFT) + (nbits << XFS_BLF_SHIFT)); | 2097 | ((uint)bit << XFS_BLF_SHIFT) + (nbits << XFS_BLF_SHIFT)); |
2098 | 2098 | ||
2099 | /* | 2099 | /* |
2100 | * The dirty regions logged in the buffer, even though | ||
2101 | * contiguous, may span multiple chunks. This is because the | ||
2102 | * dirty region may span a physical page boundary in a buffer | ||
2103 | * and hence be split into two separate vectors for writing into | ||
2104 | * the log. Hence we need to trim nbits back to the length of | ||
2105 | * the current region being copied out of the log. | ||
2106 | */ | ||
2107 | if (item->ri_buf[i].i_len < (nbits << XFS_BLF_SHIFT)) | ||
2108 | nbits = item->ri_buf[i].i_len >> XFS_BLF_SHIFT; | ||
2109 | |||
2110 | /* | ||
2100 | * Do a sanity check if this is a dquot buffer. Just checking | 2111 | * Do a sanity check if this is a dquot buffer. Just checking |
2101 | * the first dquot in the buffer should do. XXXThis is | 2112 | * the first dquot in the buffer should do. XXXThis is |
2102 | * probably a good thing to do for other buf types also. | 2113 | * probably a good thing to do for other buf types also. |
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c index c41190cad6e9..6cdf6ffc36a1 100644 --- a/fs/xfs/xfs_qm_syscalls.c +++ b/fs/xfs/xfs_qm_syscalls.c | |||
@@ -489,31 +489,36 @@ xfs_qm_scall_setqlim( | |||
489 | if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0) | 489 | if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0) |
490 | return 0; | 490 | return 0; |
491 | 491 | ||
492 | tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM); | ||
493 | error = xfs_trans_reserve(tp, 0, XFS_QM_SETQLIM_LOG_RES(mp), | ||
494 | 0, 0, XFS_DEFAULT_LOG_COUNT); | ||
495 | if (error) { | ||
496 | xfs_trans_cancel(tp, 0); | ||
497 | return (error); | ||
498 | } | ||
499 | |||
500 | /* | 492 | /* |
501 | * We don't want to race with a quotaoff so take the quotaoff lock. | 493 | * We don't want to race with a quotaoff so take the quotaoff lock. |
502 | * (We don't hold an inode lock, so there's nothing else to stop | 494 | * We don't hold an inode lock, so there's nothing else to stop |
503 | * a quotaoff from happening). (XXXThis doesn't currently happen | 495 | * a quotaoff from happening. |
504 | * because we take the vfslock before calling xfs_qm_sysent). | ||
505 | */ | 496 | */ |
506 | mutex_lock(&q->qi_quotaofflock); | 497 | mutex_lock(&q->qi_quotaofflock); |
507 | 498 | ||
508 | /* | 499 | /* |
509 | * Get the dquot (locked), and join it to the transaction. | 500 | * Get the dquot (locked) before we start, as we need to do a |
510 | * Allocate the dquot if this doesn't exist. | 501 | * transaction to allocate it if it doesn't exist. Once we have the |
502 | * dquot, unlock it so we can start the next transaction safely. We hold | ||
503 | * a reference to the dquot, so it's safe to do this unlock/lock without | ||
504 | * it being reclaimed in the mean time. | ||
511 | */ | 505 | */ |
512 | if ((error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp))) { | 506 | error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp); |
513 | xfs_trans_cancel(tp, XFS_TRANS_ABORT); | 507 | if (error) { |
514 | ASSERT(error != ENOENT); | 508 | ASSERT(error != ENOENT); |
515 | goto out_unlock; | 509 | goto out_unlock; |
516 | } | 510 | } |
511 | xfs_dqunlock(dqp); | ||
512 | |||
513 | tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM); | ||
514 | error = xfs_trans_reserve(tp, 0, XFS_QM_SETQLIM_LOG_RES(mp), | ||
515 | 0, 0, XFS_DEFAULT_LOG_COUNT); | ||
516 | if (error) { | ||
517 | xfs_trans_cancel(tp, 0); | ||
518 | goto out_rele; | ||
519 | } | ||
520 | |||
521 | xfs_dqlock(dqp); | ||
517 | xfs_trans_dqjoin(tp, dqp); | 522 | xfs_trans_dqjoin(tp, dqp); |
518 | ddq = &dqp->q_core; | 523 | ddq = &dqp->q_core; |
519 | 524 | ||
@@ -621,9 +626,10 @@ xfs_qm_scall_setqlim( | |||
621 | xfs_trans_log_dquot(tp, dqp); | 626 | xfs_trans_log_dquot(tp, dqp); |
622 | 627 | ||
623 | error = xfs_trans_commit(tp, 0); | 628 | error = xfs_trans_commit(tp, 0); |
624 | xfs_qm_dqrele(dqp); | ||
625 | 629 | ||
626 | out_unlock: | 630 | out_rele: |
631 | xfs_qm_dqrele(dqp); | ||
632 | out_unlock: | ||
627 | mutex_unlock(&q->qi_quotaofflock); | 633 | mutex_unlock(&q->qi_quotaofflock); |
628 | return error; | 634 | return error; |
629 | } | 635 | } |
diff --git a/fs/xfs/xfs_symlink.c b/fs/xfs/xfs_symlink.c index 5f234389327c..195a403e1522 100644 --- a/fs/xfs/xfs_symlink.c +++ b/fs/xfs/xfs_symlink.c | |||
@@ -56,16 +56,9 @@ xfs_symlink_blocks( | |||
56 | struct xfs_mount *mp, | 56 | struct xfs_mount *mp, |
57 | int pathlen) | 57 | int pathlen) |
58 | { | 58 | { |
59 | int fsblocks = 0; | 59 | int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize); |
60 | int len = pathlen; | ||
61 | 60 | ||
62 | do { | 61 | return (pathlen + buflen - 1) / buflen; |
63 | fsblocks++; | ||
64 | len -= XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize); | ||
65 | } while (len > 0); | ||
66 | |||
67 | ASSERT(fsblocks <= XFS_SYMLINK_MAPS); | ||
68 | return fsblocks; | ||
69 | } | 62 | } |
70 | 63 | ||
71 | static int | 64 | static int |
@@ -405,7 +398,7 @@ xfs_symlink( | |||
405 | if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version)) | 398 | if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version)) |
406 | fs_blocks = 0; | 399 | fs_blocks = 0; |
407 | else | 400 | else |
408 | fs_blocks = XFS_B_TO_FSB(mp, pathlen); | 401 | fs_blocks = xfs_symlink_blocks(mp, pathlen); |
409 | resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks); | 402 | resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks); |
410 | error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0, | 403 | error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0, |
411 | XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT); | 404 | XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT); |
@@ -512,7 +505,7 @@ xfs_symlink( | |||
512 | cur_chunk = target_path; | 505 | cur_chunk = target_path; |
513 | offset = 0; | 506 | offset = 0; |
514 | for (n = 0; n < nmaps; n++) { | 507 | for (n = 0; n < nmaps; n++) { |
515 | char *buf; | 508 | char *buf; |
516 | 509 | ||
517 | d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); | 510 | d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); |
518 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); | 511 | byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); |
@@ -525,9 +518,7 @@ xfs_symlink( | |||
525 | bp->b_ops = &xfs_symlink_buf_ops; | 518 | bp->b_ops = &xfs_symlink_buf_ops; |
526 | 519 | ||
527 | byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt); | 520 | byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt); |
528 | if (pathlen < byte_cnt) { | 521 | byte_cnt = min(byte_cnt, pathlen); |
529 | byte_cnt = pathlen; | ||
530 | } | ||
531 | 522 | ||
532 | buf = bp->b_addr; | 523 | buf = bp->b_addr; |
533 | buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset, | 524 | buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset, |
@@ -542,6 +533,7 @@ xfs_symlink( | |||
542 | xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) - | 533 | xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) - |
543 | (char *)bp->b_addr); | 534 | (char *)bp->b_addr); |
544 | } | 535 | } |
536 | ASSERT(pathlen == 0); | ||
545 | } | 537 | } |
546 | 538 | ||
547 | /* | 539 | /* |