hw/9pfs: Add new virtfs option writeout=immediate skip host page cache
writeout=immediate implies the after pwritev we do a sync_file_range. Reviewed-by: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
This commit is contained in:
		
							parent
							
								
									5745e38afe
								
							
						
					
					
						commit
						d3ab98e691
					
				| @ -53,12 +53,16 @@ struct xattr_operations; | ||||
| /* FsContext flag values */ | ||||
| #define PATHNAME_FSCONTEXT 0x1 | ||||
| 
 | ||||
| /* export flags */ | ||||
| #define V9FS_IMMEDIATE_WRITEOUT 0x1 | ||||
| 
 | ||||
| typedef struct FsContext | ||||
| { | ||||
|     int flags; | ||||
|     char *fs_root; | ||||
|     SecModel fs_sm; | ||||
|     uid_t uid; | ||||
|     int export_flags; | ||||
|     struct xattr_operations **xops; | ||||
|     /* fs driver specific data */ | ||||
|     void *private; | ||||
|  | ||||
| @ -34,6 +34,8 @@ int qemu_fsdev_add(QemuOpts *opts) | ||||
|     const char *fstype = qemu_opt_get(opts, "fstype"); | ||||
|     const char *path = qemu_opt_get(opts, "path"); | ||||
|     const char *sec_model = qemu_opt_get(opts, "security_model"); | ||||
|     const char *writeout = qemu_opt_get(opts, "writeout"); | ||||
| 
 | ||||
| 
 | ||||
|     if (!fsdev_id) { | ||||
|         fprintf(stderr, "fsdev: No id specified\n"); | ||||
| @ -72,10 +74,14 @@ int qemu_fsdev_add(QemuOpts *opts) | ||||
|     fsle->fse.path = g_strdup(path); | ||||
|     fsle->fse.security_model = g_strdup(sec_model); | ||||
|     fsle->fse.ops = FsTypes[i].ops; | ||||
| 
 | ||||
|     fsle->fse.export_flags = 0; | ||||
|     if (writeout) { | ||||
|         if (!strcmp(writeout, "immediate")) { | ||||
|             fsle->fse.export_flags = V9FS_IMMEDIATE_WRITEOUT; | ||||
|         } | ||||
|     } | ||||
|     QTAILQ_INSERT_TAIL(&fstype_entries, fsle, next); | ||||
|     return 0; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| FsTypeEntry *get_fsdev_fsentry(char *id) | ||||
|  | ||||
| @ -41,6 +41,7 @@ typedef struct FsTypeEntry { | ||||
|     char *fsdev_id; | ||||
|     char *path; | ||||
|     char *security_model; | ||||
|     int export_flags; | ||||
|     FileOperations *ops; | ||||
| } FsTypeEntry; | ||||
| 
 | ||||
|  | ||||
| @ -115,6 +115,7 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf) | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     s->ctx.export_flags = fse->export_flags; | ||||
|     s->ctx.fs_root = g_strdup(fse->path); | ||||
|     len = strlen(conf->tag); | ||||
|     if (len > MAX_TAG_LEN) { | ||||
|  | ||||
| @ -192,16 +192,29 @@ static ssize_t handle_preadv(FsContext *ctx, int fd, const struct iovec *iov, | ||||
| static ssize_t handle_pwritev(FsContext *ctx, int fd, const struct iovec *iov, | ||||
|                               int iovcnt, off_t offset) | ||||
| { | ||||
|     ssize_t ret; | ||||
| #ifdef CONFIG_PREADV | ||||
|     return pwritev(fd, iov, iovcnt, offset); | ||||
|     ret = pwritev(fd, iov, iovcnt, offset); | ||||
| #else | ||||
|     int err = lseek(fd, offset, SEEK_SET); | ||||
|     if (err == -1) { | ||||
|         return err; | ||||
|     } else { | ||||
|         return writev(fd, iov, iovcnt); | ||||
|         ret = writev(fd, iov, iovcnt); | ||||
|     } | ||||
| #endif | ||||
| #ifdef CONFIG_SYNC_FILE_RANGE | ||||
|     if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) { | ||||
|         /*
 | ||||
|          * Initiate a writeback. This is not a data integrity sync. | ||||
|          * We want to ensure that we don't leave dirty pages in the cache | ||||
|          * after write when writeout=immediate is sepcified. | ||||
|          */ | ||||
|         sync_file_range(fd, offset, ret, | ||||
|                         SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE); | ||||
|     } | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static int handle_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) | ||||
|  | ||||
| @ -203,16 +203,30 @@ static ssize_t local_preadv(FsContext *ctx, int fd, const struct iovec *iov, | ||||
| static ssize_t local_pwritev(FsContext *ctx, int fd, const struct iovec *iov, | ||||
|                              int iovcnt, off_t offset) | ||||
| { | ||||
|     ssize_t ret | ||||
| ; | ||||
| #ifdef CONFIG_PREADV | ||||
|     return pwritev(fd, iov, iovcnt, offset); | ||||
|     ret = pwritev(fd, iov, iovcnt, offset); | ||||
| #else | ||||
|     int err = lseek(fd, offset, SEEK_SET); | ||||
|     if (err == -1) { | ||||
|         return err; | ||||
|     } else { | ||||
|         return writev(fd, iov, iovcnt); | ||||
|         ret = writev(fd, iov, iovcnt); | ||||
|     } | ||||
| #endif | ||||
| #ifdef CONFIG_SYNC_FILE_RANGE | ||||
|     if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) { | ||||
|         /*
 | ||||
|          * Initiate a writeback. This is not a data integrity sync. | ||||
|          * We want to ensure that we don't leave dirty pages in the cache | ||||
|          * after write when writeout=immediate is sepcified. | ||||
|          */ | ||||
|         sync_file_range(fd, offset, ret, | ||||
|                         SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE); | ||||
|     } | ||||
| #endif | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| static int local_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp) | ||||
|  | ||||
| @ -80,6 +80,20 @@ void cred_init(FsCred *credp) | ||||
|     credp->fc_rdev = -1; | ||||
| } | ||||
| 
 | ||||
| static int get_dotl_openflags(V9fsState *s, int oflags) | ||||
| { | ||||
|     int flags; | ||||
|     /*
 | ||||
|      * Filter the client open flags | ||||
|      */ | ||||
|     flags = oflags & ~(O_NOCTTY | O_ASYNC | O_CREAT); | ||||
|     /*
 | ||||
|      * Ignore direct disk access hint until the server supports it. | ||||
|      */ | ||||
|     flags &= ~O_DIRECT; | ||||
|     return flags; | ||||
| } | ||||
| 
 | ||||
| void v9fs_string_init(V9fsString *str) | ||||
| { | ||||
|     str->data = NULL; | ||||
| @ -1598,10 +1612,7 @@ static void v9fs_open(void *opaque) | ||||
|         err = offset; | ||||
|     } else { | ||||
|         if (s->proto_version == V9FS_PROTO_2000L) { | ||||
|             flags = mode; | ||||
|             flags &= ~(O_NOCTTY | O_ASYNC | O_CREAT); | ||||
|             /* Ignore direct disk access hint until the server supports it. */ | ||||
|             flags &= ~O_DIRECT; | ||||
|             flags = get_dotl_openflags(s, mode); | ||||
|         } else { | ||||
|             flags = omode_to_uflags(mode); | ||||
|         } | ||||
| @ -1650,8 +1661,7 @@ static void v9fs_lcreate(void *opaque) | ||||
|         goto out_nofid; | ||||
|     } | ||||
| 
 | ||||
|     /* Ignore direct disk access hint until the server supports it. */ | ||||
|     flags &= ~O_DIRECT; | ||||
|     flags = get_dotl_openflags(pdu->s, flags); | ||||
|     err = v9fs_co_open2(pdu, fidp, &name, gid, | ||||
|                         flags | O_CREAT, mode, &stbuf); | ||||
|     if (err < 0) { | ||||
|  | ||||
| @ -177,6 +177,9 @@ QemuOptsList qemu_fsdev_opts = { | ||||
|         }, { | ||||
|             .name = "security_model", | ||||
|             .type = QEMU_OPT_STRING, | ||||
|         }, { | ||||
|             .name = "writeout", | ||||
|             .type = QEMU_OPT_STRING, | ||||
|         }, | ||||
|         { /*End of list */ } | ||||
|     }, | ||||
| @ -199,6 +202,9 @@ QemuOptsList qemu_virtfs_opts = { | ||||
|         }, { | ||||
|             .name = "security_model", | ||||
|             .type = QEMU_OPT_STRING, | ||||
|         }, { | ||||
|             .name = "writeout", | ||||
|             .type = QEMU_OPT_STRING, | ||||
|         }, | ||||
| 
 | ||||
|         { /*End of list */ } | ||||
|  | ||||
| @ -525,7 +525,8 @@ ETEXI | ||||
| DEFHEADING(File system options:) | ||||
| 
 | ||||
| DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev, | ||||
|     "-fsdev local,id=id,path=path,security_model=[mapped|passthrough|none]\n", | ||||
|     "-fsdev local,id=id,path=path,security_model=[mapped|passthrough|none]\n" | ||||
|     "       [,writeout=immediate]\n", | ||||
|     QEMU_ARCH_ALL) | ||||
| 
 | ||||
| STEXI | ||||
| @ -541,7 +542,7 @@ The specific Fstype will determine the applicable options. | ||||
| 
 | ||||
| Options to each backend are described below. | ||||
| 
 | ||||
| @item -fsdev local ,id=@var{id} ,path=@var{path} ,security_model=@var{security_model} | ||||
| @item -fsdev local ,id=@var{id} ,path=@var{path} ,security_model=@var{security_model}[,writeout=@var{writeout}] | ||||
| 
 | ||||
| Create a file-system-"device" for local-filesystem. | ||||
| 
 | ||||
| @ -552,13 +553,17 @@ Create a file-system-"device" for local-filesystem. | ||||
| @option{security_model} specifies the security model to be followed. | ||||
| @option{security_model} is required. | ||||
| 
 | ||||
| @option{writeout} specifies whether to skip the host page cache. | ||||
| @option{writeout} is an optional argument. | ||||
| 
 | ||||
| @end table | ||||
| ETEXI | ||||
| 
 | ||||
| DEFHEADING(Virtual File system pass-through options:) | ||||
| 
 | ||||
| DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs, | ||||
|     "-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n", | ||||
|     "-virtfs local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n" | ||||
|     "        [,writeout=immediate]\n", | ||||
|     QEMU_ARCH_ALL) | ||||
| 
 | ||||
