qemu-nbd: introduce NBDExport
Wrap the common parameters of nbd_trip and nbd_negotiate in a single opaque struct. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									a030b347aa
								
							
						
					
					
						commit
						af49bbbe78
					
				
							
								
								
									
										64
									
								
								nbd.c
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								nbd.c
									
									
									
									
									
								
							| @ -18,6 +18,7 @@ | ||||
| 
 | ||||
| #include "nbd.h" | ||||
| #include "block.h" | ||||
| #include "block_int.h" | ||||
| 
 | ||||
| #include <errno.h> | ||||
| #include <string.h> | ||||
| @ -186,7 +187,7 @@ int unix_socket_outgoing(const char *path) | ||||
|                   Request (type == 2) | ||||
| */ | ||||
| 
 | ||||
| int nbd_negotiate(int csock, off_t size, uint32_t flags) | ||||
| static int nbd_send_negotiate(int csock, off_t size, uint32_t flags) | ||||
| { | ||||
|     char buf[8 + 8 + 8 + 128]; | ||||
| 
 | ||||
| @ -583,6 +584,33 @@ static int nbd_send_reply(int csock, struct nbd_reply *reply) | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| struct NBDExport { | ||||
|     BlockDriverState *bs; | ||||
|     off_t dev_offset; | ||||
|     off_t size; | ||||
|     uint8_t *data; | ||||
|     uint32_t nbdflags; | ||||
| }; | ||||
| 
 | ||||
| NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, | ||||
|                           off_t size, uint32_t nbdflags) | ||||
| { | ||||
|     NBDExport *exp = g_malloc0(sizeof(NBDExport)); | ||||
|     exp->bs = bs; | ||||
|     exp->dev_offset = dev_offset; | ||||
|     exp->nbdflags = nbdflags; | ||||
|     exp->size = size == -1 ? exp->bs->total_sectors * 512 : size; | ||||
|     exp->data = qemu_blockalign(exp->bs, NBD_BUFFER_SIZE); | ||||
|     return exp; | ||||
| } | ||||
| 
 | ||||
| void nbd_export_close(NBDExport *exp) | ||||
| { | ||||
|     qemu_vfree(exp->data); | ||||
|     bdrv_close(exp->bs); | ||||
|     g_free(exp); | ||||
| } | ||||
| 
 | ||||
| static int nbd_do_send_reply(int csock, struct nbd_reply *reply, | ||||
|                              uint8_t *data, int len) | ||||
| { | ||||
| @ -652,9 +680,7 @@ out: | ||||
|     return rc; | ||||
| } | ||||
| 
 | ||||
| int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
|              uint64_t dev_offset, uint32_t nbdflags, | ||||
|              uint8_t *data) | ||||
| int nbd_trip(NBDExport *exp, int csock) | ||||
| { | ||||
|     struct nbd_request request; | ||||
|     struct nbd_reply reply; | ||||
| @ -662,7 +688,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
| 
 | ||||
|     TRACE("Reading request."); | ||||
| 
 | ||||
|     ret = nbd_do_receive_request(csock, &request, data); | ||||
|     ret = nbd_do_receive_request(csock, &request, exp->data); | ||||
|     if (ret == -EIO) { | ||||
|         return -1; | ||||
|     } | ||||
| @ -675,10 +701,11 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
|         goto error_reply; | ||||
|     } | ||||
| 
 | ||||
|     if ((request.from + request.len) > size) { | ||||
|     if ((request.from + request.len) > exp->size) { | ||||
|             LOG("From: %" PRIu64 ", Len: %u, Size: %" PRIu64 | ||||
|             ", Offset: %" PRIu64 "\n", | ||||
|                     request.from, request.len, (uint64_t)size, dev_offset); | ||||
|                     request.from, request.len, | ||||
|                     (uint64_t)exp->size, exp->dev_offset); | ||||
|         LOG("requested operation past EOF--bad client?"); | ||||
|         goto invalid_request; | ||||
|     } | ||||
| @ -687,8 +714,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
|     case NBD_CMD_READ: | ||||
|         TRACE("Request type is READ"); | ||||
| 
 | ||||
