From 0cdfb6c99d8facc3b6a56503d9e3fbe347d38748 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 10 Feb 2003 15:53:17 -0100 Subject: [AGPGART] alpha agp infrastructure --- include/linux/agp_backend.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h index 36568e4a3d14..5154f6a98153 100644 --- a/include/linux/agp_backend.h +++ b/include/linux/agp_backend.h @@ -84,6 +84,7 @@ enum chipset_type { SVWRKS_LE, SVWRKS_GENERIC, HP_ZX1, + ALPHA_CORE_AGP, }; struct agp_version { @@ -102,6 +103,7 @@ typedef struct _agp_kern_info { int current_memory; int cant_use_aperture; unsigned long page_mask; + struct vm_operations_struct *vm_ops; } agp_kern_info; /* -- cgit v1.2.3 From f083e8d1f972c50b2c13d6d38de053a22576e1af Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 10 Feb 2003 16:49:13 -0100 Subject: [AGPGART] Remove pointless enums from VIA GART driver. --- drivers/char/agp/via-agp.c | 27 ++------------------------- include/linux/agp_backend.h | 11 ----------- 2 files changed, 2 insertions(+), 36 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index 1d0c22b170b2..731feb6eab25 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c @@ -179,7 +179,7 @@ static struct aper_size_info_16 via_generic_agp3_sizes[11] = static int __init via_generic_agp3_setup (struct pci_dev *pdev) { agp_bridge->dev = pdev; - agp_bridge->type = VIA_APOLLO_KT400_3; + agp_bridge->type = VIA_GENERIC; agp_bridge->masks = via_generic_masks; agp_bridge->aperture_sizes = (void *) via_generic_agp3_sizes; agp_bridge->size_type = U16_APER_SIZE; @@ -282,101 +282,86 @@ static struct agp_device_ids via_agp_device_ids[] __initdata = { { .device_id = PCI_DEVICE_ID_VIA_82C597_0, - .chipset = VIA_VP3, .chipset_name = "VP3", }, { .device_id = PCI_DEVICE_ID_VIA_82C598_0, - .chipset = VIA_MVP3, .chipset_name = "MVP3", }, { .device_id = PCI_DEVICE_ID_VIA_8501_0, - .chipset = VIA_MVP4, .chipset_name = "MVP4", }, /* VT8601 */ /* { .device_id = PCI_DEVICE_ID_VIA_8601_0, // 0x0601 - .chipset = , .chipset_name = "PLE133 ProMedia", },*/ /* VT82C693A / VT28C694T */ { .device_id = PCI_DEVICE_ID_VIA_82C691, - .chipset = VIA_APOLLO_PRO, .chipset_name = "Apollo Pro 133", }, { .device_id = PCI_DEVICE_ID_VIA_8371_0, - .chipset = VIA_APOLLO_KX133, .chipset_name = "Apollo Pro KX133", }, /* VT8633 */ { .device_id = PCI_DEVICE_ID_VIA_8633_0, - .chipset = VIA_APOLLO_PRO_266, .chipset_name = "Apollo Pro 266", }, /* VT8361 */ /* { .device_id = PCI_DEVICE_ID_VIA_8361, // 0x3112 - .chipset = ?, .chipset_name = "Apollo KLE133", }, */ /* VT8365 / VT8362 */ { .device_id = PCI_DEVICE_ID_VIA_8363_0, - .chipset = VIA_APOLLO_KT133, .chipset_name = "Apollo Pro KT133/KM133/TwisterK", }, /* VT8753A */ /* { .device_id = PCI_DEVICE_ID_VIA_8753_0, // 0x3128 - .chipset = VIA_P4X266, .chipset_name = "P4X266", }, */ /* VT8366 */ { .device_id = PCI_DEVICE_ID_VIA_8367_0, - .chipset = VIA_APOLLO_KT133, .chipset_name = "Apollo Pro KT266/KT333", }, /* VT8633 (for CuMine/ Celeron) */ { .device_id = PCI_DEVICE_ID_VIA_8653_0, - .chipset = VIA_APOLLO_PRO, .chipset_name = "Apollo Pro 266T", }, /* KM266 / PM266 */ /* { .device_id = PCI_DEVICE_ID_VIA_KM266, // 0x3116 - .chipset = VIA_KM266, .chipset_name = "KM266/PM266", }, */ /* CLE266 */ /* { .device_id = PCI_DEVICE_ID_VIA_CLE266, // 0x3123 - .chipset = VIA_CLE266, .chipset_name = "CLE266", }, */ { .device_id = PCI_DEVICE_ID_VIA_8377_0, - .chipset = VIA_APOLLO_KT400, .chipset_name = "Apollo Pro KT400", .chipset_setup = via_kt400_setup, }, @@ -385,56 +370,48 @@ static struct agp_device_ids via_agp_device_ids[] __initdata = * (Apollo Pro133A chipset with S3 Savage4) */ { .device_id = PCI_DEVICE_ID_VIA_82C694X_0, - .chipset = VIA_VT8605, .chipset_name = "Apollo ProSavage PM133/PL133/PN133/Twister" }, /* VT8752*/ /* { .device_id = PCI_DEVICE_ID_VIA_8752, // 0x3148 - .chipset = VIA_P4M266, .chipset_name = "ProSavage DDR P4M266", }, */ /* KN266/PN266 */ /* { .device_id = PCI_DEVICE_ID_KN266, // 0x3156 - .chipset = VIA_KN266, .chipset_name = "KN266/PN266", }, */ /* VT8754 */ { .device_id = PCI_DEVICE_ID_VIA_8754, - .chipset = VIA_P4X, .chipset_name = "Apollo P4X333/P4X400" }, /* P4N333 */ /* { .device_id = PCI_DEVICE_ID_VIA_P4N333, // 0x3178 - .chipset = VIA_P4N, .chipset_name = "P4N333", }, */ /* P4X600 */ /* { .device_id = PCI_DEVICE_ID_VIA_P4X600, // 0x0198 - .chipset = VIA_P4X600, .chipset_name = "P4X600", }, */ /* KM400 */ /* { .device_id = PCI_DEVICE_ID_VIA_KM400, // 0x3205 - .chipset = VIA_KM400, .chipset_name = "KM400", }, */ /* P4M400 */ /* { .device_id = PCI_DEVICE_ID_VIA_P4M400, // 0x3209 - .chipset = VIA_P4M400, .chipset_name = "PM400", }, */ @@ -453,7 +430,7 @@ static int __init agp_lookup_host_bridge (struct pci_dev *pdev) while (devs[j].chipset_name != NULL) { if (pdev->device == devs[j].device_id) { printk (KERN_INFO PFX "Detected VIA %s chipset\n", devs[j].chipset_name); - agp_bridge->type = devs[j].chipset; + agp_bridge->type = VIA_GENERIC; if (devs[j].chipset_setup != NULL) return devs[j].chipset_setup(pdev); diff --git a/include/linux/agp_backend.h b/include/linux/agp_backend.h index 5154f6a98153..c16f1af37fc9 100644 --- a/include/linux/agp_backend.h +++ b/include/linux/agp_backend.h @@ -53,17 +53,6 @@ enum chipset_type { INTEL_460GX, INTEL_I7505, VIA_GENERIC, - VIA_VP3, - VIA_MVP3, - VIA_MVP4, - VIA_APOLLO_PRO, - VIA_APOLLO_KX133, - VIA_APOLLO_KT133, - VIA_APOLLO_KT400, - VIA_APOLLO_KT400_3, - VIA_APOLLO_PRO_266, - VIA_VT8605, - VIA_P4X, SIS_GENERIC, AMD_GENERIC, AMD_IRONGATE, -- cgit v1.2.3 From 8d49bf3f9d4f6d61f0f759f75e79caaee6dcc6e4 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 10 Feb 2003 00:29:41 -0800 Subject: [PATCH] Fix synchronous writers to wait properly for the result Mikulas Patocka points out a bug in ll_rw_block() usage. Typical usage is: mark_buffer_dirty(bh); ll_rw_block(WRITE, 1, &bh); wait_on_buffer(bh); the problem is that if the buffer was locked on entry to this code sequence (due to in-progress I/O), ll_rw_block() will not wait, and start new I/O. So this code will wait on the _old_ I/O, and will then continue execution, leaving the buffer dirty. It turns out that all callers were only writing one buffer, and they were all waiting on that writeout. So I added a new sync_dirty_buffer() function: void sync_dirty_buffer(struct buffer_head *bh) { lock_buffer(bh); if (test_clear_buffer_dirty(bh)) { get_bh(bh); bh->b_end_io = end_buffer_io_sync; submit_bh(WRITE, bh); } else { unlock_buffer(bh); } } which allowed a fair amount of code to be removed, while adding the desired data-integrity guarantees. UFS has its own wrappers around ll_rw_block() which got in the way, so this operation was open-coded in that case. --- fs/buffer.c | 18 ++++++++++++++++++ fs/ext2/balloc.c | 12 ++++-------- fs/ext2/ialloc.c | 12 ++++-------- fs/ext2/inode.c | 9 +++------ fs/ext2/super.c | 3 +-- fs/ext2/xattr.c | 9 +++------ fs/ext3/super.c | 6 ++---- fs/jbd/commit.c | 3 +-- fs/jbd/journal.c | 8 ++++---- fs/jbd/transaction.c | 6 ++---- fs/jfs/jfs_imap.c | 3 +-- fs/jfs/jfs_mount.c | 3 +-- fs/jfs/namei.c | 6 ++---- fs/jfs/resize.c | 9 +++------ fs/minix/inode.c | 3 +-- fs/ntfs/super.c | 3 +-- fs/qnx4/inode.c | 3 +-- fs/reiserfs/journal.c | 6 ++---- fs/reiserfs/resize.c | 3 +-- fs/sysv/inode.c | 3 +-- fs/sysv/itree.c | 6 ++---- fs/udf/inode.c | 3 +-- fs/ufs/balloc.c | 16 ++++++++-------- fs/ufs/dir.c | 18 ++++++------------ fs/ufs/ialloc.c | 2 ++ fs/ufs/inode.c | 12 ++++-------- fs/ufs/truncate.c | 3 +++ include/linux/buffer_head.h | 1 + include/linux/hfs_sysdep.h | 9 ++------- kernel/ksyms.c | 1 + 30 files changed, 86 insertions(+), 113 deletions(-) (limited to 'include/linux') diff --git a/fs/buffer.c b/fs/buffer.c index bf6ae714c730..b06d6ccc1966 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2618,6 +2618,24 @@ void ll_rw_block(int rw, int nr, struct buffer_head *bhs[]) } } +/* + * For a data-integrity writeout, we need to wait upon any in-progress I/O + * and then start new I/O and then wait upon it. + */ +void sync_dirty_buffer(struct buffer_head *bh) +{ + WARN_ON(atomic_read(&bh->b_count) < 1); + lock_buffer(bh); + if (test_clear_buffer_dirty(bh)) { + get_bh(bh); + bh->b_end_io = end_buffer_io_sync; + submit_bh(WRITE, bh); + wait_on_buffer(bh); + } else { + unlock_buffer(bh); + } +} + /* * Sanity checks for try_to_free_buffers. */ diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index 02c62039d8da..e5bee153791a 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -233,10 +233,8 @@ do_more: } mark_buffer_dirty(bitmap_bh); - if (sb->s_flags & MS_SYNCHRONOUS) { - ll_rw_block(WRITE, 1, &bitmap_bh); - wait_on_buffer(bitmap_bh); - } + if (sb->s_flags & MS_SYNCHRONOUS) + sync_dirty_buffer(bitmap_bh); group_release_blocks(desc, bh2, group_freed); freed += group_freed; @@ -466,10 +464,8 @@ got_block: write_unlock(&EXT2_I(inode)->i_meta_lock); mark_buffer_dirty(bitmap_bh); - if (sb->s_flags & MS_SYNCHRONOUS) { - ll_rw_block(WRITE, 1, &bitmap_bh); - wait_on_buffer(bitmap_bh); - } + if (sb->s_flags & MS_SYNCHRONOUS) + sync_dirty_buffer(bitmap_bh); ext2_debug ("allocating block %d. ", block); diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index bb02b848b77f..aaa58ce59962 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -146,10 +146,8 @@ void ext2_free_inode (struct inode * inode) mark_buffer_dirty(EXT2_SB(sb)->s_sbh); } mark_buffer_dirty(bitmap_bh); - if (sb->s_flags & MS_SYNCHRONOUS) { - ll_rw_block(WRITE, 1, &bitmap_bh); - wait_on_buffer(bitmap_bh); - } + if (sb->s_flags & MS_SYNCHRONOUS) + sync_dirty_buffer(bitmap_bh); sb->s_dirt = 1; error_return: brelse(bitmap_bh); @@ -485,10 +483,8 @@ repeat: ext2_set_bit(i, bitmap_bh->b_data); mark_buffer_dirty(bitmap_bh); - if (sb->s_flags & MS_SYNCHRONOUS) { - ll_rw_block(WRITE, 1, &bitmap_bh); - wait_on_buffer(bitmap_bh); - } + if (sb->s_flags & MS_SYNCHRONOUS) + sync_dirty_buffer(bitmap_bh); brelse(bitmap_bh); ino = group * EXT2_INODES_PER_GROUP(sb) + i + 1; diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index 65e99034fcb6..e47f84e305cd 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -443,10 +443,8 @@ static int ext2_alloc_branch(struct inode *inode, * But we now rely upon generic_osync_inode() * and b_inode_buffers. But not for directories. */ - if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) { - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); - } + if (S_ISDIR(inode->i_mode) && IS_DIRSYNC(inode)) + sync_dirty_buffer(bh); parent = nr; } if (n == num) @@ -1208,8 +1206,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync) raw_inode->i_block[n] = ei->i_data[n]; mark_buffer_dirty(bh); if (do_sync) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); + sync_dirty_buffer(bh); if (buffer_req(bh) && !buffer_uptodate(bh)) { printk ("IO error syncing ext2 inode [%s:%08lx]\n", sb->s_id, (unsigned long) ino); diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 2b0faad8aff4..c608b6f29909 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -842,8 +842,7 @@ static void ext2_sync_super(struct super_block *sb, struct ext2_super_block *es) { es->s_wtime = cpu_to_le32(get_seconds()); mark_buffer_dirty(EXT2_SB(sb)->s_sbh); - ll_rw_block(WRITE, 1, &EXT2_SB(sb)->s_sbh); - wait_on_buffer(EXT2_SB(sb)->s_sbh); + sync_dirty_buffer(EXT2_SB(sb)->s_sbh); sb->s_dirt = 0; } diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index 5a4592b0b7b6..6edc79353c67 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -774,8 +774,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, } mark_buffer_dirty(new_bh); if (IS_SYNC(inode)) { - ll_rw_block(WRITE, 1, &new_bh); - wait_on_buffer(new_bh); + sync_dirty_buffer(new_bh); error = -EIO; if (buffer_req(new_bh) && !buffer_uptodate(new_bh)) goto cleanup; @@ -865,10 +864,8 @@ ext2_xattr_delete_inode(struct inode *inode) HDR(bh)->h_refcount = cpu_to_le32( le32_to_cpu(HDR(bh)->h_refcount) - 1); mark_buffer_dirty(bh); - if (IS_SYNC(inode)) { - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); - } + if (IS_SYNC(inode)) + sync_dirty_buffer(bh); DQUOT_FREE_BLOCK(inode, 1); } EXT2_I(inode)->i_file_acl = 0; diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 3aeb04a1159c..3f92266d6f53 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -1627,10 +1627,8 @@ static void ext3_commit_super (struct super_block * sb, es->s_wtime = cpu_to_le32(get_seconds()); BUFFER_TRACE(EXT3_SB(sb)->s_sbh, "marking dirty"); mark_buffer_dirty(EXT3_SB(sb)->s_sbh); - if (sync) { - ll_rw_block(WRITE, 1, &EXT3_SB(sb)->s_sbh); - wait_on_buffer(EXT3_SB(sb)->s_sbh); - } + if (sync) + sync_dirty_buffer(EXT3_SB(sb)->s_sbh); } diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 12d4a744f07f..b1bb64d1b23f 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -562,8 +562,7 @@ start_journal_io: { struct buffer_head *bh = jh2bh(descriptor); set_buffer_uptodate(bh); - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); __brelse(bh); /* One for getblk() */ journal_unlock_journal_head(descriptor); } diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index a106e23956f7..dd5e16f8c865 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -960,9 +960,10 @@ void journal_update_superblock(journal_t *journal, int wait) BUFFER_TRACE(bh, "marking dirty"); mark_buffer_dirty(bh); - ll_rw_block(WRITE, 1, &bh); if (wait) - wait_on_buffer(bh); + sync_dirty_buffer(bh); + else + ll_rw_block(WRITE, 1, &bh); /* If we have just flushed the log (by marking s_start==0), then * any future commit will have to be careful to update the @@ -1296,8 +1297,7 @@ static int journal_convert_superblock_v1(journal_t *journal, bh = journal->j_sb_buffer; BUFFER_TRACE(bh, "marking dirty"); mark_buffer_dirty(bh); - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); return 0; } diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 14ca5228e9d6..b8333d8afdfe 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1079,8 +1079,7 @@ int journal_dirty_data (handle_t *handle, struct buffer_head *bh) atomic_inc(&bh->b_count); spin_unlock(&journal_datalist_lock); need_brelse = 1; - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); spin_lock(&journal_datalist_lock); /* The buffer may become locked again at any time if it is redirtied */ @@ -1361,8 +1360,7 @@ void journal_sync_buffer(struct buffer_head *bh) } atomic_inc(&bh->b_count); spin_unlock(&journal_datalist_lock); - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); __brelse(bh); goto out; } diff --git a/fs/jfs/jfs_imap.c b/fs/jfs/jfs_imap.c index 598ee5e5fa2f..8a243c1f55b9 100644 --- a/fs/jfs/jfs_imap.c +++ b/fs/jfs/jfs_imap.c @@ -2980,8 +2980,7 @@ static void duplicateIXtree(struct super_block *sb, s64 blkno, j_sb->s_flag |= JFS_BAD_SAIT; mark_buffer_dirty(bh); - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); brelse(bh); return; } diff --git a/fs/jfs/jfs_mount.c b/fs/jfs/jfs_mount.c index c477cdb3ff82..3f2f6ac71f97 100644 --- a/fs/jfs/jfs_mount.c +++ b/fs/jfs/jfs_mount.c @@ -449,8 +449,7 @@ int updateSuper(struct super_block *sb, uint state) } mark_buffer_dirty(bh); - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); brelse(bh); return 0; diff --git a/fs/jfs/namei.c b/fs/jfs/namei.c index 736fd5dc6c04..dd5286bf74b1 100644 --- a/fs/jfs/namei.c +++ b/fs/jfs/namei.c @@ -972,10 +972,8 @@ int jfs_symlink(struct inode *dip, struct dentry *dentry, const char *name) #if 0 set_buffer_uptodate(bp); mark_buffer_dirty(bp, 1); - if (IS_SYNC(dip)) { - ll_rw_block(WRITE, 1, &bp); - wait_on_buffer(bp); - } + if (IS_SYNC(dip)) + sync_dirty_buffer(bp); brelse(bp); #endif /* 0 */ ssize -= copy_size; diff --git a/fs/jfs/resize.c b/fs/jfs/resize.c index 07cde7e7cad8..9da18ef683fd 100644 --- a/fs/jfs/resize.c +++ b/fs/jfs/resize.c @@ -243,8 +243,7 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) /* synchronously update superblock */ mark_buffer_dirty(bh); - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); brelse(bh); /* @@ -512,15 +511,13 @@ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) memcpy(j_sb2, j_sb, sizeof (struct jfs_superblock)); mark_buffer_dirty(bh); - ll_rw_block(WRITE, 1, &bh2); - wait_on_buffer(bh2); + sync_dirty_buffer(bh2); brelse(bh2); } /* write primary superblock */ mark_buffer_dirty(bh); - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); brelse(bh); goto resume; diff --git a/fs/minix/inode.c b/fs/minix/inode.c index a58cf733da35..ec5c8bffed08 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -517,8 +517,7 @@ int minix_sync_inode(struct inode * inode) bh = minix_update_inode(inode); if (bh && buffer_dirty(bh)) { - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); if (buffer_req(bh) && !buffer_uptodate(bh)) { printk ("IO error syncing minix inode [%s:%08lx]\n", diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 55a092114ecd..5361198e1b80 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c @@ -505,8 +505,7 @@ hotfix_primary_boot_sector: memcpy(bh_primary->b_data, bh_backup->b_data, sb->s_blocksize); mark_buffer_dirty(bh_primary); - ll_rw_block(WRITE, 1, &bh_primary); - wait_on_buffer(bh_primary); + sync_dirty_buffer(bh_primary); if (buffer_uptodate(bh_primary)) { brelse(bh_backup); return bh_primary; diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 9da0bfe9a348..caac9561ab80 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -44,8 +44,7 @@ int qnx4_sync_inode(struct inode *inode) bh = qnx4_update_inode(inode); if (bh && buffer_dirty(bh)) { - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); if (buffer_req(bh) && !buffer_uptodate(bh)) { printk ("IO error syncing qnx4 inode [%s:%08lx]\n", diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index ea0ae71a89f2..045247937245 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -735,8 +735,7 @@ reiserfs_panic(s, "journal-539: flush_commit_list: BAD count(%d) > orig_commit_l } mark_buffer_dirty(jl->j_commit_bh) ; - ll_rw_block(WRITE, 1, &(jl->j_commit_bh)) ; - wait_on_buffer(jl->j_commit_bh) ; + sync_dirty_buffer(jl->j_commit_bh) ; if (!buffer_uptodate(jl->j_commit_bh)) { reiserfs_panic(s, "journal-615: buffer write failed\n") ; } @@ -828,8 +827,7 @@ static int _update_journal_header_block(struct super_block *p_s_sb, unsigned lon jh->j_first_unflushed_offset = cpu_to_le32(offset) ; jh->j_mount_id = cpu_to_le32(SB_JOURNAL(p_s_sb)->j_mount_id) ; set_buffer_dirty(SB_JOURNAL(p_s_sb)->j_header_bh) ; - ll_rw_block(WRITE, 1, &(SB_JOURNAL(p_s_sb)->j_header_bh)) ; - wait_on_buffer((SB_JOURNAL(p_s_sb)->j_header_bh)) ; + sync_dirty_buffer(SB_JOURNAL(p_s_sb)->j_header_bh) ; if (!buffer_uptodate(SB_JOURNAL(p_s_sb)->j_header_bh)) { printk( "reiserfs: journal-837: IO error during journal replay\n" ); return -EIO ; diff --git a/fs/reiserfs/resize.c b/fs/reiserfs/resize.c index 7651be142ebf..e5c6bc5aaf36 100644 --- a/fs/reiserfs/resize.c +++ b/fs/reiserfs/resize.c @@ -120,8 +120,7 @@ int reiserfs_resize (struct super_block * s, unsigned long block_count_new) mark_buffer_dirty(bitmap[i].bh) ; set_buffer_uptodate(bitmap[i].bh); - ll_rw_block(WRITE, 1, &bitmap[i].bh); - wait_on_buffer(bitmap[i].bh); + sync_dirty_buffer(bitmap[i].bh); // update bitmap_info stuff bitmap[i].first_zero_hint=1; bitmap[i].free_count = sb_blocksize(sb) * 8 - 1; diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 23bc0fc34ec6..0a8c81d23b71 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -265,8 +265,7 @@ int sysv_sync_inode(struct inode * inode) bh = sysv_update_inode(inode); if (bh && buffer_dirty(bh)) { - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); if (buffer_req(bh) && !buffer_uptodate(bh)) { printk ("IO error syncing sysv inode [%s:%08lx]\n", inode->i_sb->s_id, inode->i_ino); diff --git a/fs/sysv/itree.c b/fs/sysv/itree.c index a1c0b6361351..60b40506748d 100644 --- a/fs/sysv/itree.c +++ b/fs/sysv/itree.c @@ -15,10 +15,8 @@ enum {DIRECT = 10, DEPTH = 4}; /* Have triple indirect */ static inline void dirty_indirect(struct buffer_head *bh, struct inode *inode) { mark_buffer_dirty_inode(bh, inode); - if (IS_SYNC(inode)) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } + if (IS_SYNC(inode)) + sync_dirty_buffer(bh); } static int block_to_path(struct inode *inode, long block, int offsets[DEPTH]) diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 19a6e06cd46e..2fa65ab370d7 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -1520,8 +1520,7 @@ udf_update_inode(struct inode *inode, int do_sync) mark_buffer_dirty(bh); if (do_sync) { - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); + sync_dirty_buffer(bh); if (buffer_req(bh) && !buffer_uptodate(bh)) { printk("IO error syncing udf inode [%s:%08lx]\n", diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index f297d5365744..4209eb7f238d 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -114,6 +114,7 @@ void ufs_free_fragments (struct inode * inode, unsigned fragment, unsigned count ubh_mark_buffer_dirty (USPI_UBH); ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_wait_on_buffer (UCPI_UBH); ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); } @@ -199,6 +200,7 @@ do_more: ubh_mark_buffer_dirty (USPI_UBH); ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_wait_on_buffer (UCPI_UBH); ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); } @@ -228,10 +230,8 @@ failed: memset (bh->b_data, 0, sb->s_blocksize); \ set_buffer_uptodate(bh); \ mark_buffer_dirty (bh); \ - if (IS_SYNC(inode)) { \ - ll_rw_block (WRITE, 1, &bh); \ - wait_on_buffer (bh); \ - } \ + if (IS_SYNC(inode)) \ + sync_dirty_buffer(bh); \ brelse (bh); \ } @@ -364,10 +364,8 @@ unsigned ufs_new_fragments (struct inode * inode, u32 * p, unsigned fragment, clear_buffer_dirty(bh); bh->b_blocknr = result + i; mark_buffer_dirty (bh); - if (IS_SYNC(inode)) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } + if (IS_SYNC(inode)) + sync_dirty_buffer(bh); brelse (bh); } else @@ -459,6 +457,7 @@ unsigned ufs_add_fragments (struct inode * inode, unsigned fragment, ubh_mark_buffer_dirty (USPI_UBH); ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_wait_on_buffer (UCPI_UBH); ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); } @@ -584,6 +583,7 @@ succed: ubh_mark_buffer_dirty (USPI_UBH); ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_wait_on_buffer (UCPI_UBH); ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **)&ucpi); ubh_wait_on_buffer (UCPI_UBH); } diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index 4f87116cfcad..55e81f6b5b83 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -356,10 +356,8 @@ void ufs_set_link(struct inode *dir, struct ufs_dir_entry *de, dir->i_version++; de->d_ino = cpu_to_fs32(dir->i_sb, inode->i_ino); mark_buffer_dirty(bh); - if (IS_DIRSYNC(dir)) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer(bh); - } + if (IS_DIRSYNC(dir)) + sync_dirty_buffer(bh); brelse (bh); } @@ -457,10 +455,8 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) de->d_ino = cpu_to_fs32(sb, inode->i_ino); ufs_set_de_type(sb, de, inode->i_mode); mark_buffer_dirty(bh); - if (IS_DIRSYNC(dir)) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } + if (IS_DIRSYNC(dir)) + sync_dirty_buffer(bh); brelse (bh); dir->i_mtime = dir->i_ctime = CURRENT_TIME; dir->i_version++; @@ -508,10 +504,8 @@ int ufs_delete_entry (struct inode * inode, struct ufs_dir_entry * dir, inode->i_ctime = inode->i_mtime = CURRENT_TIME; mark_inode_dirty(inode); mark_buffer_dirty(bh); - if (IS_DIRSYNC(inode)) { - ll_rw_block(WRITE, 1, &bh); - wait_on_buffer(bh); - } + if (IS_DIRSYNC(inode)) + sync_dirty_buffer(bh); brelse(bh); UFSD(("EXIT\n")) return 0; diff --git a/fs/ufs/ialloc.c b/fs/ufs/ialloc.c index 33080eda3f86..767cb8fbbebf 100644 --- a/fs/ufs/ialloc.c +++ b/fs/ufs/ialloc.c @@ -124,6 +124,7 @@ void ufs_free_inode (struct inode * inode) ubh_mark_buffer_dirty (USPI_UBH); ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_wait_on_buffer (UCPI_UBH); ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **) &ucpi); ubh_wait_on_buffer (UCPI_UBH); } @@ -248,6 +249,7 @@ cg_found: ubh_mark_buffer_dirty (USPI_UBH); ubh_mark_buffer_dirty (UCPI_UBH); if (sb->s_flags & MS_SYNCHRONOUS) { + ubh_wait_on_buffer (UCPI_UBH); ubh_ll_rw_block (WRITE, 1, (struct ufs_buffer_head **) &ucpi); ubh_wait_on_buffer (UCPI_UBH); } diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 615f61a0b88d..442c28e17739 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -298,10 +298,8 @@ repeat: } mark_buffer_dirty(bh); - if (IS_SYNC(inode)) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } + if (IS_SYNC(inode)) + sync_dirty_buffer(bh); inode->i_ctime = CURRENT_TIME; mark_inode_dirty(inode); out: @@ -635,10 +633,8 @@ static int ufs_update_inode(struct inode * inode, int do_sync) memset (ufs_inode, 0, sizeof(struct ufs_inode)); mark_buffer_dirty(bh); - if (do_sync) { - ll_rw_block (WRITE, 1, &bh); - wait_on_buffer (bh); - } + if (do_sync) + sync_dirty_buffer(bh); brelse (bh); UFSD(("EXIT\n")) diff --git a/fs/ufs/truncate.c b/fs/ufs/truncate.c index 636bdbdbf3ce..04e50f696202 100644 --- a/fs/ufs/truncate.c +++ b/fs/ufs/truncate.c @@ -284,6 +284,7 @@ next:; } } if (IS_SYNC(inode) && ind_ubh && ubh_buffer_dirty(ind_ubh)) { + ubh_wait_on_buffer (ind_ubh); ubh_ll_rw_block (WRITE, 1, &ind_ubh); ubh_wait_on_buffer (ind_ubh); } @@ -351,6 +352,7 @@ static int ufs_trunc_dindirect (struct inode * inode, unsigned offset, u32 * p) } } if (IS_SYNC(inode) && dind_bh && ubh_buffer_dirty(dind_bh)) { + ubh_wait_on_buffer (dind_bh); ubh_ll_rw_block (WRITE, 1, &dind_bh); ubh_wait_on_buffer (dind_bh); } @@ -415,6 +417,7 @@ static int ufs_trunc_tindirect (struct inode * inode) } } if (IS_SYNC(inode) && tind_bh && ubh_buffer_dirty(tind_bh)) { + ubh_wait_on_buffer (tind_bh); ubh_ll_rw_block (WRITE, 1, &tind_bh); ubh_wait_on_buffer (tind_bh); } diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index aaefe4e964b7..8def67e47d28 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -169,6 +169,7 @@ struct buffer_head *alloc_buffer_head(void); void free_buffer_head(struct buffer_head * bh); void FASTCALL(unlock_buffer(struct buffer_head *bh)); void ll_rw_block(int, int, struct buffer_head * bh[]); +void sync_dirty_buffer(struct buffer_head *bh); int submit_bh(int, struct buffer_head *); void write_boundary_block(struct block_device *bdev, sector_t bblock, unsigned blocksize); diff --git a/include/linux/hfs_sysdep.h b/include/linux/hfs_sysdep.h index d1e67f3ada14..1468ef02e8b6 100644 --- a/include/linux/hfs_sysdep.h +++ b/include/linux/hfs_sysdep.h @@ -155,13 +155,8 @@ static inline void hfs_buffer_dirty(hfs_buffer buffer) { } static inline void hfs_buffer_sync(hfs_buffer buffer) { - while (buffer_locked(buffer)) { - wait_on_buffer(buffer); - } - if (buffer_dirty(buffer)) { - ll_rw_block(WRITE, 1, &buffer); - wait_on_buffer(buffer); - } + if (buffer_dirty(buffer)) + sync_dirty_buffer(buffer); } static inline void *hfs_buffer_data(const hfs_buffer buffer) { diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 4d7bfe2accde..0f2b487d0789 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -208,6 +208,7 @@ EXPORT_SYMBOL(close_bdev_excl); EXPORT_SYMBOL(__brelse); EXPORT_SYMBOL(__bforget); EXPORT_SYMBOL(ll_rw_block); +EXPORT_SYMBOL(sync_dirty_buffer); EXPORT_SYMBOL(submit_bh); EXPORT_SYMBOL(unlock_buffer); EXPORT_SYMBOL(__wait_on_buffer); -- cgit v1.2.3 From 9bba8dd6763f4584df03f9e41f27adbf66d1416d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 10 Feb 2003 07:35:35 -0800 Subject: [PATCH] uninline get_jiffies_64() for 32-bit architectures uninline get_jiffies_64() for 32-bit architectures --- include/linux/jiffies.h | 18 ++++-------------- kernel/ksyms.c | 3 +++ kernel/time.c | 15 ++++++++++++++- 3 files changed, 21 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 0a60a4f52077..bb1e0128228c 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -15,24 +15,14 @@ extern u64 jiffies_64; extern unsigned long volatile jiffies; +#if (BITS_PER_LONG < 64) +u64 get_jiffies_64(void); +#else static inline u64 get_jiffies_64(void) { -#if BITS_PER_LONG < 64 - extern seqlock_t xtime_lock; - unsigned long seq; - u64 tmp; - - do { - seq = read_seqbegin(&xtime_lock); - tmp = jiffies_64; - } while (read_seqretry(&xtime_lock, seq)); - - return tmp; -#else return (u64)jiffies; -#endif } - +#endif /* * These inlines deal with timer wrapping correctly. You are diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 0f2b487d0789..f0503df9fe3d 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -490,6 +490,9 @@ EXPORT_SYMBOL(xtime); EXPORT_SYMBOL(xtime_lock); EXPORT_SYMBOL(do_gettimeofday); EXPORT_SYMBOL(do_settimeofday); +#if (BITS_PER_LONG < 64) +EXPORT_SYMBOL(get_jiffies_64); +#endif #ifdef CONFIG_DEBUG_SPINLOCK_SLEEP EXPORT_SYMBOL(__might_sleep); #endif diff --git a/kernel/time.c b/kernel/time.c index c8c8a10eae1f..4ecc0a3b2ac1 100644 --- a/kernel/time.c +++ b/kernel/time.c @@ -27,7 +27,6 @@ #include #include #include - #include /* @@ -416,3 +415,17 @@ struct timespec current_kernel_time(void) return now; } + +#if (BITS_PER_LONG < 64) +u64 get_jiffies_64(void) +{ + unsigned long seq; + u64 ret; + + do { + seq = read_seqbegin(&xtime_lock); + ret = jiffies_64; + } while (read_seqretry(&xtime_lock, seq)); + return ret; +} +#endif -- cgit v1.2.3 From 2ac28750c7866b6f75692558cce95a0ab399fe97 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 10 Feb 2003 07:36:00 -0800 Subject: [PATCH] ext3: Remove journal_try_start() journal_try_start() is a function which nonblockingly attempts to open a JBD transaction handle. It was added a long time ago when there were concerns that ext3_writepage() could block kswapd for too long. It was never clearly necessary. So the patch throws it all away and just calls the blocking journal_start() from ext3_writepage(). --- fs/ext3/inode.c | 5 +- fs/jbd/journal.c | 1 - fs/jbd/transaction.c | 117 ++--------------------------------------------- include/linux/ext3_jbd.h | 8 ---- include/linux/jbd.h | 1 - 5 files changed, 4 insertions(+), 128 deletions(-) (limited to 'include/linux') diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 24897acf33da..ca17eb33b07d 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1317,10 +1317,7 @@ static int ext3_writepage(struct page *page, struct writeback_control *wbc) goto out_fail; needed = ext3_writepage_trans_blocks(inode); - if (wbc->for_reclaim) - handle = ext3_journal_try_start(inode, needed); - else - handle = ext3_journal_start(inode, needed); + handle = ext3_journal_start(inode, needed); if (IS_ERR(handle)) { ret = PTR_ERR(handle); diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index dd5e16f8c865..3a8be07f8c7e 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -38,7 +38,6 @@ #include EXPORT_SYMBOL(journal_start); -EXPORT_SYMBOL(journal_try_start); EXPORT_SYMBOL(journal_restart); EXPORT_SYMBOL(journal_extend); EXPORT_SYMBOL(journal_stop); diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index b8333d8afdfe..e5c9b88cb493 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -266,113 +266,6 @@ handle_t *journal_start(journal_t *journal, int nblocks) return handle; } -/* - * Return zero on success - */ -static int try_start_this_handle(journal_t *journal, handle_t *handle) -{ - transaction_t *transaction; - int needed; - int nblocks = handle->h_buffer_credits; - int ret = 0; - - jbd_debug(3, "New handle %p maybe going live.\n", handle); - - lock_journal(journal); - - if (is_journal_aborted(journal) || - (journal->j_errno != 0 && !(journal->j_flags & JFS_ACK_ERR))) { - ret = -EROFS; - goto fail_unlock; - } - - if (journal->j_barrier_count) - goto fail_unlock; - - if (!journal->j_running_transaction && get_transaction(journal, 1) == 0) - goto fail_unlock; - - transaction = journal->j_running_transaction; - if (transaction->t_state == T_LOCKED) - goto fail_unlock; - - needed = transaction->t_outstanding_credits + nblocks; - /* We could run log_start_commit here */ - if (needed > journal->j_max_transaction_buffers) - goto fail_unlock; - - needed = journal->j_max_transaction_buffers; - if (journal->j_committing_transaction) - needed += journal->j_committing_transaction-> - t_outstanding_credits; - - if (log_space_left(journal) < needed) - goto fail_unlock; - - handle->h_transaction = transaction; - transaction->t_outstanding_credits += nblocks; - transaction->t_updates++; - jbd_debug(4, "Handle %p given %d credits (total %d, free %d)\n", - handle, nblocks, transaction->t_outstanding_credits, - log_space_left(journal)); - unlock_journal(journal); - return 0; - -fail_unlock: - unlock_journal(journal); - if (ret >= 0) - ret = -1; - return ret; -} - -/** - * handle_t *journal_try_start() - Don't block, but try and get a handle - * @journal: Journal to start transaction on. - * @nblocks: number of block buffer we might modify - * - * Try to start a handle, but non-blockingly. If we weren't able - * to, return an ERR_PTR value. - */ -handle_t *journal_try_start(journal_t *journal, int nblocks) -{ - handle_t *handle = journal_current_handle(); - int err; - - if (!journal) - return ERR_PTR(-EROFS); - - if (handle) { - jbd_debug(4, "h_ref %d -> %d\n", - handle->h_ref, - handle->h_ref + 1); - J_ASSERT(handle->h_transaction->t_journal == journal); - if (is_handle_aborted(handle)) - return ERR_PTR(-EIO); - handle->h_ref++; - return handle; - } else { - jbd_debug(4, "no current transaction\n"); - } - - if (is_journal_aborted(journal)) - return ERR_PTR(-EIO); - - handle = new_handle(nblocks); - if (!handle) - return ERR_PTR(-ENOMEM); - - current->journal_info = handle; - - err = try_start_this_handle(journal, handle); - if (err < 0) { - kfree(handle); - current->journal_info = NULL; - return ERR_PTR(err); - } - - return handle; -} - /** * int journal_extend() - extend buffer credits. * @handle: handle to 'extend' @@ -1726,13 +1619,6 @@ out: * to be called. We do this if the page is releasable by try_to_free_buffers(). * We also do it if the page has locked or dirty buffers and the caller wants * us to perform sync or async writeout. - */ -int journal_try_to_free_buffers(journal_t *journal, - struct page *page, int unused_gfp_mask) -{ -/* - * journal_try_to_free_buffers(). Try to remove all this page's buffers - * from the journal. * * This complicates JBD locking somewhat. We aren't protected by the * BKL here. We wish to remove the buffer from its committing or @@ -1752,6 +1638,9 @@ int journal_try_to_free_buffers(journal_t *journal, * cannot happen because we never reallocate freed data as metadata * while the data is part of a transaction. Yes? */ +int journal_try_to_free_buffers(journal_t *journal, + struct page *page, int unused_gfp_mask) +{ struct buffer_head *head; struct buffer_head *bh; int ret = 0; diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h index 7ac910d15863..2c75f9f6dab9 100644 --- a/include/linux/ext3_jbd.h +++ b/include/linux/ext3_jbd.h @@ -210,14 +210,6 @@ static inline handle_t *ext3_journal_start(struct inode *inode, int nblocks) return journal_start(journal, nblocks); } -static inline handle_t * -ext3_journal_try_start(struct inode *inode, int nblocks) -{ - if (inode->i_sb->s_flags & MS_RDONLY) - return ERR_PTR(-EROFS); - return journal_try_start(EXT3_JOURNAL(inode), nblocks); -} - /* * The only special thing we need to do here is to make sure that all * journal_stop calls result in the superblock being marked dirty, so diff --git a/include/linux/jbd.h b/include/linux/jbd.h index 2236641f5593..71bec2befafa 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -726,7 +726,6 @@ static inline handle_t *journal_current_handle(void) */ extern handle_t *journal_start(journal_t *, int nblocks); -extern handle_t *journal_try_start(journal_t *, int nblocks); extern int journal_restart (handle_t *, int nblocks); extern int journal_extend (handle_t *, int nblocks); extern int journal_get_write_access (handle_t *, struct buffer_head *); -- cgit v1.2.3 From 01c42c0c7d77157f44bb7429755fdc7198fb30c5 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 10 Feb 2003 07:36:32 -0800 Subject: [PATCH] hugetlbpage MAP_FIXED fix We need to validate that the address and length of a MAP_FIXED request are suitable for hugetlb pages. --- arch/i386/mm/hugetlbpage.c | 12 ++++++++++++ arch/ia64/mm/hugetlbpage.c | 12 ++++++++++++ arch/sparc64/mm/hugetlbpage.c | 12 ++++++++++++ arch/x86_64/mm/hugetlbpage.c | 12 ++++++++++++ include/linux/hugetlb.h | 2 ++ mm/mmap.c | 13 +++++++++++-- 6 files changed, 61 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/mm/hugetlbpage.c b/arch/i386/mm/hugetlbpage.c index 243d844a1a79..749cadb2e5a3 100644 --- a/arch/i386/mm/hugetlbpage.c +++ b/arch/i386/mm/hugetlbpage.c @@ -88,6 +88,18 @@ static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma, struc set_pte(page_table, entry); } +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + return 0; +} + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { diff --git a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c index a08a64c1d39d..c71ed65b5a2d 100644 --- a/arch/ia64/mm/hugetlbpage.c +++ b/arch/ia64/mm/hugetlbpage.c @@ -96,6 +96,18 @@ set_huge_pte (struct mm_struct *mm, struct vm_area_struct *vma, return; } +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + return 0; +} + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { diff --git a/arch/sparc64/mm/hugetlbpage.c b/arch/sparc64/mm/hugetlbpage.c index c137cb8c9d56..63895ce0202f 100644 --- a/arch/sparc64/mm/hugetlbpage.c +++ b/arch/sparc64/mm/hugetlbpage.c @@ -232,6 +232,18 @@ out_error: return -1; } +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + return 0; +} + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) { diff --git a/arch/x86_64/mm/hugetlbpage.c b/arch/x86_64/mm/hugetlbpage.c index f8e146193dc6..e1c31afb196e 100644 --- a/arch/x86_64/mm/hugetlbpage.c +++ b/arch/x86_64/mm/hugetlbpage.c @@ -86,6 +86,18 @@ static void set_huge_pte(struct mm_struct *mm, struct vm_area_struct *vma, struc set_pte(page_table, entry); } +/* + * This function checks for proper alignment of input addr and len parameters. + */ +int is_aligned_hugepage_range(unsigned long addr, unsigned long len) +{ + if (len & ~HPAGE_MASK) + return -EINVAL; + if (addr & ~HPAGE_MASK) + return -EINVAL; + return 0; +} + int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src, struct vm_area_struct *vma) diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 370411eaaba2..7c31efc0b61b 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -26,6 +26,7 @@ struct vm_area_struct *hugepage_vma(struct mm_struct *mm, unsigned long address); struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, pmd_t *pmd, int write); +int is_aligned_hugepage_range(unsigned long addr, unsigned long len); int pmd_huge(pmd_t pmd); extern int htlbpage_max; @@ -56,6 +57,7 @@ static inline int is_vm_hugetlb_page(struct vm_area_struct *vma) #define hugepage_vma(mm, addr) 0 #define mark_mm_hugetlb(mm, vma) do { } while (0) #define follow_huge_pmd(mm, addr, pmd, write) 0 +#define is_aligned_hugepage_range(addr, len) 0 #define pmd_huge(x) 0 #ifndef HPAGE_MASK diff --git a/mm/mmap.c b/mm/mmap.c index 07e2417185ff..7696c40185bd 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -801,6 +801,13 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, return -ENOMEM; if (addr & ~PAGE_MASK) return -EINVAL; + if (is_file_hugepages(file)) { + unsigned long ret; + + ret = is_aligned_hugepage_range(addr, len); + if (ret) + return ret; + } return addr; } @@ -1224,8 +1231,10 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) /* we have start < mpnt->vm_end */ if (is_vm_hugetlb_page(mpnt)) { - if ((start & ~HPAGE_MASK) || (len & ~HPAGE_MASK)) - return -EINVAL; + int ret = is_aligned_hugepage_range(start, len); + + if (ret) + return ret; } /* if it doesn't overlap, we have nothing.. */ -- cgit v1.2.3 From b789ebfca657a1fc77f6bd4dd648c0d5e96057c8 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 10 Feb 2003 07:37:12 -0800 Subject: [PATCH] fix current->user->processes leak Patch from: Eric Lammerts Every time you do a loop mount, a kernel thread is started (those processes are called "loop0", "loop1", etc.). The problem is that when it starts, it's counted as one of your processes. Then, it's changed to be a root-owned process without correcting that count. Patch below fixes the problem. It moves the bookkeeping of changing current->user to a new function switch_uid() (which is now also used by exec_usermodehelper() in kmod.c). The patch is tested. --- include/linux/sched.h | 1 + kernel/exit.c | 2 +- kernel/kmod.c | 10 +--------- kernel/sys.c | 13 ++----------- kernel/user.c | 17 +++++++++++++++++ 5 files changed, 22 insertions(+), 21 deletions(-) (limited to 'include/linux') diff --git a/include/linux/sched.h b/include/linux/sched.h index 16864532fcd9..b99d2eb57a82 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -509,6 +509,7 @@ extern void __set_special_pids(pid_t session, pid_t pgrp); /* per-UID process charging. */ extern struct user_struct * alloc_uid(uid_t); extern void free_uid(struct user_struct *); +extern void switch_uid(struct user_struct *); #include diff --git a/kernel/exit.c b/kernel/exit.c index 729e93bff8e4..de34ed9091f5 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -249,7 +249,7 @@ void reparent_to_init(void) /* signals? */ security_task_reparent_to_init(current); memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim))); - current->user = INIT_USER; + switch_uid(INIT_USER); write_unlock_irq(&tasklist_lock); } diff --git a/kernel/kmod.c b/kernel/kmod.c index 1930367d3736..257634f94652 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c @@ -121,15 +121,7 @@ int exec_usermodehelper(char *program_path, char *argv[], char *envp[]) if (curtask->files->fd[i]) close(i); } - /* Drop the "current user" thing */ - { - struct user_struct *user = curtask->user; - curtask->user = INIT_USER; - atomic_inc(&INIT_USER->__count); - atomic_inc(&INIT_USER->processes); - atomic_dec(&user->processes); - free_uid(user); - } + switch_uid(INIT_USER); /* Give kmod all effective privileges.. */ curtask->euid = curtask->fsuid = 0; diff --git a/kernel/sys.c b/kernel/sys.c index 9404304eba74..dffb67035c78 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -561,19 +561,12 @@ asmlinkage long sys_setgid(gid_t gid) static int set_user(uid_t new_ruid, int dumpclear) { - struct user_struct *new_user, *old_user; + struct user_struct *new_user; - /* What if a process setreuid()'s and this brings the - * new uid over his NPROC rlimit? We can check this now - * cheaply with the new uid cache, so if it matters - * we should be checking for it. -DaveM - */ new_user = alloc_uid(new_ruid); if (!new_user) return -EAGAIN; - old_user = current->user; - atomic_dec(&old_user->processes); - atomic_inc(&new_user->processes); + switch_uid(new_user); if(dumpclear) { @@ -581,8 +574,6 @@ static int set_user(uid_t new_ruid, int dumpclear) wmb(); } current->uid = new_ruid; - current->user = new_user; - free_uid(old_user); return 0; } diff --git a/kernel/user.c b/kernel/user.c index 0704b2aad9c5..592680d8cc68 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -116,6 +116,23 @@ struct user_struct * alloc_uid(uid_t uid) return up; } +void switch_uid(struct user_struct *new_user) +{ + struct user_struct *old_user; + + /* What if a process setreuid()'s and this brings the + * new uid over his NPROC rlimit? We can check this now + * cheaply with the new uid cache, so if it matters + * we should be checking for it. -DaveM + */ + old_user = current->user; + atomic_inc(&new_user->__count); + atomic_inc(&new_user->processes); + atomic_dec(&old_user->processes); + current->user = new_user; + free_uid(old_user); +} + static int __init uid_cache_init(void) { -- cgit v1.2.3