| STEXI | ||||
| @ -574,7 +579,7 @@ The specific Fstype will determine the applicable options. | ||||
| 
 | ||||
| Options to each backend are described below. | ||||
| 
 | ||||
| @item -virtfs local ,path=@var{path} ,mount_tag=@var{mount_tag} ,security_model=@var{security_model} | ||||
| @item -virtfs local ,path=@var{path} ,mount_tag=@var{mount_tag} ,security_model=@var{security_model}[,writeout=@var{writeout}] | ||||
| 
 | ||||
| Create a Virtual file-system-pass through for local-filesystem. | ||||
| 
 | ||||
| @ -585,10 +590,12 @@ Create a Virtual file-system-pass through for local-filesystem. | ||||
| @option{security_model} specifies the security model to be followed. | ||||
| @option{security_model} is required. | ||||
| 
 | ||||
| 
 | ||||
| @option{mount_tag} specifies the tag with which the exported file is mounted. | ||||
| @option{mount_tag} is required. | ||||
| 
 | ||||
| @option{writeout} specifies whether to skip the host page cache. | ||||
| @option{writeout} is an optional argument. | ||||
| 
 | ||||
| @end table | ||||
| ETEXI | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										12
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								vl.c
									
									
									
									
									
								
							| @ -2785,6 +2785,7 @@ int main(int argc, char **argv, char **envp) | ||||
