Commit d81a8ef5 authored by Al Viro's avatar Al Viro

[readdir] convert gfs2

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 75811d4f
...@@ -1212,9 +1212,7 @@ static int compare_dents(const void *a, const void *b) ...@@ -1212,9 +1212,7 @@ static int compare_dents(const void *a, const void *b)
/** /**
* do_filldir_main - read out directory entries * do_filldir_main - read out directory entries
* @dip: The GFS2 inode * @dip: The GFS2 inode
* @offset: The offset in the file to read from * @ctx: what to feed the entries to
* @opaque: opaque data to pass to filldir
* @filldir: The function to pass entries to
* @darr: an array of struct gfs2_dirent pointers to read * @darr: an array of struct gfs2_dirent pointers to read
* @entries: the number of entries in darr * @entries: the number of entries in darr
* @copied: pointer to int that's non-zero if a entry has been copied out * @copied: pointer to int that's non-zero if a entry has been copied out
...@@ -1224,11 +1222,10 @@ static int compare_dents(const void *a, const void *b) ...@@ -1224,11 +1222,10 @@ static int compare_dents(const void *a, const void *b)
* the possibility that they will fall into different readdir buffers or * the possibility that they will fall into different readdir buffers or
* that someone will want to seek to that location. * that someone will want to seek to that location.
* *
* Returns: errno, >0 on exception from filldir * Returns: errno, >0 if the actor tells you to stop
*/ */
static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, static int do_filldir_main(struct gfs2_inode *dip, struct dir_context *ctx,
void *opaque, filldir_t filldir,
const struct gfs2_dirent **darr, u32 entries, const struct gfs2_dirent **darr, u32 entries,
int *copied) int *copied)
{ {
...@@ -1236,7 +1233,6 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, ...@@ -1236,7 +1233,6 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
u64 off, off_next; u64 off, off_next;
unsigned int x, y; unsigned int x, y;
int run = 0; int run = 0;
int error = 0;
sort(darr, entries, sizeof(struct gfs2_dirent *), compare_dents, NULL); sort(darr, entries, sizeof(struct gfs2_dirent *), compare_dents, NULL);
...@@ -1253,9 +1249,9 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, ...@@ -1253,9 +1249,9 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
off_next = be32_to_cpu(dent_next->de_hash); off_next = be32_to_cpu(dent_next->de_hash);
off_next = gfs2_disk_hash2offset(off_next); off_next = gfs2_disk_hash2offset(off_next);
if (off < *offset) if (off < ctx->pos)
continue; continue;
*offset = off; ctx->pos = off;
if (off_next == off) { if (off_next == off) {
if (*copied && !run) if (*copied && !run)
...@@ -1264,26 +1260,25 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset, ...@@ -1264,26 +1260,25 @@ static int do_filldir_main(struct gfs2_inode *dip, u64 *offset,
} else } else
run = 0; run = 0;
} else { } else {
if (off < *offset) if (off < ctx->pos)
continue; continue;
*offset = off; ctx->pos = off;
} }
error = filldir(opaque, (const char *)(dent + 1), if (!dir_emit(ctx, (const char *)(dent + 1),
be16_to_cpu(dent->de_name_len), be16_to_cpu(dent->de_name_len),
off, be64_to_cpu(dent->de_inum.no_addr), be64_to_cpu(dent->de_inum.no_addr),
be16_to_cpu(dent->de_type)); be16_to_cpu(dent->de_type)))
if (error)
return 1; return 1;
*copied = 1; *copied = 1;
} }
/* Increment the *offset by one, so the next time we come into the /* Increment the ctx->pos by one, so the next time we come into the
do_filldir fxn, we get the next entry instead of the last one in the do_filldir fxn, we get the next entry instead of the last one in the
current leaf */ current leaf */
(*offset)++; ctx->pos++;
return 0; return 0;
} }
...@@ -1307,8 +1302,8 @@ static void gfs2_free_sort_buffer(void *ptr) ...@@ -1307,8 +1302,8 @@ static void gfs2_free_sort_buffer(void *ptr)
kfree(ptr); kfree(ptr);
} }
static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, static int gfs2_dir_read_leaf(struct inode *inode, struct dir_context *ctx,
filldir_t filldir, int *copied, unsigned *depth, int *copied, unsigned *depth,
u64 leaf_no) u64 leaf_no)
{ {
struct gfs2_inode *ip = GFS2_I(inode); struct gfs2_inode *ip = GFS2_I(inode);
...@@ -1386,8 +1381,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque, ...@@ -1386,8 +1381,7 @@ static int gfs2_dir_read_leaf(struct inode *inode, u64 *offset, void *opaque,
} while(lfn); } while(lfn);
BUG_ON(entries2 != entries); BUG_ON(entries2 != entries);
error = do_filldir_main(ip, offset, opaque, filldir, darr, error = do_filldir_main(ip, ctx, darr, entries, copied);
entries, copied);
out_free: out_free:
for(i = 0; i < leaf; i++) for(i = 0; i < leaf; i++)
brelse(larr[i]); brelse(larr[i]);
...@@ -1446,15 +1440,13 @@ static void gfs2_dir_readahead(struct inode *inode, unsigned hsize, u32 index, ...@@ -1446,15 +1440,13 @@ static void gfs2_dir_readahead(struct inode *inode, unsigned hsize, u32 index,
/** /**
* dir_e_read - Reads the entries from a directory into a filldir buffer * dir_e_read - Reads the entries from a directory into a filldir buffer
* @dip: dinode pointer * @dip: dinode pointer
* @offset: the hash of the last entry read shifted to the right once * @ctx: actor to feed the entries to
* @opaque: buffer for the filldir function to fill
* @filldir: points to the filldir function to use
* *
* Returns: errno * Returns: errno
*/ */
static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, static int dir_e_read(struct inode *inode, struct dir_context *ctx,
filldir_t filldir, struct file_ra_state *f_ra) struct file_ra_state *f_ra)
{ {
struct gfs2_inode *dip = GFS2_I(inode); struct gfs2_inode *dip = GFS2_I(inode);
u32 hsize, len = 0; u32 hsize, len = 0;
...@@ -1465,7 +1457,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, ...@@ -1465,7 +1457,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
unsigned depth = 0; unsigned depth = 0;
hsize = 1 << dip->i_depth; hsize = 1 << dip->i_depth;
hash = gfs2_dir_offset2hash(*offset); hash = gfs2_dir_offset2hash(ctx->pos);
index = hash >> (32 - dip->i_depth); index = hash >> (32 - dip->i_depth);
if (dip->i_hash_cache == NULL) if (dip->i_hash_cache == NULL)
...@@ -1477,7 +1469,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, ...@@ -1477,7 +1469,7 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
gfs2_dir_readahead(inode, hsize, index, f_ra); gfs2_dir_readahead(inode, hsize, index, f_ra);
while (index < hsize) { while (index < hsize) {
error = gfs2_dir_read_leaf(inode, offset, opaque, filldir, error = gfs2_dir_read_leaf(inode, ctx,
&copied, &depth, &copied, &depth,
be64_to_cpu(lp[index])); be64_to_cpu(lp[index]));
if (error) if (error)
...@@ -1492,8 +1484,8 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque, ...@@ -1492,8 +1484,8 @@ static int dir_e_read(struct inode *inode, u64 *offset, void *opaque,
return error; return error;
} }
int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
filldir_t filldir, struct file_ra_state *f_ra) struct file_ra_state *f_ra)
{ {
struct gfs2_inode *dip = GFS2_I(inode); struct gfs2_inode *dip = GFS2_I(inode);
struct gfs2_sbd *sdp = GFS2_SB(inode); struct gfs2_sbd *sdp = GFS2_SB(inode);
...@@ -1507,7 +1499,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, ...@@ -1507,7 +1499,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
return 0; return 0;
if (dip->i_diskflags & GFS2_DIF_EXHASH) if (dip->i_diskflags & GFS2_DIF_EXHASH)
return dir_e_read(inode, offset, opaque, filldir, f_ra); return dir_e_read(inode, ctx, f_ra);
if (!gfs2_is_stuffed(dip)) { if (!gfs2_is_stuffed(dip)) {
gfs2_consist_inode(dip); gfs2_consist_inode(dip);
...@@ -1539,7 +1531,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, ...@@ -1539,7 +1531,7 @@ int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque,
error = -EIO; error = -EIO;
goto out; goto out;
} }
error = do_filldir_main(dip, offset, opaque, filldir, darr, error = do_filldir_main(dip, ctx, darr,
dip->i_entries, &copied); dip->i_entries, &copied);
out: out:
kfree(darr); kfree(darr);
......
...@@ -24,8 +24,8 @@ extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename, ...@@ -24,8 +24,8 @@ extern int gfs2_dir_check(struct inode *dir, const struct qstr *filename,
extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename, extern int gfs2_dir_add(struct inode *inode, const struct qstr *filename,
const struct gfs2_inode *ip); const struct gfs2_inode *ip);
extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry); extern int gfs2_dir_del(struct gfs2_inode *dip, const struct dentry *dentry);
extern int gfs2_dir_read(struct inode *inode, u64 *offset, void *opaque, extern int gfs2_dir_read(struct inode *inode, struct dir_context *ctx,
filldir_t filldir, struct file_ra_state *f_ra); struct file_ra_state *f_ra);
extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename, extern int gfs2_dir_mvino(struct gfs2_inode *dip, const struct qstr *filename,
const struct gfs2_inode *nip, unsigned int new_type); const struct gfs2_inode *nip, unsigned int new_type);
......
...@@ -64,6 +64,7 @@ static int gfs2_encode_fh(struct inode *inode, __u32 *p, int *len, ...@@ -64,6 +64,7 @@ static int gfs2_encode_fh(struct inode *inode, __u32 *p, int *len,
} }
struct get_name_filldir { struct get_name_filldir {
struct dir_context ctx;
struct gfs2_inum_host inum; struct gfs2_inum_host inum;
char *name; char *name;
}; };
...@@ -90,7 +91,6 @@ static int gfs2_get_name(struct dentry *parent, char *name, ...@@ -90,7 +91,6 @@ static int gfs2_get_name(struct dentry *parent, char *name,
struct gfs2_inode *dip, *ip; struct gfs2_inode *dip, *ip;
struct get_name_filldir gnfd; struct get_name_filldir gnfd;
struct gfs2_holder gh; struct gfs2_holder gh;
u64 offset = 0;
int error; int error;
struct file_ra_state f_ra = { .start = 0 }; struct file_ra_state f_ra = { .start = 0 };
...@@ -107,12 +107,14 @@ static int gfs2_get_name(struct dentry *parent, char *name, ...@@ -107,12 +107,14 @@ static int gfs2_get_name(struct dentry *parent, char *name,
gnfd.inum.no_addr = ip->i_no_addr; gnfd.inum.no_addr = ip->i_no_addr;
gnfd.inum.no_formal_ino = ip->i_no_formal_ino; gnfd.inum.no_formal_ino = ip->i_no_formal_ino;
gnfd.name = name; gnfd.name = name;
gnfd.ctx.actor = get_name_filldir;
gnfd.ctx.pos = 0;
error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh); error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &gh);
if (error) if (error)
return error; return error;
error = gfs2_dir_read(dir, &offset, &gnfd, get_name_filldir, &f_ra); error = gfs2_dir_read(dir, &gnfd.ctx, &f_ra);
gfs2_glock_dq_uninit(&gh); gfs2_glock_dq_uninit(&gh);
......
...@@ -82,35 +82,28 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int whence) ...@@ -82,35 +82,28 @@ static loff_t gfs2_llseek(struct file *file, loff_t offset, int whence)
} }
/** /**
* gfs2_readdir - Read directory entries from a directory * gfs2_readdir - Iterator for a directory
* @file: The directory to read from * @file: The directory to read from
* @dirent: Buffer for dirents * @ctx: What to feed directory entries to
* @filldir: Function used to do the copying
* *
* Returns: errno * Returns: errno
*/ */
static int gfs2_readdir(struct file *file, void *dirent, filldir_t filldir) static int gfs2_readdir(struct file *file, struct dir_context *ctx)
{ {
struct inode *dir = file->f_mapping->host; struct inode *dir = file->f_mapping->host;
struct gfs2_inode *dip = GFS2_I(dir); struct gfs2_inode *dip = GFS2_I(dir);
struct gfs2_holder d_gh; struct gfs2_holder d_gh;
u64 offset = file->f_pos;
int error; int error;
gfs2_holder_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh); error = gfs2_glock_nq_init(dip->i_gl, LM_ST_SHARED, 0, &d_gh);
error = gfs2_glock_nq(&d_gh); if (error)
if (error) {
gfs2_holder_uninit(&d_gh);
return error; return error;
}
error = gfs2_dir_read(dir, &offset, dirent, filldir, &file->f_ra); error = gfs2_dir_read(dir, ctx, &file->f_ra);
gfs2_glock_dq_uninit(&d_gh); gfs2_glock_dq_uninit(&d_gh);
file->f_pos = offset;
return error; return error;
} }
...@@ -1048,7 +1041,7 @@ const struct file_operations gfs2_file_fops = { ...@@ -1048,7 +1041,7 @@ const struct file_operations gfs2_file_fops = {
}; };
const struct file_operations gfs2_dir_fops = { const struct file_operations gfs2_dir_fops = {
.readdir = gfs2_readdir, .iterate = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl, .unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open, .open = gfs2_open,
.release = gfs2_release, .release = gfs2_release,
...@@ -1078,7 +1071,7 @@ const struct file_operations gfs2_file_fops_nolock = { ...@@ -1078,7 +1071,7 @@ const struct file_operations gfs2_file_fops_nolock = {
}; };
const struct file_operations gfs2_dir_fops_nolock = { const struct file_operations gfs2_dir_fops_nolock = {
.readdir = gfs2_readdir, .iterate = gfs2_readdir,
.unlocked_ioctl = gfs2_ioctl, .unlocked_ioctl = gfs2_ioctl,
.open = gfs2_open, .open = gfs2_open,
.release = gfs2_release, .release = gfs2_release,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment