1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * This file contians vfs file ops for 9P2000. 4 * 5 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 6 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 7 */ 8 9 #include <linux/module.h> 10 #include <linux/errno.h> 11 #include <linux/fs.h> 12 #include <linux/filelock.h> 13 #include <linux/sched.h> 14 #include <linux/file.h> 15 #include <linux/stat.h> 16 #include <linux/string.h> 17 #include <linux/list.h> 18 #include <linux/pagemap.h> 19 #include <linux/utsname.h> 20 #include <linux/uaccess.h> 21 #include <linux/uio.h> 22 #include <linux/slab.h> 23 #include <net/9p/9p.h> 24 #include <net/9p/client.h> 25 26 #include "v9fs.h" 27 #include "v9fs_vfs.h" 28 #include "fid.h" 29 #include "cache.h" 30 31 static const struct vm_operations_struct v9fs_mmap_file_vm_ops; 32 33 /** 34 * v9fs_file_open - open a file (or directory) 35 * @inode: inode to be opened 36 * @file: file being opened 37 * 38 */ 39 40 int v9fs_file_open(struct inode *inode, struct file *file) 41 { 42 int err; 43 struct v9fs_session_info *v9ses; 44 struct p9_fid *fid; 45 int omode; 46 47 p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); 48 v9ses = v9fs_inode2v9ses(inode); 49 if (v9fs_proto_dotl(v9ses)) 50 omode = v9fs_open_to_dotl_flags(file->f_flags); 51 else 52 omode = v9fs_uflags2omode(file->f_flags, 53 v9fs_proto_dotu(v9ses)); 54 fid = file->private_data; 55 if (!fid) { 56 fid = v9fs_fid_clone(file_dentry(file)); 57 if (IS_ERR(fid)) 58 return PTR_ERR(fid); 59 60 if ((v9ses->cache & CACHE_WRITEBACK) && (omode & P9_OWRITE)) { 61 int writeback_omode = (omode & ~P9_OWRITE) | P9_ORDWR; 62 63 p9_debug(P9_DEBUG_CACHE, "write-only file with writeback enabled, try opening O_RDWR\n"); 64 err = p9_client_open(fid, writeback_omode); 65 if (err < 0) { 66 p9_debug(P9_DEBUG_CACHE, "could not open O_RDWR, disabling caches\n"); 67 err = p9_client_open(fid, omode); 68 fid->mode |= P9L_DIRECT; 69 } 70 } else { 71 err = p9_client_open(fid, omode); 72 } 73 if (err < 0) { 74 p9_fid_put(fid); 75 return err; 76 } 77 if ((file->f_flags & O_APPEND) && 78 (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses))) 79 generic_file_llseek(file, 0, SEEK_END); 80 81 file->private_data = fid; 82 } 83 84 #ifdef CONFIG_9P_FSCACHE 85 if (v9ses->cache & CACHE_FSCACHE) 86 fscache_use_cookie(v9fs_inode_cookie(V9FS_I(inode)), 87 file->f_mode & FMODE_WRITE); 88 #endif 89 v9fs_fid_add_modes(fid, v9ses->flags, v9ses->cache, file->f_flags); 90 v9fs_open_fid_add(inode, &fid); 91 return 0; 92 } 93 94 /** 95 * v9fs_file_lock - lock a file (or directory) 96 * @filp: file to be locked 97 * @cmd: lock command 98 * @fl: file lock structure 99 * 100 * Bugs: this looks like a local only lock, we should extend into 9P 101 * by using open exclusive 102 */ 103 104 static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) 105 { 106 struct inode *inode = file_inode(filp); 107 108 p9_debug(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); 109 110 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 111 filemap_write_and_wait(inode->i_mapping); 112 invalidate_mapping_pages(&inode->i_data, 0, -1); 113 } 114 115 return 0; 116 } 117 118 static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) 119 { 120 struct p9_flock flock; 121 struct p9_fid *fid; 122 uint8_t status = P9_LOCK_ERROR; 123 int res = 0; 124 unsigned char fl_type; 125 struct v9fs_session_info *v9ses; 126 127 fid = filp->private_data; 128 BUG_ON(fid == NULL); 129 130 BUG_ON((fl->fl_flags & FL_POSIX) != FL_POSIX); 131 132 res = locks_lock_file_wait(filp, fl); 133 if (res < 0) 134 goto out; 135 136 /* convert posix lock to p9 tlock args */ 137 memset(&flock, 0, sizeof(flock)); 138 /* map the lock type */ 139 switch (fl->fl_type) { 140 case F_RDLCK: 141 flock.type = P9_LOCK_TYPE_RDLCK; 142 break; 143 case F_WRLCK: 144 flock.type = P9_LOCK_TYPE_WRLCK; 145 break; 146 case F_UNLCK: 147 flock.type = P9_LOCK_TYPE_UNLCK; 148 break; 149 } 150 flock.start = fl->fl_start; 151 if (fl->fl_end == OFFSET_MAX) 152 flock.length = 0; 153 else 154 flock.length = fl->fl_end - fl->fl_start + 1; 155 flock.proc_id = fl->fl_pid; 156 flock.client_id = fid->clnt->name; 157 if (IS_SETLKW(cmd)) 158 flock.flags = P9_LOCK_FLAGS_BLOCK; 159 160 v9ses = v9fs_inode2v9ses(file_inode(filp)); 161 162 /* 163 * if its a blocked request and we get P9_LOCK_BLOCKED as the status 164 * for lock request, keep on trying 165 */ 166 for (;;) { 167 res = p9_client_lock_dotl(fid, &flock, &status); 168 if (res < 0) 169 goto out_unlock; 170 171 if (status != P9_LOCK_BLOCKED) 172 break; 173 if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd)) 174 break; 175 if (schedule_timeout_interruptible(v9ses->session_lock_timeout) 176 != 0) 177 break; 178 /* 179 * p9_client_lock_dotl overwrites flock.client_id with the 180 * server message, free and reuse the client name 181 */ 182 if (flock.client_id != fid->clnt->name) { 183 kfree(flock.client_id); 184 flock.client_id = fid->clnt->name; 185 } 186 } 187 188 /* map 9p status to VFS status */ 189 switch (status) { 190 case P9_LOCK_SUCCESS: 191 res = 0; 192 break; 193 case P9_LOCK_BLOCKED: 194 res = -EAGAIN; 195 break; 196 default: 197 WARN_ONCE(1, "unknown lock status code: %d\n", status); 198 fallthrough; 199 case P9_LOCK_ERROR: 200 case P9_LOCK_GRACE: 201 res = -ENOLCK; 202 break; 203 } 204 205 out_unlock: 206 /* 207 * incase server returned error for lock request, revert 208 * it locally 209 */ 210 if (res < 0 && fl->fl_type != F_UNLCK) { 211 fl_type = fl->fl_type; 212 fl->fl_type = F_UNLCK; 213 /* Even if this fails we want to return the remote error */ 214 locks_lock_file_wait(filp, fl); 215 fl->fl_type = fl_type; 216 } 217 if (flock.client_id != fid->clnt->name) 218 kfree(flock.client_id); 219 out: 220 return res; 221 } 222 223 static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) 224 { 225 struct p9_getlock glock; 226 struct p9_fid *fid; 227 int res = 0; 228 229 fid = filp->private_data; 230 BUG_ON(fid == NULL); 231 232 posix_test_lock(filp, fl); 233 /* 234 * if we have a conflicting lock locally, no need to validate 235 * with server 236 */ 237 if (fl->fl_type != F_UNLCK) 238 return res; 239 240 /* convert posix lock to p9 tgetlock args */ 241 memset(&glock, 0, sizeof(glock)); 242 glock.type = P9_LOCK_TYPE_UNLCK; 243 glock.start = fl->fl_start; 244 if (fl->fl_end == OFFSET_MAX) 245 glock.length = 0; 246 else 247 glock.length = fl->fl_end - fl->fl_start + 1; 248 glock.proc_id = fl->fl_pid; 249 glock.client_id = fid->clnt->name; 250 251 res = p9_client_getlock_dotl(fid, &glock); 252 if (res < 0) 253 goto out; 254 /* map 9p lock type to os lock type */ 255 switch (glock.type) { 256 case P9_LOCK_TYPE_RDLCK: 257 fl->fl_type = F_RDLCK; 258 break; 259 case P9_LOCK_TYPE_WRLCK: 260 fl->fl_type = F_WRLCK; 261 break; 262 case P9_LOCK_TYPE_UNLCK: 263 fl->fl_type = F_UNLCK; 264 break; 265 } 266 if (glock.type != P9_LOCK_TYPE_UNLCK) { 267 fl->fl_start = glock.start; 268 if (glock.length == 0) 269 fl->fl_end = OFFSET_MAX; 270 else 271 fl->fl_end = glock.start + glock.length - 1; 272 fl->fl_pid = -glock.proc_id; 273 } 274 out: 275 if (glock.client_id != fid->clnt->name) 276 kfree(glock.client_id); 277 return res; 278 } 279 280 /** 281 * v9fs_file_lock_dotl - lock a file (or directory) 282 * @filp: file to be locked 283 * @cmd: lock command 284 * @fl: file lock structure 285 * 286 */ 287 288 static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl) 289 { 290 struct inode *inode = file_inode(filp); 291 int ret = -ENOLCK; 292 293 p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %pD\n", 294 filp, cmd, fl, filp); 295 296 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 297 filemap_write_and_wait(inode->i_mapping); 298 invalidate_mapping_pages(&inode->i_data, 0, -1); 299 } 300 301 if (IS_SETLK(cmd) || IS_SETLKW(cmd)) 302 ret = v9fs_file_do_lock(filp, cmd, fl); 303 else if (IS_GETLK(cmd)) 304 ret = v9fs_file_getlock(filp, fl); 305 else 306 ret = -EINVAL; 307 return ret; 308 } 309 310 /** 311 * v9fs_file_flock_dotl - lock a file 312 * @filp: file to be locked 313 * @cmd: lock command 314 * @fl: file lock structure 315 * 316 */ 317 318 static int v9fs_file_flock_dotl(struct file *filp, int cmd, 319 struct file_lock *fl) 320 { 321 struct inode *inode = file_inode(filp); 322 int ret = -ENOLCK; 323 324 p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %pD\n", 325 filp, cmd, fl, filp); 326 327 if (!(fl->fl_flags & FL_FLOCK)) 328 goto out_err; 329 330 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 331 filemap_write_and_wait(inode->i_mapping); 332 invalidate_mapping_pages(&inode->i_data, 0, -1); 333 } 334 /* Convert flock to posix lock */ 335 fl->fl_flags |= FL_POSIX; 336 fl->fl_flags ^= FL_FLOCK; 337 338 if (IS_SETLK(cmd) | IS_SETLKW(cmd)) 339 ret = v9fs_file_do_lock(filp, cmd, fl); 340 else 341 ret = -EINVAL; 342 out_err: 343 return ret; 344 } 345 346 /** 347 * v9fs_file_read_iter - read from a file 348 * @iocb: The operation parameters 349 * @to: The buffer to read into 350 * 351 */ 352 static ssize_t 353 v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) 354 { 355 struct p9_fid *fid = iocb->ki_filp->private_data; 356 int ret, err = 0; 357 358 p9_debug(P9_DEBUG_VFS, "fid %d count %zu offset %lld\n", 359 fid->fid, iov_iter_count(to), iocb->ki_pos); 360 361 if (!(fid->mode & P9L_DIRECT)) { 362 p9_debug(P9_DEBUG_VFS, "(cached)\n"); 363 return generic_file_read_iter(iocb, to); 364 } 365 366 if (iocb->ki_filp->f_flags & O_NONBLOCK) 367 ret = p9_client_read_once(fid, iocb->ki_pos, to, &err); 368 else 369 ret = p9_client_read(fid, iocb->ki_pos, to, &err); 370 if (!ret) 371 return err; 372 373 iocb->ki_pos += ret; 374 return ret; 375 } 376 377 /* 378 * v9fs_file_splice_read - splice-read from a file 379 * @in: The 9p file to read from 380 * @ppos: Where to find/update the file position 381 * @pipe: The pipe to splice into 382 * @len: The maximum amount of data to splice 383 * @flags: SPLICE_F_* flags 384 */ 385 static ssize_t v9fs_file_splice_read(struct file *in, loff_t *ppos, 386 struct pipe_inode_info *pipe, 387 size_t len, unsigned int flags) 388 { 389 struct p9_fid *fid = in->private_data; 390 391 p9_debug(P9_DEBUG_VFS, "fid %d count %zu offset %lld\n", 392 fid->fid, len, *ppos); 393 394 if (fid->mode & P9L_DIRECT) 395 return copy_splice_read(in, ppos, pipe, len, flags); 396 return filemap_splice_read(in, ppos, pipe, len, flags); 397 } 398 399 /** 400 * v9fs_file_write_iter - write to a file 401 * @iocb: The operation parameters 402 * @from: The data to write 403 * 404 */ 405 static ssize_t 406 v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) 407 { 408 struct file *file = iocb->ki_filp; 409 struct p9_fid *fid = file->private_data; 410 ssize_t retval; 411 loff_t origin; 412 int err = 0; 413 414 p9_debug(P9_DEBUG_VFS, "fid %d\n", fid->fid); 415 416 if (!(fid->mode & (P9L_DIRECT | P9L_NOWRITECACHE))) { 417 p9_debug(P9_DEBUG_CACHE, "(cached)\n"); 418 return generic_file_write_iter(iocb, from); 419 } 420 421 retval = generic_write_checks(iocb, from); 422 if (retval <= 0) 423 return retval; 424 425 origin = iocb->ki_pos; 426 retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err); 427 if (retval > 0) { 428 struct inode *inode = file_inode(file); 429 loff_t i_size; 430 unsigned long pg_start, pg_end; 431 432 pg_start = origin >> PAGE_SHIFT; 433 pg_end = (origin + retval - 1) >> PAGE_SHIFT; 434 if (inode->i_mapping && inode->i_mapping->nrpages) 435 invalidate_inode_pages2_range(inode->i_mapping, 436 pg_start, pg_end); 437 iocb->ki_pos += retval; 438 i_size = i_size_read(inode); 439 if (iocb->ki_pos > i_size) { 440 inode_add_bytes(inode, iocb->ki_pos - i_size); 441 /* 442 * Need to serialize against i_size_write() in 443 * v9fs_stat2inode() 444 */ 445 v9fs_i_size_write(inode, iocb->ki_pos); 446 } 447 return retval; 448 } 449 return err; 450 } 451 452 static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, 453 int datasync) 454 { 455 struct p9_fid *fid; 456 struct inode *inode = filp->f_mapping->host; 457 struct p9_wstat wstat; 458 int retval; 459 460 retval = file_write_and_wait_range(filp, start, end); 461 if (retval) 462 return retval; 463 464 inode_lock(inode); 465 p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync); 466 467 fid = filp->private_data; 468 v9fs_blank_wstat(&wstat); 469 470 retval = p9_client_wstat(fid, &wstat); 471 inode_unlock(inode); 472 473 return retval; 474 } 475 476 int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, 477 int datasync) 478 { 479 struct p9_fid *fid; 480 struct inode *inode = filp->f_mapping->host; 481 int retval; 482 483 retval = file_write_and_wait_range(filp, start, end); 484 if (retval) 485 return retval; 486 487 inode_lock(inode); 488 p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync); 489 490 fid = filp->private_data; 491 492 retval = p9_client_fsync(fid, datasync); 493 inode_unlock(inode); 494 495 return retval; 496 } 497 498 static int 499 v9fs_file_mmap(struct file *filp, struct vm_area_struct *vma) 500 { 501 int retval; 502 struct inode *inode = file_inode(filp); 503 struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 504 505 p9_debug(P9_DEBUG_MMAP, "filp :%p\n", filp); 506 507 if (!(v9ses->cache & CACHE_WRITEBACK)) { 508 p9_debug(P9_DEBUG_CACHE, "(no mmap mode)"); 509 if (vma->vm_flags & VM_MAYSHARE) 510 return -ENODEV; 511 invalidate_inode_pages2(filp->f_mapping); 512 return generic_file_readonly_mmap(filp, vma); 513 } 514 515 retval = generic_file_mmap(filp, vma); 516 if (!retval) 517 vma->vm_ops = &v9fs_mmap_file_vm_ops; 518 519 return retval; 520 } 521 522 static vm_fault_t 523 v9fs_vm_page_mkwrite(struct vm_fault *vmf) 524 { 525 struct folio *folio = page_folio(vmf->page); 526 struct file *filp = vmf->vma->vm_file; 527 struct inode *inode = file_inode(filp); 528 529 530 p9_debug(P9_DEBUG_VFS, "folio %p fid %lx\n", 531 folio, (unsigned long)filp->private_data); 532 533 /* Wait for the page to be written to the cache before we allow it to 534 * be modified. We then assume the entire page will need writing back. 535 */ 536 #ifdef CONFIG_9P_FSCACHE 537 if (folio_test_fscache(folio) && 538 folio_wait_fscache_killable(folio) < 0) 539 return VM_FAULT_NOPAGE; 540 #endif 541 542 /* Update file times before taking page lock */ 543 file_update_time(filp); 544 545 if (folio_lock_killable(folio) < 0) 546 return VM_FAULT_RETRY; 547 if (folio_mapping(folio) != inode->i_mapping) 548 goto out_unlock; 549 folio_wait_stable(folio); 550 551 return VM_FAULT_LOCKED; 552 out_unlock: 553 folio_unlock(folio); 554 return VM_FAULT_NOPAGE; 555 } 556 557 static void v9fs_mmap_vm_close(struct vm_area_struct *vma) 558 { 559 struct inode *inode; 560 561 struct writeback_control wbc = { 562 .nr_to_write = LONG_MAX, 563 .sync_mode = WB_SYNC_ALL, 564 .range_start = (loff_t)vma->vm_pgoff * PAGE_SIZE, 565 /* absolute end, byte at end included */ 566 .range_end = (loff_t)vma->vm_pgoff * PAGE_SIZE + 567 (vma->vm_end - vma->vm_start - 1), 568 }; 569 570 if (!(vma->vm_flags & VM_SHARED)) 571 return; 572 573 p9_debug(P9_DEBUG_VFS, "9p VMA close, %p, flushing", vma); 574 575 inode = file_inode(vma->vm_file); 576 filemap_fdatawrite_wbc(inode->i_mapping, &wbc); 577 } 578 579 static const struct vm_operations_struct v9fs_mmap_file_vm_ops = { 580 .close = v9fs_mmap_vm_close, 581 .fault = filemap_fault, 582 .map_pages = filemap_map_pages, 583 .page_mkwrite = v9fs_vm_page_mkwrite, 584 }; 585 586 const struct file_operations v9fs_file_operations = { 587 .llseek = generic_file_llseek, 588 .read_iter = v9fs_file_read_iter, 589 .write_iter = v9fs_file_write_iter, 590 .open = v9fs_file_open, 591 .release = v9fs_dir_release, 592 .lock = v9fs_file_lock, 593 .mmap = generic_file_readonly_mmap, 594 .splice_read = v9fs_file_splice_read, 595 .splice_write = iter_file_splice_write, 596 .fsync = v9fs_file_fsync, 597 }; 598 599 const struct file_operations v9fs_file_operations_dotl = { 600 .llseek = generic_file_llseek, 601 .read_iter = v9fs_file_read_iter, 602 .write_iter = v9fs_file_write_iter, 603 .open = v9fs_file_open, 604 .release = v9fs_dir_release, 605 .lock = v9fs_file_lock_dotl, 606 .flock = v9fs_file_flock_dotl, 607 .mmap = v9fs_file_mmap, 608 .splice_read = v9fs_file_splice_read, 609 .splice_write = iter_file_splice_write, 610 .fsync = v9fs_file_fsync_dotl, 611 }; 612