Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 70831
b: refs/heads/master
c: 051e7cd
h: refs/heads/master
i:
  70829: 3d8b71e
  70827: 5c9b914
  70823: c396f95
  70815: 5144268
v: v3
  • Loading branch information
Christoph Hellwig authored and Tim Shimmin committed Oct 15, 2007
1 parent 46ffe09 commit a3c3f66
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 407 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 2bdf7cd0baa67608ada1517a281af359faf4c58c
refs/heads/master: 051e7cd44ab8f0f7c2958371485b4a1ff64a8d1b
90 changes: 23 additions & 67 deletions trunk/fs/xfs/linux-2.6/xfs_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,74 +233,30 @@ xfs_file_readdir(
void *dirent,
filldir_t filldir)
{
int error = 0;
bhv_vnode_t *vp = vn_from_inode(filp->f_path.dentry->d_inode);
uio_t uio;
iovec_t iov;
int eof = 0;
caddr_t read_buf;
int namelen, size = 0;
size_t rlen = PAGE_CACHE_SIZE;
xfs_off_t start_offset, curr_offset;
xfs_dirent_t *dbp = NULL;

/* Try fairly hard to get memory */
do {
if ((read_buf = kmalloc(rlen, GFP_KERNEL)))
break;
rlen >>= 1;
} while (rlen >= 1024);

if (read_buf == NULL)
return -ENOMEM;

uio.uio_iov = &iov;
uio.uio_segflg = UIO_SYSSPACE;
curr_offset = filp->f_pos;
if (filp->f_pos != 0x7fffffff)
uio.uio_offset = filp->f_pos;
else
uio.uio_offset = 0xffffffff;

while (!eof) {
uio.uio_resid = iov.iov_len = rlen;
iov.iov_base = read_buf;
uio.uio_iovcnt = 1;

start_offset = uio.uio_offset;

error = bhv_vop_readdir(vp, &uio, NULL, &eof);
if ((uio.uio_offset == start_offset) || error) {
size = 0;
break;
}

size = rlen - uio.uio_resid;
dbp = (xfs_dirent_t *)read_buf;
while (size > 0) {
namelen = strlen(dbp->d_name);

if (filldir(dirent, dbp->d_name, namelen,
(loff_t) curr_offset & 0x7fffffff,
(ino_t) dbp->d_ino,
DT_UNKNOWN)) {
goto done;
}
size -= dbp->d_reclen;
curr_offset = (loff_t)dbp->d_off /* & 0x7fffffff */;
dbp = (xfs_dirent_t *)((char *)dbp + dbp->d_reclen);
}
}
done:
if (!error) {
if (size == 0)
filp->f_pos = uio.uio_offset & 0x7fffffff;
else if (dbp)
filp->f_pos = curr_offset;
}
struct inode *inode = filp->f_path.dentry->d_inode;
bhv_vnode_t *vp = vn_from_inode(inode);
int error;
size_t bufsize;

/*
* The Linux API doesn't pass down the total size of the buffer
* we read into down to the filesystem. With the filldir concept
* it's not needed for correct information, but the XFS dir2 leaf
* code wants an estimate of the buffer size to calculate it's
* readahead window and size the buffers used for mapping to
* physical blocks.
*
* Try to give it an estimate that's good enough, maybe at some
* point we can change the ->readdir prototype to include the
* buffer size.
*/
bufsize = (size_t)min_t(loff_t, PAGE_SIZE, inode->i_size);

kfree(read_buf);
return -error;
error = bhv_vop_readdir(vp, dirent, bufsize,
(xfs_off_t *)&filp->f_pos, filldir);
if (error)
return -error;
return 0;
}

STATIC int
Expand Down
8 changes: 4 additions & 4 deletions trunk/fs/xfs/linux-2.6/xfs_vnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ typedef int (*vop_rename_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *,
typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *,
bhv_vnode_t **, struct cred *);
typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *);
typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *,
int *);
typedef int (*vop_readdir_t)(bhv_desc_t *, void *dirent, size_t bufsize,
xfs_off_t *offset, filldir_t filldir);
typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*,
char *, bhv_vnode_t **, struct cred *);
typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int,
Expand Down Expand Up @@ -267,8 +267,8 @@ typedef struct bhv_vnodeops {
#define bhv_vop_mkdir(dp,d,vap,vpp,cr) \
VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr)
#define bhv_vop_rmdir(dp,d,cr) VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr)
#define bhv_vop_readdir(vp,uiop,cr,eofp) \
VOP(vop_readdir, vp)(VNHEAD(vp),uiop,cr,eofp)
#define bhv_vop_readdir(vp,dirent,bufsize,offset,filldir) \
VOP(vop_readdir, vp)(VNHEAD(vp),dirent,bufsize,offset,filldir)
#define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \
VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr)
#define bhv_vop_readlink(vp,uiop,fl,cr) \
Expand Down
121 changes: 18 additions & 103 deletions trunk/fs/xfs/xfs_dir2.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@
#include "xfs_dir2_trace.h"
#include "xfs_error.h"

static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa);
static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa);

