Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S262543AbTE2TbR (ORCPT ); Thu, 29 May 2003 15:31:17 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S262548AbTE2TbR (ORCPT ); Thu, 29 May 2003 15:31:17 -0400 Received: from waste.org ([209.173.204.2]:45009 "EHLO waste.org") by vger.kernel.org with ESMTP id S262543AbTE2TbC (ORCPT ); Thu, 29 May 2003 15:31:02 -0400 Date: Thu, 29 May 2003 14:44:10 -0500 From: Matt Mackall To: Andrew Morton Cc: linux-kernel@vger.kernel.org Subject: [PATCH] write errors [2/3] flags Message-ID: <20030529194410.GZ23715@waste.org> References: <20030514032712.0c7fa0d1.akpm@digeo.com> <20030514171000.GB23380@waste.org> <20030514104455.374b5df6.akpm@digeo.com> <20030529194232.GY23715@waste.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20030529194232.GY23715@waste.org> User-Agent: Mutt/1.3.28i Sender: linux-kernel-owner@vger.kernel.org X-Mailing-List: linux-kernel@vger.kernel.org Combine mapping->error and ->gfp_mask into ->flags diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/drivers/block/loop.c patched/drivers/block/loop.c --- orig/drivers/block/loop.c 2003-05-29 12:49:24.000000000 -0500 +++ patched/drivers/block/loop.c 2003-05-29 12:52:28.000000000 -0500 @@ -714,8 +714,8 @@ fput(file); goto out_putf; } - lo->old_gfp_mask = inode->i_mapping->gfp_mask; - inode->i_mapping->gfp_mask = GFP_NOIO; + lo->old_gfp_mask = mapping_gfp_mask(inode->i_mapping); + mapping_set_gfp_mask(inode->i_mapping, GFP_NOIO); set_blocksize(bdev, lo_blocksize); @@ -823,7 +823,7 @@ memset(lo->lo_name, 0, LO_NAME_SIZE); invalidate_bdev(bdev, 0); set_capacity(disks[lo->lo_number], 0); - filp->f_dentry->d_inode->i_mapping->gfp_mask = gfp; + mapping_set_gfp_mask(filp->f_dentry->d_inode->i_mapping, gfp); lo->lo_state = Lo_unbound; fput(filp); /* This is safe: open() is still holding a reference. */ diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/fs/block_dev.c patched/fs/block_dev.c --- orig/fs/block_dev.c 2003-05-29 12:49:42.000000000 -0500 +++ patched/fs/block_dev.c 2003-05-29 12:52:28.000000000 -0500 @@ -318,7 +318,7 @@ inode->i_rdev = kdev; inode->i_bdev = new_bdev; inode->i_data.a_ops = &def_blk_aops; - inode->i_data.gfp_mask = GFP_USER; + mapping_set_gfp_mask(&inode->i_data, GFP_USER); inode->i_data.backing_dev_info = &default_backing_dev_info; spin_lock(&bdev_lock); bdev = bdfind(dev, head); diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/fs/buffer.c patched/fs/buffer.c --- orig/fs/buffer.c 2003-05-29 12:52:33.000000000 -0500 +++ patched/fs/buffer.c 2003-05-29 12:52:28.000000000 -0500 @@ -600,7 +600,7 @@ buffer_io_error(bh); printk(KERN_WARNING "lost page write due to I/O error on %s\n", bdevname(bh->b_bdev, b)); - page->mapping->error = -EIO; + set_bit(AS_EIO, &page->mapping->flags); clear_buffer_uptodate(bh); SetPageError(page); } @@ -2846,7 +2846,7 @@ do { check_ttfb_buffer(page, bh); if (buffer_write_io_error(bh)) - page->mapping->error = -EIO; + set_bit(AS_EIO, &page->mapping->flags); if (buffer_busy(bh)) goto failed; if (!buffer_uptodate(bh) && !buffer_req(bh)) diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/fs/inode.c patched/fs/inode.c --- orig/fs/inode.c 2003-05-29 12:52:33.000000000 -0500 +++ patched/fs/inode.c 2003-05-29 12:53:07.000000000 -0500 @@ -18,6 +18,7 @@ #include #include #include +#include #include /* @@ -142,11 +143,11 @@ mapping->a_ops = &empty_aops; mapping->host = inode; - mapping->gfp_mask = GFP_HIGHUSER; + mapping->flags = 0; + mapping_set_gfp_mask(mapping, GFP_HIGHUSER); mapping->dirtied_when = 0; mapping->assoc_mapping = NULL; mapping->backing_dev_info = &default_backing_dev_info; - mapping->error = 0; if (sb->s_bdev) mapping->backing_dev_info = sb->s_bdev->bd_inode->i_mapping->backing_dev_info; memset(&inode->u, 0, sizeof(inode->u)); diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/fs/jfs/inode.c patched/fs/jfs/inode.c --- orig/fs/jfs/inode.c 2003-04-19 21:48:46.000000000 -0500 +++ patched/fs/jfs/inode.c 2003-05-29 12:52:28.000000000 -0500 @@ -20,6 +20,7 @@ #include #include #include +#include #include "jfs_incore.h" #include "jfs_filsys.h" #include "jfs_imap.h" @@ -57,7 +58,7 @@ inode->i_op = &jfs_dir_inode_operations; inode->i_fop = &jfs_dir_operations; inode->i_mapping->a_ops = &jfs_aops; - inode->i_mapping->gfp_mask = GFP_NOFS; + mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS); } else if (S_ISLNK(inode->i_mode)) { if (inode->i_size >= IDATASIZE) { inode->i_op = &page_symlink_inode_operations; diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/fs/jfs/jfs_imap.c patched/fs/jfs/jfs_imap.c --- orig/fs/jfs/jfs_imap.c 2003-04-19 21:48:53.000000000 -0500 +++ patched/fs/jfs/jfs_imap.c 2003-05-29 12:52:28.000000000 -0500 @@ -43,6 +43,7 @@ #include #include +#include #include "jfs_incore.h" #include "jfs_filsys.h" @@ -504,7 +505,7 @@ } ip->i_mapping->a_ops = &jfs_aops; - ip->i_mapping->gfp_mask = GFP_NOFS; + mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS); if ((inum == FILESYSTEM_I) && (JFS_IP(ip)->ipimap == sbi->ipaimap)) { sbi->gengen = le32_to_cpu(dp->di_gengen); diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/fs/jfs/namei.c patched/fs/jfs/namei.c --- orig/fs/jfs/namei.c 2003-04-19 21:50:35.000000000 -0500 +++ patched/fs/jfs/namei.c 2003-05-29 12:52:28.000000000 -0500 @@ -257,7 +257,7 @@ ip->i_op = &jfs_dir_inode_operations; ip->i_fop = &jfs_dir_operations; ip->i_mapping->a_ops = &jfs_aops; - ip->i_mapping->gfp_mask = GFP_NOFS; + mapping_set_gfp_mask(ip->i_mapping, GFP_NOFS); insert_inode_hash(ip); mark_inode_dirty(ip); diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/fs/mpage.c patched/fs/mpage.c --- orig/fs/mpage.c 2003-05-29 12:52:33.000000000 -0500 +++ patched/fs/mpage.c 2003-05-29 12:52:28.000000000 -0500 @@ -570,8 +570,12 @@ * mapping. */ lock_page(page); - if (page->mapping == mapping) - mapping->error = *ret; + if (page->mapping == mapping) { + if (*ret == -EIO) + set_bit(AS_EIO, &mapping->flags); + else if (*ret == -ENOSPC) + set_bit(AS_ENOSPC, &mapping->flags); + } unlock_page(page); } out: @@ -684,8 +688,12 @@ * mapping. */ lock_page(page); - if (page->mapping == mapping) - mapping->error = ret; + if (page->mapping == mapping) { + if (ret == -EIO) + set_bit(AS_EIO, &mapping->flags); + else if (ret == -ENOSPC) + set_bit(AS_ENOSPC, &mapping->flags); + } unlock_page(page); } } else { diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/fs/open.c patched/fs/open.c --- orig/fs/open.c 2003-05-29 12:52:33.000000000 -0500 +++ patched/fs/open.c 2003-05-29 12:52:28.000000000 -0500 @@ -20,6 +20,7 @@ #include #include #include +#include #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m)) @@ -852,11 +853,10 @@ retval = err; } - err = mapping->error; - if (err && !retval) { - mapping->error = 0; - retval = err; - } + if (test_and_clear_bit(AS_ENOSPC, &mapping->flags)) + retval = -ENOSPC; + if (test_and_clear_bit(AS_EIO, &mapping->flags)) + retval = -EIO; if (!file_count(filp)) { printk(KERN_ERR "VFS: Close: file count is 0\n"); diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/include/linux/fs.h patched/include/linux/fs.h --- orig/include/linux/fs.h 2003-05-29 12:52:33.000000000 -0500 +++ patched/include/linux/fs.h 2003-05-29 12:52:28.000000000 -0500 @@ -324,12 +324,11 @@ struct list_head i_mmap_shared; /* list of shared mappings */ struct semaphore i_shared_sem; /* protect both above lists */ unsigned long dirtied_when; /* jiffies of first page dirtying */ - int gfp_mask; /* how to allocate the pages */ + unsigned long flags; /* error bits/gfp mask */ struct backing_dev_info *backing_dev_info; /* device readahead, etc */ spinlock_t private_lock; /* for use by the address_space */ struct list_head private_list; /* ditto */ struct address_space *assoc_mapping; /* ditto */ - int error; /* write error for fsync */ }; struct block_device { diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/include/linux/gfp.h patched/include/linux/gfp.h --- orig/include/linux/gfp.h 2003-05-12 14:34:35.000000000 -0500 +++ patched/include/linux/gfp.h 2003-05-29 12:52:28.000000000 -0500 @@ -33,6 +33,9 @@ #define __GFP_NORETRY 0x1000 /* Do not retry. Might fail */ #define __GFP_NO_GROW 0x2000 /* Slab internal usage */ +#define __GFP_BITS_SHIFT 16 /* Room for 16 __GFP_FOO bits */ +#define __GFP_BITS_MASK ((1 << __GFP_BITS_SHIFT) - 1) + #define GFP_ATOMIC (__GFP_HIGH) #define GFP_NOIO (__GFP_WAIT) #define GFP_NOFS (__GFP_WAIT | __GFP_IO) diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/include/linux/pagemap.h patched/include/linux/pagemap.h --- orig/include/linux/pagemap.h 2003-05-29 12:52:33.000000000 -0500 +++ patched/include/linux/pagemap.h 2003-05-29 12:52:28.000000000 -0500 @@ -8,7 +8,30 @@ #include #include #include +#include #include +#include + +/* + * Bits in mapping->flags. The lower __GFP_BITS_SHIFT bits are the page + * allocation mode flags. + */ +#define AS_EIO (__GFP_BITS_SHIFT + 0) /* IO error on async write */ +#define AS_ENOSPC (__GFP_BITS_SHIFT + 1) /* ENOSPC on async write */ + +static inline int mapping_gfp_mask(struct address_space * mapping) +{ + return mapping->flags & __GFP_BITS_MASK; +} + +/* + * This is non-atomic. Only to be used before the mapping is activated. + * Probably needs a barrier... + */ +static inline void mapping_set_gfp_mask(struct address_space *m, int mask) +{ + m->flags = (m->flags & ~__GFP_BITS_MASK) | mask; +} /* * The page cache can done in larger chunks than @@ -29,12 +52,12 @@ static inline struct page *page_cache_alloc(struct address_space *x) { - return alloc_pages(x->gfp_mask, 0); + return alloc_pages(mapping_gfp_mask(x), 0); } static inline struct page *page_cache_alloc_cold(struct address_space *x) { - return alloc_pages(x->gfp_mask|__GFP_COLD, 0); + return alloc_pages(mapping_gfp_mask(x)|__GFP_COLD, 0); } typedef int filler_t(void *, struct page *); @@ -56,7 +79,7 @@ */ static inline struct page *grab_cache_page(struct address_space *mapping, unsigned long index) { - return find_or_create_page(mapping, index, mapping->gfp_mask); + return find_or_create_page(mapping, index, mapping_gfp_mask(mapping)); } extern struct page * grab_cache_page_nowait(struct address_space *mapping, diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/mm/filemap.c patched/mm/filemap.c --- orig/mm/filemap.c 2003-05-29 12:52:33.000000000 -0500 +++ patched/mm/filemap.c 2003-05-29 12:52:28.000000000 -0500 @@ -201,11 +201,10 @@ spin_unlock(&mapping->page_lock); /* Check for outstanding write errors */ - if (mapping->error) - { - ret = mapping->error; - mapping->error = 0; - } + if (test_and_clear_bit(AS_ENOSPC, &mapping->flags)) + ret = -ENOSPC; + if (test_and_clear_bit(AS_EIO, &mapping->flags)) + ret = -EIO; return ret; } @@ -591,7 +590,7 @@ page_cache_release(page); return NULL; } - gfp_mask = mapping->gfp_mask & ~__GFP_FS; + gfp_mask = mapping_gfp_mask(mapping) & ~__GFP_FS; page = alloc_pages(gfp_mask, 0); if (page && add_to_page_cache_lru(page, mapping, index, gfp_mask)) { page_cache_release(page); diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/mm/shmem.c patched/mm/shmem.c --- orig/mm/shmem.c 2003-05-29 12:49:55.000000000 -0500 +++ patched/mm/shmem.c 2003-05-29 12:52:28.000000000 -0500 @@ -318,7 +318,7 @@ spin_unlock(&sbinfo->stat_lock); spin_unlock(&info->lock); - page = shmem_dir_alloc(inode->i_mapping->gfp_mask); + page = shmem_dir_alloc(mapping_gfp_mask(inode->i_mapping)); if (page) { clear_highpage(page); page->nr_swapped = 0; diff -urN -x genksyms -x '*.ver' -x '.patch*' -x '*.orig' orig/mm/vmscan.c patched/mm/vmscan.c --- orig/mm/vmscan.c 2003-05-29 12:52:34.000000000 -0500 +++ patched/mm/vmscan.c 2003-05-29 12:52:28.000000000 -0500 @@ -347,13 +347,14 @@ * mapping. */ lock_page(page); - if (page->mapping == mapping) - mapping->error = res; + if (page->mapping == mapping) { + if (res == -EIO) + set_bit(AS_EIO, &mapping->flags); + else if (res == -ENOSPC) + set_bit(AS_ENOSPC, &mapping->flags); + } unlock_page(page); } - if (res < 0) { - mapping->error = res; - } if (res == WRITEPAGE_ACTIVATE) { ClearPageReclaim(page); goto activate_locked; -- Matt Mackall : http://www.selenic.com : of or relating to the moon - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/