diff options
Diffstat (limited to 'fs/9p/vfs_file.c')
| -rw-r--r-- | fs/9p/vfs_file.c | 114 |
1 files changed, 33 insertions, 81 deletions
diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index a4799e971d1c..bbc3cc63854f 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c | |||
| @@ -175,16 +175,16 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) | |||
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | /** | 177 | /** |
| 178 | * v9fs_read - read from a file (internal) | 178 | * v9fs_file_read - read from a file |
| 179 | * @filep: file pointer to read | 179 | * @filep: file pointer to read |
| 180 | * @data: data buffer to read data into | 180 | * @data: data buffer to read data into |
| 181 | * @count: size of buffer | 181 | * @count: size of buffer |
| 182 | * @offset: offset at which to read data | 182 | * @offset: offset at which to read data |
| 183 | * | 183 | * |
| 184 | */ | 184 | */ |
| 185 | |||
| 186 | static ssize_t | 185 | static ssize_t |
| 187 | v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | 186 | v9fs_file_read(struct file *filp, char __user * data, size_t count, |
| 187 | loff_t * offset) | ||
| 188 | { | 188 | { |
| 189 | struct inode *inode = filp->f_dentry->d_inode; | 189 | struct inode *inode = filp->f_dentry->d_inode; |
| 190 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 190 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
| @@ -194,6 +194,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 194 | int rsize = 0; | 194 | int rsize = 0; |
| 195 | int result = 0; | 195 | int result = 0; |
| 196 | int total = 0; | 196 | int total = 0; |
| 197 | int n; | ||
| 197 | 198 | ||
| 198 | dprintk(DEBUG_VFS, "\n"); | 199 | dprintk(DEBUG_VFS, "\n"); |
| 199 | 200 | ||
| @@ -216,10 +217,15 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 216 | } else | 217 | } else |
| 217 | *offset += result; | 218 | *offset += result; |
| 218 | 219 | ||
| 219 | /* XXX - extra copy */ | 220 | n = copy_to_user(data, fcall->params.rread.data, result); |
| 220 | memcpy(buffer, fcall->params.rread.data, result); | 221 | if (n) { |
| 222 | dprintk(DEBUG_ERROR, "Problem copying to user %d\n", n); | ||
| 223 | kfree(fcall); | ||
| 224 | return -EFAULT; | ||
| 225 | } | ||
| 226 | |||
| 221 | count -= result; | 227 | count -= result; |
| 222 | buffer += result; | 228 | data += result; |
| 223 | total += result; | 229 | total += result; |
| 224 | 230 | ||
| 225 | kfree(fcall); | 231 | kfree(fcall); |
| @@ -232,42 +238,7 @@ v9fs_read(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 232 | } | 238 | } |
| 233 | 239 | ||
| 234 | /** | 240 | /** |
| 235 | * v9fs_file_read - read from a file | 241 | * v9fs_file_write - write to a file |
| 236 | * @filep: file pointer to read | ||
| 237 | * @data: data buffer to read data into | ||
| 238 | * @count: size of buffer | ||
| 239 | * @offset: offset at which to read data | ||
| 240 | * | ||
| 241 | */ | ||
| 242 | |||
| 243 | static ssize_t | ||
| 244 | v9fs_file_read(struct file *filp, char __user * data, size_t count, | ||
| 245 | loff_t * offset) | ||
| 246 | { | ||
| 247 | int retval = -1; | ||
| 248 | int ret = 0; | ||
| 249 | char *buffer; | ||
| 250 | |||
| 251 | buffer = kmalloc(count, GFP_KERNEL); | ||
| 252 | if (!buffer) | ||
| 253 | return -ENOMEM; | ||
| 254 | |||
| 255 | retval = v9fs_read(filp, buffer, count, offset); | ||
| 256 | if (retval > 0) { | ||
| 257 | if ((ret = copy_to_user(data, buffer, retval)) != 0) { | ||
| 258 | dprintk(DEBUG_ERROR, "Problem copying to user %d\n", | ||
| 259 | ret); | ||
| 260 | retval = ret; | ||
| 261 | } | ||
| 262 | } | ||
| 263 | |||
| 264 | kfree(buffer); | ||
| 265 | |||
| 266 | return retval; | ||
| 267 | } | ||
| 268 | |||
| 269 | /** | ||
| 270 | * v9fs_write - write to a file | ||
| 271 | * @filep: file pointer to write | 242 | * @filep: file pointer to write |
| 272 | * @data: data buffer to write data from | 243 | * @data: data buffer to write data from |
| 273 | * @count: size of buffer | 244 | * @count: size of buffer |
| @@ -276,7 +247,8 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count, | |||
| 276 | */ | 247 | */ |
| 277 | 248 | ||
| 278 | static ssize_t | 249 | static ssize_t |
| 279 | v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | 250 | v9fs_file_write(struct file *filp, const char __user * data, |
| 251 | size_t count, loff_t * offset) | ||
| 280 | { | 252 | { |
| 281 | struct inode *inode = filp->f_dentry->d_inode; | 253 | struct inode *inode = filp->f_dentry->d_inode; |
| 282 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); | 254 | struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); |
| @@ -286,30 +258,42 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 286 | int result = -EIO; | 258 | int result = -EIO; |
| 287 | int rsize = 0; | 259 | int rsize = 0; |
| 288 | int total = 0; | 260 | int total = 0; |
| 261 | char *buf; | ||
| 289 | 262 | ||
| 290 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", buffer, (int)count, | 263 | dprintk(DEBUG_VFS, "data %p count %d offset %x\n", data, (int)count, |
| 291 | (int)*offset); | 264 | (int)*offset); |
| 292 | rsize = v9ses->maxdata - V9FS_IOHDRSZ; | 265 | rsize = v9ses->maxdata - V9FS_IOHDRSZ; |
| 293 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) | 266 | if (v9fid->iounit != 0 && rsize > v9fid->iounit) |
| 294 | rsize = v9fid->iounit; | 267 | rsize = v9fid->iounit; |
| 295 | 268 | ||
| 296 | dump_data(buffer, count); | 269 | buf = kmalloc(v9ses->maxdata - V9FS_IOHDRSZ, GFP_KERNEL); |
| 270 | if (!buf) | ||
| 271 | return -ENOMEM; | ||
| 297 | 272 | ||
| 298 | do { | 273 | do { |
| 299 | if (count < rsize) | 274 | if (count < rsize) |
| 300 | rsize = count; | 275 | rsize = count; |
| 301 | 276 | ||
| 302 | result = | 277 | result = copy_from_user(buf, data, rsize); |
| 303 | v9fs_t_write(v9ses, fid, *offset, rsize, buffer, &fcall); | 278 | if (result) { |
| 279 | dprintk(DEBUG_ERROR, "Problem copying from user\n"); | ||
| 280 | kfree(buf); | ||
| 281 | return -EFAULT; | ||
| 282 | } | ||
| 283 | |||
| 284 | dump_data(buf, rsize); | ||
| 285 | result = v9fs_t_write(v9ses, fid, *offset, rsize, buf, &fcall); | ||
| 304 | if (result < 0) { | 286 | if (result < 0) { |
| 305 | eprintk(KERN_ERR, "error while writing: %s(%d)\n", | 287 | eprintk(KERN_ERR, "error while writing: %s(%d)\n", |
| 306 | FCALL_ERROR(fcall), result); | 288 | FCALL_ERROR(fcall), result); |
| 307 | kfree(fcall); | 289 | kfree(fcall); |
| 290 | kfree(buf); | ||
| 308 | return result; | 291 | return result; |
| 309 | } else | 292 | } else |
| 310 | *offset += result; | 293 | *offset += result; |
| 311 | 294 | ||
| 312 | kfree(fcall); | 295 | kfree(fcall); |
| 296 | fcall = NULL; | ||
| 313 | 297 | ||
| 314 | if (result != rsize) { | 298 | if (result != rsize) { |
| 315 | eprintk(KERN_ERR, | 299 | eprintk(KERN_ERR, |
| @@ -319,46 +303,14 @@ v9fs_write(struct file *filp, char *buffer, size_t count, loff_t * offset) | |||
| 319 | } | 303 | } |
| 320 | 304 | ||
| 321 | count -= result; | 305 | count -= result; |
| 322 | buffer += result; | 306 | data += result; |
| 323 | total += result; | 307 | total += result; |
| 324 | } while (count); | 308 | } while (count); |
| 325 | 309 | ||
| 310 | kfree(buf); | ||
| 326 | return total; | 311 | return total; |
| 327 | } | 312 | } |
| 328 | 313 | ||
| 329 | /** | ||
| 330 | * v9fs_file_write - write to a file | ||
| 331 | * @filep: file pointer to write | ||
| 332 | * @data: data buffer to write data from | ||
| 333 | * @count: size of buffer | ||
| 334 | * @offset: offset at which to write data | ||
| 335 | * | ||
| 336 | */ | ||
| 337 | |||
| 338 | static ssize_t | ||
| 339 | v9fs_file_write(struct file *filp, const char __user * data, | ||
| 340 | size_t count, loff_t * offset) | ||
| 341 | { | ||
| 342 | int ret = -1; | ||
| 343 | char *buffer; | ||
| 344 | |||
| 345 | buffer = kmalloc(count, GFP_KERNEL); | ||
| 346 | if (buffer == NULL) | ||
| 347 | return -ENOMEM; | ||
| 348 | |||
| 349 | ret = copy_from_user(buffer, data, count); | ||
| 350 | if (ret) { | ||
| 351 | dprintk(DEBUG_ERROR, "Problem copying from user\n"); | ||
| 352 | ret = -EFAULT; | ||
| 353 | } else { | ||
| 354 | ret = v9fs_write(filp, buffer, count, offset); | ||
| 355 | } | ||
| 356 | |||
| 357 | kfree(buffer); | ||
| 358 | |||
| 359 | return ret; | ||
| 360 | } | ||
| 361 | |||
| 362 | struct file_operations v9fs_file_operations = { | 314 | struct file_operations v9fs_file_operations = { |
| 363 | .llseek = generic_file_llseek, | 315 | .llseek = generic_file_llseek, |
| 364 | .read = v9fs_file_read, | 316 | .read = v9fs_file_read, |
