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

« back to all changes in this revision

Viewing changes to fs/aufs25/vfsub.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) 2007-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
 
21
 *
 
22
 * $Id: vfsub.c,v 1.2 2008/04/21 01:49:05 sfjro Exp $
 
23
 */
 
24
// I'm going to slightly mad
 
25
 
 
26
#include <linux/uaccess.h>
 
27
#include "aufs.h"
 
28
 
 
29
/* ---------------------------------------------------------------------- */
 
30
 
 
31
void vfsub_args_init(struct vfsub_args *vargs, struct au_hin_ignore *ign,
 
32
                     int dlgt, int force_unlink)
 
33
{
 
34
        do_vfsub_args_reinit(vargs, ign);
 
35
        vargs->flags = 0;
 
36
        if (unlikely(dlgt))
 
37
                vfsub_fset(vargs->flags, DLGT);
 
38
        if (force_unlink)
 
39
                vfsub_fset(vargs->flags, FORCE_UNLINK);
 
40
}
 
41
 
 
42
/* ---------------------------------------------------------------------- */
 
43
 
 
44
struct file *vfsub_filp_open(const char *path, int oflags, int mode)
 
45
{
 
46
        struct file *err;
 
47
 
 
48
        LKTRTrace("%s\n", path);
 
49
 
 
50
        lockdep_off();
 
51
        err = filp_open(path, oflags, mode);
 
52
        lockdep_on();
 
53
        if (!IS_ERR(err))
 
54
                au_update_fuse_h_inode(err->f_vfsmnt, err->f_dentry); /*ignore*/
 
55
        return err;
 
56
}
 
57
 
 
58
int vfsub_path_lookup(const char *name, unsigned int flags,
 
59
                      struct nameidata *nd)
 
60
{
 
61
        int err;
 
62
 
 
63
        LKTRTrace("%s\n", name);
 
64
 
 
65
        /* lockdep_off(); */
 
66
        err = path_lookup(name, flags, nd);
 
67
        /* lockdep_on(); */
 
68
        if (!err)
 
69
                au_update_fuse_h_inode(nd->path.mnt, nd->path.dentry);
 
70
        /*ignore*/
 
71
        return err;
 
72
}
 
73
 
 
74
struct dentry *vfsub_lookup_one_len(const char *name, struct dentry *parent,
 
75
                                    int len)
 
76
{
 
77
        struct dentry *d;
 
78
 
 
79
        LKTRTrace("%.*s/%.*s\n", AuDLNPair(parent), len, name);
 
80
        IMustLock(parent->d_inode);
 
81
 
 
82
        d = lookup_one_len(name, parent, len);
 
83
        if (!IS_ERR(d))
 
84
                au_update_fuse_h_inode(NULL, d); /*ignore*/
 
85
        return d;
 
86
}
 
87
 
 
88
#ifdef CONFIG_AUFS_LHASH_PATCH
 
89
struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent,
 
90
                                  struct nameidata *nd)
 
91
{
 
92
        struct dentry *d;
 
93
 
 
94
        LKTRTrace("%.*s/%.*s, nd %d\n",
 
95
                  AuDLNPair(parent), AuLNPair(name), !!nd);
 
96
        IMustLock(parent->d_inode);
 
97
 
 
98
        d = __lookup_hash(name, parent, nd);
 
99
        if (!IS_ERR(d))
 
100
                au_update_fuse_h_inode(NULL, d); /*ignore*/
 
101
        return d;
 
102
}
 
103
#endif
 
104
 
 
105
/* ---------------------------------------------------------------------- */
 
106
 
 
107
int do_vfsub_create(struct inode *dir, struct dentry *dentry, int mode,
 
108
                    struct nameidata *nd)
 
109
{
 
110
        int err;
 
111
        struct vfsmount *mnt;
 
112
 
 
113
        LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
 
114
        IMustLock(dir);
 
115
 
 
116
        err = vfs_create(dir, dentry, mode, nd);
 
117
        if (!err) {
 
118
                mnt = NULL;
 
119
                if (nd)
 
120
                        mnt = nd->path.mnt;
 
121
                /* dir inode is locked */
 
122
                au_update_fuse_h_inode(mnt, dentry->d_parent); /*ignore*/
 
123
                au_update_fuse_h_inode(mnt, dentry); /*ignore*/
 
124
        }
 
125
        return err;
 
126
}
 
