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

« back to all changes in this revision

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