|             case QEMU_OPTION_virtfs: { | ||||
|                 QemuOpts *fsdev; | ||||
|                 QemuOpts *device; | ||||
|                 const char *writeout; | ||||
| 
 | ||||
|                 olist = qemu_find_opts("virtfs"); | ||||
|                 if (!olist) { | ||||
| @ -2814,6 +2815,17 @@ int main(int argc, char **argv, char **envp) | ||||
|                             qemu_opt_get(opts, "mount_tag")); | ||||
|                     exit(1); | ||||
|                 } | ||||
| 
 | ||||
|                 writeout = qemu_opt_get(opts, "writeout"); | ||||
|                 if (writeout) { | ||||
| #ifdef CONFIG_SYNC_FILE_RANGE | ||||
|                     qemu_opt_set(fsdev, "writeout", writeout); | ||||
| #else | ||||
|                     fprintf(stderr, "writeout=immediate not supported on " | ||||
|                             "this platform\n"); | ||||
|                     exit(1); | ||||
| #endif | ||||
|                 } | ||||
|                 qemu_opt_set(fsdev, "fstype", qemu_opt_get(opts, "fstype")); | ||||
|                 qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path")); | ||||
|                 qemu_opt_set(fsdev, "security_model", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Aneesh Kumar K.V
						Aneesh Kumar K.V