Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 834840 Details for
Bug 850426
gfs2: Add xgetdents syscall to the kernel
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Another variant that adds a syscall to do readahead on the relevant blocks
readahead-try-02.patch (text/plain), 13.66 KB, created by
Abhijith Das
on 2013-12-10 15:57:35 UTC
(
hide
)
Description:
Another variant that adds a syscall to do readahead on the relevant blocks
Filename:
MIME Type:
Creator:
Abhijith Das
Created:
2013-12-10 15:57:35 UTC
Size:
13.66 KB
patch
obsolete
>diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl >index aabfb83..3b75649 100644 >--- a/arch/x86/syscalls/syscall_32.tbl >+++ b/arch/x86/syscalls/syscall_32.tbl >@@ -357,3 +357,4 @@ > 348 i386 process_vm_writev sys_process_vm_writev compat_sys_process_vm_writev > 349 i386 kcmp sys_kcmp > 350 i386 finit_module sys_finit_module >+351 i386 rddir_readahead sys_rddir_readahead >diff --git a/arch/x86/syscalls/syscall_64.tbl b/arch/x86/syscalls/syscall_64.tbl >index 38ae65d..2ede45e 100644 >--- a/arch/x86/syscalls/syscall_64.tbl >+++ b/arch/x86/syscalls/syscall_64.tbl >@@ -320,6 +320,7 @@ > 311 64 process_vm_writev sys_process_vm_writev > 312 common kcmp sys_kcmp > 313 common finit_module sys_finit_module >+314 common rddir_readahead sys_rddir_readahead > > # > # x32-specific system call numbers start at 512 to avoid cache impact >diff --git a/fs/gfs2/Makefile b/fs/gfs2/Makefile >index 8612820..b1e4490 100644 >--- a/fs/gfs2/Makefile >+++ b/fs/gfs2/Makefile >@@ -4,7 +4,8 @@ gfs2-y := acl.o bmap.o dir.o xattr.o glock.o \ > glops.o log.o lops.o main.o meta_io.o \ > aops.o dentry.o export.o file.o \ > ops_fstype.o inode.o quota.o \ >- recovery.o rgrp.o super.o sys.o trans.o util.o >+ recovery.o rgrp.o super.o sys.o trans.o \ >+ rddir_ra.o util.o > > gfs2-$(CONFIG_GFS2_FS_LOCKING_DLM) += lock_dlm.o > >diff --git a/fs/gfs2/dir.c b/fs/gfs2/dir.c >index 2e5fc26..4481b95 100644 >--- a/fs/gfs2/dir.c >+++ b/fs/gfs2/dir.c >@@ -1227,6 +1227,7 @@ static int compare_dents(const void *a, const void *b) > */ > > static int do_filldir_main(struct gfs2_inode *dip, struct dir_context *ctx, >+ struct gfs2_rddir_ra *rra, > const struct gfs2_dirent **darr, u32 entries, > int *copied) > { >@@ -1266,11 +1267,18 @@ static int do_filldir_main(struct gfs2_inode *dip, struct dir_context *ctx, > ctx->pos = off; > } > >- if (!dir_emit(ctx, (const char *)(dent + 1), >- be16_to_cpu(dent->de_name_len), >- be64_to_cpu(dent->de_inum.no_addr), >- be16_to_cpu(dent->de_type))) >- return 1; >+ if (!rra) { >+ if (!dir_emit(ctx, (const char *)(dent + 1), >+ be16_to_cpu(dent->de_name_len), >+ be64_to_cpu(dent->de_inum.no_addr), >+ be16_to_cpu(dent->de_type))) >+ return 1; >+ } else { /* we were called by rddir_ra syscall */ >+ if (collect_inode_blocks(rra, >+ be64_to_cpu(dent->de_inum.no_addr), >+ be16_to_cpu(dent->de_type))) >+ return 1; >+ } > > *copied = 1; > } >@@ -1304,8 +1312,8 @@ static void gfs2_free_sort_buffer(void *ptr) > } > > static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx, >- int *copied, unsigned *depth, >- u64 leaf_no) >+ struct gfs2_rddir_ra *rra, int *copied, >+ unsigned *depth, u64 leaf_no) > { > struct gfs2_inode *ip = GFS2_I(inode); > struct gfs2_sbd *sdp = GFS2_SB(inode); >@@ -1382,7 +1390,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx, > } while(lfn); > > BUG_ON(entries2 != entries); >- error = do_filldir_main(ip, ctx, darr, entries, copied); >+ error = do_filldir_main(ip, ctx, rra, darr, entries, copied); > out_free: > for(i = 0; i < leaf; i++) > brelse(larr[i]); >@@ -1447,7 +1455,7 @@ static void gfs2_dir_readahead(struct inode *inode, unsigned hsize, u32 index, > */ > > static int dir_e_read(struct inode *inode, struct dir_context *ctx, >- struct file_ra_state *f_ra) >+ struct gfs2_rddir_ra *rra, struct file_ra_state *f_ra) > { > struct gfs2_inode *dip = GFS2_I(inode); > u32 hsize, len = 0; >@@ -1470,7 +1478,7 @@ static int dir_e_read(struct inode *inode, struct dir_context *ctx, > gfs2_dir_readahead(inode, hsize, index, f_ra); > > while (index < hsize) { >- error = gfs2_dir_read_leaf(inode, ctx, >+ error = gfs2_dir_read_leaf(inode, ctx, rra, > &copied, &depth, > be64_to_cpu(lp[index])); > if (error) >@@ -1486,7 +1494,7 @@ static int dir_e_read(struct inode *inode, struct dir_context *ctx, > } > > int gfs2_dir_read(struct inode *inode, struct dir_context *ctx, >- struct file_ra_state *f_ra) >+ struct gfs2_rddir_ra *rra, struct file_ra_state *f_ra) > { > struct gfs2_inode *dip = GFS2_I(inode); > struct gfs2_sbd *sdp = GFS2_SB(inode); >@@ -1500,7 +1508,7 @@ int gfs2_dir_read(struct inode *inode, struct dir_context *ctx, > return 0; > > if (dip->i_diskflags & GFS2_DIF_EXHASH) >- return dir_e_read(inode, ctx, f_ra); >+ return dir_e_read(inode, ctx, rra, f_ra); > > if (!gfs2_is_stuffed(dip)) { > gfs2_consist_inode(dip); >@@ -1532,7 +1540,7 @@ int gfs2_dir_read(struct inode *inode, struct dir_context *ctx, > error = -EIO; > goto out; > } >- error = do_filldir_main(dip, ctx, darr, >+ error = do_filldir_main(dip, ctx, rra, darr, > dip->i_entries, &copied); > out: > kfree(darr); >diff --git a/fs/gfs2/dir.h b/fs/gfs2/dir.h >index 4f03bbd..825dfd4 100644 >--- a/fs/gfs2/dir.h >+++ b/fs/gfs2/dir.h >@@ -17,6 +17,19 @@ struct inode; > struct gfs2_inode; > struct gfs2_inum; > >+struct gfs2_rddir_ra { >+ u32 rra_count; >+ u32 rra_req_count; >+ u32 rra_flags; >+ struct gfs2_file *rra_fp; >+ >+ u64 *rra_blknrs; >+}; >+ >+extern int gfs2_rddir_ra(struct file *file, unsigned flags, u64 *offset, >+ unsigned int count); >+extern int collect_inode_blocks(struct gfs2_rddir_ra *rra, u64 ino, unsigned int d_type); >+ > extern struct inode *gfs2_dir_search(struct inode *dir, > const struct qstr *filename, > bool fail_on_exist); >@@ -26,7 +39,7 @@ extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, > const struct gfs2_inode *ip); > extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry); > extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx, >- struct file_ra_state *f_ra); >+ struct gfs2_rddir_ra *rra, struct file_ra_state *f_ra); > extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, > const struct gfs2_inode *nip, unsigned int new_type); > >diff --git a/fs/gfs2/export.c b/fs/gfs2/export.c >index 8b9b377..1f5085d 100644 >--- a/fs/gfs2/export.c >+++ b/fs/gfs2/export.c >@@ -114,7 +114,7 @@ static int gfs2_get_name(struct dentry *parent, char *name, > if (error) > return error; > >- error = gfs2_dir_read(dir, &gnfd.ctx, &f_ra); >+ error = gfs2_dir_read(dir, &gnfd.ctx, NULL, &f_ra); > > gfs2_glock_dq_uninit(&gh); > >diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c >index efc078f..cccbfa9 100644 >--- a/fs/gfs2/file.c >+++ b/fs/gfs2/file.c >@@ -100,7 +100,7 @@ static int gfs2_readdir(struct file *file, struct dir_context *ctx) > if (error) > return error; > >- error = gfs2_dir_read(dir, ctx, &file->f_ra); >+ error = gfs2_dir_read(dir, ctx, NULL, &file->f_ra); > > gfs2_glock_dq_uninit(&d_gh); > >@@ -1071,6 +1071,7 @@ const struct file_operations gfs2_file_fops = { > > const struct file_operations gfs2_dir_fops = { > .iterate = gfs2_readdir, >+ .rddir_ra = gfs2_rddir_ra, > .unlocked_ioctl = gfs2_ioctl, > .open = gfs2_open, > .release = gfs2_release, >@@ -1101,6 +1102,7 @@ const struct file_operations gfs2_file_fops_nolock = { > > const struct file_operations gfs2_dir_fops_nolock = { > .iterate = gfs2_readdir, >+ .rddir_ra = gfs2_rddir_ra, > .unlocked_ioctl = gfs2_ioctl, > .open = gfs2_open, > .release = gfs2_release, >diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h >index 0132816..4fdcbc8 100644 >--- a/fs/gfs2/incore.h >+++ b/fs/gfs2/incore.h >@@ -405,6 +405,7 @@ static inline struct gfs2_sbd *GFS2_SB(const struct inode *inode) > struct gfs2_file { > struct mutex f_fl_mutex; > struct gfs2_holder f_fl_gh; >+ struct gfs2_rddir_ra *f_rra; > }; > > struct gfs2_revoke_replay { >diff --git a/fs/readdir.c b/fs/readdir.c >index 5b53d99..d5b4aa5 100644 >--- a/fs/readdir.c >+++ b/fs/readdir.c >@@ -302,3 +302,39 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd, > fdput(f); > return error; > } >+ >+SYSCALL_DEFINE4(rddir_readahead, unsigned int, fd, unsigned, flags, >+ u64 *, offset, unsigned int, count) >+{ >+ struct file *file; >+ struct inode *inode; >+ int fput_needed; >+ int error = -ENOTDIR; >+ >+ file = fget_light(fd, &fput_needed); >+ if (!file) >+ return -EBADF; >+ >+ inode = file->f_path.dentry->d_inode; >+ >+ if (!file->f_op || !file->f_op->rddir_ra) >+ goto out; >+ >+ error = security_file_permission(file, MAY_READ); >+ if (error) >+ goto out; >+ >+ error = mutex_lock_killable(&inode->i_mutex); >+ if (error) >+ goto out; >+ >+ error = -ENOENT; >+ if (!IS_DEADDIR(inode)) { >+ error = file->f_op->rddir_ra(file, flags, offset, count); >+ file_accessed(file); >+ } >+ mutex_unlock(&inode->i_mutex); >+out: >+ fput_light(file, fput_needed); >+ return error; >+} >diff --git a/include/linux/fs.h b/include/linux/fs.h >index 121f11f..6a15e9d 100644 >--- a/include/linux/fs.h >+++ b/include/linux/fs.h >@@ -1526,6 +1526,7 @@ struct file_operations { > ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t); > ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t); > int (*iterate) (struct file *, struct dir_context *); >+ int (*rddir_ra) (struct file *, unsigned flags, u64 *offset, unsigned int count); > unsigned int (*poll) (struct file *, struct poll_table_struct *); > long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); > long (*compat_ioctl) (struct file *, unsigned int, unsigned long); >diff --git a/fs/gfs2/rddir_ra.c b/fs/gfs2/rddir_ra.c >new file mode 100644 >index 0000000..c83af6a >--- /dev/null >+++ b/fs/gfs2/rddir_ra.c >@@ -0,0 +1,188 @@ >+#include <linux/slab.h> >+#include <linux/spinlock.h> >+#include <linux/completion.h> >+#include <linux/buffer_head.h> >+#include <linux/pagemap.h> >+#include <linux/uio.h> >+#include <linux/blkdev.h> >+#include <linux/mm.h> >+#include <linux/mount.h> >+#include <linux/sort.h> >+#include <linux/fs.h> >+#include <linux/gfs2_ondisk.h> >+#include <linux/falloc.h> >+#include <linux/swap.h> >+#include <linux/crc32.h> >+#include <linux/writeback.h> >+#include <asm/uaccess.h> >+#include <linux/dlm.h> >+#include <linux/dlm_plock.h> >+ >+#include "gfs2.h" >+#include "incore.h" >+#include "bmap.h" >+#include "dir.h" >+#include "glock.h" >+#include "glops.h" >+#include "inode.h" >+#include "log.h" >+#include "meta_io.h" >+#include "quota.h" >+#include "rgrp.h" >+#include "trans.h" >+#include "util.h" >+ >+void gfs2_rddir_ra_uninit(struct gfs2_rddir_ra *rra) >+{ >+ if (!rra || !rra->rra_blknrs) >+ return; >+ >+ if (is_vmalloc_addr(rra->rra_blknrs)) >+ vfree(rra->rra_blknrs); >+ else >+ kfree(rra->rra_blknrs); >+ kfree(rra); >+} >+ >+struct gfs2_rddir_ra* gfs2_rddir_ra_init(struct gfs2_file *fp, u32 req_count) >+{ >+ int error = -ENOMEM; >+ u32 size = req_count * sizeof(u64); >+ struct gfs2_rddir_ra *rra = NULL; >+ >+ rra = kzalloc(sizeof(struct gfs2_rddir_ra), GFP_NOFS | __GFP_NOWARN); >+ if (!rra) >+ goto err; >+ >+ if (size < KMALLOC_MAX_SIZE) >+ rra->rra_blknrs = kmalloc(size, GFP_NOFS | __GFP_NOWARN); >+ if (!rra->rra_blknrs) >+ rra->rra_blknrs = __vmalloc(size, GFP_NOFS, PAGE_KERNEL); >+ if (!rra->rra_blknrs) >+ goto free; >+ >+ rra->rra_req_count = req_count; >+ rra->rra_fp = fp; >+ >+ return rra; >+free: >+ kfree(rra); >+err: >+ return ERR_PTR(error); >+} >+ >+static int compare_inos(const void *a, const void *b) >+{ >+ u64 ino_a, ino_b; >+ >+ ino_a = *(u64 *)a; >+ ino_b = *(u64 *)b; >+ >+ if (ino_a > ino_b) >+ return 1; >+ return -1; >+} >+ >+int gfs2_rddir_ra_inodes(struct gfs2_inode *dip, struct gfs2_rddir_ra *rra) >+{ >+ int i, error = 0; >+ int issue_count = 0; >+ struct gfs2_glock *gl = dip->i_gl; >+ struct buffer_head *bh; >+ >+ if (!rra || !rra->rra_count || !rra->rra_blknrs) >+ goto out; >+ >+ sort(rra->rra_blknrs, rra->rra_count, sizeof(u64), compare_inos, NULL); >+ for (i=0; i<rra->rra_count; i++) { >+ bh = gfs2_getbuf(gl, rra->rra_blknrs[i], 1); >+ if (trylock_buffer(bh)) { >+ if (buffer_uptodate(bh)) { >+ unlock_buffer(bh); >+ brelse(bh); >+ continue; >+ } >+ bh->b_end_io = end_buffer_read_sync; >+ submit_bh(READA | REQ_META, bh); >+ issue_count++; >+ continue; >+ } >+ brelse(bh); >+ } >+ printk(KERN_WARNING "%s %s %d: Issued %d readaheads\n", __FILE__, >+ __FUNCTION__, __LINE__, issue_count); >+out: >+ return error; >+} >+ >+int collect_inode_blocks(struct gfs2_rddir_ra *rra, u64 ino, unsigned int d_type) >+{ >+ if (rra->rra_count >= rra->rra_req_count) >+ return 1; /* Collected requested blocks */ >+ >+ rra->rra_blknrs[rra->rra_count++] = ino; >+ >+ return 0; >+} >+ >+/** >+ * gfs2_rddir_ra - GFS2's implementation of readdir readahead >+ * @file : The directory to be read from >+ * @flags : Flags to determine what blocks to readahead >+ * @offset: Pointer to offset in dir to start prefetching from >+ * @count : How many entries to prefetch >+ * >+ * Readahead inode disk blocks (and extended attribute blocks if requested) >+ * of every directory entry >+ * >+ * Returns: +ve number: The number of entries for which readahead calls >+ * were issued >+ * -ve values: For error conditions >+ */ >+int gfs2_rddir_ra(struct file *file, unsigned flags, u64 *offset, unsigned int count) >+{ >+ int error = 0; >+ struct gfs2_file *fp = file->private_data; >+ struct inode *dir = file->f_mapping->host; >+ struct gfs2_inode *dip = GFS2_I(dir); >+ struct gfs2_holder d_gh; >+ struct dir_context ctx = { >+ .actor = NULL, >+ .pos = *offset >+ }; >+ >+ printk(KERN_WARNING "Start gfs2_rddir_ra syscall\n"); >+ >+ error = -EINVAL; >+ if (count <= 0) >+ goto err; >+ >+ error = -EBUSY; >+ if (fp->f_rra) >+ goto err; >+ >+ error = -ENOMEM; >+ fp->f_rra = gfs2_rddir_ra_init(fp, count); >+ if (!fp->f_rra) >+ goto err; >+ >+ gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); >+ error = gfs2_glock_nq(&d_gh); >+ if (error) { >+ gfs2_holder_uninit(&d_gh); >+ goto out; >+ } >+ error = gfs2_dir_read(dir, &ctx, fp->f_rra, &file->f_ra); >+ printk(KERN_WARNING "%s %s %d: Collected %u blocks to cache - requested:%u\n", >+ __FILE__, __FUNCTION__, __LINE__, fp->f_rra->rra_count, fp->f_rra->rra_req_count); >+ >+ error = gfs2_rddir_ra_inodes(dip, fp->f_rra); >+ >+ gfs2_glock_dq_uninit(&d_gh); >+out: >+ gfs2_rddir_ra_uninit(fp->f_rra); >+ fp->f_rra = NULL; >+err: >+ printk(KERN_WARNING "End gfs2_rddir_ra syscall\n"); >+ return error; >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 850426
:
605960
|
617073
|
625592
|
678841
|
680222
|
680282
|
708389
|
731269
|
731270
|
731272
|
731273
|
731274
|
731278
|
731279
|
732739
|
732740
|
732845
|
834840
|
853502
|
909528
|
909529
|
909534
|
912745
|
917238
|
917239
|
920895
|
920896
|
920897
|
920898
|
920899
|
920902
|
920903
|
947987