diff options
author | Pavel Shilovsky <piastryyy@gmail.com> | 2010-12-12 05:11:13 -0500 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2011-01-20 16:42:21 -0500 |
commit | 8be7e6ba142423e6ad98fed293c96f196f685229 (patch) | |
tree | 25bd7ce4aed4740082f0a472a8eed35127d9d61e /fs | |
parent | 4f8ba8a0c095933dd54a2c281750c8a85b329b26 (diff) |
CIFS: Implement cifs_strict_fsync
Invalidate inode mapping if we don't have at least Level II oplock in
cifs_strict_fsync. Also remove filemap_write_and_wait call from cifs_fsync
because it is previously called from vfs_fsync_range. Add file operations'
structures for strict cache mode.
Reviewed-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Pavel Shilovsky <piastryyy@gmail.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/cifsfs.c | 38 | ||||
-rw-r--r-- | fs/cifs/cifsfs.h | 8 | ||||
-rw-r--r-- | fs/cifs/file.c | 36 | ||||
-rw-r--r-- | fs/cifs/inode.c | 8 |
4 files changed, 78 insertions, 12 deletions
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 99d777a03dd0..f6093e401c5a 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -733,6 +733,25 @@ const struct file_operations cifs_file_ops = { | |||
733 | .setlease = cifs_setlease, | 733 | .setlease = cifs_setlease, |
734 | }; | 734 | }; |
735 | 735 | ||
736 | const struct file_operations cifs_file_strict_ops = { | ||
737 | .read = do_sync_read, | ||
738 | .write = do_sync_write, | ||
739 | .aio_read = generic_file_aio_read, | ||
740 | .aio_write = cifs_file_aio_write, | ||
741 | .open = cifs_open, | ||
742 | .release = cifs_close, | ||
743 | .lock = cifs_lock, | ||
744 | .fsync = cifs_strict_fsync, | ||
745 | .flush = cifs_flush, | ||
746 | .mmap = cifs_file_mmap, | ||
747 | .splice_read = generic_file_splice_read, | ||
748 | .llseek = cifs_llseek, | ||
749 | #ifdef CONFIG_CIFS_POSIX | ||
750 | .unlocked_ioctl = cifs_ioctl, | ||
751 | #endif /* CONFIG_CIFS_POSIX */ | ||
752 | .setlease = cifs_setlease, | ||
753 | }; | ||
754 | |||
736 | const struct file_operations cifs_file_direct_ops = { | 755 | const struct file_operations cifs_file_direct_ops = { |
737 | /* no aio, no readv - | 756 | /* no aio, no readv - |
738 | BB reevaluate whether they can be done with directio, no cache */ | 757 | BB reevaluate whether they can be done with directio, no cache */ |
@@ -751,6 +770,7 @@ const struct file_operations cifs_file_direct_ops = { | |||
751 | .llseek = cifs_llseek, | 770 | .llseek = cifs_llseek, |
752 | .setlease = cifs_setlease, | 771 | .setlease = cifs_setlease, |
753 | }; | 772 | }; |
773 | |||
754 | const struct file_operations cifs_file_nobrl_ops = { | 774 | const struct file_operations cifs_file_nobrl_ops = { |
755 | .read = do_sync_read, | 775 | .read = do_sync_read, |
756 | .write = do_sync_write, | 776 | .write = do_sync_write, |
@@ -769,6 +789,24 @@ const struct file_operations cifs_file_nobrl_ops = { | |||
769 | .setlease = cifs_setlease, | 789 | .setlease = cifs_setlease, |
770 | }; | 790 | }; |
771 | 791 | ||
792 | const struct file_operations cifs_file_strict_nobrl_ops = { | ||
793 | .read = do_sync_read, | ||
794 | .write = do_sync_write, | ||
795 | .aio_read = generic_file_aio_read, | ||
796 | .aio_write = cifs_file_aio_write, | ||
797 | .open = cifs_open, | ||
798 | .release = cifs_close, | ||
799 | .fsync = cifs_strict_fsync, | ||
800 | .flush = cifs_flush, | ||
801 | .mmap = cifs_file_mmap, | ||
802 | .splice_read = generic_file_splice_read, | ||
803 | .llseek = cifs_llseek, | ||
804 | #ifdef CONFIG_CIFS_POSIX | ||
805 | .unlocked_ioctl = cifs_ioctl, | ||
806 | #endif /* CONFIG_CIFS_POSIX */ | ||
807 | .setlease = cifs_setlease, | ||
808 | }; | ||
809 | |||
772 | const struct file_operations cifs_file_direct_nobrl_ops = { | 810 | const struct file_operations cifs_file_direct_nobrl_ops = { |
773 | /* no mmap, no aio, no readv - | 811 | /* no mmap, no aio, no readv - |
774 | BB reevaluate whether they can be done with directio, no cache */ | 812 | BB reevaluate whether they can be done with directio, no cache */ |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 4739a531cded..10c4303c282d 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -61,6 +61,7 @@ extern int cifs_rename(struct inode *, struct dentry *, struct inode *, | |||
61 | struct dentry *); | 61 | struct dentry *); |
62 | extern int cifs_revalidate_file(struct file *filp); | 62 | extern int cifs_revalidate_file(struct file *filp); |
63 | extern int cifs_revalidate_dentry(struct dentry *); | 63 | extern int cifs_revalidate_dentry(struct dentry *); |
64 | extern void cifs_invalidate_mapping(struct inode *inode); | ||
64 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); | 65 | extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *); |
65 | extern int cifs_setattr(struct dentry *, struct iattr *); | 66 | extern int cifs_setattr(struct dentry *, struct iattr *); |
66 | 67 | ||
@@ -72,8 +73,10 @@ extern const struct inode_operations cifs_dfs_referral_inode_operations; | |||
72 | /* Functions related to files and directories */ | 73 | /* Functions related to files and directories */ |
73 | extern const struct file_operations cifs_file_ops; | 74 | extern const struct file_operations cifs_file_ops; |
74 | extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */ | 75 | extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */ |
75 | extern const struct file_operations cifs_file_nobrl_ops; | 76 | extern const struct file_operations cifs_file_strict_ops; /* if strictio mnt */ |
76 | extern const struct file_operations cifs_file_direct_nobrl_ops; /* no brlocks */ | 77 | extern const struct file_operations cifs_file_nobrl_ops; /* no brlocks */ |
78 | extern const struct file_operations cifs_file_direct_nobrl_ops; | ||
79 | extern const struct file_operations cifs_file_strict_nobrl_ops; | ||
77 | extern int cifs_open(struct inode *inode, struct file *file); | 80 | extern int cifs_open(struct inode *inode, struct file *file); |
78 | extern int cifs_close(struct inode *inode, struct file *file); | 81 | extern int cifs_close(struct inode *inode, struct file *file); |
79 | extern int cifs_closedir(struct inode *inode, struct file *file); | 82 | extern int cifs_closedir(struct inode *inode, struct file *file); |
@@ -83,6 +86,7 @@ extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
83 | size_t write_size, loff_t *poffset); | 86 | size_t write_size, loff_t *poffset); |
84 | extern int cifs_lock(struct file *, int, struct file_lock *); | 87 | extern int cifs_lock(struct file *, int, struct file_lock *); |
85 | extern int cifs_fsync(struct file *, int); | 88 | extern int cifs_fsync(struct file *, int); |
89 | extern int cifs_strict_fsync(struct file *, int); | ||
86 | extern int cifs_flush(struct file *, fl_owner_t id); | 90 | extern int cifs_flush(struct file *, fl_owner_t id); |
87 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); | 91 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); |
88 | extern const struct file_operations cifs_dir_ops; | 92 | extern const struct file_operations cifs_dir_ops; |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 1b26c2717599..5790fab7349b 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1528,27 +1528,47 @@ static int cifs_write_end(struct file *file, struct address_space *mapping, | |||
1528 | return rc; | 1528 | return rc; |
1529 | } | 1529 | } |
1530 | 1530 | ||
1531 | int cifs_fsync(struct file *file, int datasync) | 1531 | int cifs_strict_fsync(struct file *file, int datasync) |
1532 | { | 1532 | { |
1533 | int xid; | 1533 | int xid; |
1534 | int rc = 0; | 1534 | int rc = 0; |
1535 | struct cifsTconInfo *tcon; | 1535 | struct cifsTconInfo *tcon; |
1536 | struct cifsFileInfo *smbfile = file->private_data; | 1536 | struct cifsFileInfo *smbfile = file->private_data; |
1537 | struct inode *inode = file->f_path.dentry->d_inode; | 1537 | struct inode *inode = file->f_path.dentry->d_inode; |
1538 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1538 | 1539 | ||
1539 | xid = GetXid(); | 1540 | xid = GetXid(); |
1540 | 1541 | ||
1541 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | 1542 | cFYI(1, "Sync file - name: %s datasync: 0x%x", |
1542 | file->f_path.dentry->d_name.name, datasync); | 1543 | file->f_path.dentry->d_name.name, datasync); |
1543 | 1544 | ||
1544 | rc = filemap_write_and_wait(inode->i_mapping); | 1545 | if (!CIFS_I(inode)->clientCanCacheRead) |
1545 | if (rc == 0) { | 1546 | cifs_invalidate_mapping(inode); |
1546 | struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); | ||
1547 | 1547 | ||
1548 | tcon = tlink_tcon(smbfile->tlink); | 1548 | tcon = tlink_tcon(smbfile->tlink); |
1549 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | 1549 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) |
1550 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | 1550 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); |
1551 | } | 1551 | |
1552 | FreeXid(xid); | ||
1553 | return rc; | ||
1554 | } | ||
1555 | |||
1556 | int cifs_fsync(struct file *file, int datasync) | ||
1557 | { | ||
1558 | int xid; | ||
1559 | int rc = 0; | ||
1560 | struct cifsTconInfo *tcon; | ||
1561 | struct cifsFileInfo *smbfile = file->private_data; | ||
1562 | struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); | ||
1563 | |||
1564 | xid = GetXid(); | ||
1565 | |||
1566 | cFYI(1, "Sync file - name: %s datasync: 0x%x", | ||
1567 | file->f_path.dentry->d_name.name, datasync); | ||
1568 | |||
1569 | tcon = tlink_tcon(smbfile->tlink); | ||
1570 | if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC)) | ||
1571 | rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); | ||
1552 | 1572 | ||
1553 | FreeXid(xid); | 1573 | FreeXid(xid); |
1554 | return rc; | 1574 | return rc; |
diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 6c9ee8014ff0..8852470b4fbb 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c | |||
@@ -44,13 +44,17 @@ static void cifs_set_ops(struct inode *inode) | |||
44 | inode->i_fop = &cifs_file_direct_nobrl_ops; | 44 | inode->i_fop = &cifs_file_direct_nobrl_ops; |
45 | else | 45 | else |
46 | inode->i_fop = &cifs_file_direct_ops; | 46 | inode->i_fop = &cifs_file_direct_ops; |
47 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) { | ||
48 | if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | ||
49 | inode->i_fop = &cifs_file_strict_nobrl_ops; | ||
50 | else | ||
51 | inode->i_fop = &cifs_file_strict_ops; | ||
47 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) | 52 | } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL) |
48 | inode->i_fop = &cifs_file_nobrl_ops; | 53 | inode->i_fop = &cifs_file_nobrl_ops; |
49 | else { /* not direct, send byte range locks */ | 54 | else { /* not direct, send byte range locks */ |
50 | inode->i_fop = &cifs_file_ops; | 55 | inode->i_fop = &cifs_file_ops; |
51 | } | 56 | } |
52 | 57 | ||
53 | |||
54 | /* check if server can support readpages */ | 58 | /* check if server can support readpages */ |
55 | if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf < | 59 | if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf < |
56 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) | 60 | PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE) |
@@ -1679,7 +1683,7 @@ cifs_inode_needs_reval(struct inode *inode) | |||
1679 | /* | 1683 | /* |
1680 | * Zap the cache. Called when invalid_mapping flag is set. | 1684 | * Zap the cache. Called when invalid_mapping flag is set. |
1681 | */ | 1685 | */ |
1682 | static void | 1686 | void |
1683 | cifs_invalidate_mapping(struct inode *inode) | 1687 | cifs_invalidate_mapping(struct inode *inode) |
1684 | { | 1688 | { |
1685 | int rc; | 1689 | int rc; |