diff -burp linux/fs/xfs/pagebuf/page_buf_io.c linux-work/fs/xfs/pagebuf/page_buf_io.c --- linux/fs/xfs/pagebuf/page_buf_io.c Thu Mar 7 12:52:21 2002 +++ linux-work/fs/xfs/pagebuf/page_buf_io.c Mon Mar 11 23:25:40 2002 @@ -310,7 +310,8 @@ int pagebuf_iozero( /* zero contents of __pb_block_prepare_write_async(ip, page, cpoff, cpoff+csize, at_eof, NULL, pbmapp, PBF_WRITE); - memset((void *) (kmap(page) + cpoff), 0, csize); + /* __pb_block_prepare_write already kmap'd the page */ + memset((void *) (page_address(page) + cpoff), 0, csize); pagebuf_commit_write_core(ip, page, cpoff, cpoff + csize); pos = ((loff_t)page->index << PAGE_CACHE_SHIFT) + cpoff + csize; @@ -721,7 +722,7 @@ int pagebuf_write_full_page(struct page ret = __pb_block_prepare_write_async(inode, page, 0, PAGE_CACHE_SIZE, 1, bmap, NULL, pb_flags); if (!ret) { - struct buffer_head *bh, *head; + struct buffer_head *bh, *head, *next; __pb_block_commit_write_async(inode, page, 0); @@ -745,8 +746,9 @@ int pagebuf_write_full_page(struct page } while (bh != head); do { + next = bh->b_this_page; submit_bh(WRITE, bh); - bh = bh->b_this_page; + bh = next; } while (bh != head); } diff -burp linux/fs/xfs/xfs_alloc.c linux-work/fs/xfs/xfs_alloc.c --- linux/fs/xfs/xfs_alloc.c Thu Mar 7 12:52:21 2002 +++ linux-work/fs/xfs/xfs_alloc.c Mon Mar 11 15:42:59 2002 @@ -2232,6 +2232,8 @@ xfs_alloc_read_agf( pag->pagf_levels[XFS_BTNUM_CNTi] = INT_GET(agf->agf_levels[XFS_BTNUM_CNTi], ARCH_CONVERT); spinlock_init(&pag->pagb_lock, "xfspagb"); + pag->pagb_list = kmem_zalloc(XFS_PAGB_NUM_SLOTS * + sizeof(xfs_perag_busy_t), KM_SLEEP); pag->pagf_init = 1; } #ifdef DEBUG diff -burp linux/fs/xfs/xfs_inode.c linux-work/fs/xfs/xfs_inode.c --- linux/fs/xfs/xfs_inode.c Thu Mar 7 12:52:22 2002 +++ linux-work/fs/xfs/xfs_inode.c Mon Mar 11 15:46:27 2002 @@ -1100,7 +1100,7 @@ xfs_ialloc( * cleared. */ if (ip->i_d.di_mode & ISGID) { - if (!in_group_p((gid_t)ip->i_d.di_gid)) { + if (!in_group_p((gid_t)ip->i_d.di_gid) && !capable(CAP_FSETID)) { ip->i_d.di_mode &= ~ISGID; } } diff -burp linux/fs/xfs/xfs_mount.c linux-work/fs/xfs/xfs_mount.c --- linux/fs/xfs/xfs_mount.c Thu Mar 7 12:52:22 2002 +++ linux-work/fs/xfs/xfs_mount.c Mon Mar 11 15:44:04 2002 @@ -149,6 +149,7 @@ xfs_mount_free( mrfree(&mp->m_peraglock); for (agno = 0; agno < mp->m_maxagi; agno++) + if (mp->m_perag[agno].pagb_list) kmem_free(mp->m_perag[agno].pagb_list, sizeof(xfs_perag_busy_t) * XFS_PAGB_NUM_SLOTS); kmem_free(mp->m_perag, @@ -888,11 +889,6 @@ xfs_mountfs( mrinit(&mp->m_peraglock, "xperag"); mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), KM_SLEEP); - for (agno = 0; agno < sbp->sb_agcount; agno++) { - mp->m_perag[agno].pagb_count = 0; - mp->m_perag[agno].pagb_list = kmem_zalloc(XFS_PAGB_NUM_SLOTS * - sizeof(xfs_perag_busy_t), KM_SLEEP); - } xfs_initialize_perag(mp, sbp->sb_agcount); @@ -942,6 +938,30 @@ xfs_mountfs( xfs_iunlock(rip, XFS_ILOCK_EXCL); + quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && + mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT); + + /* + * If the device itself is read-only, we can't allow + * the user to change the state of quota on the mount - + * this would generate a transaction on the ro device, + * which would lead to an I/O error and shutdown + */ + + if (((quotaondisk && !XFS_IS_QUOTA_ON(mp)) || + (!quotaondisk && XFS_IS_QUOTA_ON(mp))) && + (is_read_only(mp->m_dev) || is_read_only(mp->m_logdev))) { + cmn_err(CE_WARN, + "XFS: device %s is read-only, cannot change " + "quota state. Please mount with%s quota option.", + mp->m_fsname, quotaondisk ? "" : "out"); + rvp->v_flag |= VPURGE; + VN_RELE(rvp); + vn_remove(rvp); + error = XFS_ERROR(EPERM); + goto error3; + } + /* * Initialize realtime inode pointers in the mount structure */ @@ -966,8 +986,7 @@ xfs_mountfs( quotaflags = 0; needquotamount = B_FALSE; - quotaondisk = XFS_SB_VERSION_HASQUOTA(&mp->m_sb) && - mp->m_sb.sb_qflags & (XFS_UQUOTA_ACCT|XFS_GQUOTA_ACCT); + /* * Figure out if we'll need to do a quotacheck. * The requirements are a little different depending on whether @@ -1054,6 +1073,7 @@ xfs_mountfs( xfs_chash_free(mp); mrfree(&mp->m_peraglock); for (agno = 0; agno < sbp->sb_agcount; agno++) + if (mp->m_perag[agno].pagb_list) kmem_free(mp->m_perag[agno].pagb_list, sizeof(xfs_perag_busy_t) * XFS_PAGB_NUM_SLOTS); kmem_free(mp->m_perag, sbp->sb_agcount * sizeof(xfs_perag_t)); diff -burp linux/fs/xfs/xfs_utils.c linux-work/fs/xfs/xfs_utils.c --- linux/fs/xfs/xfs_utils.c Thu Mar 7 12:52:22 2002 +++ linux-work/fs/xfs/xfs_utils.c Mon Mar 11 15:43:32 2002 @@ -32,7 +32,9 @@ #include +#ifdef CONFIG_PROC_FS struct xfsstats xfsstats; +#endif /* * Test the sticky attribute of a directory. We can unlink from a sticky