void
xfs_dir_mount(
Expand Down Expand Up @@ -293,47 +291,35 @@ xfs_dir_removename(
* Read a directory.
*/
int
xfs_dir_getdents(
xfs_trans_t *tp,
xfs_inode_t *dp,
uio_t *uio, /* caller's buffer control */
int *eofp) /* out: eof reached */
xfs_readdir(
bhv_desc_t *dir_bdp,
void *dirent,
size_t bufsize,
xfs_off_t *offset,
filldir_t filldir)
{
int alignment; /* alignment required for ABI */
xfs_dirent_t *dbp; /* malloc'ed buffer */
xfs_dir2_put_t put; /* entry formatting routine */
xfs_inode_t *dp = XFS_BHVTOI(dir_bdp);
int rval; /* return value */
int v; /* type-checking value */

vn_trace_entry(BHV_TO_VNODE(dir_bdp), __FUNCTION__,
(inst_t *)__return_address);

if (XFS_FORCED_SHUTDOWN(dp->i_mount))
return XFS_ERROR(EIO);

ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR);
XFS_STATS_INC(xs_dir_getdents);
/*
* If our caller has given us a single contiguous aligned memory buffer,
* just work directly within that buffer. If it's in user memory,
* lock it down first.
*/
alignment = sizeof(xfs_off_t) - 1;
if ((uio->uio_iovcnt == 1) &&
(((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) &&
((uio->uio_iov[0].iov_len & alignment) == 0)) {
dbp = NULL;
put = xfs_dir2_put_dirent64_direct;
} else {
dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP);
put = xfs_dir2_put_dirent64_uio;
}

*eofp = 0;
if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL)
rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put);
else if ((rval = xfs_dir2_isblock(tp, dp, &v)))
rval = xfs_dir2_sf_getdents(dp, dirent, offset, filldir);
else if ((rval = xfs_dir2_isblock(NULL, dp, &v)))
;
else if (v)
rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put);
rval = xfs_dir2_block_getdents(dp, dirent, offset, filldir);
else
rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put);
if (dbp != NULL)
kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN);
rval = xfs_dir2_leaf_getdents(dp, dirent, bufsize, offset,
filldir);
return rval;
}

Expand Down Expand Up @@ -612,77 +598,6 @@ xfs_dir2_isleaf(
return 0;
}

/*
* Getdents put routine for 64-bit ABI, direct form.
*/
static int
xfs_dir2_put_dirent64_direct(
xfs_dir2_put_args_t *pa)
{
xfs_dirent_t *idbp; /* dirent pointer */
iovec_t *iovp; /* io vector */
int namelen; /* entry name length */
int reclen; /* entry total length */
uio_t *uio; /* I/O control */

namelen = pa->namelen;
reclen = DIRENTSIZE(namelen);
uio = pa->uio;
/*
* Won't fit in the remaining space.
*/
if (reclen > uio->uio_resid) {
pa->done = 0;
return 0;
}
iovp = uio->uio_iov;
idbp = (xfs_dirent_t *)iovp->iov_base;
iovp->iov_base = (char *)idbp + reclen;
iovp->iov_len -= reclen;
uio->uio_resid -= reclen;
idbp->d_reclen = reclen;
idbp->d_ino = pa->ino;
idbp->d_off = pa->cook;
idbp->d_name[namelen] = '\0';
pa->done = 1;
memcpy(idbp->d_name, pa->name, namelen);
return 0;
}

/*
* Getdents put routine for 64-bit ABI, uio form.
*/
static int
xfs_dir2_put_dirent64_uio(
xfs_dir2_put_args_t *pa)
{
xfs_dirent_t *idbp; /* dirent pointer */
int namelen; /* entry name length */
int reclen; /* entry total length */
int rval; /* return value */
uio_t *uio; /* I/O control */

namelen = pa->namelen;
reclen = DIRENTSIZE(namelen);
uio = pa->uio;
/*
* Won't fit in the remaining space.
*/
if (reclen > uio->uio_resid) {
pa->done = 0;
return 0;
}
idbp = pa->dbp;
idbp->d_reclen = reclen;
idbp->d_ino = pa->ino;
idbp->d_off = pa->cook;
idbp->d_name[namelen] = '\0';
memcpy(idbp->d_name, pa->name, namelen);
rval = xfs_uio_read((caddr_t)idbp, reclen, uio);
pa->done = (rval == 0);
return rval;
}

/*
* Remove the given block from the directory.
* This routine is used for data and free blocks, leaf/node are done
Expand Down
19 changes: 2 additions & 17 deletions trunk/fs/xfs/xfs_dir2.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,6 @@ typedef __uint32_t xfs_dir2_db_t;
*/
typedef xfs_off_t xfs_dir2_off_t;

/*
* For getdents, argument struct for put routines.
*/
typedef int (*xfs_dir2_put_t)(struct xfs_dir2_put_args *pa);
typedef struct xfs_dir2_put_args {
xfs_off_t cook; /* cookie of (next) entry */
xfs_intino_t ino; /* inode number */
xfs_dirent_t *dbp; /* buffer pointer */
char *name; /* directory entry name */
int namelen; /* length of name */
int done; /* output: set if value was stored */
xfs_dir2_put_t put; /* put function ptr (i/o) */
struct uio *uio; /* uio control structure */
} xfs_dir2_put_args_t;

/*
* Generic directory interface routines
*/
Expand All @@ -92,15 +77,15 @@ extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp,
char *name, int namelen, xfs_ino_t ino,
xfs_fsblock_t *first,
struct xfs_bmap_free *flist, xfs_extlen_t tot);
extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp,
uio_t *uio, int *eofp);
extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp,
char *name, int namelen, xfs_ino_t inum,
xfs_fsblock_t *first,
struct xfs_bmap_free *flist, xfs_extlen_t tot);
extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp,
char *name, int namelen);
extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino);
extern int xfs_readdir(bhv_desc_t *dir_bdp, void *dirent, size_t bufsize,
xfs_off_t *offset, filldir_t filldir);

/*
* Utility routines for v2 directories.
Expand Down
Loading

0 comments on commit a3c3f66

Please sign in to comment.