Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag '9p-6.4-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs

Pull 9p updates from Eric Van Hensbergen:
"This includes a number of patches that didn't quite make the cut last
merge window while we addressed some outstanding issues and review
comments. It includes some new caching modes for those that only want
readahead caches and reworks how we do writeback caching so we are not
keeping extra references around which both causes performance problems
and uses lots of additional resources on the server.

It also includes a new flag to force disabling of xattrs which can
also cause major performance issues, particularly if the underlying
filesystem on the server doesn't support them.

Finally it adds a couple of additional mount options to better support
directio and enabling caches when the server doesn't support
qid.version.

There was one late-breaking bug report that has also been included as
its own patch where I forgot to propagate an embarassing bit-logic fix
to the various variations of open"

* tag '9p-6.4-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ericvh/v9fs:
fs/9p: Fix bit operation logic error
fs/9p: Rework cache modes and add new options to Documentation
fs/9p: remove writeback fid and fix per-file modes
fs/9p: Add new mount modes
9p: Add additional debug flags and open modes
fs/9p: allow disable of xattr support on mount
fs/9p: Remove unnecessary superblock flags
fs/9p: Consolidate file operations and add readahead and writeback

+367 -415
+38 -12
Documentation/filesystems/9p.rst
··· 78 78 offering several exported file systems. 79 79 80 80 cache=mode specifies a caching policy. By default, no caches are used. 81 + The mode can be specified as a bitmask or by using one of the 82 + prexisting common 'shortcuts'. 83 + The bitmask is described below: (unspecified bits are reserved) 81 84 82 - none 83 - default no cache policy, metadata and data 84 - alike are synchronous. 85 - loose 86 - no attempts are made at consistency, 87 - intended for exclusive, read-only mounts 88 - fscache 89 - use FS-Cache for a persistent, read-only 90 - cache backend. 91 - mmap 92 - minimal cache that is only used for read-write 93 - mmap. Northing else is cached, like cache=none 85 + ========== ==================================================== 86 + 0b00000000 all caches disabled, mmap disabled 87 + 0b00000001 file caches enabled 88 + 0b00000010 meta-data caches enabled 89 + 0b00000100 writeback behavior (as opposed to writethrough) 90 + 0b00001000 loose caches (no explicit consistency with server) 91 + 0b10000000 fscache enabled for persistent caching 92 + ========== ==================================================== 93 + 94 + The current shortcuts and their associated bitmask are: 95 + 96 + ========= ==================================================== 97 + none 0b00000000 (no caching) 98 + readahead 0b00000001 (only read-ahead file caching) 99 + mmap 0b00000101 (read-ahead + writeback file cache) 100 + loose 0b00001111 (non-coherent file and meta-data caches) 101 + fscache 0b10001111 (persistent loose cache) 102 + ========= ==================================================== 103 + 104 + NOTE: only these shortcuts are tested modes of operation at the 105 + moment, so using other combinations of bit-patterns is not 106 + known to work. Work on better cache support is in progress. 107 + 108 + IMPORTANT: loose caches (and by extension at the moment fscache) 109 + do not necessarily validate cached values on the server. In other 110 + words changes on the server are not guaranteed to be reflected 111 + on the client system. Only use this mode of operation if you 112 + have an exclusive mount and the server will modify the filesystem 113 + underneath you. 94 114 95 115 debug=n specifies debug level. The debug level is a bitmask. 96 116 ··· 156 136 nodevmap do not map special files - represent them as normal files. 157 137 This can be used to share devices/named pipes/sockets between 158 138 hosts. This functionality will be expanded in later versions. 139 + 140 + directio bypass page cache on all read/write operations 141 + 142 + ignoreqv ignore qid.version==0 as a marker to ignore cache 143 + 144 + noxattr do not offer xattr functions on this mount. 159 145 160 146 access there are four access modes. 161 147 user
+1 -2
fs/9p/cache.h
··· 8 8 #ifndef _9P_CACHE_H 9 9 #define _9P_CACHE_H 10 10 11 - #include <linux/fscache.h> 12 - 13 11 #ifdef CONFIG_9P_FSCACHE 12 + #include <linux/fscache.h> 14 13 15 14 extern int v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses, 16 15 const char *dev_name);
+19 -29
fs/9p/fid.c
··· 41 41 *pfid = NULL; 42 42 } 43 43 44 + static bool v9fs_is_writeable(int mode) 45 + { 46 + if (mode & (P9_OWRITE|P9_ORDWR)) 47 + return true; 48 + else 49 + return false; 50 + } 51 + 44 52 /** 45 53 * v9fs_fid_find_inode - search for an open fid off of the inode list 46 54 * @inode: return a fid pointing to a specific inode 55 + * @want_writeable: only consider fids which are writeable 47 56 * @uid: return a fid belonging to the specified user 57 + * @any: ignore uid as a selection criteria 48 58 * 49 59 */ 50 - 51 - static struct p9_fid *v9fs_fid_find_inode(struct inode *inode, kuid_t uid) 60 + struct p9_fid *v9fs_fid_find_inode(struct inode *inode, bool want_writeable, 61 + kuid_t uid, bool any) 52 62 { 53 63 struct hlist_head *h; 54 64 struct p9_fid *fid, *ret = NULL; ··· 68 58 spin_lock(&inode->i_lock); 69 59 h = (struct hlist_head *)&inode->i_private; 70 60 hlist_for_each_entry(fid, h, ilist) { 71 - if (uid_eq(fid->uid, uid)) { 61 + if (any || uid_eq(fid->uid, uid)) { 62 + if (want_writeable && !v9fs_is_writeable(fid->mode)) { 63 + p9_debug(P9_DEBUG_VFS, " mode: %x not writeable?\n", 64 + fid->mode); 65 + continue; 66 + } 72 67 p9_fid_get(fid); 73 68 ret = fid; 74 69 break; ··· 133 118 spin_unlock(&dentry->d_lock); 134 119 } else { 135 120 if (dentry->d_inode) 136 - ret = v9fs_fid_find_inode(dentry->d_inode, uid); 121 + ret = v9fs_fid_find_inode(dentry->d_inode, false, uid, any); 137 122 } 138 123 139 124 return ret; ··· 314 299 return v9fs_fid_lookup_with_uid(dentry, uid, any); 315 300 } 316 301 317 - struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) 318 - { 319 - int err; 320 - struct p9_fid *fid, *ofid; 321 - 322 - ofid = v9fs_fid_lookup_with_uid(dentry, GLOBAL_ROOT_UID, 0); 323 - fid = clone_fid(ofid); 324 - if (IS_ERR(fid)) 325 - goto error_out; 326 - p9_fid_put(ofid); 327 - /* 328 - * writeback fid will only be used to write back the 329 - * dirty pages. We always request for the open fid in read-write 330 - * mode so that a partial page write which result in page 331 - * read can work. 332 - */ 333 - err = p9_client_open(fid, O_RDWR); 334 - if (err < 0) { 335 - p9_fid_put(fid); 336 - fid = ERR_PTR(err); 337 - goto error_out; 338 - } 339 - error_out: 340 - return fid; 341 - }
+30 -1
fs/9p/fid.h
··· 7 7 #ifndef FS_9P_FID_H 8 8 #define FS_9P_FID_H 9 9 #include <linux/list.h> 10 + #include "v9fs.h" 10 11 12 + struct p9_fid *v9fs_fid_find_inode(struct inode *inode, bool want_writeable, 13 + kuid_t uid, bool any); 11 14 struct p9_fid *v9fs_fid_lookup(struct dentry *dentry); 12 15 static inline struct p9_fid *v9fs_parent_fid(struct dentry *dentry) 13 16 { 14 17 return v9fs_fid_lookup(dentry->d_parent); 15 18 } 16 19 void v9fs_fid_add(struct dentry *dentry, struct p9_fid **fid); 17 - struct p9_fid *v9fs_writeback_fid(struct dentry *dentry); 18 20 void v9fs_open_fid_add(struct inode *inode, struct p9_fid **fid); 19 21 static inline struct p9_fid *clone_fid(struct p9_fid *fid) 20 22 { ··· 33 31 nfid = clone_fid(fid); 34 32 p9_fid_put(fid); 35 33 return nfid; 34 + } 35 + /** 36 + * v9fs_fid_addmodes - add cache flags to fid mode (for client use only) 37 + * @fid: fid to augment 38 + * @s_flags: session info mount flags 39 + * @s_cache: session info cache flags 40 + * @f_flags: unix open flags 41 + * 42 + * make sure mode reflects flags of underlying mounts 43 + * also qid.version == 0 reflects a synthetic or legacy file system 44 + * NOTE: these are set after open so only reflect 9p client not 45 + * underlying file system on server. 46 + */ 47 + static inline void v9fs_fid_add_modes(struct p9_fid *fid, int s_flags, 48 + int s_cache, unsigned int f_flags) 49 + { 50 + if (fid->qid.type != P9_QTFILE) 51 + return; 52 + 53 + if ((!s_cache) || 54 + ((fid->qid.version == 0) && !(s_flags & V9FS_IGNORE_QV)) || 55 + (s_flags & V9FS_DIRECT_IO) || (f_flags & O_DIRECT)) { 56 + fid->mode |= P9L_DIRECT; /* no read or write cache */ 57 + } else if ((!(s_cache & CACHE_WRITEBACK)) || 58 + (f_flags & O_DSYNC) | (s_flags & V9FS_SYNC)) { 59 + fid->mode |= P9L_NOWRITECACHE; 60 + } 36 61 } 37 62 #endif
+31 -28
fs/9p/v9fs.c
··· 38 38 /* String options */ 39 39 Opt_uname, Opt_remotename, Opt_cache, Opt_cachetag, 40 40 /* Options that take no arguments */ 41 - Opt_nodevmap, 42 - /* Cache options */ 43 - Opt_cache_loose, Opt_fscache, Opt_mmap, 41 + Opt_nodevmap, Opt_noxattr, Opt_directio, Opt_ignoreqv, 44 42 /* Access options */ 45 43 Opt_access, Opt_posixacl, 46 44 /* Lock timeout option */ ··· 55 57 {Opt_uname, "uname=%s"}, 56 58 {Opt_remotename, "aname=%s"}, 57 59 {Opt_nodevmap, "nodevmap"}, 60 + {Opt_noxattr, "noxattr"}, 61 + {Opt_directio, "directio"}, 62 + {Opt_ignoreqv, "ignoreqv"}, 58 63 {Opt_cache, "cache=%s"}, 59 - {Opt_cache_loose, "loose"}, 60 - {Opt_fscache, "fscache"}, 61 - {Opt_mmap, "mmap"}, 62 64 {Opt_cachetag, "cachetag=%s"}, 63 65 {Opt_access, "access=%s"}, 64 66 {Opt_posixacl, "posixacl"}, 65 67 {Opt_locktimeout, "locktimeout=%u"}, 66 68 {Opt_err, NULL} 67 - }; 68 - 69 - static const char *const v9fs_cache_modes[nr__p9_cache_modes] = { 70 - [CACHE_NONE] = "none", 71 - [CACHE_MMAP] = "mmap", 72 - [CACHE_LOOSE] = "loose", 73 - [CACHE_FSCACHE] = "fscache", 74 69 }; 75 70 76 71 /* Interpret mount options for cache mode */ ··· 72 81 int version = -EINVAL; 73 82 74 83 if (!strcmp(s, "loose")) { 75 - version = CACHE_LOOSE; 84 + version = CACHE_SC_LOOSE; 76 85 p9_debug(P9_DEBUG_9P, "Cache mode: loose\n"); 77 86 } else if (!strcmp(s, "fscache")) { 78 - version = CACHE_FSCACHE; 87 + version = CACHE_SC_FSCACHE; 79 88 p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n"); 80 89 } else if (!strcmp(s, "mmap")) { 81 - version = CACHE_MMAP; 90 + version = CACHE_SC_MMAP; 82 91 p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n"); 92 + } else if (!strcmp(s, "readahead")) { 93 + version = CACHE_SC_READAHEAD; 94 + p9_debug(P9_DEBUG_9P, "Cache mode: readahead\n"); 83 95 } else if (!strcmp(s, "none")) { 84 - version = CACHE_NONE; 96 + version = CACHE_SC_NONE; 85 97 p9_debug(P9_DEBUG_9P, "Cache mode: none\n"); 86 - } else 87 - pr_info("Unknown Cache mode %s\n", s); 98 + } else if (kstrtoint(s, 0, &version) != 0) { 99 + version = -EINVAL; 100 + pr_info("Unknown Cache mode or invalid value %s\n", s); 101 + } 88 102 return version; 89 103 } 90 104 ··· 117 121 if (v9ses->nodev) 118 122 seq_puts(m, ",nodevmap"); 119 123 if (v9ses->cache) 120 - seq_printf(m, ",%s", v9fs_cache_modes[v9ses->cache]); 124 + seq_printf(m, ",cache=%x", v9ses->cache); 121 125 #ifdef CONFIG_9P_FSCACHE 122 - if (v9ses->cachetag && v9ses->cache == CACHE_FSCACHE) 126 + if (v9ses->cachetag && (v9ses->cache & CACHE_FSCACHE)) 123 127 seq_printf(m, ",cachetag=%s", v9ses->cachetag); 124 128 #endif 125 129 ··· 139 143 break; 140 144 } 141 145 146 + if (v9ses->flags & V9FS_IGNORE_QV) 147 + seq_puts(m, ",ignoreqv"); 148 + if (v9ses->flags & V9FS_DIRECT_IO) 149 + seq_puts(m, ",directio"); 142 150 if (v9ses->flags & V9FS_POSIX_ACL) 143 151 seq_puts(m, ",posixacl"); 152 + 153 + if (v9ses->flags & V9FS_NO_XATTR) 154 + seq_puts(m, ",noxattr"); 144 155 145 156 return p9_show_client_options(m, v9ses->clnt); 146 157 } ··· 269 266 case Opt_nodevmap: 270 267 v9ses->nodev = 1; 271 268 break; 272 - case Opt_cache_loose: 273 - v9ses->cache = CACHE_LOOSE; 269 + case Opt_noxattr: 270 + v9ses->flags |= V9FS_NO_XATTR; 274 271 break; 275 - case Opt_fscache: 276 - v9ses->cache = CACHE_FSCACHE; 272 + case Opt_directio: 273 + v9ses->flags |= V9FS_DIRECT_IO; 277 274 break; 278 - case Opt_mmap: 279 - v9ses->cache = CACHE_MMAP; 275 + case Opt_ignoreqv: 276 + v9ses->flags |= V9FS_IGNORE_QV; 280 277 break; 281 278 case Opt_cachetag: 282 279 #ifdef CONFIG_9P_FSCACHE ··· 471 468 472 469 #ifdef CONFIG_9P_FSCACHE 473 470 /* register the session for caching */ 474 - if (v9ses->cache == CACHE_FSCACHE) { 471 + if (v9ses->cache & CACHE_FSCACHE) { 475 472 rc = v9fs_cache_session_get_cookie(v9ses, dev_name); 476 473 if (rc < 0) 477 474 goto err_clnt;
+43 -19
fs/9p/v9fs.h
··· 31 31 #define V9FS_ACL_MASK V9FS_POSIX_ACL 32 32 33 33 enum p9_session_flags { 34 - V9FS_PROTO_2000U = 0x01, 35 - V9FS_PROTO_2000L = 0x02, 36 - V9FS_ACCESS_SINGLE = 0x04, 37 - V9FS_ACCESS_USER = 0x08, 38 - V9FS_ACCESS_CLIENT = 0x10, 39 - V9FS_POSIX_ACL = 0x20 34 + V9FS_PROTO_2000U = 0x01, 35 + V9FS_PROTO_2000L = 0x02, 36 + V9FS_ACCESS_SINGLE = 0x04, 37 + V9FS_ACCESS_USER = 0x08, 38 + V9FS_ACCESS_CLIENT = 0x10, 39 + V9FS_POSIX_ACL = 0x20, 40 + V9FS_NO_XATTR = 0x40, 41 + V9FS_IGNORE_QV = 0x80, /* ignore qid.version for cache hints */ 42 + V9FS_DIRECT_IO = 0x100, 43 + V9FS_SYNC = 0x200 40 44 }; 41 45 42 - /* possible values of ->cache */ 43 46 /** 44 - * enum p9_cache_modes - user specified cache preferences 45 - * @CACHE_NONE: do not cache data, dentries, or directory contents (default) 46 - * @CACHE_LOOSE: cache data, dentries, and directory contents w/no consistency 47 + * enum p9_cache_shortcuts - human readable cache preferences 48 + * @CACHE_SC_NONE: disable all caches 49 + * @CACHE_SC_READAHEAD: only provide caching for readahead 50 + * @CACHE_SC_MMAP: provide caching to enable mmap 51 + * @CACHE_SC_LOOSE: non-coherent caching for files and meta data 52 + * @CACHE_SC_FSCACHE: persistent non-coherent caching for files and meta-data 47 53 * 48 - * eventually support loose, tight, time, session, default always none 49 54 */ 50 55 51 - enum p9_cache_modes { 52 - CACHE_NONE, 53 - CACHE_MMAP, 54 - CACHE_LOOSE, 55 - CACHE_FSCACHE, 56 - nr__p9_cache_modes 56 + enum p9_cache_shortcuts { 57 + CACHE_SC_NONE = 0b00000000, 58 + CACHE_SC_READAHEAD = 0b00000001, 59 + CACHE_SC_MMAP = 0b00000101, 60 + CACHE_SC_LOOSE = 0b00001111, 61 + CACHE_SC_FSCACHE = 0b10001111, 62 + }; 63 + 64 + /** 65 + * enum p9_cache_bits - possible values of ->cache 66 + * @CACHE_NONE: caches disabled 67 + * @CACHE_FILE: file caching (open to close) 68 + * @CACHE_META: meta-data and directory caching 69 + * @CACHE_WRITEBACK: write-back caching for files 70 + * @CACHE_LOOSE: don't check cache consistency 71 + * @CACHE_FSCACHE: local persistent caches 72 + * 73 + */ 74 + 75 + enum p9_cache_bits { 76 + CACHE_NONE = 0b00000000, 77 + CACHE_FILE = 0b00000001, 78 + CACHE_META = 0b00000010, 79 + CACHE_WRITEBACK = 0b00000100, 80 + CACHE_LOOSE = 0b00001000, 81 + CACHE_FSCACHE = 0b10000000, 57 82 }; 58 83 59 84 /** ··· 87 62 * @nodev: set to 1 to disable device mapping 88 63 * @debug: debug level 89 64 * @afid: authentication handle 90 - * @cache: cache mode of type &p9_cache_modes 65 + * @cache: cache mode of type &p9_cache_bits 91 66 * @cachetag: the tag of the cache associated with this session 92 67 * @fscache: session cookie associated with FS-Cache 93 68 * @uname: string user name to mount hierarchy as ··· 137 112 struct netfs_inode netfs; /* Netfslib context and vfs inode */ 138 113 struct p9_qid qid; 139 114 unsigned int cache_validity; 140 - struct p9_fid *writeback_fid; 141 115 struct mutex v_mutex; 142 116 }; 143 117
-4
fs/9p/v9fs_vfs.h
··· 36 36 extern const struct file_operations v9fs_dir_operations_dotl; 37 37 extern const struct dentry_operations v9fs_dentry_operations; 38 38 extern const struct dentry_operations v9fs_cached_dentry_operations; 39 - extern const struct file_operations v9fs_cached_file_operations; 40 - extern const struct file_operations v9fs_cached_file_operations_dotl; 41 - extern const struct file_operations v9fs_mmap_file_operations; 42 - extern const struct file_operations v9fs_mmap_file_operations_dotl; 43 39 extern struct kmem_cache *v9fs_inode_cache; 44 40 45 41 struct inode *v9fs_alloc_inode(struct super_block *sb);
+28 -22
fs/9p/vfs_addr.c
··· 57 57 */ 58 58 static int v9fs_init_request(struct netfs_io_request *rreq, struct file *file) 59 59 { 60 - struct inode *inode = file_inode(file); 61 - struct v9fs_inode *v9inode = V9FS_I(inode); 62 60 struct p9_fid *fid = file->private_data; 63 61 64 62 BUG_ON(!fid); ··· 64 66 /* we might need to read from a fid that was opened write-only 65 67 * for read-modify-write of page cache, use the writeback fid 66 68 * for that */ 67 - if (rreq->origin == NETFS_READ_FOR_WRITE && 68 - (fid->mode & O_ACCMODE) == O_WRONLY) { 69 - fid = v9inode->writeback_fid; 70 - BUG_ON(!fid); 71 - } 69 + WARN_ON(rreq->origin == NETFS_READ_FOR_WRITE && 70 + !(fid->mode & P9_ORDWR)); 72 71 73 72 p9_fid_get(fid); 74 73 rreq->netfs_priv = fid; ··· 115 120 116 121 static bool v9fs_release_folio(struct folio *folio, gfp_t gfp) 117 122 { 118 - struct inode *inode = folio_inode(folio); 119 - 120 123 if (folio_test_private(folio)) 121 124 return false; 122 125 #ifdef CONFIG_9P_FSCACHE ··· 123 130 return false; 124 131 folio_wait_fscache(folio); 125 132 } 133 + fscache_note_page_release(v9fs_inode_cookie(V9FS_I(folio_inode(folio)))); 126 134 #endif 127 - fscache_note_page_release(v9fs_inode_cookie(V9FS_I(inode))); 128 135 return true; 129 136 } 130 137 ··· 134 141 folio_wait_fscache(folio); 135 142 } 136 143 144 + #ifdef CONFIG_9P_FSCACHE 137 145 static void v9fs_write_to_cache_done(void *priv, ssize_t transferred_or_error, 138 146 bool was_async) 139 147 { ··· 148 154 i_size_read(&v9inode->netfs.inode), 0); 149 155 } 150 156 } 157 + #endif 151 158 152 159 static int v9fs_vfs_write_folio_locked(struct folio *folio) 153 160 { 154 161 struct inode *inode = folio_inode(folio); 155 - struct v9fs_inode *v9inode = V9FS_I(inode); 156 - struct fscache_cookie *cookie = v9fs_inode_cookie(v9inode); 157 162 loff_t start = folio_pos(folio); 158 163 loff_t i_size = i_size_read(inode); 159 164 struct iov_iter from; 160 165 size_t len = folio_size(folio); 166 + struct p9_fid *writeback_fid; 161 167 int err; 168 + struct v9fs_inode __maybe_unused *v9inode = V9FS_I(inode); 169 + struct fscache_cookie __maybe_unused *cookie = v9fs_inode_cookie(v9inode); 162 170 163 171 if (start >= i_size) 164 172 return 0; /* Simultaneous truncation occurred */ ··· 169 173 170 174 iov_iter_xarray(&from, ITER_SOURCE, &folio_mapping(folio)->i_pages, start, len); 171 175 172 - /* We should have writeback_fid always set */ 173 - BUG_ON(!v9inode->writeback_fid); 176 + writeback_fid = v9fs_fid_find_inode(inode, true, INVALID_UID, true); 177 + if (!writeback_fid) { 178 + WARN_ONCE(1, "folio expected an open fid inode->i_private=%p\n", 179 + inode->i_private); 180 + return -EINVAL; 181 + } 174 182 175 183 folio_wait_fscache(folio); 176 184 folio_start_writeback(folio); 177 185 178 - p9_client_write(v9inode->writeback_fid, start, &from, &err); 186 + p9_client_write(writeback_fid, start, &from, &err); 179 187 188 + #ifdef CONFIG_9P_FSCACHE 180 189 if (err == 0 && 181 - fscache_cookie_enabled(cookie) && 182 - test_bit(FSCACHE_COOKIE_IS_CACHING, &cookie->flags)) { 190 + fscache_cookie_enabled(cookie) && 191 + test_bit(FSCACHE_COOKIE_IS_CACHING, &cookie->flags)) { 183 192 folio_start_fscache(folio); 184 193 fscache_write_to_cache(v9fs_inode_cookie(v9inode), 185 - folio_mapping(folio), start, len, i_size, 186 - v9fs_write_to_cache_done, v9inode, 187 - true); 194 + folio_mapping(folio), start, len, i_size, 195 + v9fs_write_to_cache_done, v9inode, 196 + true); 188 197 } 198 + #endif 189 199 190 200 folio_end_writeback(folio); 201 + p9_fid_put(writeback_fid); 202 + 191 203 return err; 192 204 } 193 205 ··· 302 298 loff_t last_pos = pos + copied; 303 299 struct folio *folio = page_folio(subpage); 304 300 struct inode *inode = mapping->host; 305 - struct v9fs_inode *v9inode = V9FS_I(inode); 306 301 307 302 p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); 308 303 ··· 321 318 if (last_pos > inode->i_size) { 322 319 inode_add_bytes(inode, last_pos - inode->i_size); 323 320 i_size_write(inode, last_pos); 324 - fscache_update_cookie(v9fs_inode_cookie(v9inode), NULL, &last_pos); 321 + #ifdef CONFIG_9P_FSCACHE 322 + fscache_update_cookie(v9fs_inode_cookie(V9FS_I(inode)), NULL, 323 + &last_pos); 324 + #endif 325 325 } 326 326 folio_mark_dirty(folio); 327 327 out:
+7 -3
fs/9p/vfs_dir.c
··· 197 197 198 198 199 199 /** 200 - * v9fs_dir_release - called on a close of a file or directory 201 - * @inode: inode of the directory 202 - * @filp: file pointer to a directory 200 + * v9fs_dir_release - close a directory or a file 201 + * @inode: inode of the directory or file 202 + * @filp: file pointer to a directory or file 203 203 * 204 204 */ 205 205 ··· 214 214 fid = filp->private_data; 215 215 p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d\n", 216 216 inode, filp, fid ? fid->fid : -1); 217 + 217 218 if (fid) { 219 + if ((S_ISREG(inode->i_mode)) && (filp->f_mode & FMODE_WRITE)) 220 + retval = filemap_fdatawrite(inode->i_mapping); 221 + 218 222 spin_lock(&inode->i_lock); 219 223 hlist_del(&fid->ilist); 220 224 spin_unlock(&inode->i_lock);
+42 -164
fs/9p/vfs_file.c
··· 29 29 #include "fid.h" 30 30 #include "cache.h" 31 31 32 - static const struct vm_operations_struct v9fs_file_vm_ops; 33 32 static const struct vm_operations_struct v9fs_mmap_file_vm_ops; 34 33 35 34 /** ··· 41 42 int v9fs_file_open(struct inode *inode, struct file *file) 42 43 { 43 44 int err; 44 - struct v9fs_inode *v9inode; 45 45 struct v9fs_session_info *v9ses; 46 - struct p9_fid *fid, *writeback_fid; 46 + struct p9_fid *fid; 47 47 int omode; 48 48 49 49 p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); 50 - v9inode = V9FS_I(inode); 51 50 v9ses = v9fs_inode2v9ses(inode); 52 51 if (v9fs_proto_dotl(v9ses)) 53 52 omode = v9fs_open_to_dotl_flags(file->f_flags); ··· 58 61 if (IS_ERR(fid)) 59 62 return PTR_ERR(fid); 60 63 61 - err = p9_client_open(fid, omode); 64 + if ((v9ses->cache & CACHE_WRITEBACK) && (omode & P9_OWRITE)) { 65 + int writeback_omode = (omode & ~P9_OWRITE) | P9_ORDWR; 66 + 67 + p9_debug(P9_DEBUG_CACHE, "write-only file with writeback enabled, try opening O_RDWR\n"); 68 + err = p9_client_open(fid, writeback_omode); 69 + if (err < 0) { 70 + p9_debug(P9_DEBUG_CACHE, "could not open O_RDWR, disabling caches\n"); 71 + err = p9_client_open(fid, omode); 72 + fid->mode |= P9L_DIRECT; 73 + } 74 + } else { 75 + err = p9_client_open(fid, omode); 76 + } 62 77 if (err < 0) { 63 78 p9_fid_put(fid); 64 79 return err; ··· 82 73 file->private_data = fid; 83 74 } 84 75 85 - mutex_lock(&v9inode->v_mutex); 86 - if ((v9ses->cache) && !v9inode->writeback_fid && 87 - ((file->f_flags & O_ACCMODE) != O_RDONLY)) { 88 - /* 89 - * clone a fid and add it to writeback_fid 90 - * we do it during open time instead of 91 - * page dirty time via write_begin/page_mkwrite 92 - * because we want write after unlink usecase 93 - * to work. 94 - */ 95 - writeback_fid = v9fs_writeback_fid(file_dentry(file)); 96 - if (IS_ERR(writeback_fid)) { 97 - err = PTR_ERR(writeback_fid); 98 - mutex_unlock(&v9inode->v_mutex); 99 - goto out_error; 100 - } 101 - v9inode->writeback_fid = (void *) writeback_fid; 102 - } 103 - mutex_unlock(&v9inode->v_mutex); 104 76 #ifdef CONFIG_9P_FSCACHE 105 - if (v9ses->cache == CACHE_FSCACHE) 106 - fscache_use_cookie(v9fs_inode_cookie(v9inode), 77 + if (v9ses->cache & CACHE_FSCACHE) 78 + fscache_use_cookie(v9fs_inode_cookie(V9FS_I(inode)), 107 79 file->f_mode & FMODE_WRITE); 108 80 #endif 81 + v9fs_fid_add_modes(fid, v9ses->flags, v9ses->cache, file->f_flags); 109 82 v9fs_open_fid_add(inode, &fid); 110 83 return 0; 111 - out_error: 112 - p9_fid_put(file->private_data); 113 - file->private_data = NULL; 114 - return err; 115 84 } 116 85 117 86 /** ··· 356 369 struct p9_fid *fid = iocb->ki_filp->private_data; 357 370 int ret, err = 0; 358 371 359 - p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", 360 - iov_iter_count(to), iocb->ki_pos); 372 + p9_debug(P9_DEBUG_VFS, "fid %d count %zu offset %lld\n", 373 + fid->fid, iov_iter_count(to), iocb->ki_pos); 374 + 375 + if (!(fid->mode & P9L_DIRECT)) { 376 + p9_debug(P9_DEBUG_VFS, "(cached)\n"); 377 + return generic_file_read_iter(iocb, to); 378 + } 361 379 362 380 if (iocb->ki_filp->f_flags & O_NONBLOCK) 363 381 ret = p9_client_read_once(fid, iocb->ki_pos, to, &err); ··· 385 393 v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) 386 394 { 387 395 struct file *file = iocb->ki_filp; 396 + struct p9_fid *fid = file->private_data; 388 397 ssize_t retval; 389 398 loff_t origin; 390 399 int err = 0; 400 + 401 + p9_debug(P9_DEBUG_VFS, "fid %d\n", fid->fid); 402 + 403 + if (!(fid->mode & (P9L_DIRECT | P9L_NOWRITECACHE))) { 404 + p9_debug(P9_DEBUG_CACHE, "(cached)\n"); 405 + return generic_file_write_iter(iocb, from); 406 + } 391 407 392 408 retval = generic_write_checks(iocb, from); 393 409 if (retval <= 0) ··· 478 478 v9fs_file_mmap(struct file *filp, struct vm_area_struct *vma) 479 479 { 480 480 int retval; 481 + struct inode *inode = file_inode(filp); 482 + struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); 481 483 484 + p9_debug(P9_DEBUG_MMAP, "filp :%p\n", filp); 482 485 483 - retval = generic_file_mmap(filp, vma); 484 - if (!retval) 485 - vma->vm_ops = &v9fs_file_vm_ops; 486 - 487 - return retval; 488 - } 489 - 490 - static int 491 - v9fs_mmap_file_mmap(struct file *filp, struct vm_area_struct *vma) 492 - { 493 - int retval; 494 - struct inode *inode; 495 - struct v9fs_inode *v9inode; 496 - struct p9_fid *fid; 497 - 498 - inode = file_inode(filp); 499 - v9inode = V9FS_I(inode); 500 - mutex_lock(&v9inode->v_mutex); 501 - if (!v9inode->writeback_fid && 502 - (vma->vm_flags & VM_SHARED) && 503 - (vma->vm_flags & VM_WRITE)) { 504 - /* 505 - * clone a fid and add it to writeback_fid 506 - * we do it during mmap instead of 507 - * page dirty time via write_begin/page_mkwrite 508 - * because we want write after unlink usecase 509 - * to work. 510 - */ 511 - fid = v9fs_writeback_fid(file_dentry(filp)); 512 - if (IS_ERR(fid)) { 513 - retval = PTR_ERR(fid); 514 - mutex_unlock(&v9inode->v_mutex); 515 - return retval; 516 - } 517 - v9inode->writeback_fid = (void *) fid; 486 + if (!(v9ses->cache & CACHE_WRITEBACK)) { 487 + p9_debug(P9_DEBUG_CACHE, "(no mmap mode)"); 488 + if (vma->vm_flags & VM_MAYSHARE) 489 + return -ENODEV; 490 + invalidate_inode_pages2(filp->f_mapping); 491 + return generic_file_readonly_mmap(filp, vma); 518 492 } 519 - mutex_unlock(&v9inode->v_mutex); 520 493 521 494 retval = generic_file_mmap(filp, vma); 522 495 if (!retval) ··· 501 528 static vm_fault_t 502 529 v9fs_vm_page_mkwrite(struct vm_fault *vmf) 503 530 { 504 - struct v9fs_inode *v9inode; 505 531 struct folio *folio = page_folio(vmf->page); 506 532 struct file *filp = vmf->vma->vm_file; 507 533 struct inode *inode = file_inode(filp); ··· 508 536 509 537 p9_debug(P9_DEBUG_VFS, "folio %p fid %lx\n", 510 538 folio, (unsigned long)filp->private_data); 511 - 512 - v9inode = V9FS_I(inode); 513 539 514 540 /* Wait for the page to be written to the cache before we allow it to 515 541 * be modified. We then assume the entire page will need writing back. ··· 521 551 /* Update file times before taking page lock */ 522 552 file_update_time(filp); 523 553 524 - BUG_ON(!v9inode->writeback_fid); 525 554 if (folio_lock_killable(folio) < 0) 526 555 return VM_FAULT_RETRY; 527 556 if (folio_mapping(folio) != inode->i_mapping) ··· 531 562 out_unlock: 532 563 folio_unlock(folio); 533 564 return VM_FAULT_NOPAGE; 534 - } 535 - 536 - /** 537 - * v9fs_mmap_file_read_iter - read from a file 538 - * @iocb: The operation parameters 539 - * @to: The buffer to read into 540 - * 541 - */ 542 - static ssize_t 543 - v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to) 544 - { 545 - /* TODO: Check if there are dirty pages */ 546 - return v9fs_file_read_iter(iocb, to); 547 - } 548 - 549 - /** 550 - * v9fs_mmap_file_write_iter - write to a file 551 - * @iocb: The operation parameters 552 - * @from: The data to write 553 - * 554 - */ 555 - static ssize_t 556 - v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from) 557 - { 558 - /* 559 - * TODO: invalidate mmaps on filp's inode between 560 - * offset and offset+count 561 - */ 562 - return v9fs_file_write_iter(iocb, from); 563 565 } 564 566 565 567 static void v9fs_mmap_vm_close(struct vm_area_struct *vma) ··· 555 615 filemap_fdatawrite_wbc(inode->i_mapping, &wbc); 556 616 } 557 617 558 - 559 - static const struct vm_operations_struct v9fs_file_vm_ops = { 560 - .fault = filemap_fault, 561 - .map_pages = filemap_map_pages, 562 - .page_mkwrite = v9fs_vm_page_mkwrite, 563 - }; 564 - 565 618 static const struct vm_operations_struct v9fs_mmap_file_vm_ops = { 566 619 .close = v9fs_mmap_vm_close, 567 620 .fault = filemap_fault, 568 621 .map_pages = filemap_map_pages, 569 622 .page_mkwrite = v9fs_vm_page_mkwrite, 570 - }; 571 - 572 - 573 - const struct file_operations v9fs_cached_file_operations = { 574 - .llseek = generic_file_llseek, 575 - .read_iter = generic_file_read_iter, 576 - .write_iter = generic_file_write_iter, 577 - .open = v9fs_file_open, 578 - .release = v9fs_dir_release, 579 - .lock = v9fs_file_lock, 580 - .mmap = v9fs_file_mmap, 581 - .splice_read = generic_file_splice_read, 582 - .splice_write = iter_file_splice_write, 583 - .fsync = v9fs_file_fsync, 584 - }; 585 - 586 - const struct file_operations v9fs_cached_file_operations_dotl = { 587 - .llseek = generic_file_llseek, 588 - .read_iter = generic_file_read_iter, 589 - .write_iter = generic_file_write_iter, 590 - .open = v9fs_file_open, 591 - .release = v9fs_dir_release, 592 - .lock = v9fs_file_lock_dotl, 593 - .flock = v9fs_file_flock_dotl, 594 - .mmap = v9fs_file_mmap, 595 - .splice_read = generic_file_splice_read, 596 - .splice_write = iter_file_splice_write, 597 - .fsync = v9fs_file_fsync_dotl, 598 623 }; 599 624 600 625 const struct file_operations v9fs_file_operations = { ··· 583 678 .release = v9fs_dir_release, 584 679 .lock = v9fs_file_lock_dotl, 585 680 .flock = v9fs_file_flock_dotl, 586 - .mmap = generic_file_readonly_mmap, 587 - .splice_read = generic_file_splice_read, 588 - .splice_write = iter_file_splice_write, 589 - .fsync = v9fs_file_fsync_dotl, 590 - }; 591 - 592 - const struct file_operations v9fs_mmap_file_operations = { 593 - .llseek = generic_file_llseek, 594 - .read_iter = v9fs_mmap_file_read_iter, 595 - .write_iter = v9fs_mmap_file_write_iter, 596 - .open = v9fs_file_open, 597 - .release = v9fs_dir_release, 598 - .lock = v9fs_file_lock, 599 - .mmap = v9fs_mmap_file_mmap, 600 - .splice_read = generic_file_splice_read, 601 - .splice_write = iter_file_splice_write, 602 - .fsync = v9fs_file_fsync, 603 - }; 604 - 605 - const struct file_operations v9fs_mmap_file_operations_dotl = { 606 - .llseek = generic_file_llseek, 607 - .read_iter = v9fs_mmap_file_read_iter, 608 - .write_iter = v9fs_mmap_file_write_iter, 609 - .open = v9fs_file_open, 610 - .release = v9fs_dir_release, 611 - .lock = v9fs_file_lock_dotl, 612 - .flock = v9fs_file_flock_dotl, 613 - .mmap = v9fs_mmap_file_mmap, 681 + .mmap = v9fs_file_mmap, 614 682 .splice_read = generic_file_splice_read, 615 683 .splice_write = iter_file_splice_write, 616 684 .fsync = v9fs_file_fsync_dotl,
+55 -56
fs/9p/vfs_inode.c
··· 230 230 v9inode = alloc_inode_sb(sb, v9fs_inode_cache, GFP_KERNEL); 231 231 if (!v9inode) 232 232 return NULL; 233 - v9inode->writeback_fid = NULL; 234 233 v9inode->cache_validity = 0; 235 234 mutex_init(&v9inode->v_mutex); 236 235 return &v9inode->netfs.inode; ··· 286 287 case S_IFREG: 287 288 if (v9fs_proto_dotl(v9ses)) { 288 289 inode->i_op = &v9fs_file_inode_operations_dotl; 289 - if (v9ses->cache == CACHE_LOOSE || 290 - v9ses->cache == CACHE_FSCACHE) 291 - inode->i_fop = 292 - &v9fs_cached_file_operations_dotl; 293 - else if (v9ses->cache == CACHE_MMAP) 294 - inode->i_fop = &v9fs_mmap_file_operations_dotl; 295 - else 296 - inode->i_fop = &v9fs_file_operations_dotl; 290 + inode->i_fop = &v9fs_file_operations_dotl; 297 291 } else { 298 292 inode->i_op = &v9fs_file_inode_operations; 299 - if (v9ses->cache == CACHE_LOOSE || 300 - v9ses->cache == CACHE_FSCACHE) 301 - inode->i_fop = 302 - &v9fs_cached_file_operations; 303 - else if (v9ses->cache == CACHE_MMAP) 304 - inode->i_fop = &v9fs_mmap_file_operations; 305 - else 306 - inode->i_fop = &v9fs_file_operations; 293 + inode->i_fop = &v9fs_file_operations; 307 294 } 308 295 309 296 break; ··· 371 386 */ 372 387 void v9fs_evict_inode(struct inode *inode) 373 388 { 374 - struct v9fs_inode *v9inode = V9FS_I(inode); 375 - __le32 version; 389 + struct v9fs_inode __maybe_unused *v9inode = V9FS_I(inode); 390 + __le32 __maybe_unused version; 376 391 377 392 truncate_inode_pages_final(&inode->i_data); 393 + 394 + #ifdef CONFIG_9P_FSCACHE 378 395 version = cpu_to_le32(v9inode->qid.version); 379 396 fscache_clear_inode_writeback(v9fs_inode_cookie(v9inode), inode, 380 397 &version); 398 + #endif 399 + 381 400 clear_inode(inode); 382 401 filemap_fdatawrite(&inode->i_data); 383 402 403 + #ifdef CONFIG_9P_FSCACHE 384 404 fscache_relinquish_cookie(v9fs_inode_cookie(v9inode), false); 385 - /* clunk the fid stashed in writeback_fid */ 386 - p9_fid_put(v9inode->writeback_fid); 387 - v9inode->writeback_fid = NULL; 405 + #endif 388 406 } 389 407 390 408 static int v9fs_test_inode(struct inode *inode, void *data) ··· 767 779 inode = NULL; 768 780 else if (IS_ERR(fid)) 769 781 inode = ERR_CAST(fid); 770 - else if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 782 + else if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) 771 783 inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); 772 784 else 773 785 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); ··· 796 808 { 797 809 int err; 798 810 u32 perm; 799 - struct v9fs_inode *v9inode; 811 + struct v9fs_inode __maybe_unused *v9inode; 800 812 struct v9fs_session_info *v9ses; 801 - struct p9_fid *fid, *inode_fid; 813 + struct p9_fid *fid; 802 814 struct dentry *res = NULL; 803 815 struct inode *inode; 816 + int p9_omode; 804 817 805 818 if (d_in_lookup(dentry)) { 806 819 res = v9fs_vfs_lookup(dir, dentry, 0); ··· 820 831 821 832 v9ses = v9fs_inode2v9ses(dir); 822 833 perm = unixmode2p9mode(v9ses, mode); 823 - fid = v9fs_create(v9ses, dir, dentry, NULL, perm, 824 - v9fs_uflags2omode(flags, 825 - v9fs_proto_dotu(v9ses))); 834 + p9_omode = v9fs_uflags2omode(flags, v9fs_proto_dotu(v9ses)); 835 + 836 + if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) { 837 + p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR; 838 + p9_debug(P9_DEBUG_CACHE, 839 + "write-only file with writeback enabled, creating w/ O_RDWR\n"); 840 + } 841 + fid = v9fs_create(v9ses, dir, dentry, NULL, perm, p9_omode); 826 842 if (IS_ERR(fid)) { 827 843 err = PTR_ERR(fid); 828 844 goto error; ··· 836 842 v9fs_invalidate_inode_attr(dir); 837 843 inode = d_inode(dentry); 838 844 v9inode = V9FS_I(inode); 839 - mutex_lock(&v9inode->v_mutex); 840 - if ((v9ses->cache) && !v9inode->writeback_fid && 841 - ((flags & O_ACCMODE) != O_RDONLY)) { 842 - /* 843 - * clone a fid and add it to writeback_fid 844 - * we do it during open time instead of 845 - * page dirty time via write_begin/page_mkwrite 846 - * because we want write after unlink usecase 847 - * to work. 848 - */ 849 - inode_fid = v9fs_writeback_fid(dentry); 850 - if (IS_ERR(inode_fid)) { 851 - err = PTR_ERR(inode_fid); 852 - mutex_unlock(&v9inode->v_mutex); 853 - goto error; 854 - } 855 - v9inode->writeback_fid = (void *) inode_fid; 856 - } 857 - mutex_unlock(&v9inode->v_mutex); 858 845 err = finish_open(file, dentry, generic_file_open); 859 846 if (err) 860 847 goto error; 861 848 862 849 file->private_data = fid; 863 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 850 + #ifdef CONFIG_9P_FSCACHE 851 + if (v9ses->cache & CACHE_FSCACHE) 864 852 fscache_use_cookie(v9fs_inode_cookie(v9inode), 865 853 file->f_mode & FMODE_WRITE); 854 + #endif 855 + 856 + v9fs_fid_add_modes(fid, v9ses->flags, v9ses->cache, file->f_flags); 866 857 v9fs_open_fid_add(inode, &fid); 867 858 868 859 file->f_mode |= FMODE_CREATED; ··· 1009 1030 struct kstat *stat, u32 request_mask, unsigned int flags) 1010 1031 { 1011 1032 struct dentry *dentry = path->dentry; 1033 + struct inode *inode = d_inode(dentry); 1012 1034 struct v9fs_session_info *v9ses; 1013 1035 struct p9_fid *fid; 1014 1036 struct p9_wstat *st; 1015 1037 1016 1038 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); 1017 1039 v9ses = v9fs_dentry2v9ses(dentry); 1018 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 1019 - generic_fillattr(&nop_mnt_idmap, d_inode(dentry), stat); 1040 + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) { 1041 + generic_fillattr(&nop_mnt_idmap, inode, stat); 1020 1042 return 0; 1043 + } else if (v9ses->cache & CACHE_WRITEBACK) { 1044 + if (S_ISREG(inode->i_mode)) { 1045 + int retval = filemap_fdatawrite(inode->i_mapping); 1046 + 1047 + if (retval) 1048 + p9_debug(P9_DEBUG_ERROR, 1049 + "flushing writeback during getattr returned %d\n", retval); 1050 + } 1021 1051 } 1022 1052 fid = v9fs_fid_lookup(dentry); 1023 1053 if (IS_ERR(fid)) ··· 1058 1070 { 1059 1071 int retval, use_dentry = 0; 1060 1072 struct inode *inode = d_inode(dentry); 1061 - struct v9fs_inode *v9inode = V9FS_I(inode); 1062 1073 struct v9fs_session_info *v9ses; 1063 1074 struct p9_fid *fid = NULL; 1064 1075 struct p9_wstat wstat; ··· 1102 1115 } 1103 1116 1104 1117 /* Write all dirty data */ 1105 - if (d_is_reg(dentry)) 1106 - filemap_write_and_wait(inode->i_mapping); 1118 + if (d_is_reg(dentry)) { 1119 + retval = filemap_fdatawrite(inode->i_mapping); 1120 + if (retval) 1121 + p9_debug(P9_DEBUG_ERROR, 1122 + "flushing writeback during setattr returned %d\n", retval); 1123 + } 1107 1124 1108 1125 retval = p9_client_wstat(fid, &wstat); 1109 1126 ··· 1118 1127 return retval; 1119 1128 1120 1129 if ((iattr->ia_valid & ATTR_SIZE) && 1121 - iattr->ia_size != i_size_read(inode)) { 1130 + iattr->ia_size != i_size_read(inode)) { 1122 1131 truncate_setsize(inode, iattr->ia_size); 1123 - fscache_resize_cookie(v9fs_inode_cookie(v9inode), iattr->ia_size); 1132 + truncate_pagecache(inode, iattr->ia_size); 1133 + 1134 + #ifdef CONFIG_9P_FSCACHE 1135 + if (v9ses->cache & CACHE_FSCACHE) { 1136 + struct v9fs_inode *v9inode = V9FS_I(inode); 1137 + 1138 + fscache_resize_cookie(v9fs_inode_cookie(v9inode), iattr->ia_size); 1139 + } 1140 + #endif 1124 1141 } 1125 1142 1126 1143 v9fs_invalidate_inode_attr(inode); ··· 1412 1413 * We don't want to refresh inode->i_size, 1413 1414 * because we may have cached data 1414 1415 */ 1415 - flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ? 1416 + flags = (v9ses->cache & CACHE_LOOSE) ? 1416 1417 V9FS_STAT2INODE_KEEP_ISIZE : 0; 1417 1418 v9fs_stat2inode(st, inode, inode->i_sb, flags); 1418 1419 out:
+51 -39
fs/9p/vfs_inode_dotl.c
··· 232 232 int err = 0; 233 233 kgid_t gid; 234 234 umode_t mode; 235 + int p9_omode = v9fs_open_to_dotl_flags(flags); 235 236 const unsigned char *name = NULL; 236 237 struct p9_qid qid; 237 238 struct inode *inode; 238 239 struct p9_fid *fid = NULL; 239 - struct v9fs_inode *v9inode; 240 - struct p9_fid *dfid = NULL, *ofid = NULL, *inode_fid = NULL; 240 + struct p9_fid *dfid = NULL, *ofid = NULL; 241 241 struct v9fs_session_info *v9ses; 242 242 struct posix_acl *pacl = NULL, *dacl = NULL; 243 243 struct dentry *res = NULL; ··· 282 282 /* Update mode based on ACL value */ 283 283 err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); 284 284 if (err) { 285 - p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n", 285 + p9_debug(P9_DEBUG_VFS, "Failed to get acl values in create %d\n", 286 286 err); 287 287 goto out; 288 288 } 289 - err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags), 290 - mode, gid, &qid); 289 + 290 + if ((v9ses->cache & CACHE_WRITEBACK) && (p9_omode & P9_OWRITE)) { 291 + p9_omode = (p9_omode & ~P9_OWRITE) | P9_ORDWR; 292 + p9_debug(P9_DEBUG_CACHE, 293 + "write-only file with writeback enabled, creating w/ O_RDWR\n"); 294 + } 295 + err = p9_client_create_dotl(ofid, name, p9_omode, mode, gid, &qid); 291 296 if (err < 0) { 292 - p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n", 297 + p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in create %d\n", 293 298 err); 294 299 goto out; 295 300 } ··· 319 314 v9fs_fid_add(dentry, &fid); 320 315 d_instantiate(dentry, inode); 321 316 322 - v9inode = V9FS_I(inode); 323 - mutex_lock(&v9inode->v_mutex); 324 - if ((v9ses->cache) && !v9inode->writeback_fid && 325 - ((flags & O_ACCMODE) != O_RDONLY)) { 326 - /* 327 - * clone a fid and add it to writeback_fid 328 - * we do it during open time instead of 329 - * page dirty time via write_begin/page_mkwrite 330 - * because we want write after unlink usecase 331 - * to work. 332 - */ 333 - inode_fid = v9fs_writeback_fid(dentry); 334 - if (IS_ERR(inode_fid)) { 335 - err = PTR_ERR(inode_fid); 336 - mutex_unlock(&v9inode->v_mutex); 337 - goto out; 338 - } 339 - v9inode->writeback_fid = (void *) inode_fid; 340 - } 341 - mutex_unlock(&v9inode->v_mutex); 342 317 /* Since we are opening a file, assign the open fid to the file */ 343 318 err = finish_open(file, dentry, generic_file_open); 344 319 if (err) 345 320 goto out; 346 321 file->private_data = ofid; 347 322 #ifdef CONFIG_9P_FSCACHE 348 - if (v9ses->cache == CACHE_FSCACHE) 323 + if (v9ses->cache & CACHE_FSCACHE) { 324 + struct v9fs_inode *v9inode = V9FS_I(inode); 349 325 fscache_use_cookie(v9fs_inode_cookie(v9inode), 350 326 file->f_mode & FMODE_WRITE); 327 + } 351 328 #endif 329 + v9fs_fid_add_modes(ofid, v9ses->flags, v9ses->cache, flags); 352 330 v9fs_open_fid_add(inode, &ofid); 353 331 file->f_mode |= FMODE_CREATED; 354 332 out: ··· 403 415 } 404 416 405 417 /* instantiate inode and assign the unopened fid to the dentry */ 406 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 418 + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) { 407 419 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); 408 420 if (IS_ERR(inode)) { 409 421 err = PTR_ERR(inode); ··· 446 458 struct dentry *dentry = path->dentry; 447 459 struct v9fs_session_info *v9ses; 448 460 struct p9_fid *fid; 461 + struct inode *inode = d_inode(dentry); 449 462 struct p9_stat_dotl *st; 450 463 451 464 p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); 452 465 v9ses = v9fs_dentry2v9ses(dentry); 453 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 454 - generic_fillattr(&nop_mnt_idmap, d_inode(dentry), stat); 466 + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) { 467 + generic_fillattr(&nop_mnt_idmap, inode, stat); 455 468 return 0; 469 + } else if (v9ses->cache) { 470 + if (S_ISREG(inode->i_mode)) { 471 + int retval = filemap_fdatawrite(inode->i_mapping); 472 + 473 + if (retval) 474 + p9_debug(P9_DEBUG_ERROR, 475 + "flushing writeback during getattr returned %d\n", retval); 476 + } 456 477 } 457 478 fid = v9fs_fid_lookup(dentry); 458 479 if (IS_ERR(fid)) ··· 537 540 struct dentry *dentry, struct iattr *iattr) 538 541 { 539 542 int retval, use_dentry = 0; 543 + struct inode *inode = d_inode(dentry); 544 + struct v9fs_session_info __maybe_unused *v9ses; 540 545 struct p9_fid *fid = NULL; 541 546 struct p9_iattr_dotl p9attr = { 542 547 .uid = INVALID_UID, 543 548 .gid = INVALID_GID, 544 549 }; 545 - struct inode *inode = d_inode(dentry); 546 550 547 551 p9_debug(P9_DEBUG_VFS, "\n"); 548 552 549 553 retval = setattr_prepare(&nop_mnt_idmap, dentry, iattr); 550 554 if (retval) 551 555 return retval; 556 + 557 + v9ses = v9fs_dentry2v9ses(dentry); 552 558 553 559 p9attr.valid = v9fs_mapped_iattr_valid(iattr->ia_valid); 554 560 if (iattr->ia_valid & ATTR_MODE) ··· 583 583 return PTR_ERR(fid); 584 584 585 585 /* Write all dirty data */ 586 - if (S_ISREG(inode->i_mode)) 587 - filemap_write_and_wait(inode->i_mapping); 586 + if (S_ISREG(inode->i_mode)) { 587 + retval = filemap_fdatawrite(inode->i_mapping); 588 + if (retval < 0) 589 + p9_debug(P9_DEBUG_ERROR, 590 + "Flushing file prior to setattr failed: %d\n", retval); 591 + } 588 592 589 593 retval = p9_client_setattr(fid, &p9attr); 590 594 if (retval < 0) { ··· 597 593 return retval; 598 594 } 599 595 600 - if ((iattr->ia_valid & ATTR_SIZE) && 601 - iattr->ia_size != i_size_read(inode)) 596 + if ((iattr->ia_valid & ATTR_SIZE) && iattr->ia_size != 597 + i_size_read(inode)) { 602 598 truncate_setsize(inode, iattr->ia_size); 599 + truncate_pagecache(inode, iattr->ia_size); 600 + 601 + #ifdef CONFIG_9P_FSCACHE 602 + if (v9ses->cache & CACHE_FSCACHE) 603 + fscache_resize_cookie(v9fs_inode_cookie(V9FS_I(inode)), 604 + iattr->ia_size); 605 + #endif 606 + } 603 607 604 608 v9fs_invalidate_inode_attr(inode); 605 609 setattr_copy(&nop_mnt_idmap, inode, iattr); ··· 734 722 } 735 723 736 724 v9fs_invalidate_inode_attr(dir); 737 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 725 + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) { 738 726 /* Now walk from the parent so we can get an unopened fid. */ 739 727 fid = p9_client_walk(dfid, 1, &name, 1); 740 728 if (IS_ERR(fid)) { ··· 811 799 } 812 800 813 801 v9fs_invalidate_inode_attr(dir); 814 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 802 + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) { 815 803 /* Get the latest stat info from server. */ 816 804 struct p9_fid *fid; 817 805 ··· 888 876 } 889 877 890 878 /* instantiate inode and assign the unopened fid to the dentry */ 891 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { 879 + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) { 892 880 inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); 893 881 if (IS_ERR(inode)) { 894 882 err = PTR_ERR(inode); ··· 973 961 * We don't want to refresh inode->i_size, 974 962 * because we may have cached data 975 963 */ 976 - flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ? 964 + flags = (v9ses->cache & CACHE_LOOSE) ? 977 965 V9FS_STAT2INODE_KEEP_ISIZE : 0; 978 966 v9fs_stat2inode_dotl(st, inode, flags); 979 967 out:
+12 -32
fs/9p/vfs_super.c
··· 64 64 sb->s_magic = V9FS_MAGIC; 65 65 if (v9fs_proto_dotl(v9ses)) { 66 66 sb->s_op = &v9fs_super_ops_dotl; 67 - sb->s_xattr = v9fs_xattr_handlers; 67 + if (!(v9ses->flags & V9FS_NO_XATTR)) 68 + sb->s_xattr = v9fs_xattr_handlers; 68 69 } else { 69 70 sb->s_op = &v9fs_super_ops; 70 71 sb->s_time_max = U32_MAX; ··· 85 84 sb->s_bdi->io_pages = v9ses->maxdata >> PAGE_SHIFT; 86 85 } 87 86 88 - sb->s_flags |= SB_ACTIVE | SB_DIRSYNC; 89 - if (!v9ses->cache) 90 - sb->s_flags |= SB_SYNCHRONOUS; 87 + sb->s_flags |= SB_ACTIVE; 91 88 92 89 #ifdef CONFIG_9P_FS_POSIX_ACL 93 90 if ((v9ses->flags & V9FS_ACL_MASK) == V9FS_POSIX_ACL) ··· 136 137 if (retval) 137 138 goto release_sb; 138 139 139 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 140 + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) 140 141 sb->s_d_op = &v9fs_cached_dentry_operations; 141 142 else 142 143 sb->s_d_op = &v9fs_dentry_operations; ··· 277 278 struct v9fs_session_info *v9ses; 278 279 279 280 v9ses = v9fs_inode2v9ses(inode); 280 - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) 281 + if (v9ses->cache & (CACHE_META|CACHE_LOOSE)) 281 282 return generic_drop_inode(inode); 282 283 /* 283 284 * in case of non cached mode always drop the ··· 290 291 static int v9fs_write_inode(struct inode *inode, 291 292 struct writeback_control *wbc) 292 293 { 293 - int ret; 294 - struct p9_wstat wstat; 295 294 struct v9fs_inode *v9inode; 295 + 296 296 /* 297 297 * send an fsync request to server irrespective of 298 298 * wbc->sync_mode. 299 299 */ 300 300 p9_debug(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); 301 - v9inode = V9FS_I(inode); 302 - if (!v9inode->writeback_fid) 303 - return 0; 304 - v9fs_blank_wstat(&wstat); 305 301 306 - ret = p9_client_wstat(v9inode->writeback_fid, &wstat); 307 - if (ret < 0) { 308 - __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 309 - return ret; 310 - } 302 + v9inode = V9FS_I(inode); 311 303 fscache_unpin_writeback(wbc, v9fs_inode_cookie(v9inode)); 304 + 312 305 return 0; 313 306 } 314 307 315 308 static int v9fs_write_inode_dotl(struct inode *inode, 316 309 struct writeback_control *wbc) 317 310 { 318 - int ret; 319 311 struct v9fs_inode *v9inode; 320 - /* 321 - * send an fsync request to server irrespective of 322 - * wbc->sync_mode. 323 - */ 324 - v9inode = V9FS_I(inode); 325 - p9_debug(P9_DEBUG_VFS, "%s: inode %p, writeback_fid %p\n", 326 - __func__, inode, v9inode->writeback_fid); 327 - if (!v9inode->writeback_fid) 328 - return 0; 329 312 330 - ret = p9_client_fsync(v9inode->writeback_fid, 0); 331 - if (ret < 0) { 332 - __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 333 - return ret; 334 - } 313 + v9inode = V9FS_I(inode); 314 + p9_debug(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); 315 + 335 316 fscache_unpin_writeback(wbc, v9fs_inode_cookie(v9inode)); 317 + 336 318 return 0; 337 319 } 338 320
+6
include/net/9p/9p.h
··· 42 42 P9_DEBUG_PKT = (1<<10), 43 43 P9_DEBUG_FSC = (1<<11), 44 44 P9_DEBUG_VPKT = (1<<12), 45 + P9_DEBUG_CACHE = (1<<13), 46 + P9_DEBUG_MMAP = (1<<14), 45 47 }; 46 48 47 49 #ifdef CONFIG_NET_9P_DEBUG ··· 215 213 P9_ORCLOSE = 0x40, 216 214 P9_OAPPEND = 0x80, 217 215 P9_OEXCL = 0x1000, 216 + P9L_MODE_MASK = 0x1FFF, /* don't send anything under this to server */ 217 + P9L_DIRECT = 0x2000, /* cache disabled */ 218 + P9L_NOWRITECACHE = 0x4000, /* no write caching */ 219 + P9L_LOOSE = 0x8000, /* loose cache */ 218 220 }; 219 221 220 222 /**
+4 -4
net/9p/client.c
··· 1230 1230 return -EINVAL; 1231 1231 1232 1232 if (p9_is_proto_dotl(clnt)) 1233 - req = p9_client_rpc(clnt, P9_TLOPEN, "dd", fid->fid, mode); 1233 + req = p9_client_rpc(clnt, P9_TLOPEN, "dd", fid->fid, mode & P9L_MODE_MASK); 1234 1234 else 1235 - req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode); 1235 + req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode & P9L_MODE_MASK); 1236 1236 if (IS_ERR(req)) { 1237 1237 err = PTR_ERR(req); 1238 1238 goto error; ··· 1277 1277 return -EINVAL; 1278 1278 1279 1279 req = p9_client_rpc(clnt, P9_TLCREATE, "dsddg", ofid->fid, name, flags, 1280 - mode, gid); 1280 + mode & P9L_MODE_MASK, gid); 1281 1281 if (IS_ERR(req)) { 1282 1282 err = PTR_ERR(req); 1283 1283 goto error; ··· 1321 1321 return -EINVAL; 1322 1322 1323 1323 req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm, 1324 - mode, extension); 1324 + mode & P9L_MODE_MASK, extension); 1325 1325 if (IS_ERR(req)) { 1326 1326 err = PTR_ERR(req); 1327 1327 goto error;