~ubuntu-branches/ubuntu/vivid/aufs/vivid

« back to all changes in this revision

Viewing changes to fs/aufs25/hin_or_dlgt.c

  • Committer: Bazaar Package Importer
  • Author(s): Julian Andres Klode
  • Date: 2008-05-06 18:35:50 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080506183550-0b6c974kkgc46oeh
Tags: 0+20080506-1
* New upstream release, supports Kernel 2.6.25 (Closes: #479717)
* Fix building with older Kernels (Closes: #475042)
* Update the patches 01, 04 and 07 to also patch fs/aufs25

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2008 Junjiro Okajima
 
3
 *
 
4
 * This program, aufs is free software; you can redistribute it and/or modify
 
5
 * it under the terms of the GNU General Public License as published by
 
6
 * the Free Software Foundation; either version 2 of the License, or
 
7
 * (at your option) any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License
 
15
 * along with this program; if not, write to the Free Software
 
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
17
 */
 
18
 
 
19
/*
 
20
 * sub-routines for vfs in hinotify or dlgt mode
 
21
 *
 
22
 * $Id: hin_or_dlgt.c,v 1.2 2008/04/21 02:00:37 sfjro Exp $
 
23
 */
 
24
// I'm going to slightly mad
 
25
 
 
26
#include <linux/uaccess.h>
 
27
#include "aufs.h"
 
28
 
 
29
#if !defined(CONFIG_AUFS_HINOTIFY) && !defined(CONFIG_AUFS_DLGT)
 
30
#error mis-configuraion or Makefile
 
31
#endif
 
32
 
 
33
/* ---------------------------------------------------------------------- */
 
34
 
 
35
struct permission_args {
 
36
        int *errp;
 
37
        struct inode *inode;
 
38
        int mask;
 
39
        struct nameidata *nd;
 
40
};
 
41
 
 
42
static void call_permission(void *args)
 
43
{
 
44
        struct permission_args *a = args;
 
45
        *a->errp = do_vfsub_permission(a->inode, a->mask, a->nd);
 
46
}
 
47
 
 
48
int vfsub_permission(struct inode *inode, int mask, struct nameidata *nd,
 
49
                     int dlgt)
 
50
{
 
51
        if (!dlgt)
 
52
                return do_vfsub_permission(inode, mask, nd);
 
53
        else {
 
54
                int err, wkq_err;
 
55
                struct permission_args args = {
 
56
                        .errp   = &err,
 
57
                        .inode  = inode,
 
58
                        .mask   = mask,
 
59
                        .nd     = nd
 
60
                };
 
61
                wkq_err = au_wkq_wait(call_permission, &args, /*dlgt*/1);
 
62
                if (unlikely(wkq_err))
 
63
                        err = wkq_err;
 
64
                return err;
 
65
        }
 
66
}
 
67
 
 
68
/* ---------------------------------------------------------------------- */
 
69
 
 
70
struct create_args {
 
71
        int *errp;
 
72
        struct inode *dir;
 
73
        struct dentry *dentry;
 
74
        int mode;
 
75
        struct nameidata *nd;
 
76
};
 
77
 
 
78
static void call_create(void *args)
 
79
{
 
80
        struct create_args *a = args;
 
81
        *a->errp = do_vfsub_create(a->dir, a->dentry, a->mode, a->nd);
 
82
}
 
83
 
 
84
int vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
 
85
                 struct nameidata *nd, int dlgt)
 
86
{
 
87
        if (!dlgt)
 
88
                return do_vfsub_create(dir, dentry, mode, nd);
 
89
        else {
 
90
                int err, wkq_err;
 
91
                struct create_args args = {
 
92
                        .errp   = &err,
 
93
                        .dir    = dir,
 
94
                        .dentry = dentry,
 
95
                        .mode   = mode,
 
96
                        .nd     = nd
 
97
                };
 
98
                wkq_err = au_wkq_wait(call_create, &args, /*dlgt*/1);
 
99
                if (unlikely(wkq_err))
 
100
                        err = wkq_err;
 
101
                return err;
 
102
        }
 
103
}
 
104
 
 
105
struct symlink_args {
 
106
        int *errp;
 
107
        struct inode *dir;
 
108
        struct dentry *dentry;
 
109
        const char *symname;
 
110
        int mode;
 
111
};
 
112
 
 
113
static void call_symlink(void *args)
 
114
{
 
115
        struct symlink_args *a = args;
 
116
        *a->errp = do_vfsub_symlink(a->dir, a->dentry, a->symname, a->mode);
 
117
}
 
118
 
 
119
int vfsub_symlink(struct inode *dir, struct dentry *dentry, const char *symname,
 
120
                  int mode, int dlgt)
 
121
{
 
122
        if (!dlgt)
 
123
                return do_vfsub_symlink(dir, dentry, symname, mode);
 
124
        else {
 
125
                int err, wkq_err;
 
126
                struct symlink_args args = {
 
127
                        .errp           = &err,
 
128
                        .dir            = dir,
 
129
                        .dentry         = dentry,
 
130
                        .symname        = symname,
 
131
                        .mode           = mode
 
132
                };
 
133
                wkq_err = au_wkq_wait(call_symlink, &args, /*dlgt*/1);
 
134
                if (unlikely(wkq_err))
 
135
                        err = wkq_err;
 
136
                return err;
 
137
        }
 
138
}
 
139
 
 
140
struct mknod_args {
 
141
        int *errp;
 
142
        struct inode *dir;
 
143
        struct dentry *dentry;
 
144
        int mode;
 
145
        dev_t dev;
 
146
};
 
147
 
 
148
static void call_mknod(void *args)
 
149
{
 
150
        struct mknod_args *a = args;
 
151
        *a->errp = do_vfsub_mknod(a->dir, a->dentry, a->mode, a->dev);
 
152
}
 
153
 
 
154
int vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev,
 
155
                int dlgt)
 
