hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/fs/afs/mntpt.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /* mountpoint management
23 *
34 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
45 * Written by David Howells (dhowells@redhat.com)
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License
8
- * as published by the Free Software Foundation; either version
9
- * 2 of the License, or (at your option) any later version.
106 */
117
128 #include <linux/kernel.h>
....@@ -17,6 +13,7 @@
1713 #include <linux/mount.h>
1814 #include <linux/namei.h>
1915 #include <linux/gfp.h>
16
+#include <linux/fs_context.h>
2017 #include "internal.h"
2118
2219
....@@ -35,7 +32,6 @@
3532 .lookup = afs_mntpt_lookup,
3633 .readlink = page_readlink,
3734 .getattr = afs_getattr,
38
- .listxattr = afs_listxattr,
3935 };
4036
4137 const struct inode_operations afs_autocell_inode_operations = {
....@@ -46,6 +42,8 @@
4642 static DECLARE_DELAYED_WORK(afs_mntpt_expiry_timer, afs_mntpt_expiry_timed_out);
4743
4844 static unsigned long afs_mntpt_expiry_timeout = 10 * 60;
45
+
46
+static const char afs_root_volume[] = "root.cell";
4947
5048 /*
5149 * no valid lookup procedure on this sort of dir
....@@ -68,107 +66,114 @@
6866 }
6967
7068 /*
69
+ * Set the parameters for the proposed superblock.
70
+ */
71
+static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
72
+{
73
+ struct afs_fs_context *ctx = fc->fs_private;
74
+ struct afs_super_info *src_as = AFS_FS_S(mntpt->d_sb);
75
+ struct afs_vnode *vnode = AFS_FS_I(d_inode(mntpt));
76
+ struct afs_cell *cell;
77
+ const char *p;
78
+ int ret;
79
+
80
+ if (fc->net_ns != src_as->net_ns) {
81
+ put_net(fc->net_ns);
82
+ fc->net_ns = get_net(src_as->net_ns);
83
+ }
84
+
85
+ if (src_as->volume && src_as->volume->type == AFSVL_RWVOL) {
86
+ ctx->type = AFSVL_RWVOL;
87
+ ctx->force = true;
88
+ }
89
+ if (ctx->cell) {
90
+ afs_unuse_cell(ctx->net, ctx->cell, afs_cell_trace_unuse_mntpt);
91
+ ctx->cell = NULL;
92
+ }
93
+ if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) {
94
+ /* if the directory is a pseudo directory, use the d_name */
95
+ unsigned size = mntpt->d_name.len;
96
+
97
+ if (size < 2)
98
+ return -ENOENT;
99
+
100
+ p = mntpt->d_name.name;
101
+ if (mntpt->d_name.name[0] == '.') {
102
+ size--;
103
+ p++;
104
+ ctx->type = AFSVL_RWVOL;
105
+ ctx->force = true;
106
+ }
107
+ if (size > AFS_MAXCELLNAME)
108
+ return -ENAMETOOLONG;
109
+
110
+ cell = afs_lookup_cell(ctx->net, p, size, NULL, false);
111
+ if (IS_ERR(cell)) {
112
+ pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt);
113
+ return PTR_ERR(cell);
114
+ }
115
+ ctx->cell = cell;
116
+
117
+ ctx->volname = afs_root_volume;
118
+ ctx->volnamesz = sizeof(afs_root_volume) - 1;
119
+ } else {
120
+ /* read the contents of the AFS special symlink */
121
+ struct page *page;
122
+ loff_t size = i_size_read(d_inode(mntpt));
123
+ char *buf;
124
+
125
+ if (src_as->cell)
126
+ ctx->cell = afs_use_cell(src_as->cell, afs_cell_trace_use_mntpt);
127
+
128
+ if (size < 2 || size > PAGE_SIZE - 1)
129
+ return -EINVAL;
130
+
131
+ page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
132
+ if (IS_ERR(page))
133
+ return PTR_ERR(page);
134
+
135
+ if (PageError(page)) {
136
+ ret = afs_bad(AFS_FS_I(d_inode(mntpt)), afs_file_error_mntpt);
137
+ put_page(page);
138
+ return ret;
139
+ }
140
+
141
+ buf = kmap(page);
142
+ ret = -EINVAL;
143
+ if (buf[size - 1] == '.')
144
+ ret = vfs_parse_fs_string(fc, "source", buf, size - 1);
145
+ kunmap(page);
146
+ put_page(page);
147
+ if (ret < 0)
148
+ return ret;
149
+ }
150
+
151
+ return 0;
152
+}
153
+
154
+/*
71155 * create a vfsmount to be automounted
72156 */
73157 static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
74158 {
75
- struct afs_super_info *as;
159
+ struct fs_context *fc;
76160 struct vfsmount *mnt;
77
- struct afs_vnode *vnode;
78
- struct page *page;
79
- char *devname, *options;
80
- bool rwpath = false;
81161 int ret;
82
-
83
- _enter("{%pd}", mntpt);
84162
85163 BUG_ON(!d_inode(mntpt));
86164
87
- ret = -ENOMEM;
88
- devname = (char *) get_zeroed_page(GFP_KERNEL);
89
- if (!devname)
90
- goto error_no_devname;
165
+ fc = fs_context_for_submount(&afs_fs_type, mntpt);
166
+ if (IS_ERR(fc))
167
+ return ERR_CAST(fc);
91168
92
- options = (char *) get_zeroed_page(GFP_KERNEL);
93
- if (!options)
94
- goto error_no_options;
169
+ ret = afs_mntpt_set_params(fc, mntpt);
170
+ if (!ret)
171
+ mnt = fc_mount(fc);
172
+ else
173
+ mnt = ERR_PTR(ret);
95174
96
- vnode = AFS_FS_I(d_inode(mntpt));
97
- if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) {
98
- /* if the directory is a pseudo directory, use the d_name */
99
- static const char afs_root_cell[] = ":root.cell.";
100
- unsigned size = mntpt->d_name.len;
101
-
102
- ret = -ENOENT;
103
- if (size < 2 || size > AFS_MAXCELLNAME)
104
- goto error_no_page;
105
-
106
- if (mntpt->d_name.name[0] == '.') {
107
- devname[0] = '%';
108
- memcpy(devname + 1, mntpt->d_name.name + 1, size - 1);
109
- memcpy(devname + size, afs_root_cell,
110
- sizeof(afs_root_cell));
111
- rwpath = true;
112
- } else {
113
- devname[0] = '#';
114
- memcpy(devname + 1, mntpt->d_name.name, size);
115
- memcpy(devname + size + 1, afs_root_cell,
116
- sizeof(afs_root_cell));
117
- }
118
- } else {
119
- /* read the contents of the AFS special symlink */
120
- loff_t size = i_size_read(d_inode(mntpt));
121
- char *buf;
122
-
123
- ret = -EINVAL;
124
- if (size > PAGE_SIZE - 1)
125
- goto error_no_page;
126
-
127
- page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
128
- if (IS_ERR(page)) {
129
- ret = PTR_ERR(page);
130
- goto error_no_page;
131
- }
132
-
133
- ret = -EIO;
134
- if (PageError(page))
135
- goto error;
136
-
137
- buf = kmap_atomic(page);
138
- memcpy(devname, buf, size);
139
- kunmap_atomic(buf);
140
- put_page(page);
141
- page = NULL;
142
- }
143
-
144
- /* work out what options we want */
145
- as = AFS_FS_S(mntpt->d_sb);
146
- if (as->cell) {
147
- memcpy(options, "cell=", 5);
148
- strcpy(options + 5, as->cell->name);
149
- if ((as->volume && as->volume->type == AFSVL_RWVOL) || rwpath)
150
- strcat(options, ",rwpath");
151
- }
152
-
153
- /* try and do the mount */
154
- _debug("--- attempting mount %s -o %s ---", devname, options);
155
- mnt = vfs_submount(mntpt, &afs_fs_type, devname, options);
156
- _debug("--- mount result %p ---", mnt);
157
-
158
- free_page((unsigned long) devname);
159
- free_page((unsigned long) options);
160
- _leave(" = %p", mnt);
175
+ put_fs_context(fc);
161176 return mnt;
162
-
163
-error:
164
- put_page(page);
165
-error_no_page:
166
- free_page((unsigned long) options);
167
-error_no_options:
168
- free_page((unsigned long) devname);
169
-error_no_devname:
170
- _leave(" = %d", ret);
171
- return ERR_PTR(ret);
172177 }
173178
174179 /*