Skip to content

Commit c99c217

Browse files
dhowellsAl Viro
authored and
Al Viro
committed
afs: Use fs_context to pass parameters over automount
Alter the AFS automounting code to create and modify an fs_context struct when parameterising a new mount triggered by an AFS mountpoint rather than constructing device name and option strings. Also remove the cell=, vol= and rwpath options as they are then redundant. The reason they existed is because the 'device name' may be derived literally from a mountpoint object in the filesystem, so default cell and parent-type information needed to be passed in by some other method from the automount routines. The vol= option didn't end up being used. Signed-off-by: David Howells <[email protected]> cc: Eric W. Biederman <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 13fcc68 commit c99c217

File tree

3 files changed

+80
-109
lines changed

3 files changed

+80
-109
lines changed

Diff for: fs/afs/internal.h

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ struct pagevec;
3737
struct afs_call;
3838

3939
struct afs_fs_context {
40-
bool rwpath; /* T if the parent should be considered R/W */
4140
bool force; /* T to force cell type */
4241
bool autocell; /* T if set auto mount operation */
4342
bool dyn_root; /* T if dynamic root */

Diff for: fs/afs/mntpt.c

+77-71
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ static DECLARE_DELAYED_WORK(afs_mntpt_expiry_timer, afs_mntpt_expiry_timed_out);
4848

4949
static unsigned long afs_mntpt_expiry_timeout = 10 * 60;
5050

51+
static const char afs_root_volume[] = "root.cell";
52+
5153
/*
5254
* no valid lookup procedure on this sort of dir
5355
*/
@@ -69,108 +71,112 @@ static int afs_mntpt_open(struct inode *inode, struct file *file)
6971
}
7072