156
{
 
157
        if (!dlgt)
 
158
                return do_vfsub_mknod(dir, dentry, mode, dev);
 
159
        else {
 
160
                int err, wkq_err;
 
161
                struct mknod_args args = {
 
162
                        .errp   = &err,
 
163
                        .dir    = dir,
 
164
                        .dentry = dentry,
 
165
                        .mode   = mode,
 
166
                        .dev    = dev
 
167
                };
 
168
                wkq_err = au_wkq_wait(call_mknod, &args, /*dlgt*/1);
 
169
                if (unlikely(wkq_err))
 
170
                        err = wkq_err;
 
171
                return err;
 
172
        }
 
173
}
 
174
 
 
175
struct mkdir_args {
 
176
        int *errp;
 
177
        struct inode *dir;
 
178
        struct dentry *dentry;
 
179
        int mode;
 
180
};
 
181
 
 
182
static void call_mkdir(void *args)
 
183
{
 
184
        struct mkdir_args *a = args;
 
185
        *a->errp = do_vfsub_mkdir(a->dir, a->dentry, a->mode);
 
186
}
 
187
 
 
188
int vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode, int dlgt)
 
189
{
 
190
        if (!dlgt)
 
191
                return do_vfsub_mkdir(dir, dentry, mode);
 
192
        else {
 
193
                int err, wkq_err;
 
194
                struct mkdir_args args = {
 
195
                        .errp   = &err,
 
196
                        .dir    = dir,
 
197
                        .dentry = dentry,
 
198
                        .mode   = mode
 
199
                };
 
200
                wkq_err = au_wkq_wait(call_mkdir, &args, /*dlgt*/1);
 
201
                if (unlikely(wkq_err))
 
202
                        err = wkq_err;
 
203
                return err;
 
204
        }
 
205
}
 
206
 
 
207
/* ---------------------------------------------------------------------- */
 
208
 
 
209
struct link_args {
 
210
        int *errp;
 
211
        struct inode *dir;
 
212
        struct dentry *src_dentry, *dentry;
 
213
};
 
214
 
 
215
static void call_link(void *args)
 
216
{
 
217
        struct link_args *a = args;
 
218
        *a->errp = do_vfsub_link(a->src_dentry, a->dir, a->dentry);
 
219
}
 
220
 
 
221
int vfsub_link(struct dentry *src_dentry, struct inode *dir,
 
222
               struct dentry *dentry, int dlgt)
 
223
{
 
224
        if (!dlgt)
 
225
                return do_vfsub_link(src_dentry, dir, dentry);
 
226
        else {
 
227
                int err, wkq_err;
 
228
                struct link_args args = {
 
229
                        .errp           = &err,
 
230
                        .src_dentry     = src_dentry,
 
231
                        .dir            = dir,
 
232
                        .dentry         = dentry
 
233
                };
 
234
                wkq_err = au_wkq_wait(call_link, &args, /*dlgt*/1);
 
235
                if (unlikely(wkq_err))
 
236
                        err = wkq_err;
 
237
                return err;
 
238
        }
 
239
}
 
