From: Thiago Rafael Becker <trbecker@gmail.com>
To: linux-nfs@vger.kernel.org
Cc: tbecker@redhat.com, steved@redhat.com, chuck.lever@oracle.com,
Thiago Rafael Becker <trbecker@gmail.com>
Subject: [RFC PATCH 5/7] readahead: create the configuration file
Date: Wed, 9 Mar 2022 15:26:51 -0300 [thread overview]
Message-ID: <20220309182653.1885252-6-trbecker@gmail.com> (raw)
In-Reply-To: <20220309182653.1885252-1-trbecker@gmail.com>
At this stage, the configuration file only accepts the default value.
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1946283
Signed-off-by: Thiago Rafael Becker <trbecker@gmail.com>
---
.gitignore | 5 ++
configure.ac | 3 +
tools/nfs-readahead-udev/Makefile.am | 16 ++++-
tools/nfs-readahead-udev/config_parser.c | 25 ++++++++
tools/nfs-readahead-udev/config_parser.h | 14 +++++
tools/nfs-readahead-udev/list.h | 48 +++++++++++++++
tools/nfs-readahead-udev/main.c | 68 ++++++++++++++++++++-
tools/nfs-readahead-udev/parser.y | 78 ++++++++++++++++++++++++
tools/nfs-readahead-udev/readahead.conf | 1 +
tools/nfs-readahead-udev/scanner.l | 14 +++++
10 files changed, 269 insertions(+), 3 deletions(-)
create mode 100644 tools/nfs-readahead-udev/config_parser.c
create mode 100644 tools/nfs-readahead-udev/config_parser.h
create mode 100644 tools/nfs-readahead-udev/list.h
create mode 100644 tools/nfs-readahead-udev/parser.y
create mode 100644 tools/nfs-readahead-udev/readahead.conf
create mode 100644 tools/nfs-readahead-udev/scanner.l
diff --git a/.gitignore b/.gitignore
index c99269a4..340ee8fb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -17,6 +17,7 @@ aclocal/ltoptions.m4
aclocal/ltsugar.m4
aclocal/ltversion.m4
aclocal/lt~obsolete.m4
+ylwrap
# files generated by configure
confdefs.h
config.cache
@@ -61,7 +62,11 @@ utils/statd/statd
tools/locktest/testlk
tools/getiversion/getiversion
tools/nfsconf/nfsconf
+tools/nfs-readahead-udev/99-nfs_bdi.rules
tools/nfs-readahead-udev/nfs-readahead-udev
+tools/nfs-readahead-udev/parser.c
+tools/nfs-readahead-udev/parser.h
+tools/nfs-readahead-udev/scanner.c
support/export/mount.h
support/export/mount_clnt.c
support/export/mount_xdr.c
diff --git a/configure.ac b/configure.ac
index 7e5ba5d9..03cdf8f6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -300,7 +300,10 @@ AC_PROG_INSTALL
AC_PROG_LN_S
AC_PROG_MAKE_SET
AC_PROG_LIBTOOL
+AC_PROG_YACC
AM_PROG_CC_C_O
+AM_PROG_LEX
+
if test "x$cross_compiling" = "xno"; then
CC_FOR_BUILD=${CC_FOR_BUILD-${CC-gcc}}
diff --git a/tools/nfs-readahead-udev/Makefile.am b/tools/nfs-readahead-udev/Makefile.am
index 551d22e9..010350aa 100644
--- a/tools/nfs-readahead-udev/Makefile.am
+++ b/tools/nfs-readahead-udev/Makefile.am
@@ -1,12 +1,24 @@
libexec_PROGRAMS = nfs-readahead-udev
-nfs_readahead_udev_SOURCES = main.c syslog.c
+BUILT_SOURCES = parser.c parser.h scanner.c
+nfs_readahead_udev_SOURCES = main.c syslog.c config_parser.c parser.y scanner.l
nfs_readahead_udev_LDFLAGS= -lmount
+AM_YFLAGS = -d
-udev_rulesdir = /etc/udev/rules.d
+udev_rulesdir = $(sysconfdir)/udev/rules.d
udev_rules_DATA = 99-nfs_bdi.rules
+ra_confdir = $(sysconfdir)
+ra_conf_DATA = readahead.conf
+
99-nfs_bdi.rules: 99-nfs_bdi.rules.in $(builddefs)
$(SED) "s|_libexecdir_|@libexecdir@|g" 99-nfs_bdi.rules.in > $@
clean-local:
$(RM) 99-nfs_bdi.rules
+ $(RM) parser.c parser.h scanner.c
+
+parser.$(OBJEXT): CFLAGS += -Wno-strict-prototypes
+
+scanner.$(OBJEXT): CFLAGS += -Wno-strict-prototypes
+
+main.$(OBJEXT): CFLAGS += -DSYSCONFDIR=\"@sysconfdir@\"
diff --git a/tools/nfs-readahead-udev/config_parser.c b/tools/nfs-readahead-udev/config_parser.c
new file mode 100644
index 00000000..24d58a6b
--- /dev/null
+++ b/tools/nfs-readahead-udev/config_parser.c
@@ -0,0 +1,25 @@
+#include <stdlib.h>
+#include <string.h>
+#include "config_parser.h"
+
+struct config_entry *config_entry_new(void);
+
+struct config_entry *config_entry_new(void) {
+ struct config_entry *new = malloc(sizeof(struct config_entry));
+ if (!new) {
+ return NULL; // Make this an err_ptr
+ }
+
+ memset(new, 0, sizeof(struct config_entry));
+ list_init(&new->list);
+ return new;
+}
+
+
+void config_entry_free(struct config_entry *ce)
+{
+#define sfree(ce) if (ce) free(ce)
+ sfree(ce->mountpoint);
+ sfree(ce->fstype);
+#undef sfree
+}
diff --git a/tools/nfs-readahead-udev/config_parser.h b/tools/nfs-readahead-udev/config_parser.h
new file mode 100644
index 00000000..f9f138bb
--- /dev/null
+++ b/tools/nfs-readahead-udev/config_parser.h
@@ -0,0 +1,14 @@
+#ifndef __ra_libparser_h__
+#define __ra_libparser_h__
+#include "list.h"
+
+struct config_entry {
+ struct list_head list;
+ char *mountpoint;
+ char *fstype;
+ int readahead;
+};
+
+extern int parse_config(const char *, struct list_head *config_list);
+extern void config_entry_free(struct config_entry *);
+#endif
diff --git a/tools/nfs-readahead-udev/list.h b/tools/nfs-readahead-udev/list.h
new file mode 100644
index 00000000..69239502
--- /dev/null
+++ b/tools/nfs-readahead-udev/list.h
@@ -0,0 +1,48 @@
+#ifndef __ra_list_h__
+#define __ra_list_h__
+struct list_head
+{
+ struct list_head *next, *prev;
+};
+
+static inline void list_init(struct list_head *lh)
+{
+ lh->next = lh;
+ lh->prev = lh;
+}
+
+#define LIST_DECLARE(name) \
+ struct list_head name; \
+ list_init(&name);
+
+static inline void list_add(struct list_head *l, struct list_head *a)
+{
+ a->prev = l;
+ a->next = l->next;
+ l->next->prev = a;
+ l->next = a;
+}
+
+static inline void list_del(struct list_head *a)
+{
+ a->next->prev = a->prev;
+ a->prev->next = a->next;
+ a->next = a;
+ a->prev = a;
+}
+
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_free(head, free_func) ({ \
+ for (struct list_head *__lh = (head)->next; \
+ __lh != head; __lh = (head)->next) { \
+ list_del(__lh); \
+ free_func(__lh); \
+ }})
+
+#define containerof(p, type, field) ({ \
+ const __typeof__(((type *)0)->field) *__ptr = (p); \
+ (type *)((char *)__ptr - offsetof(type, field) ); })
+
+#endif
diff --git a/tools/nfs-readahead-udev/main.c b/tools/nfs-readahead-udev/main.c
index bbb408c0..2bd76138 100644
--- a/tools/nfs-readahead-udev/main.c
+++ b/tools/nfs-readahead-udev/main.c
@@ -2,16 +2,23 @@
#include <string.h>
#include <stdlib.h>
#include <errno.h>
+#include <stddef.h>
#include <libmount/libmount.h>
#include <sys/sysmacros.h>
#include "log.h"
+#include "list.h"
+#include "config_parser.h"
#ifndef MOUNTINFO_PATH
#define MOUNTINFO_PATH "/proc/self/mountinfo"
#endif
+#ifndef READAHEAD_CONFIG_FILE
+#define READAHEAD_CONFIG_FILE SYSCONFDIR "/readahead.conf"
+#endif
+
/* Device information from the system */
struct device_info {
char *device_number;
@@ -110,6 +117,60 @@ static int get_device_info(const char *device_number, struct device_info *device
return ret;
}
+static void config_entry_list_head_free(struct list_head *lh) {
+ struct config_entry *ce = containerof(lh, struct config_entry, list);
+ config_entry_free(ce);
+}
+
+static int match_config(struct device_info *di, struct config_entry *ce) {
+#define FIELD_CMP(field) \
+ (ce->field == NULL || (di->field != NULL && strcmp(di->field, ce->field) == 0))
+
+ if (!FIELD_CMP(mountpoint))
+ return 0;
+
+ if (!FIELD_CMP(fstype))
+ return 0;
+
+ debug("Device matched with config\n");
+ return 1;
+#undef FIELD_CMP
+}
+
+static int get_readahead(struct device_info *di, unsigned int *readahead)
+{
+ LIST_DECLARE(configs);
+ struct list_head *lh;
+ int ret = 0;
+ int default_ra = 0;
+
+ if ((ret = parse_config(READAHEAD_CONFIG_FILE, &configs)) != 0) {
+ err("Failed to read configuration (%d)\n", ret);
+ goto out;
+ }
+
+ list_for_each(lh, &configs) {
+ struct config_entry *ce = containerof(lh, struct config_entry, list);
+ if (ce->mountpoint == NULL && ce->fstype == NULL) {
+ default_ra = ce->readahead;
+ continue;
+ }
+
+ if (match_config(di, ce)) {
+ *readahead = ce->readahead;
+ goto out;
+ }
+ }
+
+ /* fallthrough */
+ debug("Setting readahead to default %d\n", default_ra);
+ *readahead = default_ra;
+
+out:
+ list_free(&configs, config_entry_list_head_free);
+ return ret;
+}
+
int main(int argc, char **argv, char **envp)
{
int ret = 0;
@@ -134,7 +195,12 @@ int main(int argc, char **argv, char **envp)
goto out;
}
- info("Setting %s readahead to 128\n", device.mountpoint);
+ if ((ret = get_readahead(&device, &readahead)) != 0) {
+ err("Failed to find readahead (%d)\n", ret);
+ goto out;
+ }
+
+ info("Setting %s readahead to %u\n", device.mountpoint, readahead);
log_close();
printf("%d\n", readahead);
diff --git a/tools/nfs-readahead-udev/parser.y b/tools/nfs-readahead-udev/parser.y
new file mode 100644
index 00000000..f6db05c4
--- /dev/null
+++ b/tools/nfs-readahead-udev/parser.y
@@ -0,0 +1,78 @@
+%{
+#include <stdio.h>
+#include "parser.h"
+#include "config_parser.h"
+#include "log.h"
+
+extern int yylex();
+extern int yyparse();
+extern FILE *yyin;
+void yyerror(const char *s);
+
+// This should be visible only to this file
+extern struct config_entry *config_entry_new(void);
+
+struct config_entry *current;
+%}
+
+%union {
+ int ival;
+}
+
+%token <ival> INT
+%token EQ
+%token ENDL
+%token DEFAULT
+%token READAHEAD
+%token END_CONFIG 0
+
+%%
+config:
+ lines
+lines:
+ lines line | line | endls lines
+line:
+ tokens endls {
+ struct config_entry *new = config_entry_new();
+ list_add(¤t->list, &new->list);
+ current = new;
+ }
+
+
+tokens:
+ tokens token | token
+
+token:
+ default | pair
+
+default:
+ DEFAULT
+
+pair:
+ READAHEAD EQ INT { current->readahead = $3; }
+
+endls:
+ endls ENDL | ENDL
+
+%%
+int parse_config(const char *filename, struct list_head *list)
+{
+ int ret;
+
+ yyin = fopen(filename, "r");
+ current = config_entry_new();
+ list_add(list, ¤t->list);
+
+ ret = yyparse();
+
+ /* The parser will create an empty entry that need to be eliminated */
+ list_del(¤t->list);
+ free(current);
+ fclose(yyin);
+
+ return ret;
+}
+
+void yyerror(const char *s) {
+ err("Failed to parse configuration: %s", s);
+}
diff --git a/tools/nfs-readahead-udev/readahead.conf b/tools/nfs-readahead-udev/readahead.conf
new file mode 100644
index 00000000..988b30c7
--- /dev/null
+++ b/tools/nfs-readahead-udev/readahead.conf
@@ -0,0 +1 @@
+default readahead=128
diff --git a/tools/nfs-readahead-udev/scanner.l b/tools/nfs-readahead-udev/scanner.l
new file mode 100644
index 00000000..d1ceb90b
--- /dev/null
+++ b/tools/nfs-readahead-udev/scanner.l
@@ -0,0 +1,14 @@
+%{
+#include "parser.h"
+#define yyterminate() return END_CONFIG
+%}
+%option noyywrap
+%%
+default { return DEFAULT; }
+readahead { return READAHEAD; }
+[ \t] ;
+#[^\n]*\n { return ENDL; }
+\n { return ENDL; }
+[0-9]+ { yylval.ival = atoi(yytext); return INT; }
+= { return EQ; }
+%%
--
2.35.1
next prev parent reply other threads:[~2022-03-09 18:27 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-09 18:26 [RFC PATCH 0/7] Introduce nfs-readahead-udev Thiago Rafael Becker
2022-03-09 18:26 ` [RFC PATCH 1/7] Create nfs-readahead-udev Thiago Rafael Becker
2022-03-09 18:26 ` [RFC PATCH 2/7] readahead: configure udev Thiago Rafael Becker
2022-03-09 18:26 ` [RFC PATCH 3/7] readahead: create logging facility Thiago Rafael Becker
2022-03-09 18:26 ` [RFC PATCH 4/7] readahead: only set readahead for nfs devices Thiago Rafael Becker
2022-03-09 18:26 ` Thiago Rafael Becker [this message]
2022-03-09 18:26 ` [RFC PATCH 6/7] readahead: add mountpoint and fstype options Thiago Rafael Becker
2022-03-09 18:26 ` [RFC PATCH 7/7] readahead: documentation Thiago Rafael Becker
2022-03-09 19:33 ` [RFC PATCH 0/7] Introduce nfs-readahead-udev Chuck Lever III
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220309182653.1885252-6-trbecker@gmail.com \
--to=trbecker@gmail.com \
--cc=chuck.lever@oracle.com \
--cc=linux-nfs@vger.kernel.org \
--cc=steved@redhat.com \
--cc=tbecker@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox