Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 23279
b: refs/heads/master
c: 6dac40a
h: refs/heads/master
i:
  23277: 26c92df
  23275: dcff7ff
  23271: 99f10c1
  23263: 3040724
v: v3
  • Loading branch information
Tom Zanussi authored and Jens Axboe committed Mar 23, 2006
1 parent 7b2bd3d commit 737bea9
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 85 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: 221415d76231d9012871e6e6abcbad906c46626a
refs/heads/master: 6dac40a7ce2483a47b54af07afebeb84131c7228
175 changes: 91 additions & 84 deletions trunk/kernel/relay.c
Original file line number Diff line number Diff line change
Expand Up @@ -866,131 +866,138 @@ static size_t relay_file_read_end_pos(struct rchan_buf *buf,
}

/**
* relay_file_read - read file op for relay files
* @filp: the file
* @buffer: the userspace buffer
* @count: number of bytes to read
* @ppos: position to read from
*
* Reads count bytes or the number of bytes available in the
* current sub-buffer being read, whichever is smaller.
* subbuf_read_actor - read up to one subbuf's worth of data
*/
static ssize_t relay_file_read(struct file *filp,
char __user *buffer,
size_t count,
loff_t *ppos)
static int subbuf_read_actor(size_t read_start,
struct rchan_buf *buf,
size_t avail,
read_descriptor_t *desc,
read_actor_t actor)
{
struct rchan_buf *buf = filp->private_data;
struct inode *inode = filp->f_dentry->d_inode;
size_t read_start, avail;
ssize_t ret = 0;
void *from;

mutex_lock(&inode->i_mutex);
if(!relay_file_read_avail(buf, *ppos))
goto out;

read_start = relay_file_read_start_pos(*ppos, buf);
avail = relay_file_read_subbuf_avail(read_start, buf);
if (!avail)
goto out;
int ret = 0;

from = buf->start + read_start;
ret = count = min(count, avail);
if (copy_to_user(buffer, from, count)) {
ret = -EFAULT;
goto out;
ret = avail;
if (copy_to_user(desc->arg.data, from, avail)) {
desc->error = -EFAULT;
ret = 0;
}
relay_file_read_consume(buf, read_start, count);
*ppos = relay_file_read_end_pos(buf, read_start, count);
out:
mutex_unlock(&inode->i_mutex);
desc->arg.data += ret;
desc->written += ret;
desc->count -= ret;

return ret;
}

static ssize_t relay_file_sendsubbuf(struct file *filp, loff_t *ppos,
size_t count, read_actor_t actor,
void *target)
/**
* subbuf_send_actor - send up to one subbuf's worth of data
*/
static int subbuf_send_actor(size_t read_start,
struct rchan_buf *buf,
size_t avail,
read_descriptor_t *desc,
read_actor_t actor)
{
struct rchan_buf *buf = filp->private_data;
read_descriptor_t desc;
size_t read_start, avail;
unsigned long pidx, poff;
unsigned int subbuf_pages;
ssize_t ret = 0;

if (!relay_file_read_avail(buf, *ppos))
return 0;

read_start = relay_file_read_start_pos(*ppos, buf);
avail = relay_file_read_subbuf_avail(read_start, buf);
if (!avail)
return 0;

count = min(count, avail);

desc.written = 0;
desc.count = count;
desc.arg.data = target;
desc.error = 0;
int ret = 0;

subbuf_pages = buf->chan->alloc_size >> PAGE_SHIFT;
pidx = (read_start / PAGE_SIZE) % subbuf_pages;
poff = read_start & ~PAGE_MASK;
while (count) {
while (avail) {
struct page *p = buf->page_array[pidx];
unsigned int len;

len = PAGE_SIZE - poff;
if (len > count)
len = count;
if (len > avail)
len = avail;

len = actor(&desc, p, poff, len);

if (desc.error) {
if (!ret)
ret = desc.error;
len = actor(desc, p, poff, len);
if (desc->error)
break;
}

count -= len;
avail -= len;
ret += len;
poff = 0;
pidx = (pidx + 1) % subbuf_pages;
}

if (ret > 0) {
relay_file_read_consume(buf, read_start, ret);
*ppos = relay_file_read_end_pos(buf, read_start, ret);
}

return ret;
}

static ssize_t relay_file_sendfile(struct file *filp, loff_t *ppos,
size_t count, read_actor_t actor,
void *target)
typedef int (*subbuf_actor_t) (size_t read_start,
struct rchan_buf *buf,
size_t avail,
read_descriptor_t *desc,
read_actor_t actor);

/**
* relay_file_read_subbufs - read count bytes, bridging subbuf boundaries
*/
static inline ssize_t relay_file_read_subbufs(struct file *filp,
loff_t *ppos,
size_t count,
subbuf_actor_t subbuf_actor,
read_actor_t actor,
void *target)
{
ssize_t sent = 0, ret = 0;
struct rchan_buf *buf = filp->private_data;
size_t read_start, avail;
read_descriptor_t desc;
int ret;

if (!count)
return 0;

mutex_lock(&filp->f_dentry->d_inode->i_mutex);
desc.written = 0;
desc.count = count;
desc.arg.data = target;
desc.error = 0;

mutex_lock(&filp->f_dentry->d_inode->i_mutex);
do {
ret = relay_file_sendsubbuf(filp, ppos, count, actor, target);
if (ret < 0) {
if (!sent)
sent = ret;
if (!relay_file_read_avail(buf, *ppos))
break;

read_start = relay_file_read_start_pos(*ppos, buf);
avail = relay_file_read_subbuf_avail(read_start, buf);
if (!avail)
break;
}
count -= ret;
sent += ret;
} while (count && ret);

avail = min(desc.count, avail);
ret = subbuf_actor(read_start, buf, avail, &desc, actor);
if (desc.error < 0)
break;

if (ret) {
relay_file_read_consume(buf, read_start, ret);
*ppos = relay_file_read_end_pos(buf, read_start, ret);
}
} while (desc.count && ret);
mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
return sent;

return desc.written;
}

static ssize_t relay_file_read(struct file *filp,
char __user *buffer,
size_t count,
loff_t *ppos)
{
return relay_file_read_subbufs(filp, ppos, count, subbuf_read_actor,
NULL, buffer);
}

static ssize_t relay_file_sendfile(struct file *filp,
loff_t *ppos,
size_t count,
read_actor_t actor,
void *target)
{
return relay_file_read_subbufs(filp, ppos, count, subbuf_send_actor,
actor, target);
}

struct file_operations relay_file_operations = {
Expand Down

0 comments on commit 737bea9

Please sign in to comment.