7173
/*
72-
* create a vfsmount to be automounted
74+
* Set the parameters for the proposed superblock.
7375
*/
74-
static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
76+
static int afs_mntpt_set_params(struct fs_context *fc, struct dentry *mntpt)
7577
{
76-
struct afs_super_info *as;
77-
struct vfsmount *mnt;
78-
struct afs_vnode *vnode;
79-
struct page *page;
80-
char *devname, *options;
81-
bool rwpath = false;
78+
struct afs_fs_context *ctx = fc->fs_private;
79+
struct afs_super_info *src_as = AFS_FS_S(mntpt->d_sb);
80+
struct afs_vnode *vnode = AFS_FS_I(d_inode(mntpt));
81+
struct afs_cell *cell;
82+
const char *p;
8283
int ret;
8384

84-
_enter("{%pd}", mntpt);
85-
86-
BUG_ON(!d_inode(mntpt));
87-
88-
ret = -ENOMEM;
89-
devname = (char *) get_zeroed_page(GFP_KERNEL);
90-
if (!devname)
91-
goto error_no_devname;
92-
93-
options = (char *) get_zeroed_page(GFP_KERNEL);
94-
if (!options)
95-
goto error_no_options;
85+
if (fc->net_ns != src_as->net_ns) {
86+
put_net(fc->net_ns);
87+
fc->net_ns = get_net(src_as->net_ns);
88+
}
9689

97-
vnode = AFS_FS_I(d_inode(mntpt));
90+
if (src_as->volume && src_as->volume->type == AFSVL_RWVOL) {
91+
ctx->type = AFSVL_RWVOL;
92+
ctx->force = true;
93+
}
94+
if (ctx->cell) {
95+
afs_put_cell(ctx->net, ctx->cell);
96+
ctx->cell = NULL;
97+
}
9898
if (test_bit(AFS_VNODE_PSEUDODIR, &vnode->flags)) {
9999
/* if the directory is a pseudo directory, use the d_name */
100-
static const char afs_root_cell[] = ":root.cell.";
101100
unsigned size = mntpt->d_name.len;
102101

103-
ret = -ENOENT;
104-
if (size < 2 || size > AFS_MAXCELLNAME)
105-
goto error_no_page;
102+
if (size < 2)
103+
return -ENOENT;
106104

105+
p = mntpt->d_name.name;
107106
if (mntpt->d_name.name[0] == '.') {
108-
devname[0] = '%';
109-
memcpy(devname + 1, mntpt->d_name.name + 1, size - 1);
110-
memcpy(devname + size, afs_root_cell,
111-
sizeof(afs_root_cell));
112-
rwpath = true;
113-
} else {
114-
devname[0] = '#';
115-
memcpy(devname + 1, mntpt->d_name.name, size);
116-
memcpy(devname + size + 1, afs_root_cell,
117-
sizeof(afs_root_cell));
107+
size--;
108+
p++;
109+
ctx->type = AFSVL_RWVOL;
110+
ctx->force = true;
118111
}
112+
if (size > AFS_MAXCELLNAME)
113+
return -ENAMETOOLONG;
114+
115+
cell = afs_lookup_cell(ctx->net, p, size, NULL, false);
116+
if (IS_ERR(cell)) {
117+
pr_err("kAFS: unable to lookup cell '%pd'\n", mntpt);
118+
return PTR_ERR(cell);
119+
}
120+
ctx->cell = cell;
121+
122+
ctx->volname = afs_root_volume;
123+
ctx->volnamesz = sizeof(afs_root_volume) - 1;
119124
} else {
120125
/* read the contents of the AFS special symlink */
126+
struct page *page;
121127
loff_t size = i_size_read(d_inode(mntpt));
122128
char *buf;
123129

124-
ret = -EINVAL;
130+
if (src_as->cell)
131+
ctx->cell = afs_get_cell(src_as->cell);
132+
125133
if (size > PAGE_SIZE - 1)
126-
goto error_no_page;
134+
return -EINVAL;
127135

128136
page = read_mapping_page(d_inode(mntpt)->i_mapping, 0, NULL);
129-
if (IS_ERR(page)) {
130-
ret = PTR_ERR(page);
131-
goto error_no_page;
132-
}
137+
if (IS_ERR(page))
138+
return PTR_ERR(page);
133139

134140
if (PageError(page)) {
135141
ret = afs_bad(AFS_FS_I(d_inode(mntpt)), afs_file_error_mntpt);
136-
goto error;
142+
put_page(page);
143+
return ret;
137144
}
138145

139-
buf = kmap_atomic(page);
140-
memcpy(devname, buf, size);
141-
kunmap_atomic(buf);
146+
buf = kmap(page);
147+
ret = vfs_parse_fs_string(fc, "source", buf, size);
148+
kunmap(page);
142149
put_page(page);
143-
page = NULL;
150+
if (ret < 0)
151+
return ret;
144152
}
145153

146-
/* work out what options we want */
147-
as = AFS_FS_S(mntpt->d_sb);
148-
if (as->cell) {
149-
memcpy(options, "cell=", 5);
150-
strcpy(options + 5, as->cell->name);
151-
if ((as->volume && as->volume->type == AFSVL_RWVOL) || rwpath)
152-
strcat(options, ",rwpath");
153-
}
154+
return 0;
155+
}
154156

155-
/* try and do the mount */
156-
_debug("--- attempting mount %s -o %s ---", devname, options);
157-
mnt = vfs_submount(mntpt, &afs_fs_type, devname, options);
158-
_debug("--- mount result %p ---", mnt);
157+
/*
158+
* create a vfsmount to be automounted
159+
*/
160+
static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt)
161+
{
162+
struct fs_context *fc;
163+
struct vfsmount *mnt;
164+
int ret;
159165

160-
free_page((unsigned long) devname);
161-
free_page((unsigned long) options);
162-
_leave(" = %p", mnt);
163-
return mnt;
166+
BUG_ON(!d_inode(mntpt));
164167

165-
error:
166-
put_page(page);
167-
error_no_page:
168-
free_page((unsigned long) options);
169-
error_no_options:
170-
free_page((unsigned long) devname);
171-
error_no_devname:
172-
_leave(" = %d", ret);
173-
return ERR_PTR(ret);
168+
fc = fs_context_for_submount(&afs_fs_type, mntpt);
169+
if (IS_ERR(fc))
170+
return ERR_CAST(fc);
171+
172+
ret = afs_mntpt_set_params(fc, mntpt);
173+
if (!ret)
174+
mnt = fc_mount(fc);
175+
else
176+
mnt = ERR_PTR(ret);
177+
178+
put_fs_context(fc);
179+
return mnt;
174180
}
175181

