// SPDX-License-Identifier: GPL-2.0-only /* * linux/fs/nfs/super.c * * Copyright (C) 1992 Rick Sladkey * * nfs superblock handling functions * * Modularised by Alan Cox <alan@lxorguk.ukuu.org.uk>, while hacking some * experimental NFS changes. Modularisation taken straight from SYS5 fs. * * Change to nfs_read_super() to permit NFS mounts to multi-homed hosts. * J.S.Peatfield@damtp.cam.ac.uk * * Split from inode.c by David Howells <dhowells@redhat.com> * * - superblocks are indexed on server only - all inodes, dentries, etc. associated with a * particular server are held in the same superblock * - NFS superblocks can have several effective roots to the dentry tree * - directory type roots are spliced into the tree when a path from one root reaches the root * of another (see nfs_lookup())
*/
/* * Current versions of glibc do not correctly handle the * case where f_frsize != f_bsize. Eventually we want to * report the value of wtmult in this field.
*/
buf->f_frsize = dentry->d_sb->s_blocksize;
/* * On most *nix systems, f_blocks, f_bfree, and f_bavail * are reported in units of f_frsize. Linux hasn't had * an f_frsize field in its statfs struct until recently, * thus historically Linux's sys_statfs reports these * fields in units of f_bsize.
*/
buf->f_bsize = dentry->d_sb->s_blocksize;
blockbits = dentry->d_sb->s_blocksize_bits;
blockres = (1 << blockbits) - 1;
buf->f_blocks = (res.tbytes + blockres) >> blockbits;
buf->f_bfree = (res.fbytes + blockres) >> blockbits;
buf->f_bavail = (res.abytes + blockres) >> blockbits;
switch (sap->sa_family) { case AF_INET: switch (nfss->mountd_protocol) { case IPPROTO_UDP:
proto = RPCBIND_NETID_UDP; break; case IPPROTO_TCP:
proto = RPCBIND_NETID_TCP; break;
} break; case AF_INET6: switch (nfss->mountd_protocol) { case IPPROTO_UDP:
proto = RPCBIND_NETID_UDP6; break; case IPPROTO_TCP:
proto = RPCBIND_NETID_TCP6; break;
} break;
} if (proto || showdefaults)
seq_printf(m, ",mountproto=%s", proto ?: "auto");
}
if (nfss->flags & NFS_MOUNT_NO_ALIGNWRITE)
seq_puts(m, ",noalignwrite");
if (nfss->flags & NFS_MOUNT_WRITE_EAGER) { if (nfss->flags & NFS_MOUNT_WRITE_WAIT)
seq_puts(m, ",write=wait"); else
seq_puts(m, ",write=eager");
}
}
/* * Describe the mount options on this VFS mountpoint
*/ int nfs_show_options(struct seq_file *m, struct dentry *root)
{ struct nfs_server *nfss = NFS_SB(root->d_sb);
/* * Display security flavor in effect for this mount
*/
seq_printf(m, "\n\tsec:\tflavor=%u", auth->au_ops->au_flavor); if (auth->au_flavor)
seq_printf(m, ",pseudoflavor=%u", auth->au_flavor);
for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
totals.events[i] += stats->events[i]; for (i = 0; i < __NFSIOS_BYTESMAX; i++)
totals.bytes[i] += stats->bytes[i];
preempt_enable();
}
seq_puts(m, "\n\tevents:\t"); for (i = 0; i < __NFSIOS_COUNTSMAX; i++)
seq_printf(m, "%lu ", totals.events[i]);
seq_puts(m, "\n\tbytes:\t"); for (i = 0; i < __NFSIOS_BYTESMAX; i++)
seq_printf(m, "%Lu ", totals.bytes[i]);
seq_putc(m, '\n');
rpc_clnt_show_stats(m, nfss->client);
return 0;
}
EXPORT_SYMBOL_GPL(nfs_show_stats);
/* * Begin unmount by attempting to remove all automounted mountpoints we added * in response to xdev traversals and referrals
*/ void nfs_umount_begin(struct super_block *sb)
{ struct nfs_server *server; struct rpc_clnt *rpc;
server = NFS_SB(sb); /* -EIO all pending I/O */
rpc = server->client_acl; if (!IS_ERR(rpc))
rpc_killall_tasks(rpc);
rpc = server->client; if (!IS_ERR(rpc))
rpc_killall_tasks(rpc);
}
EXPORT_SYMBOL_GPL(nfs_umount_begin);
/* * Return true if 'match' is in auth_info or auth_info is empty. * Return false otherwise.
*/ bool nfs_auth_info_match(conststruct nfs_auth_info *auth_info,
rpc_authflavor_t match)
{ int i;
if (!auth_info->flavor_len) returntrue;
for (i = 0; i < auth_info->flavor_len; i++) { if (auth_info->flavors[i] == match) returntrue;
} returnfalse;
}
EXPORT_SYMBOL_GPL(nfs_auth_info_match);
/* * Ensure that a specified authtype in ctx->auth_info is supported by * the server. Returns 0 and sets ctx->selected_flavor if it's ok, and * -EACCES if not.
*/ staticint nfs_verify_authflavors(struct nfs_fs_context *ctx,
rpc_authflavor_t *server_authlist, unsignedint count)
{
rpc_authflavor_t flavor = RPC_AUTH_MAXFLAVOR; bool found_auth_null = false; unsignedint i;
/* * If the sec= mount option is used, the specified flavor or AUTH_NULL * must be in the list returned by the server. * * AUTH_NULL has a special meaning when it's in the server list - it * means that the server will ignore the rpc creds, so any flavor * can be used but still use the sec= that was specified. * * Note also that the MNT procedure in MNTv1 does not return a list * of supported security flavors. In this case, nfs_mount() fabricates * a security flavor list containing just AUTH_NULL.
*/ for (i = 0; i < count; i++) {
flavor = server_authlist[i];
if (nfs_auth_info_match(&ctx->auth_info, flavor)) goto out;
if (flavor == RPC_AUTH_NULL)
found_auth_null = true;
}
if (found_auth_null) {
flavor = ctx->auth_info.flavors[0]; goto out;
}
dfprintk(MOUNT, "NFS: specified auth flavors not supported by server\n"); return -EACCES;
if (ctx->mount_server.hostname)
request.hostname = ctx->mount_server.hostname; else
request.hostname = ctx->nfs_server.hostname;
/* * Construct the mount server's address.
*/ if (ctx->mount_server.address.sa_family == AF_UNSPEC) {
memcpy(request.sap, &ctx->nfs_server._address,
ctx->nfs_server.addrlen);
ctx->mount_server.addrlen = ctx->nfs_server.addrlen;
}
request.salen = ctx->mount_server.addrlen;
nfs_set_port(request.sap, &ctx->mount_server.port, 0);
/* * Now ask the mount server to map our export path * to a file handle.
*/ if ((request.protocol == XPRT_TRANSPORT_UDP) ==
!(ctx->flags & NFS_MOUNT_TCP)) /* * NFS protocol and mount protocol are both UDP or neither UDP * so timeouts are compatible. Use NFS timeouts for MOUNT
*/
status = nfs_mount(&request, ctx->timeo, ctx->retrans); else
status = nfs_mount(&request, NFS_UNSPEC_TIMEO, NFS_UNSPEC_RETRANS); if (status != 0) {
dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n",
request.hostname, status); return status;
}
/* make sure 'nolock'/'lock' override the 'local_lock' mount option */ if (ctx->lock_status) { if (ctx->lock_status == NFS_LOCK_NOLOCK) {
ctx->flags |= NFS_MOUNT_NONLM;
ctx->flags |= (NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
} else {
ctx->flags &= ~NFS_MOUNT_NONLM;
ctx->flags &= ~(NFS_MOUNT_LOCAL_FLOCK | NFS_MOUNT_LOCAL_FCNTL);
}
}
status = nfs_request_mount(fc, ctx->mntfh, authlist, &authlist_len); if (status) return ERR_PTR(status);
/* * Was a sec= authflavor specified in the options? First, verify * whether the server supports it, and then just try to use it if so.
*/ if (ctx->auth_info.flavor_len > 0) {
status = nfs_verify_authflavors(ctx, authlist, authlist_len);
dfprintk(MOUNT, "NFS: using auth flavor %u\n",
ctx->selected_flavor); if (status) return ERR_PTR(status); return ctx->nfs_mod->rpc_ops->create_server(fc);
}
/* * No sec= option was provided. RFC 2623, section 2.7 suggests we * SHOULD prefer the flavor listed first. However, some servers list * AUTH_NULL first. Avoid ever choosing AUTH_NULL.
*/ for (i = 0; i < authlist_len; ++i) {
rpc_authflavor_t flavor; struct rpcsec_gss_info info;
flavor = authlist[i]; switch (flavor) { case RPC_AUTH_UNIX:
tried_auth_unix = true; break; case RPC_AUTH_NULL:
auth_null_in_list = true; continue; default: if (rpcauth_get_gssinfo(flavor, &info) != 0) continue; break;
}
dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", flavor);
ctx->selected_flavor = flavor;
server = ctx->nfs_mod->rpc_ops->create_server(fc); if (!IS_ERR(server)) return server;
}
/* * Nothing we tried so far worked. At this point, give up if we've * already tried AUTH_UNIX or if the server's list doesn't contain * AUTH_NULL
*/ if (tried_auth_unix || !auth_null_in_list) return server;
/* Last chance! Try AUTH_UNIX */
dfprintk(MOUNT, "NFS: attempting to use auth flavor %u\n", RPC_AUTH_UNIX);
ctx->selected_flavor = RPC_AUTH_UNIX; return ctx->nfs_mod->rpc_ops->create_server(fc);
}
int nfs_try_get_tree(struct fs_context *fc)
{ struct nfs_fs_context *ctx = nfs_fc2context(fc);
if (ctx->need_mount)
ctx->server = nfs_try_mount_request(fc); else
ctx->server = ctx->nfs_mod->rpc_ops->create_server(fc);
/* * The SB_RDONLY flag has been removed from the superblock during * mounts to prevent interference between different filesystems. * Similarly, it is also necessary to ignore the SB_RDONLY flag * during reconfiguration; otherwise, it may also result in the * creation of redundant superblocks when mounting a directory with * different rw and ro flags multiple times.
*/
fc->sb_flags_mask &= ~SB_RDONLY;
/* * Userspace mount programs that send binary options generally send * them populated with default values. We have no way to know which * ones were explicitly specified. Fall back to legacy behavior and * just return success.
*/ if (ctx->skip_reconfig_option_check) return 0;
/* * noac is a special case. It implies -o sync, but that's not * necessarily reflected in the mtab options. reconfigure_super * will clear SB_SYNCHRONOUS if -o sync wasn't specified in the * remount options, so we have to explicitly reset it.
*/ if (ctx->flags & NFS_MOUNT_NOAC) {
fc->sb_flags |= SB_SYNCHRONOUS;
fc->sb_flags_mask |= SB_SYNCHRONOUS;
}
/* compare new mount options with old ones */
ret = nfs_compare_remount_data(nfss, ctx); if (ret) return ret;
int nfs_get_tree_common(struct fs_context *fc)
{ struct nfs_fs_context *ctx = nfs_fc2context(fc); struct super_block *s; int (*compare_super)(struct super_block *, struct fs_context *) = nfs_compare_super; struct nfs_server *server = ctx->server; int error;
ctx->server = NULL; if (IS_ERR(server)) return PTR_ERR(server);
/* * When NFS_MOUNT_UNSHARED is not set, NFS forces the sharing of a * superblock among each filesystem that mounts sub-directories * belonging to a single exported root path. * To prevent interference between different filesystems, the * SB_RDONLY flag should be removed from the superblock.
*/ if (server->flags & NFS_MOUNT_UNSHARED)
compare_super = NULL; else
fc->sb_flags &= ~SB_RDONLY;
if (ctx->clone_data.sb) if (ctx->clone_data.sb->s_flags & SB_SYNCHRONOUS)
fc->sb_flags |= SB_SYNCHRONOUS;
/* Get a superblock - note that we may end up sharing one that already exists */
fc->s_fs_info = server;
s = sget_fc(fc, compare_super, nfs_set_super);
fc->s_fs_info = NULL; if (IS_ERR(s)) {
error = PTR_ERR(s);
nfs_errorf(fc, "NFS: Couldn't get superblock"); goto out_err_nosb;
}
if (s->s_fs_info != server) {
nfs_free_server(server);
server = NULL;
} else {
error = super_setup_bdi_name(s, "%u:%u", MAJOR(server->s_dev),
MINOR(server->s_dev)); if (error) goto error_splat_super;
s->s_bdi->io_pages = server->rpages;
server->super = s;
}
module_param_named(callback_tcpport, nfs_callback_set_tcpport, portnr, 0644);
module_param_named(callback_nr_threads, nfs_callback_nr_threads, ushort, 0644);
MODULE_PARM_DESC(callback_nr_threads, "Number of threads that will be " "assigned to the NFSv4 callback channels.");
module_param(nfs_idmap_cache_timeout, int, 0644);
module_param(nfs4_disable_idmapping, bool, 0644);
module_param_string(nfs4_unique_id, nfs4_client_id_uniquifier,
NFS4_CLIENT_ID_UNIQ_LEN, 0600);
MODULE_PARM_DESC(nfs4_disable_idmapping, "Turn off NFSv4 idmapping when using 'sec=sys'");
module_param(max_session_slots, ushort, 0644);
MODULE_PARM_DESC(max_session_slots, "Maximum number of outstanding NFSv4.1 " "requests the client will negotiate");
module_param(max_session_cb_slots, ushort, 0644);
MODULE_PARM_DESC(max_session_cb_slots, "Maximum number of parallel NFSv4.1 " "callbacks the client will process for a given server");
module_param(send_implementation_id, ushort, 0644);
MODULE_PARM_DESC(send_implementation_id, "Send implementation ID with NFSv4.1 exchange_id");
MODULE_PARM_DESC(nfs4_unique_id, "nfs_client_id4 uniquifier string");
module_param(recover_lost_locks, bool, 0644);
MODULE_PARM_DESC(recover_lost_locks, "If the server reports that a lock might be lost, " "try to recover it risking data corruption.");
module_param_named(delay_retrans, nfs_delay_retrans, short, 0644);
MODULE_PARM_DESC(delay_retrans, "Unless negative, specifies the number of times the NFSv4 " "client retries a request before returning an EAGAIN error, " "after a reply of NFS4ERR_DELAY from the server."); #endif/* CONFIG_NFS_V4 */
Messung V0.5
¤ Dauer der Verarbeitung: 0.5 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.