Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'work.__copy_to_user' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull more __copy_.._user elimination from Al Viro.

* 'work.__copy_to_user' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
drm_dp_aux_dev: switch to read_iter/write_iter

+46 -63
+46 -63
drivers/gpu/drm/drm_dp_aux_dev.c
··· 32 32 #include <linux/kernel.h> 33 33 #include <linux/module.h> 34 34 #include <linux/uaccess.h> 35 + #include <linux/uio.h> 35 36 #include <drm/drm_dp_helper.h> 36 37 #include <drm/drm_crtc.h> 37 38 #include <drm/drmP.h> ··· 141 140 return fixed_size_llseek(file, offset, whence, AUX_MAX_OFFSET); 142 141 } 143 142 144 - static ssize_t auxdev_read(struct file *file, char __user *buf, size_t count, 145 - loff_t *offset) 143 + static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to) 146 144 { 147 - size_t bytes_pending, num_bytes_processed = 0; 148 - struct drm_dp_aux_dev *aux_dev = file->private_data; 145 + struct drm_dp_aux_dev *aux_dev = iocb->ki_filp->private_data; 146 + loff_t pos = iocb->ki_pos; 149 147 ssize_t res = 0; 150 148 151 149 if (!atomic_inc_not_zero(&aux_dev->usecount)) 152 150 return -ENODEV; 153 151 154 - bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - (*offset)); 152 + iov_iter_truncate(to, AUX_MAX_OFFSET - pos); 155 153 156 - if (!access_ok(VERIFY_WRITE, buf, bytes_pending)) { 157 - res = -EFAULT; 158 - goto out; 159 - } 160 - 161 - while (bytes_pending > 0) { 162 - uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES]; 163 - ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf)); 154 + while (iov_iter_count(to)) { 155 + uint8_t buf[DP_AUX_MAX_PAYLOAD_BYTES]; 156 + ssize_t todo = min(iov_iter_count(to), sizeof(buf)); 164 157 165 158 if (signal_pending(current)) { 166 - res = num_bytes_processed ? 167 - num_bytes_processed : -ERESTARTSYS; 168 - goto out; 159 + res = -ERESTARTSYS; 160 + break; 169 161 } 170 162 171 - res = drm_dp_dpcd_read(aux_dev->aux, *offset, localbuf, todo); 172 - if (res <= 0) { 173 - res = num_bytes_processed ? num_bytes_processed : res; 174 - goto out; 163 + res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo); 164 + if (res <= 0) 165 + break; 166 + 167 + if (copy_to_iter(buf, res, to) != res) { 168 + res = -EFAULT; 169 + break; 175 170 } 176 - if (__copy_to_user(buf + num_bytes_processed, localbuf, res)) { 177 - res = num_bytes_processed ? 178 - num_bytes_processed : -EFAULT; 179 - goto out; 180 - } 181 - bytes_pending -= res; 182 - *offset += res; 183 - num_bytes_processed += res; 184 - res = num_bytes_processed; 171 + 172 + pos += res; 185 173 } 186 174 187 - out: 175 + if (pos != iocb->ki_pos) 176 + res = pos - iocb->ki_pos; 177 + iocb->ki_pos = pos; 178 + 188 179 atomic_dec(&aux_dev->usecount); 189 180 wake_up_atomic_t(&aux_dev->usecount); 190 181 return res; 191 182 } 192 183 193 - static ssize_t auxdev_write(struct file *file, const char __user *buf, 194 - size_t count, loff_t *offset) 184 + static ssize_t auxdev_write_iter(struct kiocb *iocb, struct iov_iter *from) 195 185 { 196 - size_t bytes_pending, num_bytes_processed = 0; 197 - struct drm_dp_aux_dev *aux_dev = file->private_data; 186 + struct drm_dp_aux_dev *aux_dev = iocb->ki_filp->private_data; 187 + loff_t pos = iocb->ki_pos; 198 188 ssize_t res = 0; 199 189 200 190 if (!atomic_inc_not_zero(&aux_dev->usecount)) 201 191 return -ENODEV; 202 192 203 - bytes_pending = min((loff_t)count, AUX_MAX_OFFSET - *offset); 193 + iov_iter_truncate(from, AUX_MAX_OFFSET - pos); 204 194 205 - if (!access_ok(VERIFY_READ, buf, bytes_pending)) { 206 - res = -EFAULT; 207 - goto out; 208 - } 209 - 210 - while (bytes_pending > 0) { 211 - uint8_t localbuf[DP_AUX_MAX_PAYLOAD_BYTES]; 212 - ssize_t todo = min_t(size_t, bytes_pending, sizeof(localbuf)); 195 + while (iov_iter_count(from)) { 196 + uint8_t buf[DP_AUX_MAX_PAYLOAD_BYTES]; 197 + ssize_t todo = min(iov_iter_count(from), sizeof(buf)); 213 198 214 199 if (signal_pending(current)) { 215 - res = num_bytes_processed ? 216 - num_bytes_processed : -ERESTARTSYS; 217 - goto out; 200 + res = -ERESTARTSYS; 201 + break; 218 202 } 219 203 220 - if (__copy_from_user(localbuf, 221 - buf + num_bytes_processed, todo)) { 222 - res = num_bytes_processed ? 223 - num_bytes_processed : -EFAULT; 224 - goto out; 204 + if (!copy_from_iter_full(buf, todo, from)) { 205 + res = -EFAULT; 206 + break; 225 207 } 226 208 227 - res = drm_dp_dpcd_write(aux_dev->aux, *offset, localbuf, todo); 228 - if (res <= 0) { 229 - res = num_bytes_processed ? num_bytes_processed : res; 230 - goto out; 231 - } 232 - bytes_pending -= res; 233 - *offset += res; 234 - num_bytes_processed += res; 235 - res = num_bytes_processed; 209 + res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo); 210 + if (res <= 0) 211 + break; 212 + 213 + pos += res; 236 214 } 237 215 238 - out: 216 + if (pos != iocb->ki_pos) 217 + res = pos - iocb->ki_pos; 218 + iocb->ki_pos = pos; 219 + 239 220 atomic_dec(&aux_dev->usecount); 240 221 wake_up_atomic_t(&aux_dev->usecount); 241 222 return res; ··· 234 251 static const struct file_operations auxdev_fops = { 235 252 .owner = THIS_MODULE, 236 253 .llseek = auxdev_llseek, 237 - .read = auxdev_read, 238 - .write = auxdev_write, 254 + .read_iter = auxdev_read_iter, 255 + .write_iter = auxdev_write_iter, 239 256 .open = auxdev_open, 240 257 .release = auxdev_release, 241 258 };