240
 
 
241
struct rename_args {
 
242
        int *errp;
 
243
        struct inode *src_dir, *dir;
 
244
        struct dentry *src_dentry, *dentry;
 
245
        struct vfsub_args *vargs;
 
246
};
 
247
 
 
248
static void call_rename(void *args)
 
249
{
 
250
        struct rename_args *a = args;
 
251
        vfsub_ignore(a->vargs);
 
252
        *a->errp = do_vfsub_rename(a->src_dir, a->src_dentry, a->dir,
 
253
                                   a->dentry);
 
254
        if (unlikely(*a->errp))
 
255
                vfsub_unignore(a->vargs);
 
256
}
 
257
 
 
258
int vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
 
259
                 struct inode *dir, struct dentry *dentry,
 
260
                 struct vfsub_args *vargs)
 
261
{
 
262
        int err;
 
263
 
 
264
        if (!vfsub_ftest(vargs->flags, DLGT)) {
 
265
                vfsub_ignore(vargs);
 
266
                err = do_vfsub_rename(src_dir, src_dentry, dir, dentry);
 
267
                if (unlikely(err))
 
268
                        vfsub_unignore(vargs);
 
269
        } else {
 
270
                int wkq_err;
 
271
                struct rename_args args = {
 
272
                        .errp           = &err,
 
273
                        .src_dir        = src_dir,
 
274
                        .src_dentry     = src_dentry,
 
275
                        .dir            = dir,
 
276
                        .dentry         = dentry,
 
277
                        .vargs          = vargs
 
278
                };
 
279
                wkq_err = au_wkq_wait(call_rename, &args, /*dlgt*/1);
 
280
                if (unlikely(wkq_err))
 
281
                        err = wkq_err;
 
282
        }
 
283
        return err;
 
284
}
 
285
 
 
286
struct rmdir_args {
 
287
        int *errp;
 
288
        struct inode *dir;
 
289
        struct dentry *dentry;
 
290
        struct vfsub_args *vargs;
 
291
};
 
292
 
 
293
static void call_rmdir(void *args)
 
294
{
 
295
        struct rmdir_args *a = args;
 
296
        vfsub_ignore(a->vargs);
 
297
        *a->errp = do_vfsub_rmdir(a->dir, a->dentry);
 
298
        if (unlikely(*a->errp))
 
299
                vfsub_unignore(a->vargs);
 
300
}
 
301
 
 
302
int vfsub_rmdir(struct inode *dir, struct dentry *dentry,
 
303
                struct vfsub_args *vargs)
 
304
{
 
305
        int err;
 
306
 
 
307
        if (!vfsub_ftest(vargs->flags, DLGT)) {
 
308
                vfsub_ignore(vargs);
 
309
                err = do_vfsub_rmdir(dir, dentry);
 
310
                if (unlikely(err))
 
311
                        vfsub_unignore(vargs);
 
312
        } else {
 
313
                int wkq_err;
 
314
                struct rmdir_args args = {
 
315
                        .errp   = &err,
 
316
                        .dir    = dir,
 
317
                        .dentry = dentry,
 
318
                        .vargs  = vargs
 
319
                };
 
320
                wkq_err = au_wkq_wait(call_rmdir, &args, /*dlgt*/1);
 
321
                if (unlikely(wkq_err))
 
322
                        err = wkq_err;
 
323
        }
 
324
        return err;
 
325
}
 
326
 
 
327
/* ---------------------------------------------------------------------- */
 
328
 
 
329
struct read_args {
 
330
        ssize_t *errp;
 
331
        struct file *file;
 
332
        union {
 
333
                void *kbuf;
 
334
                char __user *ubuf;
 
335
        };
 
336
        size_t count;
 
337
        loff_t *ppos;
 
338
};
 
339
 
 
340
static void call_read_k(void *args)
 
341
{
 
342
        struct read_args *a = args;
 
343
        LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
 
344
                  AuDLNPair(a->file->f_dentry), (unsigned long)a->count,
 
345
                  *a->ppos);
 
346
        *a->errp = do_vfsub_read_k(a->file, a->kbuf, a->count, a->ppos);
 
347
}
 
348
 
 
349
ssize_t vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
 
350
                     loff_t *ppos, int dlgt)
 
