Skip to content

Commit 819829f

Browse files
committed
ovl: refactor layer parsing helpers
In preparation for new mount options to add lowerdirs one by one, generalize ovl_parse_param_upperdir() into helper ovl_parse_layer() that will be used for parsing a single lower layers. Suggested-by: Miklos Szeredi <[email protected]> Link: https://lore.kernel.org/r/CAJfpegt7VC94KkRtb1dfHG8+4OzwPBLYqhtc8=QFUxpFJE+=RQ@mail.gmail.com/ Signed-off-by: Amir Goldstein <[email protected]>
1 parent 0cea4c0 commit 819829f

File tree

1 file changed

+67
-54
lines changed

1 file changed

+67
-54
lines changed

fs/overlayfs/params.c

Lines changed: 67 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ module_param_named(metacopy, ovl_metacopy_def, bool, 0644);
4343
MODULE_PARM_DESC(metacopy,
4444
"Default to on or off for the metadata only copy up feature");
4545

46-
enum {
46+
enum ovl_opt {
4747
Opt_lowerdir,
4848
Opt_upperdir,
4949
Opt_workdir,
@@ -238,19 +238,8 @@ static int ovl_mount_dir_noesc(const char *name, struct path *path)
238238
pr_err("failed to resolve '%s': %i\n", name, err);
239239
goto out;
240240
}
241-
err = -EINVAL;
242-
if (ovl_dentry_weird(path->dentry)) {
243-
pr_err("filesystem on '%s' not supported\n", name);
244-
goto out_put;
245-
}
246-
if (!d_is_dir(path->dentry)) {
247-
pr_err("'%s' not a directory\n", name);
248-
goto out_put;
249-
}
250241
return 0;
251242

252-
out_put:
253-
path_put_init(path);
254243
out:
255244
return err;
256245
}
@@ -268,68 +257,90 @@ static void ovl_unescape(char *s)
268257
}
269258
}
270259

271-
static int ovl_mount_dir(const char *name, struct path *path, bool upper)
260+
static int ovl_mount_dir(const char *name, struct path *path)
272261
{
273262
int err = -ENOMEM;
274263
char *tmp = kstrdup(name, GFP_KERNEL);
275264

276265
if (tmp) {
277266
ovl_unescape(tmp);
278267
err = ovl_mount_dir_noesc(tmp, path);
279-
280-
if (!err && upper && path->dentry->d_flags & DCACHE_OP_REAL) {
281-
pr_err("filesystem on '%s' not supported as upperdir\n",
282-
tmp);
283-
path_put_init(path);
284-
err = -EINVAL;
285-
}
286268
kfree(tmp);
287269
}
288270
return err;
289271
}
290272

291-
static int ovl_parse_param_upperdir(const char *name, struct fs_context *fc,
292-
bool workdir)
273+
static int ovl_mount_dir_check(struct fs_context *fc, const struct path *path,
274+
enum ovl_opt layer, const char *name, bool upper)
293275
{
294-
int err;
295-
struct ovl_fs *ofs = fc->s_fs_info;
296-
struct ovl_config *config = &ofs->config;
297-
struct ovl_fs_context *ctx = fc->fs_private;
298-
struct path path;
299-
char *dup;
276+
if (ovl_dentry_weird(path->dentry))
277+
return invalfc(fc, "filesystem on %s not supported", name);
300278

301-
err = ovl_mount_dir(name, &path, true);
302-
if (err)
303-
return err;
279+
if (!d_is_dir(path->dentry))
280+
return invalfc(fc, "%s is not a directory", name);
304281

305282
/*
306283
* Check whether upper path is read-only here to report failures
307284
* early. Don't forget to recheck when the superblock is created
308285
* as the mount attributes could change.
309286
*/
310-
if (__mnt_is_readonly(path.mnt)) {
311-
path_put(&path);
312-
return -EINVAL;
287+
if (upper) {
288+
if (path->dentry->d_flags & DCACHE_OP_REAL)
289+
return invalfc(fc, "filesystem on %s not supported as upperdir", name);
290+
if (__mnt_is_readonly(path->mnt))
291+
return invalfc(fc, "filesystem on %s is read-only", name);
313292
}
293+
return 0;
294+
}
314295

315-
dup = kstrdup(name, GFP_KERNEL);
316-
if (!dup) {
317-
path_put(&path);
318-
return -ENOMEM;
319-
}
296+
static void ovl_add_layer(struct fs_context *fc, enum ovl_opt layer,
297+
struct path *path, char **pname)
298+
{
299+
struct ovl_fs *ofs = fc->s_fs_info;
300+
struct ovl_config *config = &ofs->config;
301+
struct ovl_fs_context *ctx = fc->fs_private;
320302

321-
if (workdir) {
322-
kfree(config->workdir);
323-
config->workdir = dup;
324-
path_put(&ctx->work);
325-
ctx->work = path;
326-
} else {
327-
kfree(config->upperdir);
328-
config->upperdir = dup;
329-
path_put(&ctx->upper);
330-
ctx->upper = path;
303+
switch (layer) {
304+
case Opt_workdir:
305+
swap(config->workdir, *pname);
306+
swap(ctx->work, *path);
307+
break;
308+
case Opt_upperdir:
309+
swap(config->upperdir, *pname);
310+
swap(ctx->upper, *path);
311+
break;
312+
default:
313+
WARN_ON(1);
331314
}
332-
return 0;
315+
}
316+
317+
static int ovl_parse_layer(struct fs_context *fc, struct fs_parameter *param,
318+
enum ovl_opt layer)
319+
{
320+
char *name = kstrdup(param->string, GFP_KERNEL);
321+
bool upper = (layer == Opt_upperdir || layer == Opt_workdir);
322+
struct path path;
323+
int err;
324+
325+
if (!name)
326+
return -ENOMEM;
327+
328+
err = ovl_mount_dir(name, &path);
329+
if (err)
330+
goto out_free;
331+
332+
err = ovl_mount_dir_check(fc, &path, layer, name, upper);
333+
if (err)
334+
goto out_put;
335+
336+
/* Store the user provided path string in ctx to show in mountinfo */
337+
ovl_add_layer(fc, layer, &path, &name);
338+
339+
out_put:
340+
path_put(&path);
341+
out_free:
342+
kfree(name);
343+
return err;
333344
}
334345

335346
static void ovl_reset_lowerdirs(struct ovl_fs_context *ctx)
@@ -417,7 +428,11 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
417428
for (nr = 0; nr < nr_lower; nr++, l++) {
418429
memset(l, 0, sizeof(*l));
419430

420-
err = ovl_mount_dir(iter, &l->path, false);
431+
err = ovl_mount_dir(iter, &l->path);
432+
if (err)
433+
goto out_put;
434+
435+
err = ovl_mount_dir_check(fc, &l->path, Opt_lowerdir, iter, false);
421436
if (err)
422437
goto out_put;
423438

@@ -505,10 +520,8 @@ static int ovl_parse_param(struct fs_context *fc, struct fs_parameter *param)
505520
err = ovl_parse_param_lowerdir(param->string, fc);
506521
break;
507522
case Opt_upperdir:
508-
fallthrough;
509523
case Opt_workdir:
510-
err = ovl_parse_param_upperdir(param->string, fc,
511-
(Opt_workdir == opt));
524+
err = ovl_parse_layer(fc, param, opt);
512525
break;
513526
case Opt_default_permissions:
514527
config->default_permissions = true;

0 commit comments

Comments
 (0)