diff options
| -rw-r--r-- | drivers/usb/gadget/function/f_fs.c | 136 |
1 files changed, 58 insertions, 78 deletions
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 98610e4595de..175c9956cbe3 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c | |||
| @@ -864,38 +864,6 @@ error: | |||
| 864 | return ret; | 864 | return ret; |
| 865 | } | 865 | } |
| 866 | 866 | ||
| 867 | static ssize_t | ||
| 868 | ffs_epfile_write(struct file *file, const char __user *buf, size_t len, | ||
| 869 | loff_t *ptr) | ||
| 870 | { | ||
| 871 | struct ffs_io_data io_data; | ||
| 872 | struct iovec iov = {.iov_base = buf, .iov_len = len}; | ||
| 873 | |||
| 874 | ENTER(); | ||
| 875 | |||
| 876 | io_data.aio = false; | ||
| 877 | io_data.read = false; | ||
| 878 | iov_iter_init(&io_data.data, WRITE, &iov, 1, len); | ||
| 879 | |||
| 880 | return ffs_epfile_io(file, &io_data); | ||
| 881 | } | ||
| 882 | |||
| 883 | static ssize_t | ||
| 884 | ffs_epfile_read(struct file *file, char __user *buf, size_t len, loff_t *ptr) | ||
| 885 | { | ||
| 886 | struct ffs_io_data io_data; | ||
| 887 | struct iovec iov = {.iov_base = buf, .iov_len = len}; | ||
| 888 | |||
| 889 | ENTER(); | ||
| 890 | |||
| 891 | io_data.aio = false; | ||
| 892 | io_data.read = true; | ||
| 893 | io_data.to_free = NULL; | ||
| 894 | iov_iter_init(&io_data.data, READ, &iov, 1, len); | ||
| 895 | |||
| 896 | return ffs_epfile_io(file, &io_data); | ||
| 897 | } | ||
| 898 | |||
| 899 | static int | 867 | static int |
| 900 | ffs_epfile_open(struct inode *inode, struct file *file) | 868 | ffs_epfile_open(struct inode *inode, struct file *file) |
| 901 | { | 869 | { |
| @@ -932,72 +900,84 @@ static int ffs_aio_cancel(struct kiocb *kiocb) | |||
| 932 | return value; | 900 | return value; |
| 933 | } | 901 | } |
| 934 | 902 | ||
| 935 | static ssize_t ffs_epfile_aio_write(struct kiocb *kiocb, | 903 | static ssize_t ffs_epfile_write_iter(struct kiocb *kiocb, struct iov_iter *from) |
| 936 | const struct iovec *iovec, | ||
| 937 | unsigned long nr_segs, loff_t loff) | ||
| 938 | { | 904 | { |
| 939 | struct ffs_io_data *io_data; | 905 | struct ffs_io_data io_data, *p = &io_data; |
| 940 | ssize_t res; | 906 | ssize_t res; |
| 941 | 907 | ||
| 942 | ENTER(); | 908 | ENTER(); |
| 943 | 909 | ||
| 944 | io_data = kmalloc(sizeof(*io_data), GFP_KERNEL); | 910 | if (!is_sync_kiocb(kiocb)) { |
| 945 | if (unlikely(!io_data)) | 911 | p = kmalloc(sizeof(io_data), GFP_KERNEL); |
| 946 | return -ENOMEM; | 912 | if (unlikely(!p)) |
| 913 | return -ENOMEM; | ||
| 914 | p->aio = true; | ||
| 915 | } else { | ||
| 916 | p->aio = false; | ||
| 917 | } | ||
| 947 | 918 | ||
| 948 | io_data->aio = true; | 919 | p->read = false; |
| 949 | io_data->read = false; | 920 | p->kiocb = kiocb; |
| 950 | io_data->kiocb = kiocb; | 921 | p->data = *from; |
| 951 | iov_iter_init(&io_data->data, WRITE, iovec, nr_segs, kiocb->ki_nbytes); | 922 | p->mm = current->mm; |
| 952 | io_data->mm = current->mm; | ||
| 953 | 923 | ||
| 954 | kiocb->private = io_data; | 924 | kiocb->private = p; |
| 955 | 925 | ||
| 956 | kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); | 926 | kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); |
| 957 | 927 | ||
| 958 | res = ffs_epfile_io(kiocb->ki_filp, io_data); | 928 | res = ffs_epfile_io(kiocb->ki_filp, p); |
| 959 | if (res != -EIOCBQUEUED) | 929 | if (res == -EIOCBQUEUED) |
| 960 | kfree(io_data); | 930 | return res; |
| 931 | if (p->aio) | ||
| 932 | kfree(p); | ||
| 933 | else | ||
| 934 | *from = p->data; | ||
| 961 | return res; | 935 | return res; |
| 962 | } | 936 | } |
| 963 | 937 | ||
| 964 | static ssize_t ffs_epfile_aio_read(struct kiocb *kiocb, | 938 | static ssize_t ffs_epfile_read_iter(struct kiocb *kiocb, struct iov_iter *to) |
| 965 | const struct iovec *iovec, | ||
| 966 | unsigned long nr_segs, loff_t loff) | ||
| 967 | { | 939 | { |
| 968 | struct ffs_io_data *io_data; | 940 | struct ffs_io_data io_data, *p = &io_data; |
| 969 | struct iovec *iovec_copy; | ||
| 970 | ssize_t res; | 941 | ssize_t res; |
| 971 | 942 | ||
| 972 | ENTER(); | 943 | ENTER(); |
| 973 | 944 | ||
| 974 | iovec_copy = kmalloc_array(nr_segs, sizeof(*iovec_copy), GFP_KERNEL); | 945 | if (!is_sync_kiocb(kiocb)) { |
| 975 | if (unlikely(!iovec_copy)) | 946 | p = kmalloc(sizeof(io_data), GFP_KERNEL); |
| 976 | return -ENOMEM; | 947 | if (unlikely(!p)) |
| 977 | 948 | return -ENOMEM; | |
| 978 | memcpy(iovec_copy, iovec, sizeof(struct iovec)*nr_segs); | 949 | p->aio = true; |
| 979 | 950 | } else { | |
| 980 | io_data = kmalloc(sizeof(*io_data), GFP_KERNEL); | 951 | p->aio = false; |
| 981 | if (unlikely(!io_data)) { | ||
| 982 | kfree(iovec_copy); | ||
| 983 | return -ENOMEM; | ||
| 984 | } | 952 | } |
| 985 | 953 | ||
| 986 | io_data->aio = true; | 954 | p->read = true; |
| 987 | io_data->read = true; | 955 | p->kiocb = kiocb; |
| 988 | io_data->kiocb = kiocb; | 956 | if (p->aio) { |
| 989 | io_data->to_free = iovec_copy; | 957 | p->to_free = dup_iter(&p->data, to, GFP_KERNEL); |
| 990 | iov_iter_init(&io_data->data, READ, iovec_copy, nr_segs, kiocb->ki_nbytes); | 958 | if (!p->to_free) { |
| 991 | io_data->mm = current->mm; | 959 | kfree(p); |
| 960 | return -ENOMEM; | ||
| 961 | } | ||
| 962 | } else { | ||
| 963 | p->data = *to; | ||
| 964 | p->to_free = NULL; | ||
| 965 | } | ||
| 966 | p->mm = current->mm; | ||
| 992 | 967 | ||
| 993 | kiocb->private = io_data; | 968 | kiocb->private = p; |
| 994 | 969 | ||
| 995 | kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); | 970 | kiocb_set_cancel_fn(kiocb, ffs_aio_cancel); |
| 996 | 971 | ||
| 997 | res = ffs_epfile_io(kiocb->ki_filp, io_data); | 972 | res = ffs_epfile_io(kiocb->ki_filp, p); |
| 998 | if (res != -EIOCBQUEUED) { | 973 | if (res == -EIOCBQUEUED) |
| 999 | kfree(io_data->to_free); | 974 | return res; |
| 1000 | kfree(io_data); | 975 | |
| 976 | if (p->aio) { | ||
| 977 | kfree(p->to_free); | ||
| 978 | kfree(p); | ||
| 979 | } else { | ||
| 980 | *to = p->data; | ||
| 1001 | } | 981 | } |
| 1002 | return res; | 982 | return res; |
| 1003 | } | 983 | } |
| @@ -1079,10 +1059,10 @@ static const struct file_operations ffs_epfile_operations = { | |||
| 1079 | .llseek = no_llseek, | 1059 | .llseek = no_llseek, |
| 1080 | 1060 | ||
| 1081 | .open = ffs_epfile_open, | 1061 | .open = ffs_epfile_open, |
| 1082 | .write = ffs_epfile_write, | 1062 | .write = new_sync_write, |
| 1083 | .read = ffs_epfile_read, | 1063 | .read = new_sync_read, |
| 1084 | .aio_write = ffs_epfile_aio_write, | 1064 | .write_iter = ffs_epfile_write_iter, |
| 1085 | .aio_read = ffs_epfile_aio_read, | 1065 | .read_iter = ffs_epfile_read_iter, |
| 1086 | .release = ffs_epfile_release, | 1066 | .release = ffs_epfile_release, |
| 1087 | .unlocked_ioctl = ffs_epfile_ioctl, | 1067 | .unlocked_ioctl = ffs_epfile_ioctl, |
| 1088 | }; | 1068 | }; |