351
{
 
352
        if (!dlgt)
 
353
                return do_vfsub_read_u(file, ubuf, count, ppos);
 
354
        else {
 
355
                int wkq_err;
 
356
                ssize_t err, read;
 
357
                struct read_args args = {
 
358
                        .errp   = &err,
 
359
                        .file   = file,
 
360
                        .count  = count,
 
361
                        .ppos   = ppos
 
362
                };
 
363
 
 
364
                if (unlikely(!count))
 
365
                        return 0;
 
366
 
 
367
                /*
 
368
                 * workaround an application bug.
 
369
                 * generally, read(2) or write(2) may return the value shorter
 
370
                 * than requested. But many applications don't support it,
 
371
                 * for example bash.
 
372
                 */
 
373
                err = -ENOMEM;
 
374
                if (args.count > PAGE_SIZE)
 
375
                        args.count = PAGE_SIZE;
 
376
                args.kbuf = kmalloc(args.count, GFP_TEMPORARY);
 
377
                if (unlikely(!args.kbuf))
 
378
                        goto out;
 
379
 
 
380
                read = 0;
 
381
                do {
 
382
                        wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1);
 
383
                        if (unlikely(wkq_err))
 
384
                                err = wkq_err;
 
385
                        if (unlikely(err > 0
 
386
                                     && copy_to_user(ubuf, args.kbuf, err))) {
 
387
                                err = -EFAULT;
 
388
                                goto out_free;
 
389
                        } else if (!err)
 
390
                                break;
 
391
                        else if (unlikely(err < 0))
 
392
                                goto out_free;
 
393
                        count -= err;
 
394
                        /* do not read too much because of file i/o pointer */
 
395
                        if (count < args.count)
 
396
                                args.count = count;
 
397
                        ubuf += err;
 
398
                        read += err;
 
399
                } while (count);
 
400
                smp_mb(); /* flush ubuf */
 
401
                err = read;
 
402
 
 
403
        out_free:
 
404
                kfree(args.kbuf);
 
405
        out:
 
406
                return err;
 
407
        }
 
408
}
 
409
 
 
410
ssize_t vfsub_read_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
 
411
                     int dlgt)
 
412
{
 
413
        if (!dlgt)
 
414
                return do_vfsub_read_k(file, kbuf, count, ppos);
 
415
        else {
 
416
                ssize_t err;
 
417
                int wkq_err;
 
418
                struct read_args args = {
 
419
                        .errp   = &err,
 
420
                        .file   = file,
 
421
                        .count  = count,
 
422
                        .ppos   = ppos
 
423
                };
 
424
                args.kbuf = kbuf;
 
425
                wkq_err = au_wkq_wait(call_read_k, &args, /*dlgt*/1);
 
426
                if (unlikely(wkq_err))
 
427
                        err = wkq_err;
 
428
                return err;
 
429
        }
 
430
}
 
431
 
 
432
struct write_args {
 
433
        ssize_t *errp;
 
434
        struct file *file;
 
435
        union {
 
436
                void *kbuf;
 
437
                const char __user *ubuf;
 
438
        };
 
439
        void *buf;
 
440
        size_t count;
 
441
        loff_t *ppos;
 
442
        struct vfsub_args *vargs;
 
443
};
 
444
 
 
445
static void call_write_k(void *args)
 
446
{
 
447
        struct write_args *a = args;
 
448
        LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
 
449
                  AuDLNPair(a->file->f_dentry), (unsigned long)a->count,
 
450
                  *a->ppos);
 
451
        vfsub_ignore(a->vargs);
 
452
        *a->errp = do_vfsub_write_k(a->file, a->kbuf, a->count, a->ppos);
 
453
        if (unlikely(*a->errp < 0))
 
454
                vfsub_unignore(a->vargs);
 
455
}
 
456
 
 
457
ssize_t vfsub_write_u(struct file *file, const char __user *ubuf, size_t count,
 
458
                      loff_t *ppos, struct vfsub_args *vargs)
 
