diff options
Diffstat (limited to 'fs/cifs/file.c')
| -rw-r--r-- | fs/cifs/file.c | 154 |
1 files changed, 115 insertions, 39 deletions
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index b4a18c1cab0a..ddb012a68023 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | * | 5 | * |
| 6 | * Copyright (C) International Business Machines Corp., 2002,2003 | 6 | * Copyright (C) International Business Machines Corp., 2002,2003 |
| 7 | * Author(s): Steve French (sfrench@us.ibm.com) | 7 | * Author(s): Steve French (sfrench@us.ibm.com) |
| 8 | * Jeremy Allison (jra@samba.org) | ||
| 8 | * | 9 | * |
| 9 | * This library is free software; you can redistribute it and/or modify | 10 | * This library is free software; you can redistribute it and/or modify |
| 10 | * it under the terms of the GNU Lesser General Public License as published | 11 | * it under the terms of the GNU Lesser General Public License as published |
| @@ -47,6 +48,8 @@ static inline struct cifsFileInfo *cifs_init_private( | |||
| 47 | private_data->netfid = netfid; | 48 | private_data->netfid = netfid; |
| 48 | private_data->pid = current->tgid; | 49 | private_data->pid = current->tgid; |
| 49 | init_MUTEX(&private_data->fh_sem); | 50 | init_MUTEX(&private_data->fh_sem); |
| 51 | init_MUTEX(&private_data->lock_sem); | ||
| 52 | INIT_LIST_HEAD(&private_data->llist); | ||
| 50 | private_data->pfile = file; /* needed for writepage */ | 53 | private_data->pfile = file; /* needed for writepage */ |
| 51 | private_data->pInode = inode; | 54 | private_data->pInode = inode; |
| 52 | private_data->invalidHandle = FALSE; | 55 | private_data->invalidHandle = FALSE; |
| @@ -110,7 +113,6 @@ static inline int cifs_open_inode_helper(struct inode *inode, struct file *file, | |||
| 110 | &pCifsInode->openFileList); | 113 | &pCifsInode->openFileList); |
| 111 | } | 114 | } |
| 112 | write_unlock(&GlobalSMBSeslock); | 115 | write_unlock(&GlobalSMBSeslock); |
| 113 | write_unlock(&file->f_owner.lock); | ||
| 114 | if (pCifsInode->clientCanCacheRead) { | 116 | if (pCifsInode->clientCanCacheRead) { |
| 115 | /* we have the inode open somewhere else | 117 | /* we have the inode open somewhere else |
| 116 | no need to discard cache data */ | 118 | no need to discard cache data */ |
| @@ -201,7 +203,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 201 | } else { | 203 | } else { |
| 202 | if (file->f_flags & O_EXCL) | 204 | if (file->f_flags & O_EXCL) |
| 203 | cERROR(1, ("could not find file instance for " | 205 | cERROR(1, ("could not find file instance for " |
| 204 | "new file %p ", file)); | 206 | "new file %p", file)); |
| 205 | } | 207 | } |
| 206 | } | 208 | } |
| 207 | 209 | ||
| @@ -260,10 +262,15 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 260 | rc = -ENOMEM; | 262 | rc = -ENOMEM; |
| 261 | goto out; | 263 | goto out; |
| 262 | } | 264 | } |
| 263 | rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, desiredAccess, | 265 | |
| 264 | CREATE_NOT_DIR, &netfid, &oplock, buf, | 266 | if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) |
| 267 | rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, | ||
| 268 | desiredAccess, CREATE_NOT_DIR, &netfid, &oplock, buf, | ||
| 265 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags | 269 | cifs_sb->local_nls, cifs_sb->mnt_cifs_flags |
| 266 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | 270 | & CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 271 | else | ||
| 272 | rc = -EIO; /* no NT SMB support fall into legacy open below */ | ||
| 273 | |||
| 267 | if (rc == -EIO) { | 274 | if (rc == -EIO) { |
| 268 | /* Old server, try legacy style OpenX */ | 275 | /* Old server, try legacy style OpenX */ |
| 269 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, | 276 | rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, |
| @@ -272,7 +279,7 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 272 | & CIFS_MOUNT_MAP_SPECIAL_CHR); | 279 | & CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 273 | } | 280 | } |
| 274 | if (rc) { | 281 | if (rc) { |
| 275 | cFYI(1, ("cifs_open returned 0x%x ", rc)); | 282 | cFYI(1, ("cifs_open returned 0x%x", rc)); |
| 276 | goto out; | 283 | goto out; |
| 277 | } | 284 | } |
| 278 | file->private_data = | 285 | file->private_data = |
| @@ -282,7 +289,6 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 282 | goto out; | 289 | goto out; |
| 283 | } | 290 | } |
| 284 | pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); | 291 | pCifsFile = cifs_init_private(file->private_data, inode, file, netfid); |
| 285 | write_lock(&file->f_owner.lock); | ||
| 286 | write_lock(&GlobalSMBSeslock); | 292 | write_lock(&GlobalSMBSeslock); |
| 287 | list_add(&pCifsFile->tlist, &pTcon->openFileList); | 293 | list_add(&pCifsFile->tlist, &pTcon->openFileList); |
| 288 | 294 | ||
| @@ -293,7 +299,6 @@ int cifs_open(struct inode *inode, struct file *file) | |||
| 293 | &oplock, buf, full_path, xid); | 299 | &oplock, buf, full_path, xid); |
| 294 | } else { | 300 | } else { |
| 295 | write_unlock(&GlobalSMBSeslock); | 301 | write_unlock(&GlobalSMBSeslock); |
| 296 | write_unlock(&file->f_owner.lock); | ||
| 297 | } | 302 | } |
| 298 | 303 | ||
| 299 | if (oplock & CIFS_CREATE_ACTION) { | 304 | if (oplock & CIFS_CREATE_ACTION) { |
| @@ -322,7 +327,7 @@ out: | |||
| 322 | return rc; | 327 | return rc; |
| 323 | } | 328 | } |
| 324 | 329 | ||
| 325 | /* Try to reaquire byte range locks that were released when session */ | 330 | /* Try to reacquire byte range locks that were released when session */ |
| 326 | /* to server was lost */ | 331 | /* to server was lost */ |
| 327 | static int cifs_relock_file(struct cifsFileInfo *cifsFile) | 332 | static int cifs_relock_file(struct cifsFileInfo *cifsFile) |
| 328 | { | 333 | { |
| @@ -409,8 +414,8 @@ static int cifs_reopen_file(struct inode *inode, struct file *file, | |||
| 409 | CIFS_MOUNT_MAP_SPECIAL_CHR); | 414 | CIFS_MOUNT_MAP_SPECIAL_CHR); |
| 410 | if (rc) { | 415 | if (rc) { |
| 411 | up(&pCifsFile->fh_sem); | 416 | up(&pCifsFile->fh_sem); |
| 412 | cFYI(1, ("cifs_open returned 0x%x ", rc)); | 417 | cFYI(1, ("cifs_open returned 0x%x", rc)); |
| 413 | cFYI(1, ("oplock: %d ", oplock)); | 418 | cFYI(1, ("oplock: %d", oplock)); |
| 414 | } else { | 419 | } else { |
| 415 | pCifsFile->netfid = netfid; | 420 | pCifsFile->netfid = netfid; |
| 416 | pCifsFile->invalidHandle = FALSE; | 421 | pCifsFile->invalidHandle = FALSE; |
| @@ -471,8 +476,9 @@ int cifs_close(struct inode *inode, struct file *file) | |||
| 471 | cifs_sb = CIFS_SB(inode->i_sb); | 476 | cifs_sb = CIFS_SB(inode->i_sb); |
| 472 | pTcon = cifs_sb->tcon; | 477 | pTcon = cifs_sb->tcon; |
| 473 | if (pSMBFile) { | 478 | if (pSMBFile) { |
| 479 | struct cifsLockInfo *li, *tmp; | ||
| 480 | |||
| 474 | pSMBFile->closePend = TRUE; | 481 | pSMBFile->closePend = TRUE; |
| 475 | write_lock(&file->f_owner.lock); | ||
| 476 | if (pTcon) { | 482 | if (pTcon) { |
| 477 | /* no sense reconnecting to close a file that is | 483 | /* no sense reconnecting to close a file that is |
| 478 | already closed */ | 484 | already closed */ |
| @@ -487,23 +493,28 @@ int cifs_close(struct inode *inode, struct file *file) | |||
| 487 | the struct would be in each open file, | 493 | the struct would be in each open file, |
| 488 | but this should give enough time to | 494 | but this should give enough time to |
| 489 | clear the socket */ | 495 | clear the socket */ |
| 490 | write_unlock(&file->f_owner.lock); | ||
| 491 | cERROR(1,("close with pending writes")); | 496 | cERROR(1,("close with pending writes")); |
| 492 | msleep(timeout); | 497 | msleep(timeout); |
| 493 | write_lock(&file->f_owner.lock); | ||
| 494 | timeout *= 4; | 498 | timeout *= 4; |
| 495 | } | 499 | } |
| 496 | write_unlock(&file->f_owner.lock); | ||
| 497 | rc = CIFSSMBClose(xid, pTcon, | 500 | rc = CIFSSMBClose(xid, pTcon, |
| 498 | pSMBFile->netfid); | 501 | pSMBFile->netfid); |
| 499 | write_lock(&file->f_owner.lock); | ||
| 500 | } | 502 | } |
| 501 | } | 503 | } |
| 504 | |||
| 505 | /* Delete any outstanding lock records. | ||
| 506 | We'll lose them when the file is closed anyway. */ | ||
| 507 | down(&pSMBFile->lock_sem); | ||
| 508 | list_for_each_entry_safe(li, tmp, &pSMBFile->llist, llist) { | ||
| 509 | list_del(&li->llist); | ||
| 510 | kfree(li); | ||
| 511 | } | ||
| 512 | up(&pSMBFile->lock_sem); | ||
| 513 | |||
| 502 | write_lock(&GlobalSMBSeslock); | 514 | write_lock(&GlobalSMBSeslock); |
| 503 | list_del(&pSMBFile->flist); | 515 | list_del(&pSMBFile->flist); |
| 504 | list_del(&pSMBFile->tlist); | 516 | list_del(&pSMBFile->tlist); |
| 505 | write_unlock(&GlobalSMBSeslock); | 517 | write_unlock(&GlobalSMBSeslock); |
| 506 | write_unlock(&file->f_owner.lock); | ||
| 507 | kfree(pSMBFile->search_resume_name); | 518 | kfree(pSMBFile->search_resume_name); |
| 508 | kfree(file->private_data); | 519 | kfree(file->private_data); |
| 509 | file->private_data = NULL; | 520 | file->private_data = NULL; |
| @@ -531,7 +542,7 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
| 531 | (struct cifsFileInfo *)file->private_data; | 542 | (struct cifsFileInfo *)file->private_data; |
| 532 | char *ptmp; | 543 | char *ptmp; |
| 533 | 544 | ||
| 534 | cFYI(1, ("Closedir inode = 0x%p with ", inode)); | 545 | cFYI(1, ("Closedir inode = 0x%p", inode)); |
| 535 | 546 | ||
| 536 | xid = GetXid(); | 547 | xid = GetXid(); |
| 537 | 548 | ||
| @@ -574,6 +585,21 @@ int cifs_closedir(struct inode *inode, struct file *file) | |||
| 574 | return rc; | 585 | return rc; |
| 575 | } | 586 | } |
| 576 | 587 | ||
| 588 | static int store_file_lock(struct cifsFileInfo *fid, __u64 len, | ||
| 589 | __u64 offset, __u8 lockType) | ||
| 590 | { | ||
| 591 | struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); | ||
| 592 | if (li == NULL) | ||
| 593 | return -ENOMEM; | ||
| 594 | li->offset = offset; | ||
| 595 | li->length = len; | ||
| 596 | li->type = lockType; | ||
| 597 | down(&fid->lock_sem); | ||
| 598 | list_add(&li->llist, &fid->llist); | ||
| 599 | up(&fid->lock_sem); | ||
| 600 | return 0; | ||
| 601 | } | ||
| 602 | |||
| 577 | int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | 603 | int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) |
| 578 | { | 604 | { |
| 579 | int rc, xid; | 605 | int rc, xid; |
| @@ -585,6 +611,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 585 | struct cifsTconInfo *pTcon; | 611 | struct cifsTconInfo *pTcon; |
| 586 | __u16 netfid; | 612 | __u16 netfid; |
| 587 | __u8 lockType = LOCKING_ANDX_LARGE_FILES; | 613 | __u8 lockType = LOCKING_ANDX_LARGE_FILES; |
| 614 | int posix_locking; | ||
| 588 | 615 | ||
| 589 | length = 1 + pfLock->fl_end - pfLock->fl_start; | 616 | length = 1 + pfLock->fl_end - pfLock->fl_start; |
| 590 | rc = -EACCES; | 617 | rc = -EACCES; |
| @@ -605,7 +632,7 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 605 | } | 632 | } |
| 606 | if (pfLock->fl_flags & FL_ACCESS) | 633 | if (pfLock->fl_flags & FL_ACCESS) |
| 607 | cFYI(1, ("Process suspended by mandatory locking - " | 634 | cFYI(1, ("Process suspended by mandatory locking - " |
| 608 | "not implemented yet ")); | 635 | "not implemented yet")); |
| 609 | if (pfLock->fl_flags & FL_LEASE) | 636 | if (pfLock->fl_flags & FL_LEASE) |
| 610 | cFYI(1, ("Lease on file - not implemented yet")); | 637 | cFYI(1, ("Lease on file - not implemented yet")); |
| 611 | if (pfLock->fl_flags & | 638 | if (pfLock->fl_flags & |
| @@ -643,15 +670,14 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 643 | } | 670 | } |
| 644 | netfid = ((struct cifsFileInfo *)file->private_data)->netfid; | 671 | netfid = ((struct cifsFileInfo *)file->private_data)->netfid; |
| 645 | 672 | ||
| 673 | posix_locking = (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && | ||
| 674 | (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability)); | ||
| 646 | 675 | ||
| 647 | /* BB add code here to normalize offset and length to | 676 | /* BB add code here to normalize offset and length to |
| 648 | account for negative length which we can not accept over the | 677 | account for negative length which we can not accept over the |
| 649 | wire */ | 678 | wire */ |
| 650 | if (IS_GETLK(cmd)) { | 679 | if (IS_GETLK(cmd)) { |
| 651 | if(experimEnabled && | 680 | if(posix_locking) { |
| 652 | (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && | ||
| 653 | (CIFS_UNIX_FCNTL_CAP & | ||
| 654 | le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { | ||
| 655 | int posix_lock_type; | 681 | int posix_lock_type; |
| 656 | if(lockType & LOCKING_ANDX_SHARED_LOCK) | 682 | if(lockType & LOCKING_ANDX_SHARED_LOCK) |
| 657 | posix_lock_type = CIFS_RDLCK; | 683 | posix_lock_type = CIFS_RDLCK; |
| @@ -687,10 +713,15 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 687 | FreeXid(xid); | 713 | FreeXid(xid); |
| 688 | return rc; | 714 | return rc; |
| 689 | } | 715 | } |
| 690 | if (experimEnabled && | 716 | |
| 691 | (cifs_sb->tcon->ses->capabilities & CAP_UNIX) && | 717 | if (!numLock && !numUnlock) { |
| 692 | (CIFS_UNIX_FCNTL_CAP & | 718 | /* if no lock or unlock then nothing |
| 693 | le64_to_cpu(cifs_sb->tcon->fsUnixInfo.Capability))) { | 719 | to do since we do not know what it is */ |
| 720 | FreeXid(xid); | ||
| 721 | return -EOPNOTSUPP; | ||
| 722 | } | ||
| 723 | |||
| 724 | if (posix_locking) { | ||
| 694 | int posix_lock_type; | 725 | int posix_lock_type; |
| 695 | if(lockType & LOCKING_ANDX_SHARED_LOCK) | 726 | if(lockType & LOCKING_ANDX_SHARED_LOCK) |
| 696 | posix_lock_type = CIFS_RDLCK; | 727 | posix_lock_type = CIFS_RDLCK; |
| @@ -699,18 +730,47 @@ int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) | |||
| 699 | 730 | ||
| 700 | if(numUnlock == 1) | 731 | if(numUnlock == 1) |
| 701 | posix_lock_type = CIFS_UNLCK; | 732 | posix_lock_type = CIFS_UNLCK; |
| 702 | else if(numLock == 0) { | 733 | |
| 703 | /* if no lock or unlock then nothing | ||
| 704 | to do since we do not know what it is */ | ||
| 705 | FreeXid(xid); | ||
| 706 | return -EOPNOTSUPP; | ||
| 707 | } | ||
| 708 | rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, | 734 | rc = CIFSSMBPosixLock(xid, pTcon, netfid, 0 /* set */, |
| 709 | length, pfLock, | 735 | length, pfLock, |
| 710 | posix_lock_type, wait_flag); | 736 | posix_lock_type, wait_flag); |
| 711 | } else | 737 | } else { |
| 712 | rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, | 738 | struct cifsFileInfo *fid = (struct cifsFileInfo *)file->private_data; |
| 713 | numUnlock, numLock, lockType, wait_flag); | 739 | |
| 740 | if (numLock) { | ||
| 741 | rc = CIFSSMBLock(xid, pTcon, netfid, length, pfLock->fl_start, | ||
| 742 | 0, numLock, lockType, wait_flag); | ||
| 743 | |||
| 744 | if (rc == 0) { | ||
| 745 | /* For Windows locks we must store them. */ | ||
| 746 | rc = store_file_lock(fid, length, | ||
| 747 | pfLock->fl_start, lockType); | ||
| 748 | } | ||
| 749 | } else if (numUnlock) { | ||
| 750 | /* For each stored lock that this unlock overlaps | ||
| 751 | completely, unlock it. */ | ||
| 752 | int stored_rc = 0; | ||
| 753 | struct cifsLockInfo *li, *tmp; | ||
| 754 | |||
| 755 | rc = 0; | ||
| 756 | down(&fid->lock_sem); | ||
| 757 | list_for_each_entry_safe(li, tmp, &fid->llist, llist) { | ||
| 758 | if (pfLock->fl_start <= li->offset && | ||
| 759 | length >= li->length) { | ||
| 760 | stored_rc = CIFSSMBLock(xid, pTcon, netfid, | ||
| 761 | li->length, li->offset, | ||
| 762 | 1, 0, li->type, FALSE); | ||
| 763 | if (stored_rc) | ||
| 764 | rc = stored_rc; | ||
| 765 | |||
| 766 | list_del(&li->llist); | ||
| 767 | kfree(li); | ||
| 768 | } | ||
| 769 | } | ||
| 770 | up(&fid->lock_sem); | ||
| 771 | } | ||
| 772 | } | ||
| 773 | |||
| 714 | if (pfLock->fl_flags & FL_POSIX) | 774 | if (pfLock->fl_flags & FL_POSIX) |
| 715 | posix_lock_file_wait(file, pfLock); | 775 | posix_lock_file_wait(file, pfLock); |
| 716 | FreeXid(xid); | 776 | FreeXid(xid); |
| @@ -1375,7 +1435,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
| 1375 | 1435 | ||
| 1376 | xid = GetXid(); | 1436 | xid = GetXid(); |
| 1377 | 1437 | ||
| 1378 | cFYI(1, ("Sync file - name: %s datasync: 0x%x ", | 1438 | cFYI(1, ("Sync file - name: %s datasync: 0x%x", |
| 1379 | dentry->d_name.name, datasync)); | 1439 | dentry->d_name.name, datasync)); |
| 1380 | 1440 | ||
| 1381 | rc = filemap_fdatawrite(inode->i_mapping); | 1441 | rc = filemap_fdatawrite(inode->i_mapping); |
| @@ -1404,7 +1464,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
| 1404 | /* fill in rpages then | 1464 | /* fill in rpages then |
| 1405 | result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ | 1465 | result = cifs_pagein_inode(inode, index, rpages); */ /* BB finish */ |
| 1406 | 1466 | ||
| 1407 | /* cFYI(1, ("rpages is %d for sync page of Index %ld ", rpages, index)); | 1467 | /* cFYI(1, ("rpages is %d for sync page of Index %ld", rpages, index)); |
| 1408 | 1468 | ||
| 1409 | #if 0 | 1469 | #if 0 |
| 1410 | if (rc < 0) | 1470 | if (rc < 0) |
| @@ -1836,7 +1896,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page, | |||
| 1836 | if (rc < 0) | 1896 | if (rc < 0) |
| 1837 | goto io_error; | 1897 | goto io_error; |
| 1838 | else | 1898 | else |
| 1839 | cFYI(1, ("Bytes read %d ",rc)); | 1899 | cFYI(1, ("Bytes read %d",rc)); |
| 1840 | 1900 | ||
| 1841 | file->f_dentry->d_inode->i_atime = | 1901 | file->f_dentry->d_inode->i_atime = |
| 1842 | current_fs_time(file->f_dentry->d_inode->i_sb); | 1902 | current_fs_time(file->f_dentry->d_inode->i_sb); |
| @@ -1946,7 +2006,7 @@ static int cifs_prepare_write(struct file *file, struct page *page, | |||
| 1946 | return 0; | 2006 | return 0; |
| 1947 | } | 2007 | } |
| 1948 | 2008 | ||
| 1949 | struct address_space_operations cifs_addr_ops = { | 2009 | const struct address_space_operations cifs_addr_ops = { |
| 1950 | .readpage = cifs_readpage, | 2010 | .readpage = cifs_readpage, |
| 1951 | .readpages = cifs_readpages, | 2011 | .readpages = cifs_readpages, |
| 1952 | .writepage = cifs_writepage, | 2012 | .writepage = cifs_writepage, |
| @@ -1957,3 +2017,19 @@ struct address_space_operations cifs_addr_ops = { | |||
| 1957 | /* .sync_page = cifs_sync_page, */ | 2017 | /* .sync_page = cifs_sync_page, */ |
| 1958 | /* .direct_IO = */ | 2018 | /* .direct_IO = */ |
| 1959 | }; | 2019 | }; |
| 2020 | |||
| 2021 | /* | ||
| 2022 | * cifs_readpages requires the server to support a buffer large enough to | ||
| 2023 | * contain the header plus one complete page of data. Otherwise, we need | ||
| 2024 | * to leave cifs_readpages out of the address space operations. | ||
| 2025 | */ | ||
| 2026 | const struct address_space_operations cifs_addr_ops_smallbuf = { | ||
| 2027 | .readpage = cifs_readpage, | ||
| 2028 | .writepage = cifs_writepage, | ||
| 2029 | .writepages = cifs_writepages, | ||
| 2030 | .prepare_write = cifs_prepare_write, | ||
| 2031 | .commit_write = cifs_commit_write, | ||
| 2032 | .set_page_dirty = __set_page_dirty_nobuffers, | ||
| 2033 | /* .sync_page = cifs_sync_page, */ | ||
| 2034 | /* .direct_IO = */ | ||
| 2035 | }; | ||
