@@ -157,14 +157,43 @@ const struct fs_parameter_spec ovl_parameter_spec[] = {
157
157
{}
158
158
};
159
159
160
+ static char * ovl_next_opt (char * * s )
161
+ {
162
+ char * sbegin = * s ;
163
+ char * p ;
164
+
165
+ if (sbegin == NULL )
166
+ return NULL ;
167
+
168
+ for (p = sbegin ; * p ; p ++ ) {
169
+ if (* p == '\\' ) {
170
+ p ++ ;
171
+ if (!* p )
172
+ break ;
173
+ } else if (* p == ',' ) {
174
+ * p = '\0' ;
175
+ * s = p + 1 ;
176
+ return sbegin ;
177
+ }
178
+ }
179
+ * s = NULL ;
180
+ return sbegin ;
181
+ }
182
+
183
+ static int ovl_parse_monolithic (struct fs_context * fc , void * data )
184
+ {
185
+ return vfs_parse_monolithic_sep (fc , data , ovl_next_opt );
186
+ }
187
+
160
188
static ssize_t ovl_parse_param_split_lowerdirs (char * str )
161
189
{
162
190
ssize_t nr_layers = 1 , nr_colons = 0 ;
163
191
char * s , * d ;
164
192
165
193
for (s = d = str ;; s ++ , d ++ ) {
166
194
if (* s == '\\' ) {
167
- s ++ ;
195
+ /* keep esc chars in split lowerdir */
196
+ * d ++ = * s ++ ;
168
197
} else if (* s == ':' ) {
169
198
bool next_colon = (* (s + 1 ) == ':' );
170
199
@@ -239,7 +268,7 @@ static void ovl_unescape(char *s)
239
268
}
240
269
}
241
270
242
- static int ovl_mount_dir (const char * name , struct path * path )
271
+ static int ovl_mount_dir (const char * name , struct path * path , bool upper )
243
272
{
244
273
int err = - ENOMEM ;
245
274
char * tmp = kstrdup (name , GFP_KERNEL );
@@ -248,7 +277,7 @@ static int ovl_mount_dir(const char *name, struct path *path)
248
277
ovl_unescape (tmp );
249
278
err = ovl_mount_dir_noesc (tmp , path );
250
279
251
- if (!err && path -> dentry -> d_flags & DCACHE_OP_REAL ) {
280
+ if (!err && upper && path -> dentry -> d_flags & DCACHE_OP_REAL ) {
252
281
pr_err ("filesystem on '%s' not supported as upperdir\n" ,
253
282
tmp );
254
283
path_put_init (path );
@@ -269,7 +298,7 @@ static int ovl_parse_param_upperdir(const char *name, struct fs_context *fc,
269
298
struct path path ;
270
299
char * dup ;
271
300
272
- err = ovl_mount_dir (name , & path );
301
+ err = ovl_mount_dir (name , & path , true );
273
302
if (err )
274
303
return err ;
275
304
@@ -321,12 +350,6 @@ static void ovl_parse_param_drop_lowerdir(struct ovl_fs_context *ctx)
321
350
* Set "/lower1", "/lower2", and "/lower3" as lower layers and
322
351
* "/data1" and "/data2" as data lower layers. Any existing lower
323
352
* layers are replaced.
324
- * (2) lowerdir=:/lower4
325
- * Append "/lower4" to current stack of lower layers. This requires
326
- * that there already is at least one lower layer configured.
327
- * (3) lowerdir=::/lower5
328
- * Append data "/lower5" as data lower layer. This requires that
329
- * there's at least one regular lower layer present.
330
353
*/
331
354
static int ovl_parse_param_lowerdir (const char * name , struct fs_context * fc )
332
355
{
@@ -348,49 +371,9 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
348
371
return 0 ;
349
372
}
350
373
351
- if (strncmp (name , "::" , 2 ) == 0 ) {
352
- /*
353
- * This is a data layer.
354
- * There must be at least one regular lower layer
355
- * specified.
356
- */
357
- if (ctx -> nr == 0 ) {
358
- pr_err ("data lower layers without regular lower layers not allowed" );
359
- return - EINVAL ;
360
- }
361
-
362
- /* Skip the leading "::". */
363
- name += 2 ;
364
- data_layer = true;
365
- /*
366
- * A data layer is automatically an append as there
367
- * must've been at least one regular lower layer.
368
- */
369
- append = true;
370
- } else if (* name == ':' ) {
371
- /*
372
- * This is a regular lower layer.
373
- * If users want to append a layer enforce that they
374
- * have already specified a first layer before. It's
375
- * better to be strict.
376
- */
377
- if (ctx -> nr == 0 ) {
378
- pr_err ("cannot append layer if no previous layer has been specified" );
379
- return - EINVAL ;
380
- }
381
-
382
- /*
383
- * Once a sequence of data layers has started regular
384
- * lower layers are forbidden.
385
- */
386
- if (ctx -> nr_data > 0 ) {
387
- pr_err ("regular lower layers cannot follow data lower layers" );
388
- return - EINVAL ;
389
- }
390
-
391
- /* Skip the leading ":". */
392
- name ++ ;
393
- append = true;
374
+ if (* name == ':' ) {
375
+ pr_err ("cannot append lower layer" );
376
+ return - EINVAL ;
394
377
}
395
378
396
379
dup = kstrdup (name , GFP_KERNEL );
@@ -472,7 +455,7 @@ static int ovl_parse_param_lowerdir(const char *name, struct fs_context *fc)
472
455
l = & ctx -> lower [nr ];
473
456
memset (l , 0 , sizeof (* l ));
474
457
475
- err = ovl_mount_dir_noesc (dup_iter , & l -> path );
458
+ err = ovl_mount_dir (dup_iter , & l -> path , false );
476
459
if (err )
477
460
goto out_put ;
478
461
@@ -682,6 +665,7 @@ static int ovl_reconfigure(struct fs_context *fc)
682
665
}
683
666
684
667
static const struct fs_context_operations ovl_context_ops = {
668
+ .parse_monolithic = ovl_parse_monolithic ,
685
669
.parse_param = ovl_parse_param ,
686
670
.get_tree = ovl_get_tree ,
687
671
.reconfigure = ovl_reconfigure ,
@@ -950,16 +934,23 @@ int ovl_show_options(struct seq_file *m, struct dentry *dentry)
950
934
struct super_block * sb = dentry -> d_sb ;
951
935
struct ovl_fs * ofs = OVL_FS (sb );
952
936
size_t nr , nr_merged_lower = ofs -> numlayer - ofs -> numdatalayer ;
953
- char * * lowerdatadirs = & ofs -> config .lowerdirs [nr_merged_lower ];
954
-
955
- /* lowerdirs[] starts from offset 1 */
956
- seq_printf (m , ",lowerdir=%s" , ofs -> config .lowerdirs [1 ]);
957
- /* dump regular lower layers */
958
- for (nr = 2 ; nr < nr_merged_lower ; nr ++ )
959
- seq_printf (m , ":%s" , ofs -> config .lowerdirs [nr ]);
960
- /* dump data lower layers */
961
- for (nr = 0 ; nr < ofs -> numdatalayer ; nr ++ )
962
- seq_printf (m , "::%s" , lowerdatadirs [nr ]);
937
+
938
+ /*
939
+ * lowerdirs[] starts from offset 1, then
940
+ * >= 0 regular lower layers prefixed with : and
941
+ * >= 0 data-only lower layers prefixed with ::
942
+ *
943
+ * we need to escase comma and space like seq_show_option() does and
944
+ * we also need to escape the colon separator from lowerdir paths.
945
+ */
946
+ seq_puts (m , ",lowerdir=" );
947
+ for (nr = 1 ; nr < ofs -> numlayer ; nr ++ ) {
948
+ if (nr > 1 )
949
+ seq_putc (m , ':' );
950
+ if (nr >= nr_merged_lower )
951
+ seq_putc (m , ':' );
952
+ seq_escape (m , ofs -> config .lowerdirs [nr ], ":, \t\n\\" );
953
+ }
963
954
if (ofs -> config .upperdir ) {
964
955
seq_show_option (m , "upperdir" , ofs -> config .upperdir );
965
956
seq_show_option (m , "workdir" , ofs -> config .workdir );
0 commit comments