From 8070f62fb5240ee5b924d0dae501a50f4662ffe9 Mon Sep 17 00:00:00 2001 From: Justus Winter <4winter@informatik.uni-hamburg.de> Date: Thu, 14 Nov 2013 15:36:36 +0100 Subject: trans/mtab: populate mtab objects on demand Previously the mtab content was generated in the open hook. Delay this until the data is needed. A follow up patch will take advantage of this to both simplify the logic in mtab_populate and make it more robust at the same time. * trans/mtab.c (open_hook): Do not eagerly populate the mtab. (trivfs_S_io_read): Populate the mtab struct on demand. (trivfs_S_io_seek): Likewise. (trivfs_S_io_readable): Likewise. --- trans/mtab.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) (limited to 'trans/mtab.c') diff --git a/trans/mtab.c b/trans/mtab.c index 250de7d6..9b867b7b 100644 --- a/trans/mtab.c +++ b/trans/mtab.c @@ -1,6 +1,6 @@ /* This is an mtab translator. - Copyright (C) 2013 Free Software Foundation, Inc. + Copyright (C) 2013,14 Free Software Foundation, Inc. Written by Justus Winter <4winter@informatik.uni-hamburg.de> @@ -594,7 +594,30 @@ open_hook (struct trivfs_peropen *peropen) mtab->contents = NULL; mtab->contents_len = 0; - return mtab_populate (mtab, target_path, insecure); + /* The mtab object is initialized, but not yet populated. We delay + that until that data is really needed. This avoids the following + problems: + + Suppose you have + + settrans -ac /foo /hurd/mtab / + + If you now access /foo, the mtab translator will walk the tree of + all active translators starting from /. If it visits /foo, it + will talk to itself. Previously the translator migitated this by + comparing the control port of the translator with its own. This + does not work if you got two mtab translators like this: + + settrans -ac /foo /hurd/mtab / + settrans -ac /bar /hurd/mtab / + + With a single-threaded mtab server this results in a dead-lock, + with a multi-threaded server this will create more and more + threads. + + Delaying the data generation until it is really needed cleanly + avoids these kind of problems. */ + return 0; } static void @@ -624,6 +647,14 @@ trivfs_S_io_read (struct trivfs_protid *cred, /* Get the offset. */ op = cred->po->hook; + + if (op->contents == NULL) + { + error_t err = mtab_populate (op, target_path, insecure); + if (err) + return err; + } + if (offs == -1) offs = op->offs; @@ -666,6 +697,13 @@ trivfs_S_io_seek (struct trivfs_protid *cred, struct mtab *op = cred->po->hook; + if (op->contents == NULL) + { + error_t err = mtab_populate (op, target_path, insecure); + if (err) + return err; + } + switch (whence) { case SEEK_CUR: @@ -711,6 +749,13 @@ trivfs_S_io_readable (struct trivfs_protid *cred, struct mtab *op = cred->po->hook; + if (op->contents == NULL) + { + error_t err = mtab_populate (op, target_path, insecure); + if (err) + return err; + } + *amount = op->contents_len - op->offs; return 0; } -- cgit v1.2.3