mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-21 18:50:50 +01:00
ggate: Add support for O_DIRECT access
Adds support for controlling O_DIRECT access to ggated, ggatec, and ggatel. Reviewed by: markj Relnotes: yes MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D45056
This commit is contained in:
parent
e36af20691
commit
1b1e392aed
@ -34,6 +34,7 @@
|
||||
.Op Fl n
|
||||
.Op Fl v
|
||||
.Op Fl o Cm ro | wo | rw
|
||||
.Op Fl o Cm direct
|
||||
.Op Fl p Ar port
|
||||
.Op Fl q Ar queue_size
|
||||
.Op Fl R Ar rcvbuf
|
||||
@ -48,6 +49,7 @@
|
||||
.Op Fl n
|
||||
.Op Fl v
|
||||
.Op Fl o Cm ro | wo | rw
|
||||
.Op Fl o Cm direct
|
||||
.Op Fl p Ar port
|
||||
.Op Fl R Ar rcvbuf
|
||||
.Op Fl S Ar sndbuf
|
||||
@ -108,13 +110,21 @@ provider (cancels all pending requests).
|
||||
Do not use
|
||||
.Dv TCP_NODELAY
|
||||
option on TCP sockets.
|
||||
.It Fl o Cm ro | wo | rw
|
||||
Specify permissions to use when opening the file or device: read-only
|
||||
.Pq Cm ro ,
|
||||
.It Fl o Ar option
|
||||
Specify permissions and options to use when opening the file or device.
|
||||
.Bl -tag -width indent
|
||||
.It Cm ro
|
||||
read-only
|
||||
.It Cm wo
|
||||
write-only
|
||||
.Pq Cm wo ,
|
||||
or read-write
|
||||
.Pq Cm rw .
|
||||
.It Cm rw
|
||||
read-write
|
||||
.It Cm direct
|
||||
open with
|
||||
.Dv O_DIRECT
|
||||
option on the file
|
||||
.El
|
||||
.Pp
|
||||
Default is
|
||||
.Cm rw .
|
||||
.It Fl p Ar port
|
||||
@ -160,11 +170,14 @@ Use a CD-ROM device on a remote host.
|
||||
.Bd -literal -offset indent
|
||||
server# cat /etc/gg.exports
|
||||
client RO /dev/cd0
|
||||
client RW /tmp/image
|
||||
server# ggated
|
||||
|
||||
client# ggatec create -o ro server /dev/cd0
|
||||
ggate0
|
||||
client# mount_cd9660 /dev/ggate0 /cdrom
|
||||
client# ggatec create -o rw -o direct server /tmp/image
|
||||
ggate1
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr geom 4 ,
|
||||
|
@ -52,7 +52,6 @@
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <geom/gate/g_gate.h>
|
||||
#include "ggate.h"
|
||||
|
||||
|
||||
@ -62,6 +61,7 @@ static const char *path = NULL;
|
||||
static const char *host = NULL;
|
||||
static int unit = G_GATE_UNIT_AUTO;
|
||||
static unsigned flags = 0;
|
||||
static int direct_flag = 0;
|
||||
static int force = 0;
|
||||
static unsigned queue_size = G_GATE_QUEUE_SIZE;
|
||||
static unsigned port = G_GATE_PORT;
|
||||
@ -78,10 +78,12 @@ static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: %s create [-nv] [-o <ro|wo|rw>] [-p port] "
|
||||
fprintf(stderr, "usage: %s create [-nv] [-o <ro|wo|rw>] "
|
||||
"[-o <direct>] [-p port] "
|
||||
"[-q queue_size] [-R rcvbuf] [-S sndbuf] [-s sectorsize] "
|
||||
"[-t timeout] [-u unit] <host> <path>\n", getprogname());
|
||||
fprintf(stderr, " %s rescue [-nv] [-o <ro|wo|rw>] [-p port] "
|
||||
fprintf(stderr, " %s rescue [-nv] [-o <ro|wo|rw>] "
|
||||
"[-o <direct>] [-p port] "
|
||||
"[-R rcvbuf] [-S sndbuf] <-u unit> <host> <path>\n", getprogname());
|
||||
fprintf(stderr, " %s destroy [-f] <-u unit>\n", getprogname());
|
||||
fprintf(stderr, " %s list [-v] [-u unit]\n", getprogname());
|
||||
@ -361,7 +363,7 @@ handshake(int dir)
|
||||
close(sfd);
|
||||
return (-1);
|
||||
}
|
||||
cinit.gc_flags = flags | dir;
|
||||
cinit.gc_flags = flags | direct_flag | dir;
|
||||
cinit.gc_token = token;
|
||||
cinit.gc_nconn = 2;
|
||||
g_gate_swap2n_cinit(&cinit);
|
||||
@ -585,6 +587,8 @@ main(int argc, char *argv[])
|
||||
flags = G_GATE_FLAG_WRITEONLY;
|
||||
else if (strcasecmp("rw", optarg) == 0)
|
||||
flags = 0;
|
||||
else if (strcasecmp("direct", optarg) == 0)
|
||||
direct_flag = GGATE_FLAG_DIRECT;
|
||||
else {
|
||||
errx(EXIT_FAILURE,
|
||||
"Invalid argument for '-o' option.");
|
||||
|
@ -85,10 +85,51 @@ An alternate location for the exports file.
|
||||
.Pp
|
||||
The format of an exports file is as follows:
|
||||
.Bd -literal -offset indent
|
||||
1.2.3.4 RO /dev/cd0
|
||||
1.2.3.0/24 RW /tmp/test.img
|
||||
hostname WO /tmp/image
|
||||
1.2.3.4 RO /dev/cd0
|
||||
1.2.3.0/24 RW /tmp/test.img
|
||||
hostname WO /tmp/image
|
||||
hostname RW,DIRECT /tmp/direct-image
|
||||
hostname RW,NODIRECT /tmp/nodirect-image
|
||||
.Ed
|
||||
.Pp
|
||||
The first colunm specifies the ip, network with netmask, or the hostname
|
||||
that the export applies to.
|
||||
.Pp
|
||||
The next column is the access flags that apply to the export
|
||||
.Bl -tag -width ".Cm NODIRECT"
|
||||
.It Cm RO
|
||||
Read-Only the path specified will be exported to the client read only.
|
||||
.It Cm WO
|
||||
Write-Only the path specified will be exported to the client write only.
|
||||
.It Cm RW
|
||||
Read-Write the path specified will be exported to the client read-write.
|
||||
.It Cm DIRECT
|
||||
The path specified will always be opened with O_DIRECT for clients.
|
||||
.It Cm NODIRECT
|
||||
The path specified will never be opened with O_DIRECT for clients.
|
||||
.El
|
||||
.Pp
|
||||
The final column specifies the path to export.
|
||||
.Pp
|
||||
Files are opened with the least common flags between the client and the
|
||||
server. A client may request read or write only to a read-write export
|
||||
and the server will honor the client request and open the file in the
|
||||
requested mode. A client requesting greater access than permissions listed
|
||||
in the file will be rejected.
|
||||
.Pp
|
||||
DIRECT and NODIRECT are used to coerce the use of the O_DIRECT flag to
|
||||
.Xr open 2 when the specified path is opened. If DIRECT is specified the
|
||||
path is always opened with O_DIRECT. If NODIRECT is specified the path is
|
||||
never opened with O_DIRECT. DIRECT access limits the cache effects of
|
||||
IO operaions on the file. This has the effect of having clients accessing
|
||||
exports to not impact the cache of the local machine, however it
|
||||
will cause greater IO utilization to the devices on which the files reside.
|
||||
.Pp
|
||||
If neither is specified the server will use
|
||||
the preference specified by the client, with the default to not use O_DIRECT.
|
||||
If the client specifies a preference against the server's configuration the
|
||||
client preference will be silently ignored.
|
||||
.Pp
|
||||
.Sh FILES
|
||||
.Bl -tag -width ".Pa /var/run/ggated.pid" -compact
|
||||
.It Pa /var/run/ggated.pid
|
||||
@ -104,13 +145,18 @@ should be called with the
|
||||
.Fl v
|
||||
option.
|
||||
.Sh EXAMPLES
|
||||
Export CD-ROM device and a file:
|
||||
Export CD-ROM device, a file, and a file with
|
||||
.Dv O_DIRECT
|
||||
option:
|
||||
.Bd -literal -offset indent
|
||||
# echo "1.2.3.0/24 RO /dev/cd0" > /etc/gg.exports
|
||||
# echo "client RW /image" >> /etc/gg.exports
|
||||
# echo "client RW,DIRECT /image2" >> /etc/gg.exports
|
||||
# echo "client RW,NODIRECT /image3" >> /etc/gg.exports
|
||||
# ggated
|
||||
.Ed
|
||||
.Sh SEE ALSO
|
||||
.Xr open 2 ,
|
||||
.Xr geom 4 ,
|
||||
.Xr ggatec 8 ,
|
||||
.Xr ggatel 8
|
||||
|
@ -64,7 +64,7 @@
|
||||
struct ggd_connection {
|
||||
off_t c_mediasize;
|
||||
unsigned c_sectorsize;
|
||||
unsigned c_flags; /* flags (RO/RW) */
|
||||
int c_flags; /* flags (RO/RW) */
|
||||
int c_diskfd;
|
||||
int c_sendfd;
|
||||
int c_recvfd;
|
||||
@ -85,11 +85,18 @@ struct ggd_request {
|
||||
#define r_length r_hdr.gh_length
|
||||
#define r_error r_hdr.gh_error
|
||||
|
||||
#define EFLAGS_RDONLY 0x0000
|
||||
#define EFLAGS_WRONLY 0x0001
|
||||
#define EFLAGS_RDWR 0x0002
|
||||
#define EFLAGS_ACCMODE 0x0003
|
||||
#define EFLAGS_DIRECT 0x0004
|
||||
#define EFLAGS_NODIRECT 0x0008
|
||||
|
||||
struct ggd_export {
|
||||
char *e_path; /* path to device/file */
|
||||
in_addr_t e_ip; /* remote IP address */
|
||||
in_addr_t e_mask; /* IP mask */
|
||||
unsigned e_flags; /* flags (RO/RW) */
|
||||
int e_flags; /* flags (WO/RO/RW/DIRECT/NODIRECT) */
|
||||
SLIST_ENTRY(ggd_export) e_next;
|
||||
};
|
||||
|
||||
@ -146,20 +153,61 @@ countmask(unsigned m)
|
||||
return (mask);
|
||||
}
|
||||
|
||||
static int
|
||||
parse_flags(const char *flagsstr, int lineno)
|
||||
{
|
||||
char *flagscpy;
|
||||
char *word, *brkf;
|
||||
int access_flags = -1;
|
||||
int direct_flags = 0;
|
||||
|
||||
flagscpy = strdup(flagsstr);
|
||||
if (flagscpy == NULL) {
|
||||
g_gate_xlog("Not enough memory.");
|
||||
}
|
||||
|
||||
for (word = strtok_r(flagscpy, ",", &brkf);
|
||||
word != NULL;
|
||||
word = strtok_r(NULL, ",", &brkf)) {
|
||||
if (strcasecmp("ro", word) == 0 ||
|
||||
strcasecmp("rd", word) == 0) {
|
||||
access_flags = EFLAGS_RDONLY;
|
||||
} else if (strcasecmp("wo", word) == 0) {
|
||||
access_flags = EFLAGS_WRONLY;
|
||||
} else if (strcasecmp("rw", word) == 0) {
|
||||
access_flags = EFLAGS_RDWR;
|
||||
} else if (strcasecmp("direct", word) == 0) {
|
||||
direct_flags = EFLAGS_DIRECT;
|
||||
} else if (strcasecmp("nodirect", word) == 0) {
|
||||
direct_flags = EFLAGS_NODIRECT;
|
||||
} else {
|
||||
g_gate_xlog("Invalid value (%s) in flags field at "
|
||||
"line %u.", word, lineno);
|
||||
}
|
||||
}
|
||||
free(flagscpy);
|
||||
if (access_flags == -1) {
|
||||
g_gate_xlog("Invalid value (%s) in flags field at "
|
||||
"line %u.", flagsstr, lineno);
|
||||
}
|
||||
return (direct_flags | access_flags);
|
||||
}
|
||||
|
||||
static void
|
||||
line_parse(char *line, unsigned lineno)
|
||||
{
|
||||
struct ggd_export *ex;
|
||||
char *word, *path, *sflags;
|
||||
unsigned flags, i, vmask;
|
||||
char *word, *path, *sflags, *brkl;
|
||||
unsigned i, vmask;
|
||||
int flags;
|
||||
in_addr_t ip, mask;
|
||||
|
||||
ip = mask = flags = vmask = 0;
|
||||
path = NULL;
|
||||
sflags = NULL;
|
||||
|
||||
for (i = 0, word = strtok(line, " \t"); word != NULL;
|
||||
i++, word = strtok(NULL, " \t")) {
|
||||
for (i = 0, word = strtok_r(line, " \t", &brkl); word != NULL;
|
||||
i++, word = strtok_r(NULL, " \t", &brkl)) {
|
||||
switch (i) {
|
||||
case 0: /* IP address or host name */
|
||||
ip = g_gate_str2ip(strsep(&word, "/"));
|
||||
@ -185,17 +233,7 @@ line_parse(char *line, unsigned lineno)
|
||||
mask = countmask(vmask);
|
||||
break;
|
||||
case 1: /* flags */
|
||||
if (strcasecmp("rd", word) == 0 ||
|
||||
strcasecmp("ro", word) == 0) {
|
||||
flags = O_RDONLY;
|
||||
} else if (strcasecmp("wo", word) == 0) {
|
||||
flags = O_WRONLY;
|
||||
} else if (strcasecmp("rw", word) == 0) {
|
||||
flags = O_RDWR;
|
||||
} else {
|
||||
g_gate_xlog("Invalid value in flags field at "
|
||||
"line %u.", lineno);
|
||||
}
|
||||
flags = parse_flags(word, lineno);
|
||||
sflags = word;
|
||||
break;
|
||||
case 2: /* path */
|
||||
@ -306,13 +344,16 @@ exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit,
|
||||
struct ggd_connection *conn)
|
||||
{
|
||||
char ipmask[32]; /* 32 == strlen("xxx.xxx.xxx.xxx/xxx.xxx.xxx.xxx")+1 */
|
||||
int error = 0, flags;
|
||||
int error = 0, flags, access_flags, direct_flags = 0;
|
||||
|
||||
strlcpy(ipmask, ip2str(ex->e_ip), sizeof(ipmask));
|
||||
strlcat(ipmask, "/", sizeof(ipmask));
|
||||
strlcat(ipmask, ip2str(ex->e_mask), sizeof(ipmask));
|
||||
|
||||
access_flags = ex->e_flags & EFLAGS_ACCMODE;
|
||||
|
||||
if ((cinit->gc_flags & GGATE_FLAG_RDONLY) != 0) {
|
||||
if (ex->e_flags == O_WRONLY) {
|
||||
if (access_flags == EFLAGS_WRONLY) {
|
||||
g_gate_log(LOG_WARNING, "Read-only access requested, "
|
||||
"but %s (%s) is exported write-only.", ex->e_path,
|
||||
ipmask);
|
||||
@ -321,7 +362,7 @@ exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit,
|
||||
conn->c_flags |= GGATE_FLAG_RDONLY;
|
||||
}
|
||||
} else if ((cinit->gc_flags & GGATE_FLAG_WRONLY) != 0) {
|
||||
if (ex->e_flags == O_RDONLY) {
|
||||
if (access_flags == EFLAGS_RDONLY) {
|
||||
g_gate_log(LOG_WARNING, "Write-only access requested, "
|
||||
"but %s (%s) is exported read-only.", ex->e_path,
|
||||
ipmask);
|
||||
@ -330,24 +371,41 @@ exports_check(struct ggd_export *ex, struct g_gate_cinit *cinit,
|
||||
conn->c_flags |= GGATE_FLAG_WRONLY;
|
||||
}
|
||||
} else {
|
||||
if (ex->e_flags == O_RDONLY) {
|
||||
if (access_flags == EFLAGS_RDONLY) {
|
||||
g_gate_log(LOG_WARNING, "Read-write access requested, "
|
||||
"but %s (%s) is exported read-only.", ex->e_path,
|
||||
ipmask);
|
||||
return (EPERM);
|
||||
} else if (ex->e_flags == O_WRONLY) {
|
||||
} else if (access_flags == EFLAGS_WRONLY) {
|
||||
g_gate_log(LOG_WARNING, "Read-write access requested, "
|
||||
"but %s (%s) is exported write-only.", ex->e_path,
|
||||
ipmask);
|
||||
return (EPERM);
|
||||
}
|
||||
}
|
||||
|
||||
if ((cinit->gc_flags & GGATE_FLAG_DIRECT) != 0) {
|
||||
if (ex->e_flags & EFLAGS_NODIRECT) {
|
||||
g_gate_log(LOG_WARNING, "Direct IO requested, "
|
||||
"but %s (%s) is exported NODIRECT.", ex->e_path,
|
||||
ipmask);
|
||||
} else {
|
||||
conn->c_flags |= GGATE_FLAG_DIRECT;
|
||||
direct_flags = O_DIRECT;
|
||||
}
|
||||
}
|
||||
|
||||
if (ex->e_flags & EFLAGS_DIRECT) {
|
||||
direct_flags = O_DIRECT;
|
||||
}
|
||||
|
||||
if ((conn->c_flags & GGATE_FLAG_RDONLY) != 0)
|
||||
flags = O_RDONLY;
|
||||
else if ((conn->c_flags & GGATE_FLAG_WRONLY) != 0)
|
||||
flags = O_WRONLY;
|
||||
else
|
||||
flags = O_RDWR;
|
||||
flags |= direct_flags;
|
||||
if (conn->c_diskfd != -1) {
|
||||
if (strcmp(conn->c_path, ex->e_path) != 0) {
|
||||
g_gate_log(LOG_ERR, "old %s and new %s: "
|
||||
|
@ -32,7 +32,7 @@
|
||||
.Nm
|
||||
.Cm create
|
||||
.Op Fl v
|
||||
.Op Fl o Cm ro | wo | rw
|
||||
.Oo Fl o option Oc ...
|
||||
.Op Fl s Ar sectorsize
|
||||
.Op Fl t Ar timeout
|
||||
.Op Fl u Ar unit
|
||||
@ -48,7 +48,7 @@
|
||||
.Nm
|
||||
.Cm rescue
|
||||
.Op Fl v
|
||||
.Op Fl o Cm ro | wo | rw
|
||||
.Oo Fl o option Oc ...
|
||||
.Fl u Ar unit
|
||||
.Ar path
|
||||
.Sh DESCRIPTION
|
||||
@ -92,13 +92,21 @@ Available options:
|
||||
Forcibly destroy
|
||||
.Nm ggate
|
||||
provider (cancels all pending requests).
|
||||
.It Fl o Cm ro | wo | rw
|
||||
Specify permissions to use when opening the file or device: read-only
|
||||
.Pq Cm ro ,
|
||||
.It Fl o Ar option
|
||||
Specify permissions and options to use when opening the file or device.
|
||||
.Bl -tag -width indent
|
||||
.It Cm ro
|
||||
read-only
|
||||
.It Cm wo
|
||||
write-only
|
||||
.Pq Cm wo ,
|
||||
or read-write
|
||||
.Pq Cm rw .
|
||||
.It Cm rw
|
||||
read-write
|
||||
.It Cm direct
|
||||
open with
|
||||
.Dv O_DIRECT
|
||||
option on the file
|
||||
.El
|
||||
.Pp
|
||||
Default is
|
||||
.Cm rw .
|
||||
.It Fl s Ar sectorsize
|
||||
|
@ -43,7 +43,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include <geom/gate/g_gate.h>
|
||||
#include "ggate.h"
|
||||
|
||||
|
||||
@ -52,6 +51,7 @@ static enum { UNSET, CREATE, DESTROY, LIST, RESCUE } action = UNSET;
|
||||
static const char *path = NULL;
|
||||
static int unit = G_GATE_UNIT_AUTO;
|
||||
static unsigned flags = 0;
|
||||
static int direct_flag = 0;
|
||||
static int force = 0;
|
||||
static unsigned sectorsize = 0;
|
||||
static unsigned timeout = G_GATE_TIMEOUT;
|
||||
@ -60,24 +60,30 @@ static void
|
||||
usage(void)
|
||||
{
|
||||
|
||||
fprintf(stderr, "usage: %s create [-v] [-o <ro|wo|rw>] "
|
||||
fprintf(stderr, "usage: %s create [-v] [-o option] ... "
|
||||
"[-s sectorsize] [-t timeout] [-u unit] <path>\n", getprogname());
|
||||
fprintf(stderr, " %s rescue [-v] [-o <ro|wo|rw>] <-u unit> "
|
||||
fprintf(stderr, " %s rescue [-v] [-o option] ... <-u unit> "
|
||||
"<path>\n", getprogname());
|
||||
fprintf(stderr, " %s destroy [-f] <-u unit>\n", getprogname());
|
||||
fprintf(stderr, " %s list [-v] [-u unit]\n", getprogname());
|
||||
fprintf(stderr, " option = {ro, wo, rw, direct}\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static int
|
||||
g_gate_openflags(unsigned ggflags)
|
||||
{
|
||||
int openflags = O_RDWR;
|
||||
|
||||
if ((ggflags & G_GATE_FLAG_READONLY) != 0)
|
||||
return (O_RDONLY);
|
||||
openflags = O_RDONLY;
|
||||
else if ((ggflags & G_GATE_FLAG_WRITEONLY) != 0)
|
||||
return (O_WRONLY);
|
||||
return (O_RDWR);
|
||||
openflags = O_WRONLY;
|
||||
|
||||
if (direct_flag)
|
||||
openflags |= O_DIRECT;
|
||||
|
||||
return (openflags);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -248,6 +254,8 @@ main(int argc, char *argv[])
|
||||
flags = G_GATE_FLAG_WRITEONLY;
|
||||
else if (strcasecmp("rw", optarg) == 0)
|
||||
flags = 0;
|
||||
else if (strcasecmp("direct", optarg) == 0)
|
||||
direct_flag = 1;
|
||||
else {
|
||||
errx(EXIT_FAILURE,
|
||||
"Invalid argument for '-o' option.");
|
||||
|
@ -29,6 +29,7 @@
|
||||
#ifndef _GGATE_H_
|
||||
#define _GGATE_H_
|
||||
|
||||
#include <geom/gate/g_gate.h>
|
||||
#include <sys/endian.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
@ -42,8 +43,8 @@
|
||||
#define GGATE_MAGIC "GEOM_GATE "
|
||||
#define GGATE_VERSION 0
|
||||
|
||||
#define GGATE_FLAG_RDONLY 0x0001
|
||||
#define GGATE_FLAG_WRONLY 0x0002
|
||||
#define GGATE_FLAG_RDONLY G_GATE_FLAG_READONLY
|
||||
#define GGATE_FLAG_WRONLY G_GATE_FLAG_WRITEONLY
|
||||
/*
|
||||
* If neither the GGATE_FLAG_SEND nor the GGATE_FLAG_RECV flag is
|
||||
* set - this is initial connection.
|
||||
@ -53,6 +54,8 @@
|
||||
#define GGATE_FLAG_SEND 0x0004
|
||||
#define GGATE_FLAG_RECV 0x0008
|
||||
|
||||
#define GGATE_FLAG_DIRECT 0x0010
|
||||
|
||||
#define GGATE_CMD_READ 0
|
||||
#define GGATE_CMD_WRITE 1
|
||||
#define GGATE_CMD_FLUSH 3
|
||||
|
Loading…
Reference in New Issue
Block a user