fs/9p: remove writeback fid and fix per-file modes
[sfrench/cifs-2.6.git] / fs / 9p / vfs_inode_dotl.c
index a28eb3aeab29d1bb430fba47e3acf7acdf914f83..4b9488cb7a56bebe347127f05fce6ad54c3488af 100644 (file)
@@ -232,12 +232,12 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
        int err = 0;
        kgid_t gid;
        umode_t mode;
+       int p9_omode = v9fs_open_to_dotl_flags(flags);
        const unsigned char *name = NULL;
        struct p9_qid qid;
        struct inode *inode;
        struct p9_fid *fid = NULL;
-       struct v9fs_inode *v9inode;
-       struct p9_fid *dfid = NULL, *ofid = NULL, *inode_fid = NULL;
+       struct p9_fid *dfid = NULL, *ofid = NULL;
        struct v9fs_session_info *v9ses;
        struct posix_acl *pacl = NULL, *dacl = NULL;
        struct dentry *res = NULL;
@@ -282,14 +282,19 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
        /* Update mode based on ACL value */
        err = v9fs_acl_mode(dir, &mode, &dacl, &pacl);
        if (err) {
-               p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n",
+               p9_debug(P9_DEBUG_VFS, "Failed to get acl values in create %d\n",
                         err);
                goto out;
        }
-       err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags),
-                                   mode, gid, &qid);
+
+       if ((v9ses->cache >= CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) {
+               p9_omode = (p9_omode & !P9_OWRITE) | P9_ORDWR;
+               p9_debug(P9_DEBUG_CACHE,
+                       "write-only file with writeback enabled, creating w/ O_RDWR\n");
+       }
+       err = p9_client_create_dotl(ofid, name, p9_omode, mode, gid, &qid);
        if (err < 0) {
-               p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n",
+               p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in create %d\n",
                         err);
                goto out;
        }
@@ -314,36 +319,19 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
        v9fs_fid_add(dentry, &fid);
        d_instantiate(dentry, inode);
 
-       v9inode = V9FS_I(inode);
-       mutex_lock(&v9inode->v_mutex);
-       if ((v9ses->cache) && !v9inode->writeback_fid &&
-           ((flags & O_ACCMODE) != O_RDONLY)) {
-               /*
-                * clone a fid and add it to writeback_fid
-                * we do it during open time instead of
-                * page dirty time via write_begin/page_mkwrite
-                * because we want write after unlink usecase
-                * to work.
-                */
-               inode_fid = v9fs_writeback_fid(dentry);
-               if (IS_ERR(inode_fid)) {
-                       err = PTR_ERR(inode_fid);
-                       mutex_unlock(&v9inode->v_mutex);
-                       goto out;
-               }
-               v9inode->writeback_fid = (void *) inode_fid;
-       }
-       mutex_unlock(&v9inode->v_mutex);
        /* Since we are opening a file, assign the open fid to the file */
        err = finish_open(file, dentry, generic_file_open);
        if (err)
                goto out;
        file->private_data = ofid;
 #ifdef CONFIG_9P_FSCACHE
-       if (v9ses->cache == CACHE_FSCACHE)
+       if (v9ses->cache == CACHE_FSCACHE) {
+               struct v9fs_inode *v9inode = V9FS_I(inode);
                fscache_use_cookie(v9fs_inode_cookie(v9inode),
                                   file->f_mode & FMODE_WRITE);
+       }
 #endif
+       v9fs_fid_add_modes(ofid, v9ses->flags, v9ses->cache, flags);
        v9fs_open_fid_add(inode, &ofid);
        file->f_mode |= FMODE_CREATED;
 out:
@@ -464,9 +452,9 @@ v9fs_vfs_getattr_dotl(struct mnt_idmap *idmap,
        p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
        v9ses = v9fs_dentry2v9ses(dentry);
        if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
-               generic_fillattr(&nop_mnt_idmap, d_inode(dentry), stat);
+               generic_fillattr(&nop_mnt_idmap, inode, stat);
                return 0;
-       } else if (v9ses->cache >= CACHE_WRITEBACK) {
+       } else if (v9ses->cache) {
                if (S_ISREG(inode->i_mode)) {
                        int retval = filemap_fdatawrite(inode->i_mapping);
 
@@ -613,6 +601,8 @@ int v9fs_vfs_setattr_dotl(struct mnt_idmap *idmap,
        if ((iattr->ia_valid & ATTR_SIZE) && iattr->ia_size !=
                 i_size_read(inode)) {
                truncate_setsize(inode, iattr->ia_size);
+               truncate_pagecache(inode, iattr->ia_size);
+
                if (v9ses->cache == CACHE_FSCACHE)
                        fscache_resize_cookie(v9fs_inode_cookie(v9inode), iattr->ia_size);
        }