127
 
 
128
int do_vfsub_symlink(struct inode *dir, struct dentry *dentry,
 
129
                     const char *symname, int mode)
 
130
{
 
131
        int err;
 
132
 
 
133
        LKTRTrace("i%lu, %.*s, %s, 0x%x\n",
 
134
                  dir->i_ino, AuDLNPair(dentry), symname, mode);
 
135
        IMustLock(dir);
 
136
 
 
137
        err = vfs_symlink(dir, dentry, symname, mode);
 
138
        if (!err) {
 
139
                /* dir inode is locked */
 
140
                au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
 
141
                au_update_fuse_h_inode(NULL, dentry); /*ignore*/
 
142
        }
 
143
        return err;
 
144
}
 
145
 
 
146
int do_vfsub_mknod(struct inode *dir, struct dentry *dentry, int mode,
 
147
                   dev_t dev)
 
148
{
 
149
        int err;
 
150
 
 
151
        LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
 
152
        IMustLock(dir);
 
153
 
 
154
        err = vfs_mknod(dir, dentry, mode, dev);
 
155
        if (!err) {
 
156
                /* dir inode is locked */
 
157
                au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
 
158
                au_update_fuse_h_inode(NULL, dentry); /*ignore*/
 
159
        }
 
160
        return err;
 
161
}
 
162
 
 
163
int do_vfsub_link(struct dentry *src_dentry, struct inode *dir,
 
164
                  struct dentry *dentry)
 
165
{
 
166
        int err;
 
167
 
 
168
        LKTRTrace("%.*s, i%lu, %.*s\n",
 
169
                  AuDLNPair(src_dentry), dir->i_ino, AuDLNPair(dentry));
 
170
        IMustLock(dir);
 
171
 
 
172
        lockdep_off();
 
173
        err = vfs_link(src_dentry, dir, dentry);
 
174
        lockdep_on();
 
175
        if (!err) {
 
176
                LKTRTrace("src_i %p, dst_i %p\n",
 
177
                          src_dentry->d_inode, dentry->d_inode);
 
178
                /* fuse has different memory inode for the same inumber */
 
179
                au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
 
180
                /* dir inode is locked */
 
181
                au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
 
182
                au_update_fuse_h_inode(NULL, dentry); /*ignore*/
 
183
        }
 
184
        return err;
 
185
}
 
186
 
 
187
int do_vfsub_rename(struct inode *src_dir, struct dentry *src_dentry,
 
188
                    struct inode *dir, struct dentry *dentry)
 
189
{
 
190
        int err;
 
191
 
 
192
        LKTRTrace("i%lu, %.*s, i%lu, %.*s\n",
 
193
                  src_dir->i_ino, AuDLNPair(src_dentry),
 
194
                  dir->i_ino, AuDLNPair(dentry));
 
195
        IMustLock(dir);
 
196
        IMustLock(src_dir);
 
197
 
 
198
        lockdep_off();
 
199
        err = vfs_rename(src_dir, src_dentry, dir, dentry);
 
200
        lockdep_on();
 
201
        if (!err) {
 
202
                /* dir inode is locked */
 
203
                au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
 
204
                au_update_fuse_h_inode(NULL, src_dentry->d_parent); /*ignore*/
 
205
                au_update_fuse_h_inode(NULL, src_dentry); /*ignore*/
 
206
        }
 
207
        return err;
 
208
}
 
209
 
 
210
int do_vfsub_mkdir(struct inode *dir, struct dentry *dentry, int mode)
 
211
{
 
212
        int err;
 
213
 
 
214
        LKTRTrace("i%lu, %.*s, 0x%x\n", dir->i_ino, AuDLNPair(dentry), mode);
 
215
        IMustLock(dir);
 
216
 
 
217
        err = vfs_mkdir(dir, dentry, mode);
 
218
        if (!err) {
 
219
                /* dir inode is locked */
 
220
                au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
 
221
                au_update_fuse_h_inode(NULL, dentry); /*ignore*/
 
222
        }
 
223
        return err;
 
224
}
 
