From mboxrd@z Thu Jan 1 00:00:00 1970 From: Christoph Hellwig Subject: [PATCH] i_sem-less generic_file_write for O_DIRECT & XFS (1st resend) Date: Mon, 12 Aug 2002 20:10:08 +0200 Sender: linux-fsdevel-owner@vger.kernel.org Message-ID: <20020812201008.A26136@lst.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Cc: linux-fsdevel@vger.kernel.org Return-path: To: torvalds@transmeta.com Content-Disposition: inline List-Id: linux-fsdevel.vger.kernel.org [grr, silly address typo when tried first..] There are a number of places where generic_file_write could be used if it didn't take i_sem by itself or where it doesn't need it: (1) XFS needs to do some preparation in it's write file operation (most notably taking it's own per-inode locks), after taking i_sem, but before calling the guts of generic_file_write. (2) blockdevices are happy with parralel get_block() operations, and there is nothing i_sem could protect. This patch introduces a generic_file_write_nolock and makes the good old generic_file_write a wrapper around. The block device code is switched over to it. --- linux-2.5/fs/block_dev.c Mon Aug 5 19:32:56 2002 +++ linux-2.5-xfs/fs/block_dev.c Thu Aug 8 22:10:51 2002 @@ -792,7 +792,7 @@ release: blkdev_close, llseek: block_llseek, read: generic_file_read, - write: generic_file_write, + write: generic_file_write_nolock, mmap: generic_file_mmap, fsync: block_fsync, ioctl: blkdev_ioctl, --- linux-2.5/kernel/ksyms.c Thu Aug 8 22:22:26 2002 +++ linux-2.5-xfs/kernel/ksyms.c Thu Aug 8 18:52:45 2002 @@ -219,6 +219,7 @@ EXPORT_SYMBOL(generic_file_sendfile); EXPORT_SYMBOL(do_generic_file_read); EXPORT_SYMBOL(generic_file_write); +EXPORT_SYMBOL(generic_file_write_nolock); EXPORT_SYMBOL(generic_file_mmap); EXPORT_SYMBOL(generic_ro_fops); EXPORT_SYMBOL(file_lock_list); --- linux-2.5/include/linux/fs.h Mon Aug 5 19:33:54 2002 +++ linux-2.5-xfs/include/linux/fs.h Thu Aug 8 19:07:13 2002 @@ -1239,6 +1239,7 @@ extern int file_read_actor(read_descriptor_t * desc, struct page *page, unsigned long offset, unsigned long size); extern ssize_t generic_file_read(struct file *, char *, size_t, loff_t *); extern ssize_t generic_file_write(struct file *, const char *, size_t, loff_t *); +extern ssize_t generic_file_write_nolock(struct file *, const char *, size_t, loff_t *); extern ssize_t generic_file_sendfile(struct file *, struct file *, loff_t *, size_t); extern void do_generic_file_read(struct file *, loff_t *, read_descriptor_t *, read_actor_t); ssize_t generic_file_direct_IO(int rw, struct inode *inode, char *buf, --- linux-2.5/mm/filemap.c Mon Aug 5 19:34:06 2002 +++ linux-2.5-xfs/mm/filemap.c Thu Aug 8 19:06:53 2002 @@ -1821,9 +1821,8 @@ * it for writing by marking it dirty. * okir@monad.swb.de */ -ssize_t -generic_file_write(struct file *file, const char *buf, - size_t count, loff_t *ppos) +ssize_t generic_file_write_nolock(struct file *file, const char *buf, + size_t count, loff_t *ppos) { struct address_space * mapping = file->f_dentry->d_inode->i_mapping; struct address_space_operations *a_ops = mapping->a_ops; @@ -1838,18 +1837,15 @@ unsigned bytes; time_t time_now; - if (unlikely((ssize_t) count < 0)) + if (unlikely((ssize_t)count < 0)) return -EINVAL; if (unlikely(!access_ok(VERIFY_READ, buf, count))) return -EFAULT; - down(&inode->i_sem); pos = *ppos; - if (unlikely(pos < 0)) { - err = -EINVAL; - goto out; - } + if (unlikely(pos < 0)) + return -EINVAL; if (unlikely(file->f_error)) { err = file->f_error; @@ -2046,6 +2042,18 @@ out_status: err = written ? written : status; out: + return err; +} + +ssize_t generic_file_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + struct inode *inode = file->f_dentry->d_inode->i_mapping->host; + int err; + + down(&inode->i_sem); + err = generic_file_write_nolock(file, buf, count, ppos); up(&inode->i_sem); + return err; }