Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 201784
b: refs/heads/master
c: 7751bdb
h: refs/heads/master
v: v3
  • Loading branch information
Sripathi Kodi authored and Eric Van Hensbergen committed Aug 2, 2010
1 parent 2cf1591 commit 52260fd
Show file tree
Hide file tree
Showing 6 changed files with 228 additions and 17 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: 97e8442b0971ea6be9a495b3d03402985cfe5d6a
refs/heads/master: 7751bdb3a095ad32dd4fcff3443cf8dd4cb1e748
134 changes: 118 additions & 16 deletions trunk/fs/9p/vfs_dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,29 +87,19 @@ static void p9stat_init(struct p9_wstat *stbuf)
}

/**
* v9fs_dir_readdir - read a directory
* v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir
* @filp: opened file structure
* @dirent: directory structure ???
* @filldir: function to populate directory structure ???
* @buflen: Length in bytes of buffer to allocate
*
*/

static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
static int v9fs_alloc_rdir_buf(struct file *filp, int buflen)
{
int over;
struct p9_wstat st;
int err = 0;
struct p9_fid *fid;
int buflen;
int reclen = 0;
struct p9_rdir *rdir;
struct p9_fid *fid;
int err = 0;

P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
fid = filp->private_data;

buflen = fid->clnt->msize - P9_IOHDRSZ;

/* allocate rdir on demand */
if (!fid->rdir) {
rdir = kmalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL);

Expand All @@ -128,6 +118,36 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
spin_unlock(&filp->f_dentry->d_lock);
kfree(rdir);
}
exit:
return err;
}

/**
* v9fs_dir_readdir - read a directory
* @filp: opened file structure
* @dirent: directory structure ???
* @filldir: function to populate directory structure ???
*
*/

static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
{
int over;
struct p9_wstat st;
int err = 0;
struct p9_fid *fid;
int buflen;
int reclen = 0;
struct p9_rdir *rdir;

P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
fid = filp->private_data;

buflen = fid->clnt->msize - P9_IOHDRSZ;

err = v9fs_alloc_rdir_buf(filp, buflen);
if (err)
goto exit;
rdir = (struct p9_rdir *) fid->rdir;

err = mutex_lock_interruptible(&rdir->mutex);
Expand Down Expand Up @@ -176,6 +196,88 @@ static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir)
return err;
}

/**
* v9fs_dir_readdir_dotl - read a directory
* @filp: opened file structure
* @dirent: buffer to fill dirent structures
* @filldir: function to populate dirent structures
*
*/
static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent,
filldir_t filldir)
{
int over;
int err = 0;
struct p9_fid *fid;
int buflen;
struct p9_rdir *rdir;
struct p9_dirent curdirent;
u64 oldoffset = 0;

P9_DPRINTK(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name);
fid = filp->private_data;

buflen = fid->clnt->msize - P9_READDIRHDRSZ;

err = v9fs_alloc_rdir_buf(filp, buflen);
if (err)
goto exit;
rdir = (struct p9_rdir *) fid->rdir;

err = mutex_lock_interruptible(&rdir->mutex);
if (err)
return err;

while (err == 0) {
if (rdir->tail == rdir->head) {
err = p9_client_readdir(fid, rdir->buf, buflen,
filp->f_pos);
if (err <= 0)
goto unlock_and_exit;

rdir->head = 0;
rdir->tail = err;
}

while (rdir->head < rdir->tail) {

err = p9dirent_read(rdir->buf + rdir->head,
buflen - rdir->head, &curdirent,
fid->clnt->proto_version);
if (err < 0) {
P9_DPRINTK(P9_DEBUG_VFS, "returned %d\n", err);
err = -EIO;
goto unlock_and_exit;
}

/* d_off in dirent structure tracks the offset into
* the next dirent in the dir. However, filldir()
* expects offset into the current dirent. Hence
* while calling filldir send the offset from the
* previous dirent structure.
*/
over = filldir(dirent, curdirent.d_name,
strlen(curdirent.d_name),
oldoffset, v9fs_qid2ino(&curdirent.qid),
curdirent.d_type);
oldoffset = curdirent.d_off;

if (over) {
err = 0;
goto unlock_and_exit;
}

filp->f_pos = curdirent.d_off;
rdir->head += err;
}
}

unlock_and_exit:
mutex_unlock(&rdir->mutex);
exit:
return err;
}