225
 
 
226
int do_vfsub_rmdir(struct inode *dir, struct dentry *dentry)
 
227
{
 
228
        int err;
 
229
 
 
230
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
 
231
        IMustLock(dir);
 
232
 
 
233
        lockdep_off();
 
234
        err = vfs_rmdir(dir, dentry);
 
235
        lockdep_on();
 
236
        /* dir inode is locked */
 
237
        if (!err)
 
238
                au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
 
239
        return err;
 
240
}
 
241
 
 
242
int do_vfsub_unlink(struct inode *dir, struct dentry *dentry)
 
243
{
 
244
        int err;
 
245
 
 
246
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
 
247
        IMustLock(dir);
 
248
 
 
249
        /* vfs_unlink() locks inode */
 
250
        lockdep_off();
 
251
        err = vfs_unlink(dir, dentry);
 
252
        lockdep_on();
 
253
        /* dir inode is locked */
 
254
        if (!err)
 
255
                au_update_fuse_h_inode(NULL, dentry->d_parent); /*ignore*/
 
256
        return err;
 
257
}
 
258
 
 
259
/* ---------------------------------------------------------------------- */
 
260
 
 
261
ssize_t do_vfsub_read_u(struct file *file, char __user *ubuf, size_t count,
 
262
                        loff_t *ppos)
 
263
{
 
264
        ssize_t err;
 
265
 
 
266
        LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
 
267
                  AuDLNPair(file->f_dentry), (unsigned long)count, *ppos);
 
268
 
 
269
        if (0 /*!au_test_nfs(file->f_vfsmnt->mnt_sb)*/)
 
270
                err = vfs_read(file, ubuf, count, ppos);
 
271
        else {
 
272
                lockdep_off();
 
273
                err = vfs_read(file, ubuf, count, ppos);
 
274
                lockdep_on();
 
275
        }
 
276
        if (err >= 0)
 
277
                au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
 
278
        /*ignore*/
 
279
        return err;
 
280
}
 
281
 
 
282
// kernel_read() ??
 
283
ssize_t do_vfsub_read_k(struct file *file, void *kbuf, size_t count,
 
284
                        loff_t *ppos)
 
285
{
 
286
        ssize_t err;
 
287
        mm_segment_t oldfs;
 
288
 
 
289
        oldfs = get_fs();
 
290
        set_fs(KERNEL_DS);
 
291
        err = do_vfsub_read_u(file, (char __user *)kbuf, count, ppos);
 
292
        set_fs(oldfs);
 
293
        return err;
 
294
}
 
295
 
 
296
ssize_t do_vfsub_write_u(struct file *file, const char __user *ubuf,
 
297
                         size_t count, loff_t *ppos)
 
298
{
 
299
        ssize_t err;
 
300
 
 
301
        LKTRTrace("%.*s, cnt %lu, pos %Ld\n",
 
302
                  AuDLNPair(file->f_dentry), (unsigned long)count, *ppos);
 
303
 
 
304
        lockdep_off();
 
305
        err = vfs_write(file, ubuf, count, ppos);
 
306
        lockdep_on();
 
307
        if (err >= 0)
 
308
                au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
 
309
        /*ignore*/
 
310
        return err;
 
311
}
 
312
 
 
313
ssize_t do_vfsub_write_k(struct file *file, void *kbuf, size_t count,
 
314
                         loff_t *ppos)
 
315
{
 
316
        ssize_t err;
 
317
        mm_segment_t oldfs;
 
318
 
 
319
        oldfs = get_fs();
 
320
        set_fs(KERNEL_DS);
 
321
        err = do_vfsub_write_u(file, (const char __user *)kbuf, count, ppos);
 
322
        set_fs(oldfs);
 
323
        return err;
 
324
}
 
325
 
 
326
int do_vfsub_readdir(struct file *file, filldir_t filldir, void *arg)
 
327
{
 
328
        int err;
 
329
 
 
330
        LKTRTrace("%.*s\n", AuDLNPair(file->f_dentry));
 
331
 
 
332
        lockdep_off();
 
333
        err = vfs_readdir(file, filldir, arg);
 
334
        lockdep_on();
 
335
        if (err >= 0)
 
336
                au_update_fuse_h_inode(file->f_vfsmnt, file->f_dentry);
 
337
        /*ignore*/
 
338
        return err;
 
339
}
 
