^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * linux/fs/nfs/namespace.c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2005 Trond Myklebust <Trond.Myklebust@netapp.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * - Modified by David Howells <dhowells@redhat.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * NFS namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/dcache.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/gfp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mount.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/namei.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/nfs_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/sunrpc/clnt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/vfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/sunrpc/gss_api.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include "nfs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define NFSDBG_FACILITY NFSDBG_VFS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) static void nfs_expire_automounts(struct work_struct *work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static LIST_HEAD(nfs_automount_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static DECLARE_DELAYED_WORK(nfs_automount_task, nfs_expire_automounts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) int nfs_mountpoint_expiry_timeout = 500 * HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * nfs_path - reconstruct the path given an arbitrary dentry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * @base - used to return pointer to the end of devname part of path
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * @dentry_in - pointer to dentry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * @buffer - result buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * @buflen_in - length of buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * @flags - options (see below)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * Helper function for constructing the server pathname
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * by arbitrary hashed dentry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * This is mainly for use in figuring out the path on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * server side when automounting on top of an existing partition
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * and in generating /proc/mounts and friends.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * Supported flags:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * NFS_PATH_CANONICAL: ensure there is exactly one slash after
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * the original device (export) name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * (if unset, the original name is returned verbatim)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) char *nfs_path(char **p, struct dentry *dentry_in, char *buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) ssize_t buflen_in, unsigned flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) char *end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) unsigned seq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) const char *base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) struct dentry *dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) ssize_t buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) rename_retry:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) buflen = buflen_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) dentry = dentry_in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) end = buffer+buflen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) *--end = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) buflen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) seq = read_seqbegin(&rename_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) spin_lock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (IS_ROOT(dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) namelen = dentry->d_name.len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) buflen -= namelen + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) if (buflen < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) goto Elong_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) end -= namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) memcpy(end, dentry->d_name.name, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *--end = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) dentry = dentry->d_parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (read_seqretry(&rename_lock, seq)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) goto rename_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if ((flags & NFS_PATH_CANONICAL) && *end != '/') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) if (--buflen < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) goto Elong;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *--end = '/';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *p = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) base = dentry->d_fsdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (!base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) WARN_ON(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) return end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) namelen = strlen(base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) if (*end == '/') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* Strip off excess slashes in base string */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) while (namelen > 0 && base[namelen - 1] == '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) namelen--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) buflen -= namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (buflen < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) goto Elong;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) end -= namelen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) memcpy(end, base, namelen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) Elong_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) spin_unlock(&dentry->d_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (read_seqretry(&rename_lock, seq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto rename_retry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) Elong:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return ERR_PTR(-ENAMETOOLONG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) EXPORT_SYMBOL_GPL(nfs_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * nfs_d_automount - Handle crossing a mountpoint on the server
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * @path - The mountpoint
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * When we encounter a mountpoint on the server, we want to set up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * a mountpoint on the client too, to prevent inode numbers from
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * colliding, and to allow "df" to work properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * On NFSv4, we also want to allow for the fact that different
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * filesystems may be migrated to different servers in a failover
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * situation, and that different filesystems may want to use
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * different security flavours.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct vfsmount *nfs_d_automount(struct path *path)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) struct nfs_fs_context *ctx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct fs_context *fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) struct vfsmount *mnt = ERR_PTR(-ENOMEM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) struct nfs_server *server = NFS_SERVER(d_inode(path->dentry));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct nfs_client *client = server->nfs_client;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) int timeout = READ_ONCE(nfs_mountpoint_expiry_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (IS_ROOT(path->dentry))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return ERR_PTR(-ESTALE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* Open a new filesystem context, transferring parameters from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) * parent superblock, including the network namespace.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) fc = fs_context_for_submount(path->mnt->mnt_sb->s_type, path->dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (IS_ERR(fc))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return ERR_CAST(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) ctx = nfs_fc2context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ctx->clone_data.dentry = path->dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) ctx->clone_data.sb = path->dentry->d_sb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ctx->clone_data.fattr = nfs_alloc_fattr();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) if (!ctx->clone_data.fattr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) goto out_fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) if (fc->net_ns != client->cl_net) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) put_net(fc->net_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) fc->net_ns = get_net(client->cl_net);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* for submounts we want the same server; referrals will reassign */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) memcpy(&ctx->nfs_server.address, &client->cl_addr, client->cl_addrlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) ctx->nfs_server.addrlen = client->cl_addrlen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) ctx->nfs_server.port = server->port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) ctx->version = client->rpc_ops->version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) ctx->minorversion = client->cl_minorversion;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ctx->nfs_mod = client->cl_nfs_mod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) __module_get(ctx->nfs_mod->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) ret = client->rpc_ops->submount(fc, server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) mnt = ERR_PTR(ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) goto out_fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) up_write(&fc->root->d_sb->s_umount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) mnt = vfs_create_mount(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) if (IS_ERR(mnt))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) goto out_fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) mntget(mnt); /* prevent immediate expiration */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (timeout <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) goto out_fc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) mnt_set_expiry(mnt, &nfs_automount_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) schedule_delayed_work(&nfs_automount_task, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) out_fc:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) put_fs_context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return mnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) nfs_namespace_getattr(const struct path *path, struct kstat *stat,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) u32 request_mask, unsigned int query_flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (NFS_FH(d_inode(path->dentry))->size != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) return nfs_getattr(path, stat, request_mask, query_flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) generic_fillattr(d_inode(path->dentry), stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) nfs_namespace_setattr(struct dentry *dentry, struct iattr *attr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) if (NFS_FH(d_inode(dentry))->size != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return nfs_setattr(dentry, attr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) const struct inode_operations nfs_mountpoint_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .getattr = nfs_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .setattr = nfs_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) const struct inode_operations nfs_referral_inode_operations = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) .getattr = nfs_namespace_getattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) .setattr = nfs_namespace_setattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) static void nfs_expire_automounts(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct list_head *list = &nfs_automount_list;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) int timeout = READ_ONCE(nfs_mountpoint_expiry_timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) mark_mounts_for_expiry(list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) if (!list_empty(list) && timeout > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) schedule_delayed_work(&nfs_automount_task, timeout);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) void nfs_release_automount_timer(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) if (list_empty(&nfs_automount_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) cancel_delayed_work(&nfs_automount_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * nfs_do_submount - set up mountpoint when crossing a filesystem boundary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) * @fc: pointer to struct nfs_fs_context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) int nfs_do_submount(struct fs_context *fc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct nfs_fs_context *ctx = nfs_fc2context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) struct dentry *dentry = ctx->clone_data.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) struct nfs_server *server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) char *buffer, *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) /* create a new volume representation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) server = ctx->nfs_mod->rpc_ops->clone_server(NFS_SB(ctx->clone_data.sb),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) ctx->mntfh,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) ctx->clone_data.fattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) ctx->selected_flavor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (IS_ERR(server))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) return PTR_ERR(server);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) ctx->server = server;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) buffer = kmalloc(4096, GFP_USER);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) if (!buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) ctx->internal = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) ctx->clone_data.inherited_bsize = ctx->clone_data.sb->s_blocksize_bits;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) p = nfs_devname(dentry, buffer, 4096);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if (IS_ERR(p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) nfs_errorf(fc, "NFS: Couldn't determine submount pathname");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) ret = PTR_ERR(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ret = vfs_parse_fs_string(fc, "source", p, buffer + 4096 - p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) ret = vfs_get_tree(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) kfree(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) EXPORT_SYMBOL_GPL(nfs_do_submount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) int nfs_submount(struct fs_context *fc, struct nfs_server *server)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) struct nfs_fs_context *ctx = nfs_fc2context(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) struct dentry *dentry = ctx->clone_data.dentry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) struct dentry *parent = dget_parent(dentry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) /* Look it up again to get its attributes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) err = server->nfs_client->rpc_ops->lookup(d_inode(parent), dentry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) ctx->mntfh, ctx->clone_data.fattr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) dput(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) if (err != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) ctx->selected_flavor = server->client->cl_auth->au_flavor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return nfs_do_submount(fc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) EXPORT_SYMBOL_GPL(nfs_submount);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) static int param_set_nfs_timeout(const char *val, const struct kernel_param *kp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) long num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (!val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) ret = kstrtol(val, 0, &num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) if (num > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (num >= INT_MAX / HZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) num = INT_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) num *= HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) *((int *)kp->arg) = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!list_empty(&nfs_automount_list))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) mod_delayed_work(system_wq, &nfs_automount_task, num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) *((int *)kp->arg) = -1*HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) cancel_delayed_work(&nfs_automount_task);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) static int param_get_nfs_timeout(char *buffer, const struct kernel_param *kp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) long num = *((int *)kp->arg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) if (num > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if (num >= INT_MAX - (HZ - 1))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) num = INT_MAX / HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) num = (num + (HZ - 1)) / HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) num = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return scnprintf(buffer, PAGE_SIZE, "%li\n", num);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) static const struct kernel_param_ops param_ops_nfs_timeout = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) .set = param_set_nfs_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) .get = param_get_nfs_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) #define param_check_nfs_timeout(name, p) __param_check(name, p, int);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) module_param(nfs_mountpoint_expiry_timeout, nfs_timeout, 0644);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) MODULE_PARM_DESC(nfs_mountpoint_expiry_timeout,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) "Set the NFS automounted mountpoint timeout value (seconds)."
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) "Values <= 0 turn expiration off.");