From: David Howells <dhowells@redhat.com>
To: Marc Dionne <marc.dionne@auristor.com>
Cc: David Howells <dhowells@redhat.com>,
Christian Brauner <christian@brauner.io>,
linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v2 3/3] afs: Make /afs/@cell and /afs/.@cell symlinks
Date: Tue, 7 Jan 2025 18:34:51 +0000 [thread overview]
Message-ID: <20250107183454.608451-4-dhowells@redhat.com> (raw)
In-Reply-To: <20250107183454.608451-1-dhowells@redhat.com>
Make /afs/@cell a symlink in the /afs dynamic root to match what other AFS
clients do rather than doing a substitution in the dentry name. This has
the bonus of being tab-expandable also.
Further, provide a /afs/.@cell symlink to point to the dotted cell share.
Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
---
Notes:
Changes
=======
ver #2)
- Directly create the symlink nodes rather than going through lookup.
fs/afs/dynroot.c | 177 +++++++++++++++++++++++++++----------
include/trace/events/afs.h | 2 +
2 files changed, 131 insertions(+), 48 deletions(-)
diff --git a/fs/afs/dynroot.c b/fs/afs/dynroot.c
index f80a4244b9d2..d8bf52f77d93 100644
--- a/fs/afs/dynroot.c
+++ b/fs/afs/dynroot.c
@@ -185,50 +185,6 @@ struct inode *afs_try_auto_mntpt(struct dentry *dentry, struct inode *dir)
return ret == -ENOENT ? NULL : ERR_PTR(ret);
}
-/*
- * Look up @cell in a dynroot directory. This is a substitution for the
- * local cell name for the net namespace.
- */
-static struct dentry *afs_lookup_atcell(struct dentry *dentry)
-{
- struct afs_cell *cell;
- struct afs_net *net = afs_d2net(dentry);
- struct dentry *ret;
- char *name;
- int len;
-
- if (!net->ws_cell)
- return ERR_PTR(-ENOENT);
-
- ret = ERR_PTR(-ENOMEM);
- name = kmalloc(AFS_MAXCELLNAME + 1, GFP_KERNEL);
- if (!name)
- goto out_p;
-
- down_read(&net->cells_lock);
- cell = net->ws_cell;
- if (cell) {
- len = cell->name_len;
- memcpy(name, cell->name, len + 1);
- }
- up_read(&net->cells_lock);
-
- ret = ERR_PTR(-ENOENT);
- if (!cell)
- goto out_n;
-
- ret = lookup_one_len(name, dentry->d_parent, len);
-
- /* We don't want to d_add() the @cell dentry here as we don't want to
- * the cached dentry to hide changes to the local cell name.
- */
-
-out_n:
- kfree(name);
-out_p:
- return ret;
-}
-
/*
* Look up an entry in a dynroot directory.
*/
@@ -247,10 +203,6 @@ static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentr
return ERR_PTR(-ENAMETOOLONG);
}
- if (dentry->d_name.len == 5 &&
- memcmp(dentry->d_name.name, "@cell", 5) == 0)
- return afs_lookup_atcell(dentry);
-
return d_splice_alias(afs_try_auto_mntpt(dentry, dir), dentry);
}
@@ -343,6 +295,131 @@ void afs_dynroot_rmdir(struct afs_net *net, struct afs_cell *cell)
_leave("");
}
+static void afs_atcell_delayed_put_cell(void *arg)
+{
+ struct afs_cell *cell = arg;
+
+ afs_put_cell(cell, afs_cell_trace_put_atcell);
+}
+
+/*
+ * Read @cell or .@cell symlinks.
+ */
+static const char *afs_atcell_get_link(struct dentry *dentry, struct inode *inode,
+ struct delayed_call *done)
+{
+ struct afs_vnode *vnode = AFS_FS_I(inode);
+ struct afs_cell *cell;
+ struct afs_net *net = afs_i2net(inode);
+ const char *name;
+ bool dotted = vnode->fid.vnode == 3;
+
+ if (!net->ws_cell)
+ return ERR_PTR(-ENOENT);
+
+ down_read(&net->cells_lock);
+
+ cell = net->ws_cell;
+ if (dotted)
+ name = cell->name - 1;
+ else
+ name = cell->name;
+ afs_get_cell(cell, afs_cell_trace_get_atcell);
+ set_delayed_call(done, afs_atcell_delayed_put_cell, cell);
+
+ up_read(&net->cells_lock);
+ return name;
+}
+
+static const struct inode_operations afs_atcell_inode_operations = {
+ .get_link = afs_atcell_get_link,
+};
+
+/*
+ * Look up @cell or .@cell in a dynroot directory. This is a substitution for
+ * the local cell name for the net namespace.
+ */
+static struct dentry *afs_dynroot_create_symlink(struct dentry *root, const char *name)
+{
+ struct afs_vnode *vnode;
+ struct afs_fid fid = { .vnode = 2, .unique = 1, };
+ struct dentry *dentry;
+ struct inode *inode;
+
+ if (name[0] == '.')
+ fid.vnode = 3;
+
+ dentry = d_alloc_name(root, name);
+ if (!dentry)
+ return ERR_PTR(-ENOMEM);
+
+ inode = iget5_locked(dentry->d_sb, fid.vnode,
+ afs_iget5_pseudo_test, afs_iget5_pseudo_set, &fid);
+ if (!inode) {
+ dput(dentry);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ vnode = AFS_FS_I(inode);
+
+ /* there shouldn't be an existing inode */
+ if (WARN_ON_ONCE(!(inode->i_state & I_NEW))) {
+ iput(inode);
+ dput(dentry);
+ return ERR_PTR(-EIO);
+ }
+
+ netfs_inode_init(&vnode->netfs, NULL, false);
+ simple_inode_init_ts(inode);
+ set_nlink(inode, 1);
+ inode->i_size = 0;
+ inode->i_mode = S_IFLNK | 0555;
+ inode->i_op = &afs_atcell_inode_operations;
+ inode->i_uid = GLOBAL_ROOT_UID;
+ inode->i_gid = GLOBAL_ROOT_GID;
+ inode->i_blocks = 0;
+ inode->i_generation = 0;
+ inode->i_flags |= S_NOATIME;
+
+ unlock_new_inode(inode);
+ d_splice_alias(inode, dentry);
+ return dentry;
+}
+
+/*
+ * Create @cell and .@cell symlinks.
+ */
+static int afs_dynroot_symlink(struct afs_net *net)
+{
+ struct super_block *sb = net->dynroot_sb;
+ struct dentry *root, *symlink, *dsymlink;
+ int ret;
+
+ /* Let the ->lookup op do the creation */
+ root = sb->s_root;
+ inode_lock(root->d_inode);
+ symlink = afs_dynroot_create_symlink(root, "@cell");
+ if (IS_ERR(symlink)) {
+ ret = PTR_ERR(symlink);
+ goto unlock;
+ }
+
+ dsymlink = afs_dynroot_create_symlink(root, ".@cell");
+ if (IS_ERR(dsymlink)) {
+ ret = PTR_ERR(dsymlink);
+ dput(symlink);
+ goto unlock;
+ }
+
+ /* Note that we're retaining extra refs on the dentries. */
+ symlink->d_fsdata = (void *)1UL;
+ dsymlink->d_fsdata = (void *)1UL;
+ ret = 0;
+unlock:
+ inode_unlock(root->d_inode);
+ return ret;
+}
+
/*
* Populate a newly created dynamic root with cell names.
*/
@@ -355,6 +432,10 @@ int afs_dynroot_populate(struct super_block *sb)
mutex_lock(&net->proc_cells_lock);
net->dynroot_sb = sb;
+ ret = afs_dynroot_symlink(net);
+ if (ret < 0)
+ goto error;
+
hlist_for_each_entry(cell, &net->proc_cells, proc_link) {
ret = afs_dynroot_mkdir(net, cell);
if (ret < 0)
diff --git a/include/trace/events/afs.h b/include/trace/events/afs.h
index a0aed1a428a1..de0e2301a037 100644
--- a/include/trace/events/afs.h
+++ b/include/trace/events/afs.h
@@ -168,12 +168,14 @@ enum yfs_cm_operation {
#define afs_cell_traces \
EM(afs_cell_trace_alloc, "ALLOC ") \
EM(afs_cell_trace_free, "FREE ") \
+ EM(afs_cell_trace_get_atcell, "GET atcell") \
EM(afs_cell_trace_get_queue_dns, "GET q-dns ") \
EM(afs_cell_trace_get_queue_manage, "GET q-mng ") \
EM(afs_cell_trace_get_queue_new, "GET q-new ") \
EM(afs_cell_trace_get_vol, "GET vol ") \
EM(afs_cell_trace_insert, "INSERT ") \
EM(afs_cell_trace_manage, "MANAGE ") \
+ EM(afs_cell_trace_put_atcell, "PUT atcell") \
EM(afs_cell_trace_put_candidate, "PUT candid") \
EM(afs_cell_trace_put_destroy, "PUT destry") \
EM(afs_cell_trace_put_queue_work, "PUT q-work") \
prev parent reply other threads:[~2025-01-07 18:35 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-07 18:34 [PATCH v2 0/3] afs: Dynamic root improvements David Howells
2025-01-07 18:34 ` [PATCH v2 1/3] afs: Make /afs/.<cell> as well as /afs/<cell> mountpoints David Howells
2025-01-07 18:34 ` [PATCH v2 2/3] afs: Add rootcell checks David Howells
2025-01-07 18:34 ` David Howells [this message]
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=20250107183454.608451-4-dhowells@redhat.com \
--to=dhowells@redhat.com \
--cc=christian@brauner.io \
--cc=linux-afs@lists.infradead.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=marc.dionne@auristor.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.