aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Seebach <peter.seebach@windriver.com>2013-02-16 17:01:22 -0600
committerPeter Seebach <peter.seebach@windriver.com>2013-02-16 19:26:02 -0600
commit01bc8866a4aa5af17350b36e2347dc1695dbceb0 (patch)
tree590f8ed10ba2aa284e1cccbdbdefad105605a4b0
parent1b774e2f832fdbcb27ddeb2cd799d156aabefb85 (diff)
downloadpseudo-01bc8866a4aa5af17350b36e2347dc1695dbceb0.tar.gz
pseudo-01bc8866a4aa5af17350b36e2347dc1695dbceb0.tar.bz2
pseudo-01bc8866a4aa5af17350b36e2347dc1695dbceb0.zip
If you don't want the answer, don't ask the question.
Most pseudo operations don't actually USE the server's response. So why wait for a response? This patch introduces a new message type, PSEUDO_MSG_FASTOP. It also tags pseudo operation types with whether or not they need to give a response. This requires updates to maketables to allow non-string types for additional columns, and the addition of some quotes to the SQL query enums/query_type.in table. A few routines are altered to change their behavior and whether or not they perform a stat operation. The only operations that do wait are OP_FSTAT and OP_STAT, OP_MKNOD, and OP_MAY_UNLINK. Rationale: You can't query the server for replacement information and not wait for it. Makes no sense. There's extra checking in mknod, because we really do want to fail out if we couldn't do that -- that implies that we haven't created a thing that will look like a node. The result from OP_MAY_UNLINK is checked because it's used to determine whether we need to send a DID_UNLINK or CANCEL_UNLINK. It might be cheaper to send two messages without waiting than to send one, wait, and maybe send another, but I don't want to send invalid messages. This is highly experimental.
-rw-r--r--enums/msg_type.in1
-rw-r--r--enums/op.in46
-rw-r--r--enums/query_type.in18
-rwxr-xr-xmaketables41
-rw-r--r--ports/unix/guts/fchmod.c16
-rw-r--r--ports/unix/guts/fchmodat.c31
-rw-r--r--ports/unix/guts/fchown.c16
-rw-r--r--ports/unix/guts/fchownat.c16
-rw-r--r--ports/unix/guts/mknodat.c4
-rw-r--r--ports/unix/wrapfuncs.in2
-rw-r--r--pseudo.c3
-rw-r--r--pseudo_client.c22
-rw-r--r--pseudo_server.c30
13 files changed, 132 insertions, 114 deletions
diff --git a/enums/msg_type.in b/enums/msg_type.in
index 0313073..578d571 100644
--- a/enums/msg_type.in
+++ b/enums/msg_type.in
@@ -4,3 +4,4 @@ shutdown
op
ack
nak
+fastop
diff --git a/enums/op.in b/enums/op.in
index 65eb73c..3b8e23e 100644
--- a/enums/op.in
+++ b/enums/op.in
@@ -1,23 +1,23 @@
-op: OP
-chdir
-chmod
-chown
-chroot
-close
-creat
-dup
-fchmod
-fchown
-fstat
-link
-mkdir
-mknod
-open
-rename
-stat
-unlink
-symlink
-exec
-may-unlink
-did-unlink
-cancel-unlink
+op: OP; int wait = 0
+chdir, 0
+chmod, 0
+chown, 0
+chroot, 0
+close, 0
+creat, 0
+dup, 0
+fchmod, 0
+fchown, 0
+fstat, 1
+link, 0
+mkdir, 0
+mknod, 1
+open, 0
+rename, 0
+stat, 1
+unlink, 0
+symlink, 0
+exec, 0
+may-unlink, 1
+did-unlink, 0
+cancel-unlink, 0
diff --git a/enums/query_type.in b/enums/query_type.in
index 5bfc741..974e24f 100644
--- a/enums/query_type.in
+++ b/enums/query_type.in
@@ -1,9 +1,9 @@
-query_type: PSQT; sql = LITTLE BOBBY TABLES
-exact, =
-less, <
-greater, >
-bitand, &
-notequal, !=
-like, LIKE
-notlike, NOT LIKE
-sqlpat, LIKE
+query_type: PSQT; const char * sql = "LITTLE BOBBY TABLES"
+exact, "="
+less, "<"
+greater, ">"
+bitand, "&"
+notequal, "!="
+like, "LIKE"
+notlike, "NOT LIKE"
+sqlpat, "LIKE"
diff --git a/maketables b/maketables
index fe4e62c..7c54c6a 100755
--- a/maketables
+++ b/maketables
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# Copyright (c) 2008-2010 Wind River Systems, Inc.
+# Copyright (c) 2008-2010, 2013 Wind River Systems, Inc.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the Lesser GNU General Public License version 2.1 as
@@ -23,9 +23,9 @@ The names are used to create enums and a table of strings, as well as
to/from lookups between the ids and names. If additional columns are
defined, each column (separated by ", ") is used to create an additional
table of the given name, and a lookup function from ids. Example:
- foo: FFF; bar = GOZINTA
- hello, yah
- world, nope
+ foo: FFF; const char *bar = "GOZINTA"
+ hello, "yah"
+ world, "nope"
produces:
typedef enum {
FFF_UNKNOWN = -1,
@@ -74,7 +74,14 @@ class DataType:
name, default = string.split(col, ' = ')
else:
name, default = col, ""
- self.columns.append({"name":name, "value":default})
+ if " " in name:
+ words = string.split(name, ' ')
+ name = words[-1]
+ del words[-1]
+ type = ' '.join(words)
+ else:
+ type = "char *"
+ self.columns.append({"type":type, "name":name, "value":default})
else:
self.columns = []
self.data = []
@@ -94,7 +101,7 @@ class DataType:
if len(cols) > 0:
column_list.append({"name":col["name"], "value":cols.pop(0)})
else:
- column_list.append({"name":col["name"], "value":col["default"]})
+ column_list.append({"name":col["name"], "value":col["value"]})
item["cols"] = column_list
self.data.append(item)
@@ -113,15 +120,15 @@ class DataType:
out += "type: %s_t" % self.name
out += " (prefix '%s_ENUM')\n" % self.prefix
for col in self.columns:
- out += " extra column: %s (default '%s')\n" % (col["name"], col["value"])
+ out += " extra column: %s %s (default %s)\n" % (col["type"], col["name"], col["value"])
out += " "
for item in self.data:
column = column + 1
if column > 4 and column % 4 == 1:
out += "\n "
out += "%-19s" % item["name"]
-# for col in item["cols"]:
-# out += "\t%s(%s)\n" % (col["name"], col["value"])
+# for col in item["cols"]:
+# out += "\t%s(%s)\n" % (col["name"], col["value"])
return out
def comment(self):
@@ -140,11 +147,11 @@ class DataType:
decl_lines = []
column = 0
for col in self.columns:
- decl_lines.append("static const char *%s_id_to_%s[] = {" % (self.name, col["name"]))
- decl_lines.append('\t"%s",' % col["value"])
+ decl_lines.append("static %s %s_id_to_%s[] = {" % (col["type"], self.name, col["name"]))
+ decl_lines.append('\t%s,' % col["value"])
for item in self.data:
- decl_lines.append('\t"%s",' % item["cols"][column]["value"])
- decl_lines.append('\tNULL')
+ decl_lines.append('\t%s,' % item["cols"][column]["value"])
+ decl_lines.append('\t0')
decl_lines.append("};")
column = column + 1
return '\n'.join(decl_lines)
@@ -152,11 +159,11 @@ class DataType:
def column_funcs(self):
decl_lines = []
for col in self.columns:
- decl_lines.append('extern const char *')
+ decl_lines.append('extern %s' % col["type"])
decl_lines.append('pseudo_%s_%s(pseudo_%s_t id) {' %
(self.name, col["name"], self.name))
decl_lines.append('\tif (id < 0 || id >= %s_MAX)' % (self.prefix))
- decl_lines.append('\t\treturn "%s";' % col["value"])
+ decl_lines.append('\t\treturn %s;' % col["value"])
decl_lines.append('\treturn %s_id_to_%s[id];' %
(self.name, col["name"]))
decl_lines.append('}')
@@ -165,8 +172,8 @@ class DataType:
def column_protos(self):
decl_lines = []
for col in self.columns:
- decl_lines.append('extern const char *pseudo_%s_%s(pseudo_%s_t id);' %
- (self.name, col["name"], self.name))
+ decl_lines.append('extern %s pseudo_%s_%s(pseudo_%s_t id);' %
+ (col["type"], self.name, col["name"], self.name))
return '\n'.join(decl_lines)
def main():
diff --git a/ports/unix/guts/fchmod.c b/ports/unix/guts/fchmod.c
index 1d4fae8..e2301e3 100644
--- a/ports/unix/guts/fchmod.c
+++ b/ports/unix/guts/fchmod.c
@@ -1,12 +1,11 @@
/*
- * Copyright (c) 2008-2010, 2012 Wind River Systems; see
+ * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see
* guts/COPYRIGHT for information.
*
* static int
* wrap_fchmod(int fd, mode_t mode) {
* int rc = -1;
*/
- pseudo_msg_t *msg;
PSEUDO_STATBUF buf;
int save_errno = errno;
@@ -15,16 +14,11 @@
return -1;
}
buf.st_mode = (buf.st_mode & ~07777) | (mode & 07777);
- msg = pseudo_client_op(OP_FCHMOD, 0, fd, -1, 0, &buf);
+ pseudo_client_op(OP_FCHMOD, 0, fd, -1, 0, &buf);
real_fchmod(fd, PSEUDO_FS_MODE(mode, S_ISDIR(buf.st_mode)));
- if (msg && msg->result != RESULT_SUCCEED) {
- errno = EPERM;
- rc = -1;
- } else {
- /* just pretend we worked */
- errno = save_errno;
- rc = 0;
- }
+ /* just pretend we worked */
+ errno = save_errno;
+ rc = 0;
/* return rc;
* }
diff --git a/ports/unix/guts/fchmodat.c b/ports/unix/guts/fchmodat.c
index a14d1b1..59a92ce 100644
--- a/ports/unix/guts/fchmodat.c
+++ b/ports/unix/guts/fchmodat.c
@@ -1,14 +1,13 @@
/*
- * Copyright (c) 2008-2010, 2012 Wind River Systems; see
+ * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see
* guts/COPYRIGHT for information.
*
* static int
* wrap_fchmodat(int dirfd, const char *path, mode_t mode, int flags) {
* int rc = -1;
*/
- pseudo_msg_t *msg;
PSEUDO_STATBUF buf;
- int save_errno;
+ int save_errno = errno;
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
if (dirfd != AT_FDCWD) {
@@ -33,8 +32,13 @@
}
save_errno = errno;
+#if 0
+ pseudo_msg_t *msg;
/* purely for debugging purposes: check whether file
- * is already in database.
+ * is already in database. We don't need the resulting
+ * information for anything. This is currently ifdefed
+ * out because it's only useful when trying to track where
+ * files are coming from.
*/
msg = pseudo_client_op(OP_STAT, 0, -1, -1, path, &buf);
if (!msg || msg->result != RESULT_SUCCEED) {
@@ -42,6 +46,7 @@
mode, dirfd, path, (unsigned long long) buf.st_ino);
}
+#endif
/* user bits added so "root" can always access files. */
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
@@ -53,18 +58,18 @@
#endif
/* we ignore a failure from underlying fchmod, because pseudo
* may believe you are permitted to change modes that the filesystem
- * doesn't.
+ * doesn't. Note that we also don't need to know whether the
+ * file might be a (pseudo) block device or some such; pseudo
+ * will only modify permission bits based on an OP_CHMOD, and does
+ * not care about device/file type mismatches, only directory/file
+ * or symlink/file.
*/
buf.st_mode = (buf.st_mode & ~07777) | (mode & 07777);
- msg = pseudo_client_op(OP_CHMOD, 0, -1, dirfd, path, &buf);
- if (msg && msg->result != RESULT_SUCCEED) {
- errno = EPERM;
- rc = -1;
- } else {
- /* if server is down, just pretend we worked */
- rc = 0;
- }
+ pseudo_client_op(OP_CHMOD, 0, -1, dirfd, path, &buf);
+ /* don't change errno from what it was originally */
+ errno = save_errno;
+ rc = 0;
/* return rc;
* }
diff --git a/ports/unix/guts/fchown.c b/ports/unix/guts/fchown.c
index 72a1e46..1514e35 100644
--- a/ports/unix/guts/fchown.c
+++ b/ports/unix/guts/fchown.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2010, 2012 Wind River Systems; see
+ * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see
* guts/COPYRIGHT for information.
*
* static int
@@ -8,7 +8,7 @@
*/
pseudo_msg_t *msg;
PSEUDO_STATBUF buf;
- int save_errno;
+ int save_errno = errno;
if (base_fstat(fd, &buf) == -1) {
save_errno = errno;
@@ -41,14 +41,10 @@
}
pseudo_debug(2, "fchown, fd %d: %d:%d -> %d:%d\n",
fd, owner, group, buf.st_uid, buf.st_gid);
- msg = pseudo_client_op(OP_FCHOWN, 0, fd, -1, 0, &buf);
- if (msg && msg->result != RESULT_SUCCEED) {
- errno = EPERM;
- rc = -1;
- } else {
- /* just pretend we worked */
- rc = 0;
- }
+ pseudo_client_op(OP_FCHOWN, 0, fd, -1, 0, &buf);
+ /* pretend we worked, errno should be unchanged */
+ errno = save_errno;
+ rc = 0;
/* return rc;
* }
diff --git a/ports/unix/guts/fchownat.c b/ports/unix/guts/fchownat.c
index 8d3ee05..60ccfa5 100644
--- a/ports/unix/guts/fchownat.c
+++ b/ports/unix/guts/fchownat.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008-2010, 2012 Wind River Systems; see
+ * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see
* guts/COPYRIGHT for information.
*
* static int
@@ -8,7 +8,7 @@
*/
pseudo_msg_t *msg;
PSEUDO_STATBUF buf;
- int save_errno;
+ int save_errno = errno;
int doing_link = 0;
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
@@ -53,14 +53,10 @@
if (group != (gid_t) -1) {
buf.st_gid = group;
}
- msg = pseudo_client_op(OP_CHOWN, 0, -1, dirfd, path, &buf);
- if (msg && msg->result != RESULT_SUCCEED) {
- errno = EPERM;
- rc = -1;
- } else {
- /* just pretend we worked */
- rc = 0;
- }
+ pseudo_client_op(OP_CHOWN, 0, -1, dirfd, path, &buf);
+ /* just pretend we worked */
+ errno = save_errno;
+ rc = 0;
/* return rc;
* }
diff --git a/ports/unix/guts/mknodat.c b/ports/unix/guts/mknodat.c
index 32a4d5b..6fd5b42 100644
--- a/ports/unix/guts/mknodat.c
+++ b/ports/unix/guts/mknodat.c
@@ -8,6 +8,7 @@
pseudo_msg_t *msg;
PSEUDO_STATBUF buf;
+ int save_errno = errno;
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
if (dirfd != AT_FDCWD) {
@@ -50,10 +51,11 @@
rc = -1;
} else {
/* just pretend we worked */
+ errno = save_errno;
rc = 0;
}
if (rc == -1) {
- int save_errno = errno;
+ save_errno = errno;
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
real_unlink(path);
#else
diff --git a/ports/unix/wrapfuncs.in b/ports/unix/wrapfuncs.in
index a0f191c..8460a65 100644
--- a/ports/unix/wrapfuncs.in
+++ b/ports/unix/wrapfuncs.in
@@ -63,7 +63,7 @@ FILE *popen(const char *command, const char *mode); /* hand_wrapped=1 */
# during filesystem assembly.
int fsync(int fd); /* async_skip=0 */
int fdatasync(int fd); /* async_skip=0 */
-void sync(void); /* async_skip=0 */
+void sync(void); /* async_skip= */
int syncfs(int fd); /* async_skip=0 */
int sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags); /* async_skip=0 */
int msync(void *addr, size_t length, int flags); /* async_skip=0 */
diff --git a/pseudo.c b/pseudo.c
index 4ea79c5..ad71062 100644
--- a/pseudo.c
+++ b/pseudo.c
@@ -1,7 +1,7 @@
/*
* pseudo.c, main pseudo utility program
*
- * Copyright (c) 2008-2010 Wind River Systems, Inc.
+ * Copyright (c) 2008-2013 Wind River Systems, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the Lesser GNU General Public License version 2.1 as
@@ -933,6 +933,7 @@ pseudo_server_response(pseudo_msg_t *msg, const char *program, const char *tag)
return 0;
break;
case PSEUDO_MSG_OP:
+ case PSEUDO_MSG_FASTOP:
return pseudo_op(msg, program, tag);
break;
case PSEUDO_MSG_ACK: /* FALLTHROUGH */
diff --git a/pseudo_client.c b/pseudo_client.c
index a7ba100..f58ce4c 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -876,14 +876,18 @@ pseudo_client_request(pseudo_msg_t *msg, size_t len, const char *path) {
}
} while (rc != 0);
pseudo_debug(5, "sent!\n");
- response = pseudo_msg_receive(connect_fd);
- if (!response) {
- ++tries;
- if (tries > 3) {
- pseudo_debug(1, "can't get responses.\n");
- return 0;
- }
- }
+ if (msg->type != PSEUDO_MSG_FASTOP) {
+ response = pseudo_msg_receive(connect_fd);
+ if (!response) {
+ ++tries;
+ if (tries > 3) {
+ pseudo_debug(1, "can't get responses.\n");
+ return 0;
+ }
+ }
+ } else {
+ return 0;
+ }
} while (response == 0);
if (response->type != PSEUDO_MSG_ACK) {
pseudo_debug(2, "got non-ack response %d\n", response->type);
@@ -1225,6 +1229,8 @@ pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path
}
if (do_request) {
struct timeval tv1, tv2;
+ if (!pseudo_op_wait(msg.op))
+ msg.type = PSEUDO_MSG_FASTOP;
pseudo_debug(4, "sending request [ino %llu]\n", (unsigned long long) msg.ino);
gettimeofday(&tv1, NULL);
if (pseudo_local_only) {
diff --git a/pseudo_server.c b/pseudo_server.c
index 4af5265..2597def 100644
--- a/pseudo_server.c
+++ b/pseudo_server.c
@@ -1,7 +1,7 @@
/*
* pseudo_server.c, pseudo's server-side logic and message handling
*
- * Copyright (c) 2008-2010 Wind River Systems, Inc.
+ * Copyright (c) 2008-2010, 2013 Wind River Systems, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the Lesser GNU General Public License version 2.1 as
@@ -76,7 +76,7 @@ quit_now(int signal) {
die_forcefully = 1;
}
-static int messages = 0;
+static int messages = 0, responses = 0;
static struct timeval message_time = { .tv_sec = 0 };
static void pseudo_server_loop(void);
@@ -268,6 +268,7 @@ serve_client(int i) {
in = pseudo_msg_receive(clients[i].fd);
if (in) {
char *response_path = 0;
+ int send_response = 1;
pseudo_debug(4, "got a message (%d): %s\n", in->type, (in->pathlen ? in->path : "<no path>"));
/* handle incoming ping */
if (in->type == PSEUDO_MSG_PING && !clients[i].pid) {
@@ -303,6 +304,8 @@ serve_client(int i) {
* pseudo_server_response.
*/
if (in->type != PSEUDO_MSG_SHUTDOWN) {
+ if (in->type == PSEUDO_MSG_FASTOP)
+ send_response = 0;
if (pseudo_server_response(in, clients[i].program, clients[i].tag)) {
in->type = PSEUDO_MSG_NAK;
} else {
@@ -343,10 +346,14 @@ serve_client(int i) {
die_peacefully = 1;
}
}
- if ((rc = pseudo_msg_send(clients[i].fd, in, -1, response_path)) != 0)
- pseudo_debug(1, "failed to send response to client %d [%d]: %d (%s)\n",
- i, (int) clients[i].pid, rc, strerror(errno));
- rc = in->op;
+ if (send_response) {
+ if ((rc = pseudo_msg_send(clients[i].fd, in, -1, response_path)) != 0) {
+ pseudo_debug(1, "failed to send response to client %d [%d]: %d (%s)\n",
+ i, (int) clients[i].pid, rc, strerror(errno));
+ }
+ } else {
+ rc = 1;
+ }
free(response_path);
return rc;
} else {
@@ -423,10 +430,11 @@ pseudo_server_loop(void) {
die_peacefully = 1;
} else {
/* display this if not exiting */
- pseudo_debug(1, "%d messages handled in %.4f seconds\n",
+ pseudo_debug(1, "%d messages handled in %.4f seconds, %d responses\n",
messages,
(double) message_time.tv_sec +
- (double) message_time.tv_usec / 1000000.0);
+ (double) message_time.tv_usec / 1000000.0,
+ responses);
}
}
} else if (rc > 0) {
@@ -439,11 +447,13 @@ pseudo_server_loop(void) {
close_client(i);
} else if (FD_ISSET(clients[i].fd, &reads)) {
struct timeval tv1, tv2;
- int op;
+ int rc;
gettimeofday(&tv1, NULL);
- op = serve_client(i);
+ rc = serve_client(i);
gettimeofday(&tv2, NULL);
++messages;
+ if (rc == 0)
+ ++responses;
message_time.tv_sec += (tv2.tv_sec - tv1.tv_sec);
message_time.tv_usec += (tv2.tv_usec - tv1.tv_usec);
if (message_time.tv_usec < 0) {