Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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()

+95 -63
+1 -6
fs/xfs/xfs_buf_item.c
··· 262 262 vecp->i_addr = xfs_buf_offset(bp, buffer_offset); 263 263 vecp->i_len = nbits * XFS_BLF_CHUNK; 264 264 vecp->i_type = XLOG_REG_TYPE_BCHUNK; 265 - /* 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 - */ 265 + nvecs++; 271 266 vecp++; 272 267 first_bit = next_bit; 273 268 last_bit = next_bit;
+8
fs/xfs/xfs_dfrag.c
··· 219 219 int taforkblks = 0; 220 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 230 tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); 223 231 if (!tempifp) { 224 232 error = XFS_ERROR(ENOMEM);
+1
fs/xfs/xfs_dir2_format.h
··· 715 715 __be32 firstdb; /* db of first entry */ 716 716 __be32 nvalid; /* count of valid entries */ 717 717 __be32 nused; /* count of used entries */ 718 + __be32 pad; /* 64 bit alignment. */ 718 719 }; 719 720 720 721 struct xfs_dir3_free {
+6 -7
fs/xfs/xfs_dir2_node.c
··· 263 263 * Initialize the new block to be empty, and remember 264 264 * its first slot as our empty slot. 265 265 */ 266 - hdr.magic = XFS_DIR2_FREE_MAGIC; 267 - hdr.firstdb = 0; 268 - hdr.nused = 0; 269 - hdr.nvalid = 0; 266 + memset(bp->b_addr, 0, sizeof(struct xfs_dir3_free_hdr)); 267 + memset(&hdr, 0, sizeof(hdr)); 268 + 270 269 if (xfs_sb_version_hascrc(&mp->m_sb)) { 271 270 struct xfs_dir3_free_hdr *hdr3 = bp->b_addr; 272 271 273 272 hdr.magic = XFS_DIR3_FREE_MAGIC; 273 + 274 274 hdr3->hdr.blkno = cpu_to_be64(bp->b_bn); 275 275 hdr3->hdr.owner = cpu_to_be64(dp->i_ino); 276 276 uuid_copy(&hdr3->hdr.uuid, &mp->m_sb.sb_uuid); 277 - } 277 + } else 278 + hdr.magic = XFS_DIR2_FREE_MAGIC; 278 279 xfs_dir3_free_hdr_to_disk(bp->b_addr, &hdr); 279 280 *bpp = bp; 280 281 return 0; ··· 1922 1921 */ 1923 1922 freehdr.firstdb = (fbno - XFS_DIR2_FREE_FIRSTDB(mp)) * 1924 1923 xfs_dir3_free_max_bests(mp); 1925 - free->hdr.nvalid = 0; 1926 - free->hdr.nused = 0; 1927 1924 } else { 1928 1925 free = fbp->b_addr; 1929 1926 bests = xfs_dir3_free_bests_p(mp, free);
+1
fs/xfs/xfs_fs.h
··· 236 236 #define XFS_FSOP_GEOM_FLAGS_PROJID32 0x0800 /* 32-bit project IDs */ 237 237 #define XFS_FSOP_GEOM_FLAGS_DIRV2CI 0x1000 /* ASCII only CI names */ 238 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 /*
+3 -1
fs/xfs/xfs_fsops.c
··· 99 99 (xfs_sb_version_hasattr2(&mp->m_sb) ? 100 100 XFS_FSOP_GEOM_FLAGS_ATTR2 : 0) | 101 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 105 geo->logsectsize = xfs_sb_version_hassector(&mp->m_sb) ? 104 106 mp->m_sb.sb_logsectsize : BBSIZE; 105 107 geo->rtsectsize = mp->m_sb.sb_blocksize;
+32 -15
fs/xfs/xfs_iops.c
··· 455 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 480 int 459 481 xfs_setattr_nonsize( 460 482 struct xfs_inode *ip, ··· 628 606 /* 629 607 * Change file access modes. 630 608 */ 631 - if (mask & ATTR_MODE) { 632 - umode_t mode = iattr->ia_mode; 633 - 634 - if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 635 - mode &= ~S_ISGID; 636 - 637 - ip->i_d.di_mode &= S_IFMT; 638 - ip->i_d.di_mode |= mode & ~S_IFMT; 639 - 640 - inode->i_mode &= S_IFMT; 641 - inode->i_mode |= mode & ~S_IFMT; 642 - } 609 + if (mask & ATTR_MODE) 610 + xfs_setattr_mode(tp, ip, iattr); 643 611 644 612 /* 645 613 * Change file access or modified times. ··· 726 714 return XFS_ERROR(error); 727 715 728 716 ASSERT(S_ISREG(ip->i_d.di_mode)); 729 - ASSERT((mask & (ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| 730 - ATTR_MTIME_SET|ATTR_KILL_SUID|ATTR_KILL_SGID| 731 - ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); 717 + ASSERT((mask & (ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_ATIME_SET| 718 + ATTR_MTIME_SET|ATTR_KILL_PRIV|ATTR_TIMES_SET)) == 0); 732 719 733 720 if (!(flags & XFS_ATTR_NOLOCK)) { 734 721 lock_flags |= XFS_IOLOCK_EXCL; ··· 870 859 /* A truncate down always removes post-EOF blocks. */ 871 860 xfs_inode_clear_eofblocks_tag(ip); 872 861 } 862 + 863 + /* 864 + * Change file access modes. 865 + */ 866 + if (mask & ATTR_MODE) 867 + xfs_setattr_mode(tp, ip, iattr); 873 868 874 869 if (mask & ATTR_CTIME) { 875 870 inode->i_ctime = iattr->ia_ctime;
+11
fs/xfs/xfs_log_recover.c
··· 2097 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 2111 * Do a sanity check if this is a dquot buffer. Just checking 2101 2112 * the first dquot in the buffer should do. XXXThis is 2102 2113 * probably a good thing to do for other buf types also.
+26 -20
fs/xfs/xfs_qm_syscalls.c
··· 489 489 if ((newlim->d_fieldmask & XFS_DQ_MASK) == 0) 490 490 return 0; 491 491 492 + /* 493 + * We don't want to race with a quotaoff so take the quotaoff lock. 494 + * We don't hold an inode lock, so there's nothing else to stop 495 + * a quotaoff from happening. 496 + */ 497 + mutex_lock(&q->qi_quotaofflock); 498 + 499 + /* 500 + * Get the dquot (locked) before we start, as we need to do a 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. 505 + */ 506 + error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp); 507 + if (error) { 508 + ASSERT(error != ENOENT); 509 + goto out_unlock; 510 + } 511 + xfs_dqunlock(dqp); 512 + 492 513 tp = xfs_trans_alloc(mp, XFS_TRANS_QM_SETQLIM); 493 514 error = xfs_trans_reserve(tp, 0, XFS_QM_SETQLIM_LOG_RES(mp), 494 515 0, 0, XFS_DEFAULT_LOG_COUNT); 495 516 if (error) { 496 517 xfs_trans_cancel(tp, 0); 497 - return (error); 518 + goto out_rele; 498 519 } 499 520 500 - /* 501 - * 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 503 - * a quotaoff from happening). (XXXThis doesn't currently happen 504 - * because we take the vfslock before calling xfs_qm_sysent). 505 - */ 506 - mutex_lock(&q->qi_quotaofflock); 507 - 508 - /* 509 - * Get the dquot (locked), and join it to the transaction. 510 - * Allocate the dquot if this doesn't exist. 511 - */ 512 - if ((error = xfs_qm_dqget(mp, NULL, id, type, XFS_QMOPT_DQALLOC, &dqp))) { 513 - xfs_trans_cancel(tp, XFS_TRANS_ABORT); 514 - ASSERT(error != ENOENT); 515 - goto out_unlock; 516 - } 521 + xfs_dqlock(dqp); 517 522 xfs_trans_dqjoin(tp, dqp); 518 523 ddq = &dqp->q_core; 519 524 ··· 626 621 xfs_trans_log_dquot(tp, dqp); 627 622 628 623 error = xfs_trans_commit(tp, 0); 629 - xfs_qm_dqrele(dqp); 630 624 631 - out_unlock: 625 + out_rele: 626 + xfs_qm_dqrele(dqp); 627 + out_unlock: 632 628 mutex_unlock(&q->qi_quotaofflock); 633 629 return error; 634 630 }
+6 -14
fs/xfs/xfs_symlink.c
··· 56 56 struct xfs_mount *mp, 57 57 int pathlen) 58 58 { 59 - int fsblocks = 0; 60 - int len = pathlen; 59 + int buflen = XFS_SYMLINK_BUF_SPACE(mp, mp->m_sb.sb_blocksize); 61 60 62 - do { 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; 61 + return (pathlen + buflen - 1) / buflen; 69 62 } 70 63 71 64 static int ··· 398 405 if (pathlen <= XFS_LITINO(mp, dp->i_d.di_version)) 399 406 fs_blocks = 0; 400 407 else 401 - fs_blocks = XFS_B_TO_FSB(mp, pathlen); 408 + fs_blocks = xfs_symlink_blocks(mp, pathlen); 402 409 resblks = XFS_SYMLINK_SPACE_RES(mp, link_name->len, fs_blocks); 403 410 error = xfs_trans_reserve(tp, resblks, XFS_SYMLINK_LOG_RES(mp), 0, 404 411 XFS_TRANS_PERM_LOG_RES, XFS_SYMLINK_LOG_COUNT); ··· 505 512 cur_chunk = target_path; 506 513 offset = 0; 507 514 for (n = 0; n < nmaps; n++) { 508 - char *buf; 515 + char *buf; 509 516 510 517 d = XFS_FSB_TO_DADDR(mp, mval[n].br_startblock); 511 518 byte_cnt = XFS_FSB_TO_B(mp, mval[n].br_blockcount); ··· 518 525 bp->b_ops = &xfs_symlink_buf_ops; 519 526 520 527 byte_cnt = XFS_SYMLINK_BUF_SPACE(mp, byte_cnt); 521 - if (pathlen < byte_cnt) { 522 - byte_cnt = pathlen; 523 - } 528 + byte_cnt = min(byte_cnt, pathlen); 524 529 525 530 buf = bp->b_addr; 526 531 buf += xfs_symlink_hdr_set(mp, ip->i_ino, offset, ··· 533 542 xfs_trans_log_buf(tp, bp, 0, (buf + byte_cnt - 1) - 534 543 (char *)bp->b_addr); 535 544 } 545 + ASSERT(pathlen == 0); 536 546 } 537 547 538 548 /*