Ejemplo n.º 1
0
/* wait on the pipes writers queue */
static inline int pipe_wait_write(struct my_pipe_t *pipe)
{
	#ifdef DO_WAITQUEUE
	pipe_unlock(pipe);
	return wait_event_interruptible(pipe->write_queue,
			pipe_writer_should_i_wake_up(pipe));
	#endif /* DO_WAITQUEUE */
	#ifdef DO_WAITQUEUE_RISQUE
	int ret;
	pipe_unlock(pipe);
	ret = wait_event_interruptible(pipe->write_queue, pipe_room(pipe) > 0);
	pipe_lock(pipe);
	return ret;
	#endif /* DO_WAITQUEUE_RISQUE */
	#ifdef DO_SCHEDULE
	int ret;
	DEFINE_WAIT(wait);
	prepare_to_wait(&pipe->write_queue, &wait, TASK_INTERRUPTIBLE);
	pipe_unlock(pipe);
	schedule();
	if (signal_pending(current))
		ret = -ERESTARTSYS;
	else
		ret = 0;
	finish_wait(&pipe->write_queue, &wait);
	pipe_lock(pipe);
	return ret;
	#endif /* DO_SHCEDULE */
	#ifdef DO_NOTHING
	return 0;
	#endif /* DO_NOTHING */
}
Ejemplo n.º 2
0
/*
 * If called with *pipep = NULL, pipe_new will call pipe_alloc to allocate a
 * pipe control structure and set *pipep to its address.
 * pipe is locked, when pipe_new returns with no error.
 */
static int pipe_new(
  pipe_control_t **pipep
)
{
  pipe_control_t *pipe;
  int err = 0;

  err = pipe_lock();
  if (err)
    return err;

  pipe = *pipep;
  if (pipe == NULL) {
    err = pipe_alloc(&pipe);
    if (err)
      goto out;
  }

  if (! PIPE_LOCK(pipe))
    err = -EINTR;

  if (*pipep == NULL) {
    if (err)
      pipe_free(pipe);
    else
      *pipep = pipe;
  }

out:
  pipe_unlock();
  return err;
}
Ejemplo n.º 3
0
static ssize_t pipe_read(struct file *file, char __user *buf, size_t count,
		loff_t *ppos) {
	struct my_pipe_t *pipe;
	size_t data, work_size, first_chunk, second_chunk, ret;
	pr_debug("pipe_read: start with buf %p\n", buf);
	if (!access_ok(VERIFY_WRITE, buf, count))
		return -EFAULT;
	pipe = (struct my_pipe_t *)(file->private_data);
	/* lets sleep while there is no data in the pipe
	 * why do we not just use the waitqueue condition?
	 * because we want to get the pipe LOCKED with data */
	pipe_lock(pipe);
	data = pipe_data(pipe);
	while (data == 0 && pipe->writers > 0) {
		ret = pipe_wait_read(pipe);
		if (ret) {
			pipe_unlock(pipe);
			return ret;
		}
		data = pipe_data(pipe);
	}
	pr_debug("data is %zd\n", data);
	/* EOF handling */
	if (data == 0 && pipe->writers == 0) {
		pr_debug("signaling EOF\n");
		pipe_unlock(pipe);
		return 0;
	}
	/* now data > 0 */
	work_size = min(data, count);
	pr_debug("work_size is %zd\n", work_size);
	/* copy_to_user data from the pipe */
	if (pipe->read_pos <= pipe->write_pos) {
		ret = pipe_copy_to_user(pipe, work_size, &buf);
		if (ret) {
			pipe_unlock(pipe);
			return ret;
		}
	} else {
		first_chunk = min(work_size, pipe->size-pipe->read_pos);
		ret = pipe_copy_to_user(pipe, first_chunk, &buf);
		if (ret) {
			pipe_unlock(pipe);
			return ret;
		}
		if (first_chunk < work_size) {
			second_chunk = work_size-first_chunk;
			ret = pipe_copy_to_user(pipe, second_chunk, &buf);
			if (ret) {
				pipe_unlock(pipe);
				return ret;
			}
		}
	}
	pipe_unlock(pipe);
	*ppos += work_size;
	/* wake up the writers */
	pipe_wake_writers(pipe);
	return work_size;
}
Ejemplo n.º 4
0
static inline int pipe_writer_should_i_wake_up(struct my_pipe_t *pipe)
{
	int ret;
	pipe_lock(pipe);
	ret = pipe_room(pipe) > 0;
	if (!ret)
		pipe_unlock(pipe);
	return ret;
}
Ejemplo n.º 5
0
static inline int pipe_reader_should_i_wake_up(struct my_pipe_t *pipe)
{
	int ret;
	pipe_lock(pipe);
	ret = pipe_data(pipe) > 0 || pipe->writers == 0;
	if (!ret)
		pipe_unlock(pipe);
	return ret;
}
Ejemplo n.º 6
0
/*
 * Interface to file system close.
 *
 * *pipep points to pipe control structure. When the last user releases pipe,
 * it will be set to NULL.
 */