340
 
 
341
#ifdef CONFIG_AUFS_SPLICE_PATCH
 
342
long do_vfsub_splice_to(struct file *in, loff_t *ppos,
 
343
                        struct pipe_inode_info *pipe, size_t len,
 
344
                        unsigned int flags)
 
345
{
 
346
        long err;
 
347
 
 
348
        LKTRTrace("%.*s, pos %Ld, len %lu, 0x%x\n",
 
349
                  AuDLNPair(in->f_dentry), *ppos, (unsigned long)len, flags);
 
350
 
 
351
        lockdep_off();
 
352
        err = do_splice_to(in, ppos, pipe, len, flags);
 
353
        lockdep_on();
 
354
        if (err >= 0)
 
355
                au_update_fuse_h_inode(in->f_vfsmnt, in->f_dentry); /*ignore*/
 
356
        return err;
 
357
}
 
358
 
 
359
long do_vfsub_splice_from(struct pipe_inode_info *pipe, struct file *out,
 
360
                          loff_t *ppos, size_t len, unsigned int flags)
 
361
{
 
362
        long err;
 
363
 
 
364
        LKTRTrace("%.*s, pos %Ld, len %lu, 0x%x\n",
 
365
                  AuDLNPair(out->f_dentry), *ppos, (unsigned long)len, flags);
 
366
 
 
367
        lockdep_off();
 
368
        err = do_splice_from(pipe, out, ppos, len, flags);
 
369
        lockdep_on();
 
370
        if (err >= 0)
 
371
                au_update_fuse_h_inode(out->f_vfsmnt, out->f_dentry); /*ignore*/
 
372
        return err;
 
373
}
 
374
#endif
 
375
 
 
376
/* ---------------------------------------------------------------------- */
 
377
 
 
378
struct au_vfsub_mkdir_args {
 
379
        int *errp;
 
380
        struct inode *dir;
 
381
        struct dentry *dentry;
 
382
        int mode;
 
383
        int dlgt;
 
384
};
 
385
 
 
386
static void au_call_vfsub_mkdir(void *args)
 
387
{
 
388
        struct au_vfsub_mkdir_args *a = args;
 
389
        *a->errp = vfsub_mkdir(a->dir, a->dentry, a->mode, a->dlgt);
 
390
}
 
391
 
 
392
int vfsub_sio_mkdir(struct inode *dir, struct dentry *dentry, int mode,
 
393
                    int dlgt)
 
394
{
 
395
        int err, do_sio, wkq_err;
 
396
 
 
397
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
 
398
 
 
399
        do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt);
 
400
        if (!do_sio)
 
401
                err = vfsub_mkdir(dir, dentry, mode, dlgt);
 
402
        else {
 
403
                struct au_vfsub_mkdir_args args = {
 
404
                        .errp   = &err,
 
405
                        .dir    = dir,
 
406
                        .dentry = dentry,
 
407
                        .mode   = mode,
 
408
                        .dlgt   = dlgt
 
409
                };
 
410
                wkq_err = au_wkq_wait(au_call_vfsub_mkdir, &args, /*dlgt*/0);
 
411
                if (unlikely(wkq_err))
 
412
                        err = wkq_err;
 
413
        }
 
414
 
 
415
        AuTraceErr(err);
 
416
        return err;
 
417
}
 
418
 
 
419
struct au_vfsub_rmdir_args {
 
420
        int *errp;
 
421
        struct inode *dir;
 
422
        struct dentry *dentry;
 
423
        struct vfsub_args *vargs;
 
424
};
 
425
 
 
426
static void au_call_vfsub_rmdir(void *args)
 
427
{
 
428
        struct au_vfsub_rmdir_args *a = args;
 
429
        *a->errp = vfsub_rmdir(a->dir, a->dentry, a->vargs);
 
430
}
 
431
 
 
432
int vfsub_sio_rmdir(struct inode *dir, struct dentry *dentry, int dlgt)
 