459
{
 
460
        ssize_t err;
 
461
 
 
462
        if (!vfsub_ftest(vargs->flags, DLGT)) {
 
463
                vfsub_ignore(vargs);
 
464
                err = do_vfsub_write_u(file, ubuf, count, ppos);
 
465
                if (unlikely(err < 0))
 
466
                        vfsub_unignore(vargs);
 
467
        } else {
 
468
                ssize_t written;
 
469
                int wkq_err;
 
470
                struct write_args args = {
 
471
                        .errp   = &err,
 
472
                        .file   = file,
 
473
                        .count  = count,
 
474
                        .ppos   = ppos,
 
475
                        .vargs  = vargs
 
476
                };
 
477
 
 
478
                if (unlikely(!count))
 
479
                        return 0;
 
480
 
 
481
                /*
 
482
                 * workaround an application bug.
 
483
                 * generally, read(2) or write(2) may return the value shorter
 
484
                 * than requested. But many applications don't support it,
 
485
                 * for example bash.
 
486
                 */
 
487
                err = -ENOMEM;
 
488
                if (args.count > PAGE_SIZE)
 
489
                        args.count = PAGE_SIZE;
 
490
                args.kbuf = kmalloc(args.count, GFP_TEMPORARY);
 
491
                if (unlikely(!args.kbuf))
 
492
                        goto out;
 
493
 
 
494
                written = 0;
 
495
                do {
 
496
                        if (unlikely(copy_from_user(args.kbuf, ubuf,
 
497
                                                    args.count))) {
 
498
                                err = -EFAULT;
 
499
                                goto out_free;
 
500
                        }
 
501
 
 
502
                        wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1);
 
503
                        if (unlikely(wkq_err))
 
504
                                err = wkq_err;
 
505
                        if (err > 0) {
 
506
                                count -= err;
 
507
                                if (count < args.count)
 
508
                                        args.count = count;
 
509
                                ubuf += err;
 
510
                                written += err;
 
511
                        } else if (!err)
 
512
                                break;
 
513
                        else if (unlikely(err < 0))
 
514
                                goto out_free;
 
515
                } while (count);
 
516
                err = written;
 
517
 
 
518
        out_free:
 
519
                kfree(args.kbuf);
 
520
        }
 
521
 out:
 
522
        return err;
 
523
}
 
524
 
 
525
ssize_t vfsub_write_k(struct file *file, void *kbuf, size_t count, loff_t *ppos,
 
526
                      struct vfsub_args *vargs)
 
527
{
 
528
        ssize_t err;
 
529
 
 
530
        if (!vfsub_ftest(vargs->flags, DLGT)) {
 
531
                vfsub_ignore(vargs);
 
532
                err = do_vfsub_write_k(file, kbuf, count, ppos);
 
533
                if (unlikely(err < 0))
 
534
                        vfsub_unignore(vargs);
 
535
        } else {
 
536
                int wkq_err;
 
537
                struct write_args args = {
 
538
                        .errp   = &err,
 
539
                        .file   = file,
 
540
                        .count  = count,
 
541
                        .ppos   = ppos,
 
542
                        .vargs  = vargs
 
543
                };
 
544
                args.kbuf = kbuf;
 
545
                wkq_err = au_wkq_wait(call_write_k, &args, /*dlgt*/1);
 
546
                if (unlikely(wkq_err))
 
547
                        err = wkq_err;
 
548
        }
 
549
        return err;
 
550
}
 
551
 
 
552
struct readdir_args {
 
553
        int *errp;
 
554
        struct file *file;
 
555
        filldir_t filldir;
 
556
        void *arg;
 
557
};
 
558
 
 
559
static void call_readdir(void *args)
 
560
{
 
561
        struct readdir_args *a = args;
 
562
        *a->errp = do_vfsub_readdir(a->file, a->filldir, a->arg);
 
563
}
 
564
 
 
565
int vfsub_readdir(struct file *file, filldir_t filldir, void *arg, int dlgt)
 
566
{
 
567
        if (!dlgt)
 
568
                return do_vfsub_readdir(file, filldir, arg);
 
569
        else {
 
570
                int err, wkq_err;
 
571
                struct readdir_args args = {
 
572
                        .errp           = &err,
 
573
                        .file           = file,
 
574
                        .filldir        = filldir,
 
575
                        .arg            = arg
 
576
                };
 
577
                wkq_err = au_wkq_wait(call_readdir, &args, /*dlgt*/1);
 
578
                if (unlikely(wkq_err))
 
579
                        err = wkq_err;
 
580
                return err;
 
581
        }
 
582
}
 
583
 
 
584
/* ---------------------------------------------------------------------- */
 
585
 
 
586
struct splice_to_args {
 
587
        long *errp;
 
588
        struct file *in;
 
589
        loff_t *ppos;
 
590
        struct pipe_inode_info *pipe;
 
591
        size_t len;
 
592
        unsigned int flags;
 
593
};
 
