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_debug(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_debug(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 if (schedule_timeout_interruptible(P9_LOCK_TIMEOUT) != 0) 208 break; 209 } 210 211 /* map 9p status to VFS status */ 212 switch (status) { 213 case P9_LOCK_SUCCESS: 214 res = 0; 215 break; 216 case P9_LOCK_BLOCKED: 217 res = -EAGAIN; 218 break; 219 case P9_LOCK_ERROR: 220 case P9_LOCK_GRACE: 221 res = -ENOLCK; 222 break; 223 default: 224 BUG(); 225 } 226 227 /* 228 * incase server returned error for lock request, revert 229 * it locally 230 */ 231 if (res < 0 && fl->fl_type != F_UNLCK) { 232 fl_type = fl->fl_type; 233 fl->fl_type = F_UNLCK; 234 res = posix_lock_file_wait(filp, fl); 235 fl->fl_type = fl_type; 236 } 237 out: 238 return res; 239 } 240 241 static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) 242 { 243 struct p9_getlock glock; 244 struct p9_fid *fid; 245 int res = 0; 246 247 fid = filp->private_data; 248 BUG_ON(fid == NULL); 249 250 posix_test_lock(filp, fl); 251 /* 252 * if we have a conflicting lock locally, no need to validate 253 * with server 254 */ 255 if (fl->fl_type != F_UNLCK) 256 return res; 257 258 /* convert posix lock to p9 tgetlock args */ 259 memset(&glock, 0, sizeof(glock)); 260 glock.type = P9_LOCK_TYPE_UNLCK; 261 glock.start = fl->fl_start; 262 if (fl->fl_end == OFFSET_MAX) 263 glock.length = 0; 264 else 265 glock.length = fl->fl_end - fl->fl_start + 1; 266 glock.proc_id = fl->fl_pid; 267 glock.client_id = utsname()->nodename; 268 269 res = p9_client_getlock_dotl(fid, &glock); 270 if (res < 0) 271 return res; 272 /* map 9p lock type to os lock type */ 273 switch (glock.type) { 274 case P9_LOCK_TYPE_RDLCK: 275 fl->fl_type = F_RDLCK; 276 break; 277 case P9_LOCK_TYPE_WRLCK: 278 fl->fl_type = F_WRLCK; 279 break; 280 case P9_LOCK_TYPE_UNLCK: 281 fl->fl_type = F_UNLCK; 282 break; 283 } 284 if (glock.type != P9_LOCK_TYPE_UNLCK) { 285 fl->fl_start = glock.start; 286 if (glock.length == 0) 287 fl->fl_end = OFFSET_MAX; 288 else 289 fl->fl_end = glock.start + glock.length - 1; 290 fl->fl_pid = glock.proc_id; 291 } 292 return res; 293 } 294 295 /** 296 * v9fs_file_lock_dotl - lock a file (or directory) 297 * @filp: file to be locked 298 * @cmd: lock command 299 * @fl: file lock structure 300 * 301 */ 302 303 static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl) 304 { 305 struct inode *inode = filp->f_path.dentry->d_inode; 306 int ret = -ENOLCK; 307 308 p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", 309 filp, cmd, fl, filp->f_path.dentry->d_name.name); 310 311 /* No mandatory locks */ 312 if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) 313 goto out_err; 314 315 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 316 filemap_write_and_wait(inode->i_mapping); 317 invalidate_mapping_pages(&inode->i_data, 0, -1); 318 } 319 320 if (IS_SETLK(cmd) || IS_SETLKW(cmd)) 321 ret = v9fs_file_do_lock(filp, cmd, fl); 322 else if (IS_GETLK(cmd)) 323 ret = v9fs_file_getlock(filp, fl); 324 else 325 ret = -EINVAL; 326 out_err: 327 return ret; 328 } 329 330 /** 331 * v9fs_file_flock_dotl - lock a file 332 * @filp: file to be locked 333 * @cmd: lock command 334 * @fl: file lock structure 335 * 336 */ 337 338 static int v9fs_file_flock_dotl(struct file *filp, int cmd, 339 struct file_lock *fl) 340 { 341 struct inode *inode = filp->f_path.dentry->d_inode; 342 int ret = -ENOLCK; 343 344 p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", 345 filp, cmd, fl, filp->f_path.dentry->d_name.name); 346 347 /* No mandatory locks */ 348 if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) 349 goto out_err; 350 351 if (!(fl->fl_flags & FL_FLOCK)) 352 goto out_err; 353 354 if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { 355 filemap_write_and_wait(inode->i_mapping); 356 invalidate_mapping_pages(&inode->i_data, 0, -1); 357 } 358 /* Convert flock to posix lock */ 359 fl->fl_owner = (fl_owner_t)filp; 360 fl->fl_start = 0; 361 fl->fl_end = OFFSET_MAX; 362 fl->fl_flags |= FL_POSIX; 363 fl->fl_flags ^= FL_FLOCK; 364 365 if (IS_SETLK(cmd) | IS_SETLKW(cmd)) 366 ret = v9fs_file_do_lock(filp, cmd, fl); 367 else 368 ret = -EINVAL; 369 out_err: 370 return ret; 371 } 372 373 /** 374 * v9fs_fid_readn - read from a fid 375 * @fid: fid to read 376 * @data: data buffer to read data into 377 * @udata: user data buffer to read data into 378 * @count: size of buffer 379 * @offset: offset at which to read data 380 * 381 */ 382 ssize_t 383 v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count, 384 u64 offset) 385 { 386 int n, total, size; 387 388 p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", 389 fid->fid, (long long unsigned)offset, count); 390 n = 0; 391 total = 0; 392 size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; 393 do { 394 n = p9_client_read(fid, data, udata, offset, count); 395 if (n <= 0) 396 break; 397 398 if (data) 399 data += n; 400 if (udata) 401 udata += n; 402 403 offset += n; 404 count -= n; 405 total += n; 406 } while (count > 0 && n == size); 407 408 if (n < 0) 409 total = n; 410 411 return total; 412 } 413 414 /** 415 * v9fs_file_readn - read from a file 416 * @filp: file pointer to read 417 * @data: data buffer to read data into 418 * @udata: user data buffer to read data into 419 * @count: size of buffer 420 * @offset: offset at which to read data 421 * 422 */ 423 ssize_t 424 v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, 425 u64 offset) 426 { 427 return v9fs_fid_readn(filp->private_data, data, udata, count, offset); 428 } 429 430 /** 431 * v9fs_file_read - read from a file 432 * @filp: file pointer to read 433 * @udata: user data buffer to read data into 434 * @count: size of buffer 435 * @offset: offset at which to read data 436 * 437 */ 438 439 static ssize_t 440 v9fs_file_read(struct file *filp, char __user *udata, size_t count, 441 loff_t * offset) 442 { 443 int ret; 444 struct p9_fid *fid; 445 size_t size; 446 447 p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); 448 fid = filp->private_data; 449 450 size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; 451 if (count > size) 452 ret = v9fs_file_readn(filp, NULL, udata, count, *offset); 453 else 454 ret = p9_client_read(fid, NULL, udata, *offset, count); 455 456 if (ret > 0) 457 *offset += ret; 458 459 return ret; 460 } 461 462 ssize_t 463 v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, 464 const char __user *data, size_t count, 465 loff_t *offset, int invalidate) 466 { 467 int n; 468 loff_t i_size; 469 size_t total = 0; 470 struct p9_client *clnt; 471 loff_t origin = *offset; 472 unsigned long pg_start, pg_end; 473 474 p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n", 475 data, (int)count, (int)*offset); 476 477 clnt = fid->clnt; 478 do { 479 n = p9_client_write(fid, NULL, data+total, origin+total, count); 480 if (n <= 0) 481 break; 482 count -= n; 483 total += n; 484 } while (count > 0); 485 486 if (invalidate && (total > 0)) { 487 pg_start = origin >> PAGE_CACHE_SHIFT; 488 pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT; 489 if (inode->i_mapping && inode->i_mapping->nrpages) 490 invalidate_inode_pages2_range(inode->i_mapping, 491 pg_start, pg_end); 492 *offset += total; 493 i_size = i_size_read(inode); 494 if (*offset > i_size) { 495 inode_add_bytes(inode, *offset - i_size); 496 i_size_write(inode, *offset); 497 } 498 } 499 if (n < 0) 500 return n; 501 502 return total; 503 } 504 505 /** 506 * v9fs_file_write - write to a file 507 * @filp: file pointer to write 508 * @data: data buffer to write data from 509 * @count: size of buffer 510 * @offset: offset at which to write data 511 * 512 */ 513 static ssize_t 514 v9fs_file_write(struct file *filp, const char __user * data, 515 size_t count, loff_t *offset) 516 { 517 ssize_t retval = 0; 518 loff_t origin = *offset; 519 520 521 retval = generic_write_checks(filp, &origin, &count, 0); 522 if (retval) 523 goto out; 524 525 retval = -EINVAL; 526 if ((ssize_t) count < 0) 527 goto out; 528 retval = 0; 529 if (!count) 530 goto out; 531 532 retval = v9fs_file_write_internal(filp->f_path.dentry->d_inode, 533 filp->private_data, 534 data, count, &origin, 1); 535 /* update offset on successful write */ 536 if (retval > 0) 537 *offset = origin; 538 out: 539 return retval; 540 } 541 542 543 static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, 544 int datasync) 545 { 546 struct p9_fid *fid; 547 struct inode *inode = filp->f_mapping->host; 548 struct p9_wstat wstat; 549 int retval; 550 551 retval = filemap_write_and_wait_range(inode->i_mapping, start, end); 552 if (retval) 553 return retval; 554 555 mutex_lock(&inode->i_mutex); 556 p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync); 557 558 fid = filp->private_data; 559 v9fs_blank_wstat(&wstat); 560 561 retval = p9_client_wstat(fid, &wstat); 562 mutex_unlock(&inode->i_mutex); 563 564 return retval; 565 } 566 567 int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, 568 int datasync) 569 { 570 struct p9_fid *fid; 571 struct inode *inode = filp->f_mapping->host; 572 int retval; 573 574 retval = filemap_write_and_wait_range(inode->i_mapping, start, end); 575 if (retval) 576 return retval; 577 578 mutex_lock(&inode->i_mutex); 579 p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", 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_debug(P9_DEBUG_VFS, "page %p fid %lx\n", 611 page, (unsigned long)filp->private_data); 612 613 /* Update file times before taking page lock */ 614 file_update_time(filp); 615 616 v9inode = V9FS_I(inode); 617 /* make sure the cache has finished storing the page */ 618 v9fs_fscache_wait_on_page_write(inode, page); 619 BUG_ON(!v9inode->writeback_fid); 620 lock_page(page); 621 if (page->mapping != inode->i_mapping) 622 goto out_unlock; 623 624 return VM_FAULT_LOCKED; 625 out_unlock: 626 unlock_page(page); 627 return VM_FAULT_NOPAGE; 628 } 629 630 static ssize_t 631 v9fs_direct_read(struct file *filp, char __user *udata, size_t count, 632 loff_t *offsetp) 633 { 634 loff_t size, offset; 635 struct inode *inode; 636 struct address_space *mapping; 637 638 offset = *offsetp; 639 mapping = filp->f_mapping; 640 inode = mapping->host; 641 if (!count) 642 return 0; 643 size = i_size_read(inode); 644 if (offset < size) 645 filemap_write_and_wait_range(mapping, offset, 646 offset + count - 1); 647 648 return v9fs_file_read(filp, udata, count, offsetp); 649 } 650 651 /** 652 * v9fs_cached_file_read - read from a file 653 * @filp: file pointer to read 654 * @udata: user data buffer to read data into 655 * @count: size of buffer 656 * @offset: offset at which to read data 657 * 658 */ 659 static ssize_t 660 v9fs_cached_file_read(struct file *filp, char __user *data, size_t count, 661 loff_t *offset) 662 { 663 if (filp->f_flags & O_DIRECT) 664 return v9fs_direct_read(filp, data, count, offset); 665 return do_sync_read(filp, data, count, offset); 666 } 667 668 static ssize_t 669 v9fs_direct_write(struct file *filp, const char __user * data, 670 size_t count, loff_t *offsetp) 671 { 672 loff_t offset; 673 ssize_t retval; 674 struct inode *inode; 675 struct address_space *mapping; 676 677 offset = *offsetp; 678 mapping = filp->f_mapping; 679 inode = mapping->host; 680 if (!count) 681 return 0; 682 683 mutex_lock(&inode->i_mutex); 684 retval = filemap_write_and_wait_range(mapping, offset, 685 offset + count - 1); 686 if (retval) 687 goto err_out; 688 /* 689 * After a write we want buffered reads to be sure to go to disk to get 690 * the new data. We invalidate clean cached page from the region we're 691 * about to write. We do this *before* the write so that if we fail 692 * here we fall back to buffered write 693 */ 694 if (mapping->nrpages) { 695 pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT; 696 pgoff_t pg_end = (offset + count - 1) >> PAGE_CACHE_SHIFT; 697 698 retval = invalidate_inode_pages2_range(mapping, 699 pg_start, pg_end); 700 /* 701 * If a page can not be invalidated, fall back 702 * to buffered write. 703 */ 704 if (retval) { 705 if (retval == -EBUSY) 706 goto buff_write; 707 goto err_out; 708 } 709 } 710 retval = v9fs_file_write(filp, data, count, offsetp); 711 err_out: 712 mutex_unlock(&inode->i_mutex); 713 return retval; 714 715 buff_write: 716 mutex_unlock(&inode->i_mutex); 717 return do_sync_write(filp, data, count, offsetp); 718 } 719 720 /** 721 * v9fs_cached_file_write - write to a file 722 * @filp: file pointer to write 723 * @data: data buffer to write data from 724 * @count: size of buffer 725 * @offset: offset at which to write data 726 * 727 */ 728 static ssize_t 729 v9fs_cached_file_write(struct file *filp, const char __user * data, 730 size_t count, loff_t *offset) 731 { 732 733 if (filp->f_flags & O_DIRECT) 734 return v9fs_direct_write(filp, data, count, offset); 735 return do_sync_write(filp, data, count, offset); 736 } 737 738 static const struct vm_operations_struct v9fs_file_vm_ops = { 739 .fault = filemap_fault, 740 .page_mkwrite = v9fs_vm_page_mkwrite, 741 .remap_pages = generic_file_remap_pages, 742 }; 743 744 745 const struct file_operations v9fs_cached_file_operations = { 746 .llseek = generic_file_llseek, 747 .read = v9fs_cached_file_read, 748 .write = v9fs_cached_file_write, 749 .aio_read = generic_file_aio_read, 750 .aio_write = generic_file_aio_write, 751 .open = v9fs_file_open, 752 .release = v9fs_dir_release, 753 .lock = v9fs_file_lock, 754 .mmap = v9fs_file_mmap, 755 .fsync = v9fs_file_fsync, 756 }; 757 758 const struct file_operations v9fs_cached_file_operations_dotl = { 759 .llseek = generic_file_llseek, 760 .read = v9fs_cached_file_read, 761 .write = v9fs_cached_file_write, 762 .aio_read = generic_file_aio_read, 763 .aio_write = generic_file_aio_write, 764 .open = v9fs_file_open, 765 .release = v9fs_dir_release, 766 .lock = v9fs_file_lock_dotl, 767 .flock = v9fs_file_flock_dotl, 768 .mmap = v9fs_file_mmap, 769 .fsync = v9fs_file_fsync_dotl, 770 }; 771 772 const struct file_operations v9fs_file_operations = { 773 .llseek = generic_file_llseek, 774 .read = v9fs_file_read, 775 .write = v9fs_file_write, 776 .open = v9fs_file_open, 777 .release = v9fs_dir_release, 778 .lock = v9fs_file_lock, 779 .mmap = generic_file_readonly_mmap, 780 .fsync = v9fs_file_fsync, 781 }; 782 783 const struct file_operations v9fs_file_operations_dotl = { 784 .llseek = generic_file_llseek, 785 .read = v9fs_file_read, 786 .write = v9fs_file_write, 787 .open = v9fs_file_open, 788 .release = v9fs_dir_release, 789 .lock = v9fs_file_lock_dotl, 790 .flock = v9fs_file_flock_dotl, 791 .mmap = generic_file_readonly_mmap, 792 .fsync = v9fs_file_fsync_dotl, 793 }; 794