|         ret = bdrv_read(bs, (request.from + dev_offset) / 512, | ||||
|                         data, request.len / 512); | ||||
|         ret = bdrv_read(exp->bs, (request.from + exp->dev_offset) / 512, | ||||
|                         exp->data, request.len / 512); | ||||
|         if (ret < 0) { | ||||
|             LOG("reading from file failed"); | ||||
|             reply.error = -ret; | ||||
| @ -696,13 +723,13 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
|         } | ||||
| 
 | ||||
|         TRACE("Read %u byte(s)", request.len); | ||||
|         if (nbd_do_send_reply(csock, &reply, data, request.len) < 0) | ||||
|         if (nbd_do_send_reply(csock, &reply, exp->data, request.len) < 0) | ||||
|             return -1; | ||||
|         break; | ||||
|     case NBD_CMD_WRITE: | ||||
|         TRACE("Request type is WRITE"); | ||||
| 
 | ||||
|         if (nbdflags & NBD_FLAG_READ_ONLY) { | ||||
|         if (exp->nbdflags & NBD_FLAG_READ_ONLY) { | ||||
|             TRACE("Server is read-only, return error"); | ||||
|             reply.error = EROFS; | ||||
|             goto error_reply; | ||||
| @ -710,8 +737,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
| 
 | ||||
|         TRACE("Writing to device"); | ||||
| 
 | ||||
|         ret = bdrv_write(bs, (request.from + dev_offset) / 512, | ||||
|                          data, request.len / 512); | ||||
|         ret = bdrv_write(exp->bs, (request.from + exp->dev_offset) / 512, | ||||
|                          exp->data, request.len / 512); | ||||
|         if (ret < 0) { | ||||
|             LOG("writing to file failed"); | ||||
|             reply.error = -ret; | ||||
| @ -719,7 +746,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
|         } | ||||
| 
 | ||||
|         if (request.type & NBD_CMD_FLAG_FUA) { | ||||
|             ret = bdrv_flush(bs); | ||||
|             ret = bdrv_flush(exp->bs); | ||||
|             if (ret < 0) { | ||||
|                 LOG("flush failed"); | ||||
|                 reply.error = -ret; | ||||
| @ -737,7 +764,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
|     case NBD_CMD_FLUSH: | ||||
|         TRACE("Request type is FLUSH"); | ||||
| 
 | ||||
|         ret = bdrv_flush(bs); | ||||
|         ret = bdrv_flush(exp->bs); | ||||
|         if (ret < 0) { | ||||
|             LOG("flush failed"); | ||||
|             reply.error = -ret; | ||||
| @ -748,7 +775,7 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
|         break; | ||||
|     case NBD_CMD_TRIM: | ||||
|         TRACE("Request type is TRIM"); | ||||
|         ret = bdrv_discard(bs, (request.from + dev_offset) / 512, | ||||
|         ret = bdrv_discard(exp->bs, (request.from + exp->dev_offset) / 512, | ||||
|                            request.len / 512); | ||||
|         if (ret < 0) { | ||||
|             LOG("discard failed"); | ||||
| @ -771,3 +798,8 @@ int nbd_trip(BlockDriverState *bs, int csock, off_t size, | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| 
 | ||||
| int nbd_negotiate(NBDExport *exp, int csock) | ||||
| { | ||||
|     return nbd_send_negotiate(csock, exp->size, exp->nbdflags); | ||||
| } | ||||
|  | ||||
							
								
								
									
										11
									
								
								nbd.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								nbd.h
									
									
									
									
									
								
							| @ -67,15 +67,20 @@ int tcp_socket_incoming_spec(const char *address_and_port); | ||||
| int unix_socket_outgoing(const char *path); | ||||
| int unix_socket_incoming(const char *path); | ||||
| 
 | ||||
| int nbd_negotiate(int csock, off_t size, uint32_t flags); | ||||
| int nbd_receive_negotiate(int csock, const char *name, uint32_t *flags, | ||||
|                           off_t *size, size_t *blocksize); | ||||
| int nbd_init(int fd, int csock, uint32_t flags, off_t size, size_t blocksize); | ||||
| int nbd_send_request(int csock, struct nbd_request *request); | ||||
| int nbd_receive_reply(int csock, struct nbd_reply *reply); | ||||
| int nbd_trip(BlockDriverState *bs, int csock, off_t size, uint64_t dev_offset, | ||||
|              uint32_t nbdflags, uint8_t *data); | ||||
| int nbd_client(int fd); | ||||
| int nbd_disconnect(int fd); | ||||
| 
 | ||||
| typedef struct NBDExport NBDExport; | ||||
| 
 | ||||
| NBDExport *nbd_export_new(BlockDriverState *bs, off_t dev_offset, | ||||
|                           off_t size, uint32_t nbdflags); | ||||
| void nbd_export_close(NBDExport *exp); | ||||
| int nbd_negotiate(NBDExport *exp, int csock); | ||||
| int nbd_trip(NBDExport *exp, int csock); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
							
								
								
									
										15
									
								
								qemu-nbd.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								qemu-nbd.c
									
									
									
									
									
								
							| @ -36,6 +36,7 @@ | ||||
| #define SOCKET_PATH    "/var/lock/qemu-nbd-%s" | ||||
| 
 | ||||
| static int sigterm_wfd; | ||||
| static NBDExport *exp; | ||||
| static int verbose; | ||||
| static char *device; | ||||
| static char *srcpath; | ||||
| @ -280,7 +281,6 @@ int main(int argc, char **argv) | ||||
|     int partition = -1; | ||||
|     int ret; | ||||
|     int shared = 1; | ||||
|     uint8_t *data; | ||||
|     fd_set fds; | ||||
|     int *sharing_fds; | ||||
|     int fd; | ||||
| @ -489,6 +489,7 @@ int main(int argc, char **argv) | ||||
|         err(EXIT_FAILURE, "Could not find partition %d", partition); | ||||
|     } | ||||
| 
 | ||||
|     exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags); | ||||
|     sharing_fds = g_malloc((shared + 1) * sizeof(int)); | ||||
| 
 | ||||
|     if (sockpath) { | ||||
| @ -516,11 +517,6 @@ int main(int argc, char **argv) | ||||
|     max_fd = sharing_fds[0]; | ||||
|     nb_fds++; | ||||
| 
 | ||||
|     data = qemu_blockalign(bs, NBD_BUFFER_SIZE); | ||||
|     if (data == NULL) { | ||||
|         errx(EXIT_FAILURE, "Cannot allocate data buffer"); | ||||
|     } | ||||
| 
 | ||||
|     do { | ||||
|         FD_ZERO(&fds); | ||||
|         FD_SET(sigterm_fd[0], &fds); | ||||
| @ -538,8 +534,7 @@ int main(int argc, char **argv) | ||||
|             ret--; | ||||
|         for (i = 1; i < nb_fds && ret; i++) { | ||||
|             if (FD_ISSET(sharing_fds[i], &fds)) { | ||||
|                 if (nbd_trip(bs, sharing_fds[i], fd_size, dev_offset, | ||||
|                              nbdflags, data) != 0) { | ||||
|                 if (nbd_trip(exp, sharing_fds[i]) != 0) { | ||||
|                     close(sharing_fds[i]); | ||||
|                     nb_fds--; | ||||
|                     sharing_fds[i] = sharing_fds[nb_fds]; | ||||
| @ -555,7 +550,7 @@ int main(int argc, char **argv) | ||||
|                                              (struct sockaddr *)&addr, | ||||
|                                              &addr_len); | ||||
|                 if (sharing_fds[nb_fds] != -1 && | ||||
|                     nbd_negotiate(sharing_fds[nb_fds], fd_size, nbdflags) != -1) { | ||||
|                     nbd_negotiate(exp, sharing_fds[nb_fds]) != -1) { | ||||
|                         if (sharing_fds[nb_fds] > max_fd) | ||||
|                             max_fd = sharing_fds[nb_fds]; | ||||
|                         nb_fds++; | ||||
| @ -563,9 +558,9 @@ int main(int argc, char **argv) | ||||
|             } | ||||
|         } | ||||
|     } while (persistent || nb_fds > 1); | ||||
|     qemu_vfree(data); | ||||
| 
 | ||||
|     close(sharing_fds[0]); | ||||
|     nbd_export_close(exp); | ||||
|     g_free(sharing_fds); | ||||
|     if (sockpath) { | ||||
|         unlink(sockpath); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Paolo Bonzini
						Paolo Bonzini