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 909534 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]
Third patch
gfs2_rddir_ra_implementation_3of3.patch (text/plain), 13.84 KB, created by
Abhijith Das
on 2014-06-17 11:35:13 UTC
(
hide
)
Description:
Third patch
Filename:
MIME Type:
Creator:
Abhijith Das
Created:
2014-06-17 11:35:13 UTC
Size:
13.84 KB
patch
obsolete
>commit d2f0be86618519ddc7468258bb4d2129342f50a5 >Author: Abhi Das <adas@redhat.com> >Date: Tue Jun 17 05:54:59 2014 -0500 > > gfs2: GFS2's implementation of the rddir_readahead syscall > > Add the rddir_ra fop, and associated functionality > > Signed-off-by: Abhi Das <adas@redhat.com> > >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 1a349f9..6aee3ca 100644 >--- a/fs/gfs2/dir.c >+++ b/fs/gfs2/dir.c >@@ -1217,6 +1217,20 @@ static int compare_dents(const void *a, const void *b) > return ret; > } > >+static int gfs2_dirent_dot_or_dotdot(const struct gfs2_dirent *dent) >+{ >+ const char *name = (char *)(dent + 1); >+ >+ if (be16_to_cpu(dent->de_type) == DT_DIR) { >+ if (be16_to_cpu(dent->de_name_len) == 1 && name[0] == '.') >+ return 1; >+ if (be16_to_cpu(dent->de_name_len) == 2 && >+ strncmp(name, "..", 2) == 0) >+ return 1; >+ } >+ return 0; >+} >+ > /** > * do_filldir_main - read out directory entries > * @dip: The GFS2 inode >@@ -1234,6 +1248,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) > { >@@ -1262,8 +1277,11 @@ static int do_filldir_main(struct gfs2_inode *dip, struct dir_context *ctx, > ctx->pos = off; > > if (off_next == off) { >- if (*copied && !run) >+ if (*copied && !run) { >+ if (rra) >+ set_bit(RRA_FL_HASHCOLL, &rra->rra_flags); > return 1; >+ } > run = 1; > } else > run = 0; >@@ -1273,11 +1291,20 @@ 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 (gfs2_dirent_dot_or_dotdot(dent)) >+ continue; >+ if (collect_inode_blocks(rra, >+ be64_to_cpu(dent->de_inum.no_addr), >+ be16_to_cpu(dent->de_type))) >+ return 1; >+ } > > *copied = 1; > } >@@ -1311,8 +1338,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); >@@ -1389,7 +1416,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]); >@@ -1454,7 +1481,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; >@@ -1477,7 +1504,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) >@@ -1493,7 +1520,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); >@@ -1507,7 +1534,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); >@@ -1539,7 +1566,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 126c65d..784ac9f 100644 >--- a/fs/gfs2/dir.h >+++ b/fs/gfs2/dir.h >@@ -25,6 +25,27 @@ struct gfs2_diradd { > struct buffer_head *bh; > }; > >+enum { >+ RRA_FL_HASHCOLL = 1, >+ RRA_FL_QUEUED = 2, >+ RRA_FL_HAS_PENDING = 3, >+}; >+ >+struct gfs2_rddir_ra { >+ u32 rra_count; >+ u32 rra_req_count; >+ unsigned long rra_flags; >+ struct gfs2_inode *rra_ip; >+ u64 *rra_blknrs; >+}; >+ >+extern int gfs2_rddir_ra(struct file *file, unsigned flags, u64 *offset, >+ unsigned int count); >+extern int gfs2_rddir_ra_inodes(struct gfs2_sbd *sdp, struct gfs2_rddir_ra *rra); >+extern void gfs2_rddir_ra_uninit(struct gfs2_rddir_ra *rra); >+ >+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); >@@ -40,7 +61,7 @@ static inline void gfs2_dir_no_add(struct gfs2_diradd *da) > } > 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 6ab0cfb..317c7fa 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); > >@@ -1077,6 +1077,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, >@@ -1107,6 +1108,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/glock.c b/fs/gfs2/glock.c >index 1965148..239a527 100644 >--- a/fs/gfs2/glock.c >+++ b/fs/gfs2/glock.c >@@ -48,6 +48,7 @@ > #include "bmap.h" > #define CREATE_TRACE_POINTS > #include "trace_gfs2.h" >+#include "dir.h" > > struct gfs2_glock_iter { > int hash; /* hash bucket index */ >@@ -648,7 +649,19 @@ static void ra_and_del_work_func(struct work_struct *work) > else > inode = gfs2_lookup_by_inum(sdp, no_addr, NULL, GFS2_BLKST_UNLINKED); > if (inode && !IS_ERR(inode)) { >- d_prune_aliases(inode); >+ ip = GFS2_I(inode); >+ if (ip->i_rra && test_bit(RRA_FL_QUEUED, &ip->i_rra->rra_flags)) { >+ if (gfs2_rddir_ra_inodes(sdp, ip->i_rra)) { >+ fs_err(sdp, "Inode readahead failed\n"); >+ goto iput; >+ } >+ clear_bit(RRA_FL_QUEUED, &ip->i_rra->rra_flags); >+ gfs2_rddir_ra_uninit(ip->i_rra); >+ ip->i_rra = NULL; >+ } else { >+ d_prune_aliases(inode); >+ } >+ iput: > iput(inode); > } > gfs2_glock_put(gl); >diff --git a/fs/gfs2/incore.h b/fs/gfs2/incore.h >index 5f273be..78f83ec 100644 >--- a/fs/gfs2/incore.h >+++ b/fs/gfs2/incore.h >@@ -395,6 +395,7 @@ struct gfs2_inode { > u32 i_diskflags; > u8 i_height; > u8 i_depth; >+ struct gfs2_rddir_ra *i_rra; > }; > > /* >diff --git a/fs/gfs2/rddir_ra.c b/fs/gfs2/rddir_ra.c >new file mode 100644 >index 0000000..5e3b076 >--- /dev/null >+++ b/fs/gfs2/rddir_ra.c >@@ -0,0 +1,200 @@ >+#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_inode *ip, 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_ip = ip; >+ >+ 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_sbd *sdp, struct gfs2_rddir_ra *rra) >+{ >+ int i, error = 0; >+ int issue_count = 0; >+ >+ 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++) { >+ struct inode *inode = gfs2_lookup_by_inum(sdp, rra->rra_blknrs[i], >+ NULL, GFS2_BLKST_DINODE); >+ if (IS_ERR(inode)) { >+ fs_err(sdp, "can't read in inode at addr:%llu: %ld\n", >+ rra->rra_blknrs[i], PTR_ERR(inode)); >+ return PTR_ERR(inode); >+ } >+ error = gfs2_inode_refresh(GFS2_I(inode)); >+ issue_count++; >+ iput(inode); >+ } >+ >+ printk(KERN_WARNING "%s %s %d: Read in %d inodes\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) { >+ printk(KERN_WARNING "Collected enough blocks - req:%u count:%u\n", >+ rra->rra_req_count, rra->rra_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 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 (dip->i_rra) >+ goto err; >+ >+ error = -ENOMEM; >+ dip->i_rra = gfs2_rddir_ra_init(dip, count); >+ if (!dip->i_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; >+ } >+try_again: >+ error = gfs2_dir_read(dir, &ctx, dip->i_rra, &file->f_ra); >+ if (test_bit(RRA_FL_HASHCOLL, &dip->i_rra->rra_flags)) { >+ clear_bit(RRA_FL_HASHCOLL, &dip->i_rra->rra_flags); >+ goto try_again; >+ } >+ printk(KERN_WARNING "Collected %u entries\n", dip->i_rra->rra_count); >+ /* >+ * We've collected all the entries we need to readahead. >+ * Pass this task on to the workqueues >+ */ >+ set_bit(RRA_FL_QUEUED, &dip->i_rra->rra_flags); >+ spin_lock(&dip->i_gl->gl_spin); >+ dip->i_gl->gl_lockref.count++; >+ if (queue_work(gfs2_ra_and_del_workqueue, &dip->i_gl->gl_ra_and_del) == 0) >+ dip->i_gl->gl_lockref.count--; >+ spin_unlock(&dip->i_gl->gl_spin); >+ >+ gfs2_glock_dq_uninit(&d_gh); >+ printk(KERN_WARNING "End gfs2_rddir_ra syscall\n"); >+ return 0; >+ >+out: >+ gfs2_rddir_ra_uninit(dip->i_rra); >+ dip->i_rra = NULL; >+err: >+ 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