433
{
 
434
        int err, do_sio, wkq_err;
 
435
        struct vfsub_args vargs;
 
436
 
 
437
        LKTRTrace("i%lu, %.*s\n", dir->i_ino, AuDLNPair(dentry));
 
438
 
 
439
        vfsub_args_init(&vargs, /*ign*/NULL, dlgt, /*force_unlink*/0);
 
440
        do_sio = au_test_h_perm_sio(dir, MAY_EXEC | MAY_WRITE, dlgt);
 
441
        if (!do_sio)
 
442
                err = vfsub_rmdir(dir, dentry, &vargs);
 
443
        else {
 
444
                struct au_vfsub_rmdir_args args = {
 
445
                        .errp           = &err,
 
446
                        .dir            = dir,
 
447
                        .dentry         = dentry,
 
448
                        .vargs          = &vargs
 
449
                };
 
450
                wkq_err = au_wkq_wait(au_call_vfsub_rmdir, &args, /*dlgt*/0);
 
451
                if (unlikely(wkq_err))
 
452
                        err = wkq_err;
 
453
        }
 
454
 
 
455
        AuTraceErr(err);
 
456
        return err;
 
457
}
 
458
 
 
459
/* ---------------------------------------------------------------------- */
 
460
 
 
461
struct notify_change_args {
 
462
        int *errp;
 
463
        struct dentry *h_dentry;
 
464
        struct iattr *ia;
 
465
        struct vfsub_args *vargs;
 
466
};
 
467
 
 
468
static void call_notify_change(void *args)
 
469
{
 
470
        struct notify_change_args *a = args;
 
471
        struct inode *h_inode;
 
472
 
 
473
        LKTRTrace("%.*s, ia_valid 0x%x\n",
 
474
                  AuDLNPair(a->h_dentry), a->ia->ia_valid);
 
475
        h_inode = a->h_dentry->d_inode;
 
476
        IMustLock(h_inode);
 
477
 
 
478
        *a->errp = -EPERM;
 
479
        if (!IS_IMMUTABLE(h_inode) && !IS_APPEND(h_inode)) {
 
480
                vfsub_ignore(a->vargs);
 
481
                lockdep_off();
 
482
                *a->errp = notify_change(a->h_dentry, a->ia);
 
483
                lockdep_on();
 
484
                if (!*a->errp)
 
485
                        au_update_fuse_h_inode(NULL, a->h_dentry); /*ignore*/
 
486
                else
 
487
                        vfsub_unignore(a->vargs);
 
488
        }
 
489
        AuTraceErr(*a->errp);
 
490
}
 
491
 
 
492
#ifdef CONFIG_AUFS_DLGT
 
493
static void vfsub_notify_change_dlgt(struct notify_change_args *args,
 
494
                                     unsigned int flags)
 
495
{
 
496
        if (!vfsub_ftest(flags, DLGT))
 
497
                call_notify_change(args);
 
498
        else {
 
499
                int wkq_err;
 
500
                wkq_err = au_wkq_wait(call_notify_change, args, /*dlgt*/1);
 
501
                if (unlikely(wkq_err))
 
502
                        *args->errp = wkq_err;
 
503
        }
 
504
}
 
505
#else
 
506
static void vfsub_notify_change_dlgt(struct notify_change_args *args,
 
507
                                     unsigned int flags)
 
508
{
 
509
        call_notify_change(args);
 
510
}
 
511
#endif
 
512
 
 
513
int vfsub_notify_change(struct dentry *dentry, struct iattr *ia,
 
514
                        struct vfsub_args *vargs)
 
515
{
 
516
        int err;
 
517
        struct notify_change_args args = {
 
518
                .errp           = &err,
 
519
                .h_dentry       = dentry,
 
520
                .ia             = ia,
 
521
                .vargs          = vargs
 
522
        };
 
523
 
 
524
        vfsub_notify_change_dlgt(&args, vargs->flags);
 
525
 
 
526
        AuTraceErr(err);
 
527
        return err;
 
528
}
 
529
 
 
530
/* ---------------------------------------------------------------------- */
 
531
 
 
532
struct unlink_args {
 
533
        int *errp;
 
534
        struct inode *dir;
 
535
        struct dentry *dentry;
 
536
        struct vfsub_args *vargs;
 
537
};
 
538
 
 
539
static void call_unlink(void *args)
 