void pipe_release(
  pipe_control_t **pipep,
  rtems_libio_t *iop
)
{
  pipe_control_t *pipe = *pipep;
  uint32_t mode;

  #if defined(RTEMS_DEBUG)
    /* WARN pipe not freed and pipep not set to NULL! */
    if (pipe_lock())
      rtems_fatal_error_occurred(0xdeadbeef);

    /* WARN pipe not released! */
    if (!PIPE_LOCK(pipe))
      rtems_fatal_error_occurred(0xdeadbeef);
  #endif

  mode = LIBIO_ACCMODE(iop);
  if (mode & LIBIO_FLAGS_READ)
     pipe->Readers --;
  if (mode & LIBIO_FLAGS_WRITE)
     pipe->Writers --;

  PIPE_UNLOCK(pipe);

  if (pipe->Readers == 0 && pipe->Writers == 0) {
#if 0
    /* To delete an anonymous pipe file when all users closed it */
    if (pipe->Anonymous)
      delfile = TRUE;
#endif
    pipe_free(pipe);
    *pipep = NULL;
  }
  else if (pipe->Readers == 0 && mode != LIBIO_FLAGS_WRITE)
    /* Notify waiting Writers that all their partners left */
    PIPE_WAKEUPWRITERS(pipe);
  else if (pipe->Writers == 0 && mode != LIBIO_FLAGS_READ)
    PIPE_WAKEUPREADERS(pipe);

  pipe_unlock();

#if 0
  if (! delfile)
    return;
  if (iop->pathinfo.ops->unlink_h == NULL)
    return;

  /* This is safe for IMFS, but how about other FSes? */
  iop->flags &= ~LIBIO_FLAGS_OPEN;
  if(iop->pathinfo.ops->unlink_h(&iop->pathinfo))
    return;
#endif

}
Ejemplo n.º 7
0
static ssize_t pipe_write(struct file *file, const char __user *buf,
		size_t count, loff_t *ppos) {
	struct my_pipe_t *pipe;
	size_t work_size, room, first_chunk, second_chunk, ret;
	pr_debug("pipe_write: start\n");
	if (!access_ok(VERIFY_READ, buf, count))
		return -EFAULT;
	pipe = (struct my_pipe_t *)(file->private_data);
	/* lets check if we have room in the pipe
	 * why do we not just use the waitqueue condition?
	 * because we want to get the pipe LOCKED with data
	 */
	pipe_lock(pipe);
	room = pipe_room(pipe);
	while (room == 0) {
		ret = pipe_wait_write(pipe);
		if (ret) {
			pipe_unlock(pipe);
			return ret;
		}
		room = pipe_room(pipe);
	}
	pr_debug("room is %zd\n", room);
	/* now room > 0 */
	work_size = min(room, count);
	pr_debug("work_size is %zd\n", work_size);
	/* copy_from_user data from the pipe */
	if (pipe->read_pos <= pipe->write_pos) {
		first_chunk = min(work_size, pipe->size-pipe->write_pos);
		ret = pipe_copy_from_user(pipe, first_chunk, &buf);
		if (ret) {
			pipe_unlock(pipe);
			return ret;
		}
		if (first_chunk < work_size) {
			second_chunk = work_size-first_chunk;
			ret = pipe_copy_from_user(pipe, second_chunk, &buf);
			if (ret) {
				pipe_unlock(pipe);
				return ret;
			}
		}
	} else {
		ret = pipe_copy_from_user(pipe, work_size, &buf);
		if (ret) {
			pipe_unlock(pipe);
			return ret;
		}
	}
	pipe_unlock(pipe);
	*ppos += work_size;
	/* wake up the readers */
	pipe_wake_readers(pipe);
	return work_size;
}
Ejemplo n.º 8
0
static void post_write_request(OutputBuffer * bf) {
    ChannelPIPE * c = obuf2pipe(bf->queue);
    c->out_req.client_data = c;
    c->out_req.done = done_write_request;
    c->out_req.type = AsyncReqWrite;
    c->out_req.u.fio.fd = c->fd_out;
    c->out_req.u.fio.bufp = bf->buf + bf->buf_pos;
    c->out_req.u.fio.bufsz = bf->buf_len - bf->buf_pos;
    async_req_post(&c->out_req);
    pipe_lock(c->chan);
}
Ejemplo n.º 9
0
static void wait_for_dump_helpers(struct file *file)
{
	struct pipe_inode_info *pipe;

	pipe = file_inode(file)->i_pipe;

	pipe_lock(pipe);
	pipe->readers++;
	pipe->writers--;
	wake_up_interruptible_sync(&pipe->wait);
	kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
	pipe_unlock(pipe);

	wait_event_freezable(pipe->wait, pipe->readers == 1);

	pipe_lock(pipe);
	pipe->readers--;
	pipe->writers++;
	pipe_unlock(pipe);
}
Ejemplo n.º 10
0
static void wait_for_dump_helpers(struct file *file)
{
	struct pipe_inode_info *pipe = file->private_data;

	pipe_lock(pipe);
	pipe->readers++;
	pipe->writers--;
	wake_up_interruptible_sync(&pipe->wait);
	kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
	pipe_unlock(pipe);

	/*
	 * We actually want wait_event_freezable() but then we need
	 * to clear TIF_SIGPENDING and improve dump_interrupted().
	 */
	wait_event_interruptible(pipe->wait, pipe->readers == 1);

	pipe_lock(pipe);
	pipe->readers--;
	pipe->writers++;
	pipe_unlock(pipe);
}
Ejemplo n.º 11
0
/* Drop the inode semaphore and wait for a pipe event, atomically */
void pipe_wait(struct pipe_inode_info *pipe)
{
	DEFINE_WAIT(wait);

	/*
	 * Pipes are system-local resources, so sleeping on them
	 * is considered a noninteractive wait:
	 */
	prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE);
	pipe_unlock(pipe);
	schedule();
	finish_wait(&pipe->wait, &wait);
	pipe_lock(pipe);
}
Ejemplo n.º 12
0
static int pipe_open(struct inode *inode, struct file *filp)
{
	/* hide the pipe in the private_data of the struct file... */
	int the_pipe_number = iminor(inode)-MINOR(first_dev);
	struct my_pipe_t *pipe = pipes+the_pipe_number;
#ifdef DO_MUTEX
	pipe->inode = inode;
#endif /* DO_MUTEX */
	filp->private_data = pipe;
	pipe_lock(pipe);
	if (filp->f_mode & FMODE_READ)
		pipe->readers++;
	if (filp->f_mode & FMODE_WRITE)
		pipe->writers++;
	pipe_unlock(pipe);
	return 0;
}
Ejemplo n.º 13
0
static void wait_for_dump_helpers(struct file *file)
{
	struct pipe_inode_info *pipe;

	pipe = file_inode(file)->i_pipe;

	pipe_lock(pipe);
	pipe->readers++;
	pipe->writers--;

	while ((pipe->readers > 1) && (!signal_pending(current))) {
		wake_up_interruptible_sync(&pipe->wait);
		kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
		pipe_wait(pipe);
	}

	pipe->readers--;
	pipe->writers++;
	pipe_unlock(pipe);

}
Ejemplo n.º 14
0
static int pipe_release(struct inode *inode, struct file *filp)
{
	struct my_pipe_t *pipe;
	pipe = (struct my_pipe_t *)(filp->private_data);
	pipe_lock(pipe);
	if (filp->f_mode & FMODE_READ)
		pipe->readers--;
	if (filp->f_mode & FMODE_WRITE)
		pipe->writers--;
	/* wake up readers since they may want to end if there
	are no more writers...
	*/
	if (filp->f_mode & FMODE_WRITE) {
		if (pipe->writers == 0) {
			pr_debug("pipe_release: no more writers, waking up readers...\n");
			pipe_wake_readers(pipe);
		}
	}
	pipe_unlock(pipe);
	return 0;
}
Ejemplo n.º 15
0
static void pipe_write_stream(OutputStream * out, int byte) {
    ChannelPIPE * c = channel2pipe(out2channel(out));
    assert(c->magic == CHANNEL_MAGIC);
    if (c->chan->state == ChannelStateDisconnected) return;
    if (c->chan->out.cur == c->chan->out.end) pipe_flush(c);
    if (byte < 0 || byte == ESC) {
        char esc = 0;
        *c->chan->out.cur++ = ESC;
        if (byte == ESC) esc = 0;
        else if (byte == MARKER_EOM) esc = 1;
        else if (byte == MARKER_EOS) esc = 2;
        else assert(0);
        if (c->chan->state == ChannelStateDisconnected) return;
        if (c->chan->out.cur == c->chan->out.end) pipe_flush(c);
        *c->chan->out.cur++ = esc;
        if (byte == MARKER_EOM && c->out_flush_cnt < 2) {
            if (c->out_flush_cnt++ == 0) pipe_lock(c->chan);
            post_event_with_delay(pipe_flush_event, c, 0);
        }
        return;
    }
    *c->chan->out.cur++ = (char)byte;
}
Ejemplo n.º 16
0
/*
 * Almost copy of generic_file_splice_write() (added changed_begin/end,
 * tux3_iattrdirty()).
 */
