CIFS: Implement cifs_strict_fsync
authorPavel Shilovsky <piastryyy@gmail.com>
Sun, 12 Dec 2010 10:11:13 +0000 (13:11 +0300)
committerSteve French <sfrench@us.ibm.com>
Thu, 20 Jan 2011 21:42:21 +0000 (21:42 +0000)
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>
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/file.c
fs/cifs/inode.c

index 99d777a03dd07b634e6174f54be23602092a4f2b..f6093e401c5a8461fb160b3ea6d969112a7e5a53 100644 (file)
@@ -733,6 +733,25 @@ const struct file_operations cifs_file_ops = {
        .setlease = cifs_setlease,
 };
 
+const struct file_operations cifs_file_strict_ops = {
+       .read = do_sync_read,
+       .write = do_sync_write,
+       .aio_read = generic_file_aio_read,
+       .aio_write = cifs_file_aio_write,
+       .open = cifs_open,
+       .release = cifs_close,
+       .lock = cifs_lock,
+       .fsync = cifs_strict_fsync,
+       .flush = cifs_flush,
+       .mmap = cifs_file_mmap,
+       .splice_read = generic_file_splice_read,
+       .llseek = cifs_llseek,
+#ifdef CONFIG_CIFS_POSIX
+       .unlocked_ioctl = cifs_ioctl,
+#endif /* CONFIG_CIFS_POSIX */
+       .setlease = cifs_setlease,
+};
+
 const struct file_operations cifs_file_direct_ops = {
        /* no aio, no readv -
           BB reevaluate whether they can be done with directio, no cache */
@@ -751,6 +770,7 @@ const struct file_operations cifs_file_direct_ops = {
        .llseek = cifs_llseek,
        .setlease = cifs_setlease,
 };
+
 const struct file_operations cifs_file_nobrl_ops = {
        .read = do_sync_read,
        .write = do_sync_write,
@@ -769,6 +789,24 @@ const struct file_operations cifs_file_nobrl_ops = {
        .setlease = cifs_setlease,
 };
 
+const struct file_operations cifs_file_strict_nobrl_ops = {
+       .read = do_sync_read,
+       .write = do_sync_write,
+       .aio_read = generic_file_aio_read,
+       .aio_write = cifs_file_aio_write,
+       .open = cifs_open,
+       .release = cifs_close,
+       .fsync = cifs_strict_fsync,
+       .flush = cifs_flush,
+       .mmap = cifs_file_mmap,
+       .splice_read = generic_file_splice_read,
+       .llseek = cifs_llseek,
+#ifdef CONFIG_CIFS_POSIX
+       .unlocked_ioctl = cifs_ioctl,
+#endif /* CONFIG_CIFS_POSIX */
+       .setlease = cifs_setlease,
+};
+
 const struct file_operations cifs_file_direct_nobrl_ops = {
        /* no mmap, no aio, no readv -
           BB reevaluate whether they can be done with directio, no cache */
index 4739a531cdeda7306695e67d802136e8a0ce9e91..10c4303c282de3459fbbf1e2a006b3040454d6e6 100644 (file)
@@ -61,6 +61,7 @@ extern int cifs_rename(struct inode *, struct dentry *, struct inode *,
                       struct dentry *);
 extern int cifs_revalidate_file(struct file *filp);
 extern int cifs_revalidate_dentry(struct dentry *);
+extern void cifs_invalidate_mapping(struct inode *inode);
 extern int cifs_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int cifs_setattr(struct dentry *, struct iattr *);
 
@@ -72,8 +73,10 @@ extern const struct inode_operations cifs_dfs_referral_inode_operations;
 /* Functions related to files and directories */
 extern const struct file_operations cifs_file_ops;
 extern const struct file_operations cifs_file_direct_ops; /* if directio mnt */
-extern const struct file_operations cifs_file_nobrl_ops;
-extern const struct file_operations cifs_file_direct_nobrl_ops; /* no brlocks */
+extern const struct file_operations cifs_file_strict_ops; /* if strictio mnt */
+extern const struct file_operations cifs_file_nobrl_ops; /* no brlocks */
+extern const struct file_operations cifs_file_direct_nobrl_ops;
+extern const struct file_operations cifs_file_strict_nobrl_ops;
 extern int cifs_open(struct inode *inode, struct file *file);
 extern int cifs_close(struct inode *inode, struct file *file);
 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,
                         size_t write_size, loff_t *poffset);
 extern int cifs_lock(struct file *, int, struct file_lock *);
 extern int cifs_fsync(struct file *, int);
+extern int cifs_strict_fsync(struct file *, int);
 extern int cifs_flush(struct file *, fl_owner_t id);
 extern int cifs_file_mmap(struct file * , struct vm_area_struct *);
 extern const struct file_operations cifs_dir_ops;
index 1b26c2717599a0c386847fdaa826ef7c98bf9472..5790fab7349be0226b6f631b07d4a081bcd1f4cc 100644 (file)
@@ -1528,27 +1528,47 @@ static int cifs_write_end(struct file *file, struct address_space *mapping,
        return rc;
 }
 
-int cifs_fsync(struct file *file, int datasync)
+int cifs_strict_fsync(struct file *file, int datasync)
 {
        int xid;
        int rc = 0;
        struct cifsTconInfo *tcon;
        struct cifsFileInfo *smbfile = file->private_data;
        struct inode *inode = file->f_path.dentry->d_inode;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 
        xid = GetXid();
 
        cFYI(1, "Sync file - name: %s datasync: 0x%x",
                file->f_path.dentry->d_name.name, datasync);
 
-       rc = filemap_write_and_wait(inode->i_mapping);
-       if (rc == 0) {
-               struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       if (!CIFS_I(inode)->clientCanCacheRead)
+               cifs_invalidate_mapping(inode);
 
-               tcon = tlink_tcon(smbfile->tlink);
-               if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
-                       rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
-       }
+       tcon = tlink_tcon(smbfile->tlink);
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
+               rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
+
+       FreeXid(xid);
+       return rc;
+}
+
+int cifs_fsync(struct file *file, int datasync)
+{
+       int xid;
+       int rc = 0;
+       struct cifsTconInfo *tcon;
+       struct cifsFileInfo *smbfile = file->private_data;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb);
+
+       xid = GetXid();
+
+       cFYI(1, "Sync file - name: %s datasync: 0x%x",
+               file->f_path.dentry->d_name.name, datasync);
+
+       tcon = tlink_tcon(smbfile->tlink);
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC))
+               rc = CIFSSMBFlush(xid, tcon, smbfile->netfid);
 
        FreeXid(xid);
        return rc;
index 6c9ee8014ff0426e6aaed09f77a8ebffe9a406b3..8852470b4fbb50b55907cbbd2f4d75357a9f0776 100644 (file)
@@ -44,13 +44,17 @@ static void cifs_set_ops(struct inode *inode)
                                inode->i_fop = &cifs_file_direct_nobrl_ops;
                        else
                                inode->i_fop = &cifs_file_direct_ops;
+               } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) {
+                       if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
+                               inode->i_fop = &cifs_file_strict_nobrl_ops;
+                       else
+                               inode->i_fop = &cifs_file_strict_ops;
                } else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_BRL)
                        inode->i_fop = &cifs_file_nobrl_ops;
                else { /* not direct, send byte range locks */
                        inode->i_fop = &cifs_file_ops;
                }
 
-
                /* check if server can support readpages */
                if (cifs_sb_master_tcon(cifs_sb)->ses->server->maxBuf <
                                PAGE_CACHE_SIZE + MAX_CIFS_HDR_SIZE)
@@ -1679,7 +1683,7 @@ cifs_inode_needs_reval(struct inode *inode)
 /*
  * Zap the cache. Called when invalid_mapping flag is set.
  */
-static void
+void
 cifs_invalidate_mapping(struct inode *inode)
 {
        int rc;