540
{
 
541
        struct unlink_args *a = args;
 
542
        struct inode *h_inode;
 
543
        const int stop_sillyrename = (au_test_nfs(a->dentry->d_sb)
 
544
                                      && atomic_read(&a->dentry->d_count) == 1);
 
545
 
 
546
        LKTRTrace("%.*s, stop_silly %d, cnt %d\n",
 
547
                  AuDLNPair(a->dentry), stop_sillyrename,
 
548
                  atomic_read(&a->dentry->d_count));
 
549
        //IMustLock(a->dir);
 
550
 
 
551
        if (!stop_sillyrename)
 
552
                dget(a->dentry);
 
553
        h_inode = a->dentry->d_inode;
 
554
        if (h_inode)
 
555
                atomic_inc_return(&h_inode->i_count);
 
556
#if 0 // partial testing
 
557
        {
 
558
                struct qstr *name = &a->dentry->d_name;
 
559
                if (name->len == sizeof(AUFS_XINO_FNAME) - 1
 
560
                    && !strncmp(name->name, AUFS_XINO_FNAME, name->len))
 
561
                        *a->errp = do_vfsub_unlink(a->dir, a->dentry);
 
562
                else
 
563
                        err = -1;
 
564
        }
 
565
#else
 
566
        *a->errp = do_vfsub_unlink(a->dir, a->dentry);
 
567
#endif
 
568
 
 
569
        if (!stop_sillyrename)
 
570
                dput(a->dentry);
 
571
        if (h_inode)
 
572
                iput(h_inode);
 
573
 
 
574
        AuTraceErr(*a->errp);
 
575
}
 
576
 
 
577
/*
 
578
 * @dir: must be locked.
 
579
 * @dentry: target dentry.
 
580
 */
 
581
int vfsub_unlink(struct inode *dir, struct dentry *dentry,
 
582
                 struct vfsub_args *vargs)
 
583
{
 
584
        int err;
 
585
        struct unlink_args args = {
 
586
                .errp   = &err,
 
587
                .dir    = dir,
 
588
                .dentry = dentry,
 
589
                .vargs  = vargs
 
590
        };
 
591
 
 
592
        if (!vfsub_ftest(vargs->flags, DLGT)
 
593
            && !vfsub_ftest(vargs->flags, FORCE_UNLINK))
 
594
                call_unlink(&args);
 
595
        else {
 
596
                int wkq_err;
 
597
                wkq_err = au_wkq_wait(call_unlink, &args,
 
598
                                      vfsub_ftest(vargs->flags, DLGT));
 
599
                if (unlikely(wkq_err))
 
600
                        err = wkq_err;
 
601
        }
 
602
 
 
603
        return err;
 
604
}
 
605
 
 
606
/* ---------------------------------------------------------------------- */
 
607
 
 
608
struct statfs_args {
 
609
        int *errp;
 
610
        void *arg;
 
611
        struct kstatfs *buf;
 
612
};
 
613
 
 
614
static void call_statfs(void *args)
 
615
{
 
616
        struct statfs_args *a = args;
 
617
        *a->errp = vfs_statfs(a->arg, a->buf);
 
618
}
 
619
 
 
620
#ifdef CONFIG_AUFS_DLGT
 
621
static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt)
 
622
{
 
623
        if (!dlgt)
 
624
                call_statfs(args);
 
625
        else {
 
626
                int wkq_err;
 
627
                wkq_err = au_wkq_wait(call_statfs, args, /*dlgt*/1);
 
628
                if (unlikely(wkq_err))
 
629
                        *args->errp = wkq_err;
 
630
        }
 
631
}
 
632
#else
 
633
static void vfsub_statfs_dlgt(struct statfs_args *args, int dlgt)
 
634
{
 
635
        call_statfs(args);
 
636
}
 
637
#endif
 
638
 
 
639
int vfsub_statfs(void *arg, struct kstatfs *buf, int dlgt)
 
640
{
 
641
        int err;
 
642
        struct statfs_args args = {
 
643
                .errp   = &err,
 
644
                .arg    = arg,
 
645
                .buf    = buf
 
646
        };
 
647
 
 
648
        vfsub_statfs_dlgt(&args, dlgt);
 
649
 
 
650
        return err;
 
651
}