static ssize_t tux3_file_splice_write(struct pipe_inode_info *pipe,
				      struct file *out, loff_t *ppos,
				      size_t len, unsigned int flags)
{
	if(DEBUG_MODE_K==1)
	{
		printk(KERN_INFO"%25s  %25s  %4d  #in\n",__FILE__,__func__,__LINE__);
	}
	struct address_space *mapping = out->f_mapping;
	struct inode *inode = mapping->host;
	struct sb *sb = tux_sb(inode->i_sb);
	struct splice_desc sd = {
		.total_len = len,
		.flags = flags,
		.pos = *ppos,
		.u.file = out,
	};
	ssize_t ret;

	sb_start_write(inode->i_sb);

	pipe_lock(pipe);

	splice_from_pipe_begin(&sd);
	do {
		ret = splice_from_pipe_next(pipe, &sd);
		if (ret <= 0)
			break;

		mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
		/* For each ->write_end() calls change_end(). */
		change_begin(sb);
		/* For timestamp. FIXME: convert this to ->update_time
		 * handler? */
		tux3_iattrdirty(inode);
		ret = file_remove_suid(out);
		if (!ret) {
			ret = file_update_time(out);
			if (!ret)
				ret = splice_from_pipe_feed(pipe, &sd,
							    pipe_to_file);
		}
		change_end_if_needed(sb);
		mutex_unlock(&inode->i_mutex);
	} while (ret > 0);
	splice_from_pipe_end(pipe, &sd);

	pipe_unlock(pipe);

	if (sd.num_spliced)
		ret = sd.num_spliced;

	if (ret > 0) {
		int err;

		err = generic_write_sync(out, *ppos, ret);
		if (err)
			ret = err;
		else
			*ppos += ret;
		balance_dirty_pages_ratelimited(mapping);
	}
	sb_end_write(inode->i_sb);

	return ret;
}
Ejemplo n.º 17
0
Archivo: file.c Proyecto: macan/SVFS
static
ssize_t svfs_file_splice_write(struct pipe_inode_info *pipe, 
                               struct file *out, loff_t *ppos, size_t len,
                               unsigned int flags)
{
    struct address_space *mapping;
    struct inode *inode;
    struct file *llfs_filp;
    struct svfs_inode *si;
    struct splice_desc sd = {0,};
    ssize_t ret;

    svfs_entry(mdc, "pos %lu, len %ld, flags 0x%x\n", (unsigned long)*ppos,
               (long)len, flags);

    si = SVFS_I(out->f_dentry->d_inode);
    if (si->state & SVFS_STATE_DA) {
        /* create it now */
        ASSERT(!(si->state & SVFS_STATE_CONN));
        ret = llfs_create(out->f_dentry);
        if (ret)
            goto out;
    }
    if (!(si->state & SVFS_STATE_CONN)) {
        /* open it ? */
        ret = llfs_lookup(out->f_dentry->d_inode);
        if (ret)
            goto out;
    }
    llfs_filp = si->llfs_md.llfs_filp;
    ASSERT(llfs_filp);
    mapping = llfs_filp->f_mapping;
    inode = mapping->host;
    sd.total_len = len;
    sd.flags = flags;
    sd.pos = *ppos;
    sd.u.file = llfs_filp;

    pipe_lock(pipe);

    splice_from_pipe_begin(&sd);
    do {
        ret = splice_from_pipe_next(pipe, &sd);
        if (ret <= 0)
            break;

        mutex_lock_nested(&inode->i_mutex, I_MUTEX_CHILD);
        ret = file_remove_suid(out);
        if (!ret)
            ret = splice_from_pipe_feed(pipe, &sd, pipe_to_file);
        mutex_unlock(&inode->i_mutex);
    } while (ret > 0);
    splice_from_pipe_end(pipe, &sd);

    pipe_unlock(pipe);

    if (sd.num_spliced)
        ret = sd.num_spliced;

    if (ret > 0) {
        unsigned long nr_pages;

        *ppos += ret;
        nr_pages = (ret + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;

		/*
		 * If file or inode is SYNC and we actually wrote some data,
		 * sync it.
		 */
        if (unlikely((out->f_flags & O_SYNC) || IS_SYNC(inode))) {
            int err;

            mutex_lock(&inode->i_mutex);
            err = generic_osync_inode(inode, mapping,
                                      OSYNC_METADATA|OSYNC_DATA);
            mutex_unlock(&inode->i_mutex);

            if (err)
                ret = err;
        }
        balance_dirty_pages_ratelimited_nr(mapping, nr_pages);
    }