static void __process_write_request(struct stream *s) { int np = 0; struct stream_request *req; while (!event_list_empty(&s->write_queue[IO_WAIT])) { int ret; req = event_list_first_entry(&s->write_queue[IO_WAIT], struct stream_request, node); ret = __do_write(s, req); if (ret && ret != -EAGAIN && ret != -EINTR) goto out; if (!ret) __move_to_queue(req, &s->write_queue[IO_FIN]); else break; np++; } return; out: __move_to_queue(req, &s->write_queue[IO_FIN]); }
ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos) { struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len }; struct kiocb kiocb; ssize_t ret; init_sync_kiocb(&kiocb, filp); kiocb.ki_pos = *ppos; kiocb.ki_left = len; kiocb.ki_nbytes = len; for (;;) { ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos); if (ret != -EIOCBRETRY) break; wait_on_retry_sync_kiocb(&kiocb); } if (-EIOCBQUEUED == ret) ret = wait_on_sync_kiocb(&kiocb); *ppos = kiocb.ki_pos; return ret; } EXPORT_SYMBOL(do_sync_write); static ssize_t __do_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos) { if (file->f_op->write) return file->f_op->write(file, buf, len, ppos); else return do_sync_write(file, buf, len, ppos); } static ssize_t do_write(struct file *file, const char __user *buf, size_t len, loff_t *ppos, int force_block) { unsigned int saved_flags; ssize_t ret, count; if (!force_block) return __do_write(file, buf, len, ppos); /* Pretty much a copy of do_read() */ saved_flags = file->f_flags; file->f_flags &= ~O_NONBLOCK; ret = 0; while (len > 0) { count = __do_write(file, buf, len, ppos); if (count == 0) break; if (count < 0) { ret = count; break; } len -= count; buf += count; ret += count; } file->f_flags = saved_flags; return ret; }