aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/relay.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/relay.c')
-rw-r--r--kernel/relay.c175
1 files changed, 91 insertions, 84 deletions
diff --git a/kernel/relay.c b/kernel/relay.c
index fefe2b2a7277..33345e73485c 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -866,131 +866,138 @@ static size_t relay_file_read_end_pos(struct rchan_buf *buf,
866} 866}
867 867
868/** 868/**
869 * relay_file_read - read file op for relay files 869 * subbuf_read_actor - read up to one subbuf's worth of data
870 * @filp: the file
871 * @buffer: the userspace buffer
872 * @count: number of bytes to read
873 * @ppos: position to read from
874 *
875 * Reads count bytes or the number of bytes available in the
876 * current sub-buffer being read, whichever is smaller.
877 */ 870 */
878static ssize_t relay_file_read(struct file *filp, 871static int subbuf_read_actor(size_t read_start,
879 char __user *buffer, 872 struct rchan_buf *buf,
880 size_t count, 873 size_t avail,
881 loff_t *ppos) 874 read_descriptor_t *desc,
875 read_actor_t actor)
882{ 876{
883 struct rchan_buf *buf = filp->private_data;
884 struct inode *inode = filp->f_dentry->d_inode;
885 size_t read_start, avail;
886 ssize_t ret = 0;
887 void *from; 877 void *from;
888 878 int ret = 0;
889 mutex_lock(&inode->i_mutex);
890 if(!relay_file_read_avail(buf, *ppos))
891 goto out;
892
893 read_start = relay_file_read_start_pos(*ppos, buf);
894 avail = relay_file_read_subbuf_avail(read_start, buf);
895 if (!avail)
896 goto out;
897 879
898 from = buf->start + read_start; 880 from = buf->start + read_start;
899 ret = count = min(count, avail); 881 ret = avail;
900 if (copy_to_user(buffer, from, count)) { 882 if (copy_to_user(desc->arg.data, from, avail)) {
901 ret = -EFAULT; 883 desc->error = -EFAULT;
902 goto out; 884 ret = 0;
903 } 885 }
904 relay_file_read_consume(buf, read_start, count); 886 desc->arg.data += ret;
905 *ppos = relay_file_read_end_pos(buf, read_start, count); 887 desc->written += ret;
906out: 888 desc->count -= ret;
907 mutex_unlock(&inode->i_mutex); 889
908 return ret; 890 return ret;
909} 891}
910 892
911static ssize_t relay_file_sendsubbuf(struct file *filp, loff_t *ppos, 893/**
912 size_t count, read_actor_t actor, 894 * subbuf_send_actor - send up to one subbuf's worth of data
913 void *target) 895 */
896static int subbuf_send_actor(size_t read_start,
897 struct rchan_buf *buf,
898 size_t avail,
899 read_descriptor_t *desc,
900 read_actor_t actor)
914{ 901{
915 struct rchan_buf *buf = filp->private_data;
916 read_descriptor_t desc;
917 size_t read_start, avail;
918 unsigned long pidx, poff; 902 unsigned long pidx, poff;
919 unsigned int subbuf_pages; 903 unsigned int subbuf_pages;
920 ssize_t ret = 0; 904 int ret = 0;
921
922 if (!relay_file_read_avail(buf, *ppos))
923 return 0;
924
925 read_start = relay_file_read_start_pos(*ppos, buf);
926 avail = relay_file_read_subbuf_avail(read_start, buf);
927 if (!avail)
928 return 0;
929
930 count = min(count, avail);
931
932 desc.written = 0;
933 desc.count = count;
934 desc.arg.data = target;
935 desc.error = 0;
936 905
937 subbuf_pages = buf->chan->alloc_size >> PAGE_SHIFT; 906 subbuf_pages = buf->chan->alloc_size >> PAGE_SHIFT;
938 pidx = (read_start / PAGE_SIZE) % subbuf_pages; 907 pidx = (read_start / PAGE_SIZE) % subbuf_pages;
939 poff = read_start & ~PAGE_MASK; 908 poff = read_start & ~PAGE_MASK;
940 while (count) { 909 while (avail) {
941 struct page *p = buf->page_array[pidx]; 910 struct page *p = buf->page_array[pidx];
942 unsigned int len; 911 unsigned int len;
943 912
944 len = PAGE_SIZE - poff; 913 len = PAGE_SIZE - poff;
945 if (len > count) 914 if (len > avail)
946 len = count; 915 len = avail;
947 916
948 len = actor(&desc, p, poff, len); 917 len = actor(desc, p, poff, len);
949 918 if (desc->error)
950 if (desc.error) {
951 if (!ret)
952 ret = desc.error;
953 break; 919 break;
954 }
955 920
956 count -= len; 921 avail -= len;
957 ret += len; 922 ret += len;
958 poff = 0; 923 poff = 0;
959 pidx = (pidx + 1) % subbuf_pages; 924 pidx = (pidx + 1) % subbuf_pages;
960 } 925 }
961 926
962 if (ret > 0) {
963 relay_file_read_consume(buf, read_start, ret);
964 *ppos = relay_file_read_end_pos(buf, read_start, ret);
965 }
966
967 return ret; 927 return ret;
968} 928}
969 929
970static ssize_t relay_file_sendfile(struct file *filp, loff_t *ppos, 930typedef int (*subbuf_actor_t) (size_t read_start,
971 size_t count, read_actor_t actor, 931 struct rchan_buf *buf,
972 void *target) 932 size_t avail,
933 read_descriptor_t *desc,
934 read_actor_t actor);
935
936/**
937 * relay_file_read_subbufs - read count bytes, bridging subbuf boundaries
938 */
939static inline ssize_t relay_file_read_subbufs(struct file *filp,
940 loff_t *ppos,
941 size_t count,
942 subbuf_actor_t subbuf_actor,
943 read_actor_t actor,
944 void *target)
973{ 945{
974 ssize_t sent = 0, ret = 0; 946 struct rchan_buf *buf = filp->private_data;
947 size_t read_start, avail;
948 read_descriptor_t desc;
949 int ret;
975 950
976 if (!count) 951 if (!count)
977 return 0; 952 return 0;
978 953
979 mutex_lock(&filp->f_dentry->d_inode->i_mutex); 954 desc.written = 0;
955 desc.count = count;
956 desc.arg.data = target;
957 desc.error = 0;
980 958
959 mutex_lock(&filp->f_dentry->d_inode->i_mutex);
981 do { 960 do {
982 ret = relay_file_sendsubbuf(filp, ppos, count, actor, target); 961 if (!relay_file_read_avail(buf, *ppos))
983 if (ret < 0) { 962 break;
984 if (!sent) 963
985 sent = ret; 964 read_start = relay_file_read_start_pos(*ppos, buf);
965 avail = relay_file_read_subbuf_avail(read_start, buf);
966 if (!avail)
986 break; 967 break;
987 }
988 count -= ret;
989 sent += ret;
990 } while (count && ret);
991 968
969 avail = min(desc.count, avail);
970 ret = subbuf_actor(read_start, buf, avail, &desc, actor);
971 if (desc.error < 0)
972 break;
973
974 if (ret) {
975 relay_file_read_consume(buf, read_start, ret);
976 *ppos = relay_file_read_end_pos(buf, read_start, ret);
977 }
978 } while (desc.count && ret);
992 mutex_unlock(&filp->f_dentry->d_inode->i_mutex); 979 mutex_unlock(&filp->f_dentry->d_inode->i_mutex);
993 return sent; 980
981 return desc.written;
982}
983
984static ssize_t relay_file_read(struct file *filp,
985 char __user *buffer,
986 size_t count,
987 loff_t *ppos)
988{
989 return relay_file_read_subbufs(filp, ppos, count, subbuf_read_actor,
990 NULL, buffer);
991}
992
993static ssize_t relay_file_sendfile(struct file *filp,
994 loff_t *ppos,
995 size_t count,
996 read_actor_t actor,
997 void *target)
998{
999 return relay_file_read_subbufs(filp, ppos, count, subbuf_send_actor,
1000 actor, target);
994} 1001}
995 1002
996struct file_operations relay_file_operations = { 1003struct file_operations relay_file_operations = {