176182
/*

Diff for: fs/afs/super.c

+3-37
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,14 @@ static atomic_t afs_count_active_inodes;
6666

6767
enum afs_param {
6868
Opt_autocell,
69-
Opt_cell,
7069
Opt_dyn,
71-
Opt_rwpath,
7270
Opt_source,
73-
Opt_vol,
7471
};
7572

7673
static const struct fs_parameter_spec afs_param_specs[] = {
7774
fsparam_flag ("autocell", Opt_autocell),
78-
fsparam_string("cell", Opt_cell),
7975
fsparam_flag ("dyn", Opt_dyn),
80-
fsparam_flag ("rwpath", Opt_rwpath),
8176
fsparam_string("source", Opt_source),
82-
fsparam_string("vol", Opt_vol),
8377
{}
8478
};
8579

@@ -202,8 +196,8 @@ static int afs_show_options(struct seq_file *m, struct dentry *root)
202196
*
203197
* This can be one of the following:
204198
* "%[cell:]volume[.]" R/W volume
205-
* "#[cell:]volume[.]" R/O or R/W volume (rwpath=0),
206-
* or R/W (rwpath=1) volume
199+
* "#[cell:]volume[.]" R/O or R/W volume (R/O parent),
200+
* or R/W (R/W parent) volume
207201
* "%[cell:]volume.readonly" R/O volume
208202
* "#[cell:]volume.readonly" R/O volume
209203
* "%[cell:]volume.backup" Backup volume
@@ -234,9 +228,7 @@ static int afs_parse_source(struct fs_context *fc, struct fs_parameter *param)
234228
}
235229

236230
/* determine the type of volume we're looking for */
237-
ctx->type = AFSVL_ROVOL;
238-
ctx->force = false;
239-
if (ctx->rwpath || name[0] == '%') {
231+
if (name[0] == '%') {
240232
ctx->type = AFSVL_RWVOL;
241233
ctx->force = true;
242234
}
@@ -305,29 +297,13 @@ static int afs_parse_param(struct fs_context *fc, struct fs_parameter *param)
305297
{
306298
struct fs_parse_result result;
307299
struct afs_fs_context *ctx = fc->fs_private;
308-
struct afs_cell *cell;
309300
int opt;
310301

311302
opt = fs_parse(fc, &afs_fs_parameters, param, &result);
312303
if (opt < 0)
313304
return opt;
314305

315306
switch (opt) {
316-
case Opt_cell:
317-
if (param->size <= 0)
318-
return -EINVAL;
319-
if (param->size > AFS_MAXCELLNAME)
320-
return -ENAMETOOLONG;
321-
322-
rcu_read_lock();
323-
cell = afs_lookup_cell_rcu(ctx->net, param->string, param->size);
324-
rcu_read_unlock();
325-
if (IS_ERR(cell))
326-
return PTR_ERR(cell);
327-
afs_put_cell(ctx->net, ctx->cell);
328-
ctx->cell = cell;
329-
break;
330-
331307
case Opt_source:
332308
return afs_parse_source(fc, param);
333309

@@ -339,13 +315,6 @@ static int afs_parse_param(struct fs_context *fc, struct fs_parameter *param)
339315
ctx->dyn_root = true;
340316
break;
341317

342-
case Opt_rwpath:
343-
ctx->rwpath = true;
344-
break;
345-
346-
case Opt_vol:
347-
return invalf(fc, "'vol' param is obsolete");
348-
349318
default:
350319
return -EINVAL;
351320
}
@@ -616,9 +585,6 @@ static int afs_init_fs_context(struct fs_context *fc)
616585
struct afs_fs_context *ctx;
617586
struct afs_cell *cell;
618587

619-
if (current->nsproxy->net_ns != &init_net)
620-
return -EINVAL;
621-
622588
ctx = kzalloc(sizeof(struct afs_fs_context), GFP_KERNEL);
623589
if (!ctx)
624590
return -ENOMEM;

0 commit comments

Comments
 (0)