From mboxrd@z Thu Jan 1 00:00:00 1970 From: wcheng@sourceware.org Date: 17 Oct 2006 19:02:36 -0000 Subject: [Cluster-devel] cluster/gfs-kernel/src/gfs dir.c file.c file.h ... Message-ID: <20061017190236.16046.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: cluster Changes by: wcheng at sourceware.org 2006-10-17 19:02:35 Modified files: gfs-kernel/src/gfs: dir.c file.c file.h ioctl.c ops_file.c Log message: Port RHEL4 GFS AIO (asynchronous IO) implementation into RHEL5/FC6 and community-version of GFS1. Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/dir.c.diff?cvsroot=cluster&r1=1.13&r2=1.14 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/file.c.diff?cvsroot=cluster&r1=1.8&r2=1.9 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/file.h.diff?cvsroot=cluster&r1=1.4&r2=1.5 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ioctl.c.diff?cvsroot=cluster&r1=1.12&r2=1.13 http://sourceware.org/cgi-bin/cvsweb.cgi/cluster/gfs-kernel/src/gfs/ops_file.c.diff?cvsroot=cluster&r1=1.25&r2=1.26 --- cluster/gfs-kernel/src/gfs/dir.c 2006/07/10 23:22:34 1.13 +++ cluster/gfs-kernel/src/gfs/dir.c 2006/10/17 19:02:35 1.14 @@ -2210,7 +2210,7 @@ dip->i_di.di_blocks--; } - error = gfs_writei(dip, ht, index * sizeof (uint64_t), size, gfs_zero_blocks); + error = gfs_writei(dip, ht, index * sizeof (uint64_t), size, gfs_zero_blocks, NULL); if (error != size) { if (error >= 0) --- cluster/gfs-kernel/src/gfs/file.c 2006/07/10 23:22:34 1.8 +++ cluster/gfs-kernel/src/gfs/file.c 2006/10/17 19:02:35 1.9 @@ -306,7 +306,8 @@ int gfs_writei(struct gfs_inode *ip, void *buf, uint64_t offset, unsigned int size, - write_copy_fn_t copy_fn) + write_copy_fn_t copy_fn, + struct kiocb *iocb) { struct gfs_sbd *sdp = ip->i_sbd; struct buffer_head *dibh, *bh; --- cluster/gfs-kernel/src/gfs/file.h 2006/07/10 23:22:34 1.4 +++ cluster/gfs-kernel/src/gfs/file.h 2006/10/17 19:02:35 1.5 @@ -32,7 +32,8 @@ int gfs_copy_from_user(struct gfs_inode *ip, struct buffer_head *bh, void **buf, unsigned int offset, unsigned int size, int new); int gfs_writei(struct gfs_inode *ip, void *buf, uint64_t offset, - unsigned int size, write_copy_fn_t copy_fn); + unsigned int size, write_copy_fn_t copy_fn, + struct kiocb *iocb); int gfs_zero_blocks(struct gfs_inode *ip, struct buffer_head *bh, void **buf, unsigned int offset, unsigned int size, int new); @@ -48,7 +49,7 @@ gfs_internal_write(struct gfs_inode *ip, char *buf, uint64_t offset, unsigned int size) { - return gfs_writei(ip, buf, offset, size, gfs_copy_from_mem); + return gfs_writei(ip, buf, offset, size, gfs_copy_from_mem, NULL); } #endif /* __FILE_DOT_H__ */ --- cluster/gfs-kernel/src/gfs/ioctl.c 2006/08/11 14:32:32 1.12 +++ cluster/gfs-kernel/src/gfs/ioctl.c 2006/10/17 19:02:35 1.13 @@ -1229,7 +1229,7 @@ } error = gfs_writei(ip, gi->gi_data, gi->gi_offset, gi->gi_size, - gfs_copy_from_user); + gfs_copy_from_user, NULL); gfs_trans_end(sdp); --- cluster/gfs-kernel/src/gfs/ops_file.c 2006/08/11 14:32:32 1.25 +++ cluster/gfs-kernel/src/gfs/ops_file.c 2006/10/17 19:02:35 1.26 @@ -23,6 +23,7 @@ #include #include #include +#include #include #include "gfs_ioctl.h" @@ -76,6 +77,7 @@ typedef ssize_t(*do_rw_t) (struct file * file, char *buf, size_t size, loff_t * offset, + struct kiocb *iocb, unsigned int num_gh, struct gfs_holder * ghs); /** @@ -129,7 +131,7 @@ static ssize_t walk_vm_hard(struct file *file, char *buf, size_t size, loff_t *offset, - do_rw_t operation) + struct kiocb *iocb, do_rw_t operation) { struct gfs_holder *ghs; unsigned int num_gh = 0; @@ -178,7 +180,7 @@ gfs_assert(get_v2sdp(sb), x == num_gh,); } - count = operation(file, buf, size, offset, num_gh, ghs); + count = operation(file, buf, size, offset, iocb, num_gh, ghs); while (num_gh--) gfs_holder_uninit(&ghs[num_gh]); @@ -204,6 +206,7 @@ static ssize_t walk_vm(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb, do_rw_t operation) { if (current->mm) { @@ -231,11 +234,11 @@ { struct gfs_holder gh; - return operation(file, buf, size, offset, 0, &gh); + return operation(file, buf, size, offset, iocb, 0, &gh); } do_locks: - return walk_vm_hard(file, buf, size, offset, operation); + return walk_vm_hard(file, buf, size, offset, iocb, operation); } /** @@ -250,7 +253,8 @@ */ static ssize_t -do_read_readi(struct file *file, char *buf, size_t size, loff_t *offset) +do_read_readi(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb) { struct gfs_inode *ip = get_v2ip(file->f_mapping->host); ssize_t count = 0; @@ -267,6 +271,8 @@ size = 0x7FFFFFFFull - *offset; } + /* ToDo: not sure about iocb .. wcheng + */ count = gfs_readi(ip, buf, *offset, size, gfs_copy2user); if (count > 0) @@ -291,7 +297,8 @@ static ssize_t do_read_direct(struct file *file, char *buf, size_t size, loff_t *offset, - unsigned int num_gh, struct gfs_holder *ghs) + struct kiocb *iocb, + unsigned int num_gh, struct gfs_holder *ghs) { struct inode *inode = file->f_mapping->host; struct gfs_inode *ip = get_v2ip(inode); @@ -324,10 +331,16 @@ if (((*offset) & mask) || (((unsigned long)buf) & mask)) goto out_gunlock; - count = do_read_readi(file, buf, size & ~mask, offset); + count = do_read_readi(file, buf, size & ~mask, offset, iocb); + } + else { + if (!iocb) + count = generic_file_read(file, buf, size, offset); + else { + struct iovec local_iov = { .iov_base = buf, .iov_len = size}; + count = __generic_file_aio_read(iocb, &local_iov, 1, offset); + } } - else - count = generic_file_read(file, buf, size, offset); error = 0; @@ -356,7 +369,8 @@ static ssize_t do_read_buf(struct file *file, char *buf, size_t size, loff_t *offset, - unsigned int num_gh, struct gfs_holder *ghs) + struct kiocb *iocb, + unsigned int num_gh, struct gfs_holder *ghs) { struct gfs_inode *ip = get_v2ip(file->f_mapping->host); ssize_t count = 0; @@ -370,9 +384,22 @@ if (gfs_is_jdata(ip) || (gfs_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags))) - count = do_read_readi(file, buf, size, offset); - else - count = generic_file_read(file, buf, size, offset); + count = do_read_readi(file, buf, size, offset, iocb); + else { + if (!iocb) { + count = generic_file_read(file, buf, size, offset); + } else { + struct iovec local_iov = { + .iov_base = (char __user *)buf, + .iov_len = size + }; + + count = __generic_file_aio_read(iocb, + &local_iov, 1, offset); + if (count == -EIOCBQUEUED) + count = wait_on_sync_kiocb(iocb); + } + } gfs_glock_dq_m(num_gh + 1, ghs); @@ -382,6 +409,17 @@ return (count) ? count : error; } +static ssize_t +__gfs_read(struct file *file, char *buf, size_t size, loff_t *offset, struct kiocb *iocb) +{ + atomic_inc(&get_v2sdp(file->f_mapping->host->i_sb)->sd_ops_file); + + if (file->f_flags & O_DIRECT) + return walk_vm(file, buf, size, offset, iocb, do_read_direct); + else + return walk_vm(file, buf, size, offset, iocb, do_read_buf); +} + /** * gfs_read - Read bytes from a file * @file: The file to read from @@ -397,12 +435,20 @@ static ssize_t gfs_read(struct file *file, char *buf, size_t size, loff_t *offset) { - atomic_inc(&get_v2sdp(file->f_mapping->host->i_sb)->sd_ops_file); + return(__gfs_read(file, buf, size, offset, NULL)); +} - if (file->f_flags & O_DIRECT) - return walk_vm(file, buf, size, offset, do_read_direct); - else - return walk_vm(file, buf, size, offset, do_read_buf); +/* + * gfs_aio_read: match with vfs generic_file_aio_read as: + * (struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) + */ +static ssize_t +gfs_aio_read(struct kiocb *iocb, char __user *buf, size_t count, loff_t pos) +{ + struct file *filp = iocb->ki_filp; + + BUG_ON(iocb->ki_pos != pos); + return(__gfs_read(filp, buf, count, &iocb->ki_pos, iocb)); } /** @@ -449,7 +495,8 @@ */ static ssize_t -do_write_direct_alloc(struct file *file, char *buf, size_t size, loff_t *offset) +do_write_direct_alloc(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb) { struct inode *inode = file->f_mapping->host; struct gfs_inode *ip = get_v2ip(inode); @@ -502,13 +549,15 @@ brelse(dibh); } - if (gfs_is_stuffed(ip)) { - error = gfs_unstuff_dinode(ip, gfs_unstuffer_sync, NULL); - if (error) + if (gfs_is_stuffed(ip)) { error = gfs_unstuff_dinode(ip, gfs_unstuffer_sync, NULL); if (error) goto fail_end_trans; } - count = generic_file_write_nolock(file, &local_iov, 1, offset); + if (!iocb) + count = generic_file_write_nolock(file, &local_iov, 1, offset); + else { + count = generic_file_aio_write_nolock(iocb, &local_iov, 1, offset); + } if (count < 0) { error = count; goto fail_end_trans; @@ -528,6 +577,10 @@ gfs_trans_end(sdp); + /* Question (wcheng) + * 1. should IS_SYNC flush glock ? + * 2. does gfs_log_flush_glock flush data ? + */ if (file->f_flags & O_SYNC) gfs_log_flush_glock(ip->i_gl); @@ -576,6 +629,7 @@ static ssize_t do_write_direct(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb, unsigned int num_gh, struct gfs_holder *ghs) { struct gfs_inode *ip = get_v2ip(file->f_mapping->host); @@ -652,7 +706,7 @@ if (s > size) s = size; - error = do_write_direct_alloc(file, buf, s, offset); + error = do_write_direct_alloc(file, buf, s, offset, iocb); if (error < 0) goto out_gunlock; @@ -670,8 +724,16 @@ if (error) goto out_gunlock; - count = generic_file_write_nolock(file, &local_iov, 1, offset); - + /* Todo: It would be nice if init_sync_kiocb is exported. + * .. wcheng + */ + if (!iocb) + count = + generic_file_write_nolock(file, &local_iov, 1, offset); + else { + count = + generic_file_aio_write_nolock(iocb, &local_iov, 1, offset); + } gfs_glock_dq_uninit(&t_gh); } @@ -699,7 +761,8 @@ */ static ssize_t -do_do_write_buf(struct file *file, char *buf, size_t size, loff_t *offset) +do_do_write_buf(struct file *file, char *buf, size_t size, loff_t *offset, + struct kiocb *iocb) { struct inode *inode = file->f_mapping->host; struct gfs_inode *ip = get_v2ip(inode); @@ -777,7 +840,7 @@ (gfs_is_stuffed(ip) && !test_bit(GIF_PAGED, &ip->i_flags) && *offset + size <= sdp->sd_sb.sb_bsize - sizeof(struct gfs_dinode))) { - count = gfs_writei(ip, buf, *offset, size, gfs_copy_from_user); + count = gfs_writei(ip, buf, *offset, size, gfs_copy_from_user, iocb); if (count < 0) { error = count; goto fail_end_trans; @@ -794,7 +857,14 @@ } else { struct iovec local_iov = { .iov_base = buf, .iov_len = size }; - count = generic_file_write_nolock(file, &local_iov, 1, offset); + if (!iocb) { + count = generic_file_write_nolock(file, &local_iov, 1, offset); + } else { + count = generic_file_aio_write_nolock(iocb, + &local_iov, 1, offset); + if (count == -EIOCBQUEUED) + count = wait_on_sync_kiocb(iocb); + } if (count < 0) { error = count; goto fail_end_trans; @@ -869,8 +939,9 @@ static ssize_t do_write_buf(struct file *file, - char *buf, size_t size, loff_t *offset, - unsigned int num_gh, struct gfs_holder *ghs) + char *buf, size_t size, loff_t *offset, + struct kiocb *iocb, + unsigned int num_gh, struct gfs_holder *ghs) { struct gfs_inode *ip = get_v2ip(file->f_mapping->host); struct gfs_sbd *sdp = ip->i_sbd; @@ -907,7 +978,7 @@ if (s > size) s = size; - error = do_do_write_buf(file, buf, s, offset); + error = do_do_write_buf(file, buf, s, offset, iocb); if (error < 0) goto out_gunlock; @@ -940,7 +1011,7 @@ */ static ssize_t -gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset) +__gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset, struct kiocb *iocb) { struct inode *inode = file->f_mapping->host; ssize_t count; @@ -954,14 +1025,30 @@ mutex_lock(&inode->i_mutex); if (file->f_flags & O_DIRECT) - count = walk_vm(file, (char *)buf, size, offset, do_write_direct); + count = walk_vm(file, (char *)buf, size, offset, iocb, do_write_direct); else - count = walk_vm(file, (char *)buf, size, offset, do_write_buf); + count = walk_vm(file, (char *)buf, size, offset, iocb, do_write_buf); mutex_unlock(&inode->i_mutex); return count; } +static ssize_t +gfs_write(struct file *file, const char *buf, size_t size, loff_t *offset) +{ + return(__gfs_write(file, buf, size, offset, NULL)); +} + +static ssize_t +gfs_aio_write(struct kiocb *iocb, const char __user *buf, size_t size, loff_t pos) +{ + struct file *file = iocb->ki_filp; + + BUG_ON(iocb->ki_pos != pos); + + return(__gfs_write(file, buf, size, &iocb->ki_pos, iocb)); +} + /** * filldir_reg_func - Report a directory entry to the caller of gfs_dir_read() * @opaque: opaque data used by the function @@ -1642,6 +1729,8 @@ .llseek = gfs_llseek, .read = gfs_read, .write = gfs_write, + .aio_read = gfs_aio_read, + .aio_write = gfs_aio_write, .ioctl = gfs_ioctl, .mmap = gfs_mmap, .open = gfs_open,