/**
* v9fs_dir_release - close a directory
Expand Down Expand Up @@ -207,7 +309,7 @@ const struct file_operations v9fs_dir_operations = {
const struct file_operations v9fs_dir_operations_dotl = {
.read = generic_read_dir,
.llseek = generic_file_llseek,
.readdir = v9fs_dir_readdir,
.readdir = v9fs_dir_readdir_dotl,
.open = v9fs_file_open,
.release = v9fs_dir_release,
};
17 changes: 17 additions & 0 deletions trunk/include/net/9p/9p.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ enum p9_msg_t {
P9_RSTATFS,
P9_TRENAME = 20,
P9_RRENAME,
P9_TREADDIR = 40,
P9_RREADDIR,
P9_TVERSION = 100,
P9_RVERSION,
P9_TAUTH = 102,
Expand Down Expand Up @@ -275,6 +277,9 @@ enum p9_qid_t {
/* ample room for Twrite/Rread header */
#define P9_IOHDRSZ 24

/* Room for readdir header */
#define P9_READDIRHDRSZ 24

/**
* struct p9_str - length prefixed string type
* @len: length of the string
Expand Down Expand Up @@ -485,6 +490,18 @@ struct p9_rwrite {
u32 count;
};

struct p9_treaddir {
u32 fid;
u64 offset;
u32 count;
};

struct p9_rreaddir {
u32 count;
u8 *data;
};


struct p9_tclunk {
u32 fid;
};
Expand Down
18 changes: 18 additions & 0 deletions trunk/include/net/9p/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,21 @@ struct p9_fid {
struct list_head dlist; /* list of all fids attached to a dentry */
};

/**
* struct p9_dirent - directory entry structure
* @qid: The p9 server qid for this dirent
* @d_off: offset to the next dirent
* @d_type: type of file
* @d_name: file name
*/

struct p9_dirent {
struct p9_qid qid;
u64 d_off;
unsigned char d_type;
char d_name[256];
};

int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb);
int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name);
int p9_client_version(struct p9_client *);
Expand All @@ -217,6 +232,9 @@ int p9_client_read(struct p9_fid *fid, char *data, char __user *udata,
u64 offset, u32 count);
int p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
u64 offset, u32 count);
int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset);
int p9dirent_read(char *buf, int len, struct p9_dirent *dirent,
int proto_version);
struct p9_wstat *p9_client_stat(struct p9_fid *fid);
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst);

Expand Down
47 changes: 47 additions & 0 deletions trunk/net/9p/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1432,3 +1432,50 @@ int p9_client_rename(struct p9_fid *fid, struct p9_fid *newdirfid, char *name)
}
EXPORT_SYMBOL(p9_client_rename);

int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset)
{
int err, rsize, total;
struct p9_client *clnt;
struct p9_req_t *req;
char *dataptr;

P9_DPRINTK(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n",
fid->fid, (long long unsigned) offset, count);

err = 0;
clnt = fid->clnt;
total = 0;

rsize = fid->iounit;
if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ)
rsize = clnt->msize - P9_READDIRHDRSZ;

if (count < rsize)
rsize = count;

req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, offset, rsize);
if (IS_ERR(req)) {
err = PTR_ERR(req);
goto error;
}

err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr);
if (err) {
p9pdu_dump(1, req->rc);
goto free_and_error;
}

P9_DPRINTK(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count);

if (data)
memmove(data, dataptr, count);

p9_free_req(clnt, req);
return count;

free_and_error:
p9_free_req(clnt, req);
error:
return err;
}
EXPORT_SYMBOL(p9_client_readdir);
27 changes: 27 additions & 0 deletions trunk/net/9p/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,3 +580,30 @@ void p9pdu_reset(struct p9_fcall *pdu)
pdu->offset = 0;
pdu->size = 0;
}

int p9dirent_read(char *buf, int len, struct p9_dirent *dirent,
int proto_version)
{
struct p9_fcall fake_pdu;
int ret;
char *nameptr;

fake_pdu.size = len;
fake_pdu.capacity = len;
fake_pdu.sdata = buf;
fake_pdu.offset = 0;

ret = p9pdu_readf(&fake_pdu, proto_version, "Qqbs", &dirent->qid,
&dirent->d_off, &dirent->d_type, &nameptr);
if (ret) {
P9_DPRINTK(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret);
p9pdu_dump(1, &fake_pdu);
goto out;
}

strcpy(dirent->d_name, nameptr);

out:
return fake_pdu.offset;
}
EXPORT_SYMBOL(p9dirent_read);

0 comments on commit 52260fd

Please sign in to comment.