From 9999e48639b3cecb08ffb37358bcba3b48161b29 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Fri, 10 May 2024 08:50:17 +0000 Subject: [PATCH] add ax88772_rst --- kernel/fs/afs/mntpt.c | 195 +++++++++++++++++++++++++----------------------- 1 files changed, 100 insertions(+), 95 deletions(-) diff --git a/kernel/fs/afs/mntpt.c b/kernel/fs/afs/mntpt.c index 99fd135..bbb2c21 100644 --- a/kernel/fs/afs/mntpt.c +++ b/kernel/fs/afs/mntpt.c @@ -1,12 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* mountpoint management * * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. */ #include <linux/kernel.h> @@ -17,6 +13,7 @@ #include <linux/mount.h> #include <linux/namei.h> #include <linux/gfp.h> +#include <linux/fs_context.h> #include "internal.h" @@ -35,7 +32,6 @@ .lookup = afs_mntpt_lookup, .readlink = page_readlink, .getattr = afs_getattr, - .listxattr = afs_listxattr, }; const struct inode_operations afs_autocell_inode_operations = { @@ -46,6 +42,8 @@ static DECLARE_DELAYED_WORK(afs_mntpt_expiry_timer, afs_mntpt_expiry_timed_out); static unsigned long afs_mntpt_expiry_timeout = 10 * 60; + +static const char afs_root_volume[] = "root.cell"; /* * no valid lookup procedure on this sort of dir @@ -68,107 +66,114 @@ } /* + * Set the parameters for the proposed superblock. + */ +static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt) +{ + struct afs_fs_context *ctx = fc->fs_private; + struct afs_super_info *src_as = AFS_FS_S(mntpt->d_sb); + struct afs_vnode *vnode = AFS_FS_I(d_inode(mntpt)); + struct afs_cell *cell; + const char *p; + int ret; + + if (fc->net_ns != src_as->net_ns) { + put_net(fc->net_ns); + fc->net_ns = get_net(src_as->net_ns); + } + + if (src_as->volume && src_as->volume->type == AFSVL_RWVOL) { + ctx->type = AFSVL_RWVOL; + ctx->force = true; + } + if (ctx->cell) { + afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_mntpt); + ctx->cell = NULL; + } + if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) { + /* if the directory is a pseudo directory, use the d_name */ + unsigned size = mntpt->d_name.len; + + if (size < 2) + return -ENOENT; + + p = mntpt->d_name.name; + if (mntpt->d_name.name[0] == '.') { + size--; + p++; + ctx->type = AFSVL_RWVOL; + ctx->force = true; + } + if (size > AFS_MAXCELLNAME) + return -ENAMETOOLONG; + + cell = afs_lookup_cell(ctx->net, p, size, NULL, false); + if (IS_ERR(cell)) { + pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt); + return PTR_ERR(cell); + } + ctx->cell = cell; + + ctx->volname = afs_root_volume; + ctx->volnamesz = sizeof(afs_root_volume) - 1; + } else { + /* read the contents of the AFS special symlink */ + struct page *page; + loff_t size = i_size_read(d_inode(mntpt)); + char *buf; + + if (src_as->cell) + ctx->cell = afs_use_cell(src_as->cell, afs_cell_trace_use_mntpt); + + if (size < 2 || size > PAGE_SIZE - 1) + return -EINVAL; + + page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL); + if (IS_ERR(page)) + return PTR_ERR(page); + + if (PageError(page)) { + ret = afs_bad(AFS_FS_I(d_inode(mntpt)), afs_file_error_mntpt); + put_page(page); + return ret; + } + + buf = kmap(page); + ret = -EINVAL; + if (buf[size - 1] == '.') + ret = vfs_parse_fs_string(fc, "source", buf, size - 1); + kunmap(page); + put_page(page); + if (ret < 0) + return ret; + } + + return 0; +} + +/* * create a vfsmount to be automounted */ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) { - struct afs_super_info *as; + struct fs_context *fc; struct vfsmount *mnt; - struct afs_vnode *vnode; - struct page *page; - char *devname, *options; - bool rwpath = false; int ret; - - _enter("{%pd}", mntpt); BUG_ON(!d_inode(mntpt)); - ret = -ENOMEM; - devname = (char *) get_zeroed_page(GFP_KERNEL); - if (!devname) - goto error_no_devname; + fc = fs_context_for_submount(&afs_fs_type, mntpt); + if (IS_ERR(fc)) + return ERR_CAST(fc); - options = (char *) get_zeroed_page(GFP_KERNEL); - if (!options) - goto error_no_options; + ret = afs_mntpt_set_params(fc, mntpt); + if (!ret) + mnt = fc_mount(fc); + else + mnt = ERR_PTR(ret); - vnode = AFS_FS_I(d_inode(mntpt)); - if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) { - /* if the directory is a pseudo directory, use the d_name */ - static const char afs_root_cell[] = ":root.cell."; - unsigned size = mntpt->d_name.len; - - ret = -ENOENT; - if (size < 2 || size > AFS_MAXCELLNAME) - goto error_no_page; - - if (mntpt->d_name.name[0] == '.') { - devname[0] = '%'; - memcpy(devname + 1, mntpt->d_name.name + 1, size - 1); - memcpy(devname + size, afs_root_cell, - sizeof(afs_root_cell)); - rwpath = true; - } else { - devname[0] = '#'; - memcpy(devname + 1, mntpt->d_name.name, size); - memcpy(devname + size + 1, afs_root_cell, - sizeof(afs_root_cell)); - } - } else { - /* read the contents of the AFS special symlink */ - loff_t size = i_size_read(d_inode(mntpt)); - char *buf; - - ret = -EINVAL; - if (size > PAGE_SIZE - 1) - goto error_no_page; - - page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL); - if (IS_ERR(page)) { - ret = PTR_ERR(page); - goto error_no_page; - } - - ret = -EIO; - if (PageError(page)) - goto error; - - buf = kmap_atomic(page); - memcpy(devname, buf, size); - kunmap_atomic(buf); - put_page(page); - page = NULL; - } - - /* work out what options we want */ - as = AFS_FS_S(mntpt->d_sb); - if (as->cell) { - memcpy(options, "cell=", 5); - strcpy(options + 5, as->cell->name); - if ((as->volume && as->volume->type == AFSVL_RWVOL) || rwpath) - strcat(options, ",rwpath"); - } - - /* try and do the mount */ - _debug("--- attempting mount %s -o %s ---", devname, options); - mnt = vfs_submount(mntpt, &afs_fs_type, devname, options); - _debug("--- mount result %p ---", mnt); - - free_page((unsigned long) devname); - free_page((unsigned long) options); - _leave(" = %p", mnt); + put_fs_context(fc); return mnt; - -error: - put_page(page); -error_no_page: - free_page((unsigned long) options); -error_no_options: - free_page((unsigned long) devname); -error_no_devname: - _leave(" = %d", ret); - return ERR_PTR(ret); } /* -- Gitblit v1.6.2