1 /* 2 * linux/fs/9p/vfs_file.c 3 * 4 * This file contians vfs file ops for 9P2000. 5 * 6 * Copyright (C) 2004 by Eric Van Hensbergen <ericvh@gmail.com> 7 * Copyright (C) 2002 by Ron Minnich <rminnich@lanl.gov> 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License version 2 11 * as published by the Free Software Foundation. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to: 20 * Free Software Foundation 21 * 51 Franklin Street, Fifth Floor 22 * Boston, MA 02111-1301 USA 23 * 24 */ 25 26 #include <linux/module.h> 27 #include <linux/errno.h> 28 #include <linux/fs.h> 29 #include <linux/sched.h> 30 #include <linux/file.h> 31 #include <linux/stat.h> 32 #include <linux/string.h> 33 #include <linux/inet.h> 34 #include <linux/list.h> 35 #include <linux/pagemap.h> 36 #include <linux/utsname.h> 37 #include <asm/uaccess.h> 38 #include <linux/idr.h> 39 #include <net/9p/9p.h> 40 #include <net/9p/client.h> 41 42 #include "v9fs.h" 43 #include "v9fs_vfs.h" 44 #include "fid.h" 45 #include "cache.h" 46 47 static const struct vm_operations_struct v9fs_file_vm_ops; 48 49 /** 50 * v9fs_file_open - open a file (or directory) 51 * @inode: inode to be opened 52 * @file: file being opened 53 * 54 */ 55 56 int v9fs_file_open(struct inode *inode, struct file *file) 57 { 58 int err; 59 struct v9fs_inode *v9inode; 60 struct v9fs_session_info *v9ses; 61 struct p9_fid *fid; 62 int omode; 63 64 P9_DPRINTK(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); 65 v9inode = V9FS_I(inode); 66 v9ses = v9fs_inode2v9ses(inode); 67 if (v9fs_proto_dotl(v9ses)) 68 omode = v9fs_open_to_dotl_flags(file->f_flags); 69 else 70 omode = v9fs_uflags2omode(file->f_flags, 71 v9fs_proto_dotu(v9ses)); 72 fid = file->private_data; 73 if (!fid) { 74 fid = v9fs_fid_clone(file->f_path.dentry); 75 if (IS_ERR(fid)) 76 return PTR_ERR(fid); 77 78 err = p9_client_open(fid, omode); 79 if (err < 0) { 80 p9_client_clunk(fid); 81 return err; 82 } 83 if (file->f_flags & O_TRUNC) { 84 i_size_write(inode, 0); 85 inode->i_blocks = 0; 86 } 87 if ((file->f_flags & O_APPEND) && 88 (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses))) 89 generic_file_llseek(file, 0, SEEK_END); 90 } 91 92 file->private_data = fid; 93 mutex_lock(&v9inode->v_mutex); 94 if (v9ses->cache && !v9inode->writeback_fid && 95 ((file->f_flags & O_ACCMODE) != O_RDONLY)) { 96 /* 97 * clone a fid and add it to writeback_fid 98 * we do it during open time instead of 99 * page dirty time via write_begin/page_mkwrite 100 * because we want write after unlink usecase 101 * to work. 102 */ 103 fid = v9fs_writeback_fid(file->f_path.dentry); 104 if (IS_ERR(fid)) { 105 err = PTR_ERR(fid); 106 mutex_unlock(&v9inode->v_mutex); 107 goto out_error; 108 } 109 v9inode->writeback_fid = (void *) fid; 110 } 111 mutex_unlock(&v9inode->v_mutex); 112 #ifdef CONFIG_9P_FSCACHE 113 if (v9ses->cache) 114 v9fs_cache_inode_set_cookie(inode, file); 115 #endif 116 return 0; 117 out_error: 118 p9_client_clunk(file->private_data); 119 file->private_data = NULL; 120 return err; 121 } 122 123 /** 124 * v9fs_file_lock - lock a file (or directory) 125 * @filp: file to be locked 126 * @cmd: lock command 127 * @fl: file lock structure 128 * 129 * Bugs: this looks like a local only lock, we should extend into 9P 130 * by using open exclusive 131 */ 132 133 static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) 134 { 135 int res = 0; 136 struct inode *inode = filp->f_path.dentry->d_inode; 137 138 P9_DPRINTK(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); 139 140 /* No mandatory locks */ 141 if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) 142 return -ENOLCK; 143 144 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 145 filemap_write_and_wait(inode->i_mapping); 146 invalidate_mapping_pages(&inode->i_data, 0, -1); 147 } 148 149 return res; 150 } 151 152 static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) 153 { 154 struct p9_flock flock; 155 struct p9_fid *fid; 156 uint8_t status; 157 int res = 0; 158 unsigned char fl_type; 159 160 fid = filp->private_data; 161 BUG_ON(fid == NULL); 162 163 if ((fl->fl_flags & FL_POSIX) != FL_POSIX) 164 BUG(); 165 166 res = posix_lock_file_wait(filp, fl); 167 if (res < 0) 168 goto out; 169 170 /* convert posix lock to p9 tlock args */ 171 memset(&flock, 0, sizeof(flock)); 172 /* map the lock type */ 173 switch (fl->fl_type) { 174 case F_RDLCK: 175 flock.type = P9_LOCK_TYPE_RDLCK; 176 break; 177 case F_WRLCK: 178 flock.type = P9_LOCK_TYPE_WRLCK; 179 break; 180 case F_UNLCK: 181 flock.type = P9_LOCK_TYPE_UNLCK; 182 break; 183 } 184 flock.start = fl->fl_start; 185 if (fl->fl_end == OFFSET_MAX) 186 flock.length = 0; 187 else 188 flock.length = fl->fl_end - fl->fl_start + 1; 189 flock.proc_id = fl->fl_pid; 190 flock.client_id = utsname()->nodename; 191 if (IS_SETLKW(cmd)) 192 flock.flags = P9_LOCK_FLAGS_BLOCK; 193 194 /* 195 * if its a blocked request and we get P9_LOCK_BLOCKED as the status 196 * for lock request, keep on trying 197 */ 198 for (;;) { 199 res = p9_client_lock_dotl(fid, &flock, &status); 200 if (res < 0) 201 break; 202 203 if (status != P9_LOCK_BLOCKED) 204 break; 205 if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd)) 206 break; 207 schedule_timeout_interruptible(P9_LOCK_TIMEOUT); 208 } 209 210 /* map 9p status to VFS status */ 211 switch (status) { 212 case P9_LOCK_SUCCESS: 213 res = 0; 214 break; 215 case P9_LOCK_BLOCKED: 216 res = -EAGAIN; 217 break; 218 case P9_LOCK_ERROR: 219 case P9_LOCK_GRACE: 220 res = -ENOLCK; 221 break; 222 default: 223 BUG(); 224 } 225 226 /* 227 * incase server returned error for lock request, revert 228 * it locally 229 */ 230 if (res < 0 && fl->fl_type != F_UNLCK) { 231 fl_type = fl->fl_type; 232 fl->fl_type = F_UNLCK; 233 res = posix_lock_file_wait(filp, fl); 234 fl->fl_type = fl_type; 235 } 236 out: 237 return res; 238 } 239 240 static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) 241 { 242 struct p9_getlock glock; 243 struct p9_fid *fid; 244 int res = 0; 245 246 fid = filp->private_data; 247 BUG_ON(fid == NULL); 248 249 posix_test_lock(filp, fl); 250 /* 251 * if we have a conflicting lock locally, no need to validate 252 * with server 253 */ 254 if (fl->fl_type != F_UNLCK) 255 return res; 256 257 /* convert posix lock to p9 tgetlock args */ 258 memset(&glock, 0, sizeof(glock)); 259 glock.type = P9_LOCK_TYPE_UNLCK; 260 glock.start = fl->fl_start; 261 if (fl->fl_end == OFFSET_MAX) 262 glock.length = 0; 263 else 264 glock.length = fl->fl_end - fl->fl_start + 1; 265 glock.proc_id = fl->fl_pid; 266 glock.client_id = utsname()->nodename; 267 268 res = p9_client_getlock_dotl(fid, &glock); 269 if (res < 0) 270 return res; 271 /* map 9p lock type to os lock type */ 272 switch (glock.type) { 273 case P9_LOCK_TYPE_RDLCK: 274 fl->fl_type = F_RDLCK; 275 break; 276 case P9_LOCK_TYPE_WRLCK: 277 fl->fl_type = F_WRLCK; 278 break; 279 case P9_LOCK_TYPE_UNLCK: 280 fl->fl_type = F_UNLCK; 281 break; 282 } 283 if (glock.type != P9_LOCK_TYPE_UNLCK) { 284 fl->fl_start = glock.start; 285 if (glock.length == 0) 286 fl->fl_end = OFFSET_MAX; 287 else 288 fl->fl_end = glock.start + glock.length - 1; 289 fl->fl_pid = glock.proc_id; 290 } 291 return res; 292 } 293 294 /** 295 * v9fs_file_lock_dotl - lock a file (or directory) 296 * @filp: file to be locked 297 * @cmd: lock command 298 * @fl: file lock structure 299 * 300 */ 301 302 static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl) 303 { 304 struct inode *inode = filp->f_path.dentry->d_inode; 305 int ret = -ENOLCK; 306 307 P9_DPRINTK(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", filp, 308 cmd, fl, filp->f_path.dentry->d_name.name); 309 310 /* No mandatory locks */ 311 if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) 312 goto out_err; 313 314 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 315 filemap_write_and_wait(inode->i_mapping); 316 invalidate_mapping_pages(&inode->i_data, 0, -1); 317 } 318 319 if (IS_SETLK(cmd) || IS_SETLKW(cmd)) 320 ret = v9fs_file_do_lock(filp, cmd, fl); 321 else if (IS_GETLK(cmd)) 322 ret = v9fs_file_getlock(filp, fl); 323 else 324 ret = -EINVAL; 325 out_err: 326 return ret; 327 } 328 329 /** 330 * v9fs_file_flock_dotl - lock a file 331 * @filp: file to be locked 332 * @cmd: lock command 333 * @fl: file lock structure 334 * 335 */ 336 337 static int v9fs_file_flock_dotl(struct file *filp, int cmd, 338 struct file_lock *fl) 339 { 340 struct inode *inode = filp->f_path.dentry->d_inode; 341 int ret = -ENOLCK; 342 343 P9_DPRINTK(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", filp, 344 cmd, fl, filp->f_path.dentry->d_name.name); 345 346 /* No mandatory locks */ 347 if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) 348 goto out_err; 349 350 if (!(fl->fl_flags & FL_FLOCK)) 351 goto out_err; 352 353 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 354 filemap_write_and_wait(inode->i_mapping); 355 invalidate_mapping_pages(&inode->i_data, 0, -1); 356 } 357 /* Convert flock to posix lock */ 358 fl->fl_owner = (fl_owner_t)filp; 359 fl->fl_start = 0; 360 fl->fl_end = OFFSET_MAX; 361 fl->fl_flags |= FL_POSIX; 362 fl->fl_flags ^= FL_FLOCK; 363 364 if (IS_SETLK(cmd) | IS_SETLKW(cmd)) 365 ret = v9fs_file_do_lock(filp, cmd, fl); 366 else 367 ret = -EINVAL; 368 out_err: 369 return ret; 370 } 371 372 /** 373 * v9fs_fid_readn - read from a fid 374 * @fid: fid to read 375 * @data: data buffer to read data into 376 * @udata: user data buffer to read data into 377 * @count: size of buffer 378 * @offset: offset at which to read data 379 * 380 */ 381 ssize_t 382 v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count, 383 u64 offset) 384 { 385 int n, total, size; 386 387 P9_DPRINTK(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", fid->fid, 388 (long long unsigned) offset, count); 389 n = 0; 390 total = 0; 391 size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; 392 do { 393 n = p9_client_read(fid, data, udata, offset, count); 394 if (n <= 0) 395 break; 396 397 if (data) 398 data += n; 399 if (udata) 400 udata += n; 401 402 offset += n; 403 count -= n; 404 total += n; 405 } while (count > 0 && n == size); 406 407 if (n < 0) 408 total = n; 409 410 return total; 411 } 412 413 /** 414 * v9fs_file_readn - read from a file 415 * @filp: file pointer to read 416 * @data: data buffer to read data into 417 * @udata: user data buffer to read data into 418 * @count: size of buffer 419 * @offset: offset at which to read data 420 * 421 */ 422 ssize_t 423 v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, 424 u64 offset) 425 { 426 return v9fs_fid_readn(filp->private_data, data, udata, count, offset); 427 } 428 429 /** 430 * v9fs_file_read - read from a file 431 * @filp: file pointer to read 432 * @udata: user data buffer to read data into 433 * @count: size of buffer 434 * @offset: offset at which to read data 435 * 436 */ 437 438 static ssize_t 439 v9fs_file_read(struct file *filp, char __user *udata, size_t count, 440 loff_t * offset) 441 { 442 int ret; 443 struct p9_fid *fid; 444 size_t size; 445 446 P9_DPRINTK(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); 447 fid = filp->private_data; 448 449 size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; 450 if (count > size) 451 ret = v9fs_file_readn(filp, NULL, udata, count, *offset); 452 else 453 ret = p9_client_read(fid, NULL, udata, *offset, count); 454 455 if (ret > 0) 456 *offset += ret; 457 458 return ret; 459 } 460 461 ssize_t 462 v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, 463 const char __user *data, size_t count, 464 loff_t *offset, int invalidate) 465 { 466 int n; 467 loff_t i_size; 468 size_t total = 0; 469 struct p9_client *clnt; 470 loff_t origin = *offset; 471 unsigned long pg_start, pg_end; 472 473 P9_DPRINTK(P9_DEBUG_VFS, "data %p count %d offset %x\n", data, 474 (int)count, (int)*offset); 475 476 clnt = fid->clnt; 477 do { 478 n = p9_client_write(fid, NULL, data+total, origin+total, count); 479 if (n <= 0) 480 break; 481 count -= n; 482 total += n; 483 } while (count > 0); 484 485 if (invalidate && (total > 0)) { 486 pg_start = origin >> PAGE_CACHE_SHIFT; 487 pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT; 488 if (inode->i_mapping && inode->i_mapping->nrpages) 489 invalidate_inode_pages2_range(inode->i_mapping, 490 pg_start, pg_end); 491 *offset += total; 492 i_size = i_size_read(inode); 493 if (*offset > i_size) { 494 inode_add_bytes(inode, *offset - i_size); 495 i_size_write(inode, *offset); 496 } 497 } 498 if (n < 0) 499 return n; 500 501 return total; 502 } 503 504 /** 505 * v9fs_file_write - write to a file 506 * @filp: file pointer to write 507 * @data: data buffer to write data from 508 * @count: size of buffer 509 * @offset: offset at which to write data 510 * 511 */ 512 static ssize_t 513 v9fs_file_write(struct file *filp, const char __user * data, 514 size_t count, loff_t *offset) 515 { 516 ssize_t retval = 0; 517 loff_t origin = *offset; 518 519 520 retval = generic_write_checks(filp, &origin, &count, 0); 521 if (retval) 522 goto out; 523 524 retval = -EINVAL; 525 if ((ssize_t) count < 0) 526 goto out; 527 retval = 0; 528 if (!count) 529 goto out; 530 531 retval = v9fs_file_write_internal(filp->f_path.dentry->d_inode, 532 filp->private_data, 533 data, count, &origin, 1); 534 /* update offset on successful write */ 535 if (retval > 0) 536 *offset = origin; 537 out: 538 return retval; 539 } 540 541 542 static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, 543 int datasync) 544 { 545 struct p9_fid *fid; 546 struct inode *inode = filp->f_mapping->host; 547 struct p9_wstat wstat; 548 int retval; 549 550 retval = filemap_write_and_wait_range(inode->i_mapping, start, end); 551 if (retval) 552 return retval; 553 554 mutex_lock(&inode->i_mutex); 555 P9_DPRINTK(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync); 556 557 fid = filp->private_data; 558 v9fs_blank_wstat(&wstat); 559 560 retval = p9_client_wstat(fid, &wstat); 561 mutex_unlock(&inode->i_mutex); 562 563 return retval; 564 } 565 566 int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, 567 int datasync) 568 { 569 struct p9_fid *fid; 570 struct inode *inode = filp->f_mapping->host; 571 int retval; 572 573 retval = filemap_write_and_wait_range(inode->i_mapping, start, end); 574 if (retval) 575 return retval; 576 577 mutex_lock(&inode->i_mutex); 578 P9_DPRINTK(P9_DEBUG_VFS, "v9fs_file_fsync_dotl: filp %p datasync %x\n", 579 filp, datasync); 580 581 fid = filp->private_data; 582 583 retval = p9_client_fsync(fid, datasync); 584 mutex_unlock(&inode->i_mutex); 585 586 return retval; 587 } 588 589 static int 590 v9fs_file_mmap(struct file *file, struct vm_area_struct *vma) 591 { 592 int retval; 593 594 retval = generic_file_mmap(file, vma); 595 if (!retval) 596 vma->vm_ops = &v9fs_file_vm_ops; 597 598 return retval; 599 } 600 601 static int 602 v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) 603 { 604 struct v9fs_inode *v9inode; 605 struct page *page = vmf->page; 606 struct file *filp = vma->vm_file; 607 struct inode *inode = filp->f_path.dentry->d_inode; 608 609 610 P9_DPRINTK(P9_DEBUG_VFS, "page %p fid %lx\n", 611 page, (unsigned long)filp->private_data); 612 613 v9inode = V9FS_I(inode); 614 /* make sure the cache has finished storing the page */ 615 v9fs_fscache_wait_on_page_write(inode, page); 616 BUG_ON(!v9inode->writeback_fid); 617 lock_page(page); 618 if (page->mapping != inode->i_mapping) 619 goto out_unlock; 620 621 return VM_FAULT_LOCKED; 622 out_unlock: 623 unlock_page(page); 624 return VM_FAULT_NOPAGE; 625 } 626 627 static ssize_t 628 v9fs_direct_read(struct file *filp, char __user *udata, size_t count, 629 loff_t *offsetp) 630 { 631 loff_t size, offset; 632 struct inode *inode; 633 struct address_space *mapping; 634 635 offset = *offsetp; 636 mapping = filp->f_mapping; 637 inode = mapping->host; 638 if (!count) 639 return 0; 640 size = i_size_read(inode); 641 if (offset < size) 642 filemap_write_and_wait_range(mapping, offset, 643 offset + count - 1); 644 645 return v9fs_file_read(filp, udata, count, offsetp); 646 } 647 648 /** 649 * v9fs_cached_file_read - read from a file 650 * @filp: file pointer to read 651 * @udata: user data buffer to read data into 652 * @count: size of buffer 653 * @offset: offset at which to read data 654 * 655 */ 656 static ssize_t 657 v9fs_cached_file_read(struct file *filp, char __user *data, size_t count, 658 loff_t *offset) 659 { 660 if (filp->f_flags & O_DIRECT) 661 return v9fs_direct_read(filp, data, count, offset); 662 return do_sync_read(filp, data, count, offset); 663 } 664 665 static ssize_t 666 v9fs_direct_write(struct file *filp, const char __user * data, 667 size_t count, loff_t *offsetp) 668 { 669 loff_t offset; 670 ssize_t retval; 671 struct inode *inode; 672 struct address_space *mapping; 673 674 offset = *offsetp; 675 mapping = filp->f_mapping; 676 inode = mapping->host; 677 if (!count) 678 return 0; 679 680 mutex_lock(&inode->i_mutex); 681 retval = filemap_write_and_wait_range(mapping, offset, 682 offset + count - 1); 683 if (retval) 684 goto err_out; 685 /* 686 * After a write we want buffered reads to be sure to go to disk to get 687 * the new data. We invalidate clean cached page from the region we're 688 * about to write. We do this *before* the write so that if we fail 689 * here we fall back to buffered write 690 */ 691 if (mapping->nrpages) { 692 pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT; 693 pgoff_t pg_end = (offset + count - 1) >> PAGE_CACHE_SHIFT; 694 695 retval = invalidate_inode_pages2_range(mapping, 696 pg_start, pg_end); 697 /* 698 * If a page can not be invalidated, fall back 699 * to buffered write. 700 */ 701 if (retval) { 702 if (retval == -EBUSY) 703 goto buff_write; 704 goto err_out; 705 } 706 } 707 retval = v9fs_file_write(filp, data, count, offsetp); 708 err_out: 709 mutex_unlock(&inode->i_mutex); 710 return retval; 711 712 buff_write: 713 mutex_unlock(&inode->i_mutex); 714 return do_sync_write(filp, data, count, offsetp); 715 } 716 717 /** 718 * v9fs_cached_file_write - write to a file 719 * @filp: file pointer to write 720 * @data: data buffer to write data from 721 * @count: size of buffer 722 * @offset: offset at which to write data 723 * 724 */ 725 static ssize_t 726 v9fs_cached_file_write(struct file *filp, const char __user * data, 727 size_t count, loff_t *offset) 728 { 729 730 if (filp->f_flags & O_DIRECT) 731 return v9fs_direct_write(filp, data, count, offset); 732 return do_sync_write(filp, data, count, offset); 733 } 734 735 static const struct vm_operations_struct v9fs_file_vm_ops = { 736 .fault = filemap_fault, 737 .page_mkwrite = v9fs_vm_page_mkwrite, 738 }; 739 740 741 const struct file_operations v9fs_cached_file_operations = { 742 .llseek = generic_file_llseek, 743 .read = v9fs_cached_file_read, 744 .write = v9fs_cached_file_write, 745 .aio_read = generic_file_aio_read, 746 .aio_write = generic_file_aio_write, 747 .open = v9fs_file_open, 748 .release = v9fs_dir_release, 749 .lock = v9fs_file_lock, 750 .mmap = v9fs_file_mmap, 751 .fsync = v9fs_file_fsync, 752 }; 753 754 const struct file_operations v9fs_cached_file_operations_dotl = { 755 .llseek = generic_file_llseek, 756 .read = v9fs_cached_file_read, 757 .write = v9fs_cached_file_write, 758 .aio_read = generic_file_aio_read, 759 .aio_write = generic_file_aio_write, 760 .open = v9fs_file_open, 761 .release = v9fs_dir_release, 762 .lock = v9fs_file_lock_dotl, 763 .flock = v9fs_file_flock_dotl, 764 .mmap = v9fs_file_mmap, 765 .fsync = v9fs_file_fsync_dotl, 766 }; 767 768 const struct file_operations v9fs_file_operations = { 769 .llseek = generic_file_llseek, 770 .read = v9fs_file_read, 771 .write = v9fs_file_write, 772 .open = v9fs_file_open, 773 .release = v9fs_dir_release, 774 .lock = v9fs_file_lock, 775 .mmap = generic_file_readonly_mmap, 776 .fsync = v9fs_file_fsync, 777 }; 778 779 const struct file_operations v9fs_file_operations_dotl = { 780 .llseek = generic_file_llseek, 781 .read = v9fs_file_read, 782 .write = v9fs_file_write, 783 .open = v9fs_file_open, 784 .release = v9fs_dir_release, 785 .lock = v9fs_file_lock_dotl, 786 .flock = v9fs_file_flock_dotl, 787 .mmap = generic_file_readonly_mmap, 788 .fsync = v9fs_file_fsync_dotl, 789 }; 790