594
 
 
595
static void call_splice_to(void *args)
 
596
{
 
597
        struct splice_to_args *a = args;
 
598
        *a->errp = do_vfsub_splice_to(a->in, a->ppos, a->pipe, a->len,
 
599
                                      a->flags);
 
600
}
 
601
 
 
602
long vfsub_splice_to(struct file *in, loff_t *ppos,
 
603
                     struct pipe_inode_info *pipe, size_t len,
 
604
                     unsigned int flags, int dlgt)
 
605
{
 
606
        if (!dlgt)
 
607
                return do_vfsub_splice_to(in, ppos, pipe, len, flags);
 
608
        else {
 
609
                long err;
 
610
                int wkq_err;
 
611
                struct splice_to_args args = {
 
612
                        .errp   = &err,
 
613
                        .in     = in,
 
614
                        .ppos   = ppos,
 
615
                        .pipe   = pipe,
 
616
                        .len    = len,
 
617
                        .flags  = flags
 
618
                };
 
619
                wkq_err = au_wkq_wait(call_splice_to, &args, /*dlgt*/1);
 
620
                if (unlikely(wkq_err))
 
621
                        err = wkq_err;
 
622
                return err;
 
623
        }
 
624
}
 
625
 
 
626
struct splice_from_args {
 
627
        long *errp;
 
628
        struct pipe_inode_info *pipe;
 
629
        struct file *out;
 
630
        loff_t *ppos;
 
631
        size_t len;
 
632
        unsigned int flags;
 
633
        struct vfsub_args *vargs;
 
634
};
 
635
 
 
636
static void call_splice_from(void *args)
 
637
{
 
638
        struct splice_from_args *a = args;
 
639
        vfsub_ignore(a->vargs);
 
640
        *a->errp = do_vfsub_splice_from(a->pipe, a->out, a->ppos, a->len,
 
641
                                        a->flags);
 
642
        if (unlikely(*a->errp < 0))
 
643
                vfsub_unignore(a->vargs);
 
644
}
 
645
 
 
646
long vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
 
647
                       loff_t *ppos, size_t len, unsigned int flags,
 
648
                       struct vfsub_args *vargs)
 
649
{
 
650
        long err;
 
651
 
 
652
        if (!vfsub_ftest(vargs->flags, DLGT)) {
 
653
                vfsub_ignore(vargs);
 
654
                err = do_vfsub_splice_from(pipe, out, ppos, len, flags);
 
655
                if (unlikely(err < 0))
 
656
                        vfsub_unignore(vargs);
 
657
        } else {
 
658
                int wkq_err;
 
659
                struct splice_from_args args = {
 
660
                        .errp   = &err,
 
661
                        .pipe   = pipe,
 
662
                        .out    = out,
 
663
                        .ppos   = ppos,
 
664
                        .len    = len,
 
665
                        .flags  = flags,
 
666
                        .vargs  = vargs
 
667
                };
 
668
                wkq_err = au_wkq_wait(call_splice_from, &args, /*dlgt*/1);
 
669
                if (unlikely(wkq_err))
 
670
                        err = wkq_err;
 
671
        }
 
672
        return err;
 
673
}
 
674
 
 
675
/* ---------------------------------------------------------------------- */
 
676
 
 
677
struct getattr_args {
 
678
        int *errp;
 
679
        struct vfsmount *mnt;
 
680
        struct dentry *dentry;
 
681
        struct kstat *st;
 
682
};
 
683
 
 
684
static void call_getattr(void *args)
 
685
{
 
686
        struct getattr_args *a = args;
 
687
        *a->errp = do_vfsub_getattr(a->mnt, a->dentry, a->st);
 
688
}
 
689
 
 
690
int vfsub_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *st,
 
691
                  int dlgt)
 
692
{
 
693
        if (!dlgt)
 
694
                return do_vfsub_getattr(mnt, dentry, st);
 
695
        else {
 
696
                int err, wkq_err;
 
697
                struct getattr_args args = {
 
698
                        .errp   = &err,
 
699
                        .mnt    = mnt,
 
700
                        .dentry = dentry,
 
701
                        .st     = st
 
702
                };
 
703
                wkq_err = au_wkq_wait(call_getattr, &args, /*dlgt*/1);
 
704
                if (unlikely(wkq_err))
 
705
                        err = wkq_err;
 
706
                return err;
 
707
        }
 
708
}