]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - fs/aufs/dir.c
UBUNTU: Ubuntu-4.13.0-45.50
[mirror_ubuntu-artful-kernel.git] / fs / aufs / dir.c
CommitLineData
b6450630
SF
1/*
2 * Copyright (C) 2005-2017 Junjiro R. 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, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * directory operations
20 */
21
22#include <linux/fs_stack.h>
23#include "aufs.h"
24
25void au_add_nlink(struct inode *dir, struct inode *h_dir)
26{
27 unsigned int nlink;
28
29 AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
30
31 nlink = dir->i_nlink;
32 nlink += h_dir->i_nlink - 2;
33 if (h_dir->i_nlink < 2)
34 nlink += 2;
35 smp_mb(); /* for i_nlink */
36 /* 0 can happen in revaliding */
37 set_nlink(dir, nlink);
38}
39
40void au_sub_nlink(struct inode *dir, struct inode *h_dir)
41{
42 unsigned int nlink;
43
44 AuDebugOn(!S_ISDIR(dir->i_mode) || !S_ISDIR(h_dir->i_mode));
45
46 nlink = dir->i_nlink;
47 nlink -= h_dir->i_nlink - 2;
48 if (h_dir->i_nlink < 2)
49 nlink -= 2;
50 smp_mb(); /* for i_nlink */
51 /* nlink == 0 means the branch-fs is broken */
52 set_nlink(dir, nlink);
53}
54
55loff_t au_dir_size(struct file *file, struct dentry *dentry)
56{
57 loff_t sz;
58 aufs_bindex_t bindex, bbot;
59 struct file *h_file;
60 struct dentry *h_dentry;
61
62 sz = 0;
63 if (file) {
64 AuDebugOn(!d_is_dir(file->f_path.dentry));
65
66 bbot = au_fbbot_dir(file);
67 for (bindex = au_fbtop(file);
68 bindex <= bbot && sz < KMALLOC_MAX_SIZE;
69 bindex++) {
70 h_file = au_hf_dir(file, bindex);
71 if (h_file && file_inode(h_file))
72 sz += vfsub_f_size_read(h_file);
73 }
74 } else {
75 AuDebugOn(!dentry);
76 AuDebugOn(!d_is_dir(dentry));
77
78 bbot = au_dbtaildir(dentry);
79 for (bindex = au_dbtop(dentry);
80 bindex <= bbot && sz < KMALLOC_MAX_SIZE;
81 bindex++) {
82 h_dentry = au_h_dptr(dentry, bindex);
83 if (h_dentry && d_is_positive(h_dentry))
84 sz += i_size_read(d_inode(h_dentry));
85 }
86 }
87 if (sz < KMALLOC_MAX_SIZE)
88 sz = roundup_pow_of_two(sz);
89 if (sz > KMALLOC_MAX_SIZE)
90 sz = KMALLOC_MAX_SIZE;
91 else if (sz < NAME_MAX) {
92 BUILD_BUG_ON(AUFS_RDBLK_DEF < NAME_MAX);
93 sz = AUFS_RDBLK_DEF;
94 }
95 return sz;
96}
97
98struct au_dir_ts_arg {
99 struct dentry *dentry;
100 aufs_bindex_t brid;
101};
102
103static void au_do_dir_ts(void *arg)
104{
105 struct au_dir_ts_arg *a = arg;
106 struct au_dtime dt;
107 struct path h_path;
108 struct inode *dir, *h_dir;
109 struct super_block *sb;
110 struct au_branch *br;
111 struct au_hinode *hdir;
112 int err;
113 aufs_bindex_t btop, bindex;
114
115 sb = a->dentry->d_sb;
116 if (d_really_is_negative(a->dentry))
117 goto out;
118 /* no dir->i_mutex lock */
119 aufs_read_lock(a->dentry, AuLock_DW); /* noflush */
120
121 dir = d_inode(a->dentry);
122 btop = au_ibtop(dir);
123 bindex = au_br_index(sb, a->brid);
124 if (bindex < btop)
125 goto out_unlock;
126
127 br = au_sbr(sb, bindex);
128 h_path.dentry = au_h_dptr(a->dentry, bindex);
129 if (!h_path.dentry)
130 goto out_unlock;
131 h_path.mnt = au_br_mnt(br);
132 au_dtime_store(&dt, a->dentry, &h_path);
133
134 br = au_sbr(sb, btop);
135 if (!au_br_writable(br->br_perm))
136 goto out_unlock;
137 h_path.dentry = au_h_dptr(a->dentry, btop);
138 h_path.mnt = au_br_mnt(br);
139 err = vfsub_mnt_want_write(h_path.mnt);
140 if (err)
141 goto out_unlock;
142 hdir = au_hi(dir, btop);
143 au_hn_inode_lock_nested(hdir, AuLsc_I_PARENT);
144 h_dir = au_h_iptr(dir, btop);
145 if (h_dir->i_nlink
146 && timespec_compare(&h_dir->i_mtime, &dt.dt_mtime) < 0) {
147 dt.dt_h_path = h_path;
148 au_dtime_revert(&dt);
149 }
150 au_hn_inode_unlock(hdir);
151 vfsub_mnt_drop_write(h_path.mnt);
152 au_cpup_attr_timesizes(dir);
153
154out_unlock:
155 aufs_read_unlock(a->dentry, AuLock_DW);
156out:
157 dput(a->dentry);
158 au_nwt_done(&au_sbi(sb)->si_nowait);
159 kfree(arg);
160}
161
162void au_dir_ts(struct inode *dir, aufs_bindex_t bindex)
163{
164 int perm, wkq_err;
165 aufs_bindex_t btop;
166 struct au_dir_ts_arg *arg;
167 struct dentry *dentry;
168 struct super_block *sb;
169
170 IMustLock(dir);
171
172 dentry = d_find_any_alias(dir);
173 AuDebugOn(!dentry);
174 sb = dentry->d_sb;
175 btop = au_ibtop(dir);
176 if (btop == bindex) {
177 au_cpup_attr_timesizes(dir);
178 goto out;
179 }
180
181 perm = au_sbr_perm(sb, btop);
182 if (!au_br_writable(perm))
183 goto out;
184
185 arg = kmalloc(sizeof(*arg), GFP_NOFS);
186 if (!arg)
187 goto out;
188
189 arg->dentry = dget(dentry); /* will be dput-ted by au_do_dir_ts() */
190 arg->brid = au_sbr_id(sb, bindex);
191 wkq_err = au_wkq_nowait(au_do_dir_ts, arg, sb, /*flags*/0);
192 if (unlikely(wkq_err)) {
193 pr_err("wkq %d\n", wkq_err);
194 dput(dentry);
195 kfree(arg);
196 }
197
198out:
199 dput(dentry);
200}
201
202/* ---------------------------------------------------------------------- */
203
204static int reopen_dir(struct file *file)
205{
206 int err;
207 unsigned int flags;
208 aufs_bindex_t bindex, btail, btop;
209 struct dentry *dentry, *h_dentry;
210 struct file *h_file;
211
212 /* open all lower dirs */
213 dentry = file->f_path.dentry;
214 btop = au_dbtop(dentry);
215 for (bindex = au_fbtop(file); bindex < btop; bindex++)
216 au_set_h_fptr(file, bindex, NULL);
217 au_set_fbtop(file, btop);
218
219 btail = au_dbtaildir(dentry);
220 for (bindex = au_fbbot_dir(file); btail < bindex; bindex--)
221 au_set_h_fptr(file, bindex, NULL);
222 au_set_fbbot_dir(file, btail);
223
224 flags = vfsub_file_flags(file);
225 for (bindex = btop; bindex <= btail; bindex++) {
226 h_dentry = au_h_dptr(dentry, bindex);
227 if (!h_dentry)
228 continue;
229 h_file = au_hf_dir(file, bindex);
230 if (h_file)
231 continue;
232
233 h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
234 err = PTR_ERR(h_file);
235 if (IS_ERR(h_file))
236 goto out; /* close all? */
237 au_set_h_fptr(file, bindex, h_file);
238 }
239 au_update_figen(file);
240 /* todo: necessary? */
241 /* file->f_ra = h_file->f_ra; */
242 err = 0;
243
244out:
245 return err;
246}
247
248static int do_open_dir(struct file *file, int flags, struct file *h_file)
249{
250 int err;
251 aufs_bindex_t bindex, btail;
252 struct dentry *dentry, *h_dentry;
253 struct vfsmount *mnt;
254
255 FiMustWriteLock(file);
256 AuDebugOn(h_file);
257
258 err = 0;
259 mnt = file->f_path.mnt;
260 dentry = file->f_path.dentry;
261 file->f_version = d_inode(dentry)->i_version;
262 bindex = au_dbtop(dentry);
263 au_set_fbtop(file, bindex);
264 btail = au_dbtaildir(dentry);
265 au_set_fbbot_dir(file, btail);
266 for (; !err && bindex <= btail; bindex++) {
267 h_dentry = au_h_dptr(dentry, bindex);
268 if (!h_dentry)
269 continue;
270
271 err = vfsub_test_mntns(mnt, h_dentry->d_sb);
272 if (unlikely(err))
273 break;
274 h_file = au_h_open(dentry, bindex, flags, file, /*force_wr*/0);
275 if (IS_ERR(h_file)) {
276 err = PTR_ERR(h_file);
277 break;
278 }
279 au_set_h_fptr(file, bindex, h_file);
280 }
281 au_update_figen(file);
282 /* todo: necessary? */
283 /* file->f_ra = h_file->f_ra; */
284 if (!err)
285 return 0; /* success */
286
287 /* close all */
288 for (bindex = au_fbtop(file); bindex <= btail; bindex++)
289 au_set_h_fptr(file, bindex, NULL);
290 au_set_fbtop(file, -1);
291 au_set_fbbot_dir(file, -1);
292
293 return err;
294}
295
296static int aufs_open_dir(struct inode *inode __maybe_unused,
297 struct file *file)
298{
299 int err;
300 struct super_block *sb;
301 struct au_fidir *fidir;
302
303 err = -ENOMEM;
304 sb = file->f_path.dentry->d_sb;
305 si_read_lock(sb, AuLock_FLUSH);
306 fidir = au_fidir_alloc(sb);
307 if (fidir) {
308 struct au_do_open_args args = {
309 .open = do_open_dir,
310 .fidir = fidir
311 };
312 err = au_do_open(file, &args);
313 if (unlikely(err))
314 kfree(fidir);
315 }
316 si_read_unlock(sb);
317 return err;
318}
319
320static int aufs_release_dir(struct inode *inode __maybe_unused,
321 struct file *file)
322{
323 struct au_vdir *vdir_cache;
324 struct au_finfo *finfo;
325 struct au_fidir *fidir;
326 struct au_hfile *hf;
327 aufs_bindex_t bindex, bbot;
328
329 finfo = au_fi(file);
330 fidir = finfo->fi_hdir;
331 if (fidir) {
332 au_sphl_del(&finfo->fi_hlist,
333 &au_sbi(file->f_path.dentry->d_sb)->si_files);
334 vdir_cache = fidir->fd_vdir_cache; /* lock-free */
335 if (vdir_cache)
336 au_vdir_free(vdir_cache);
337
338 bindex = finfo->fi_btop;
339 if (bindex >= 0) {
340 hf = fidir->fd_hfile + bindex;
341 /*
342 * calls fput() instead of filp_close(),
343 * since no dnotify or lock for the lower file.
344 */
345 bbot = fidir->fd_bbot;
346 for (; bindex <= bbot; bindex++, hf++)
347 if (hf->hf_file)
348 au_hfput(hf, /*execed*/0);
349 }
350 kfree(fidir);
351 finfo->fi_hdir = NULL;
352 }
353 au_finfo_fin(file);
354 return 0;
355}
356
357/* ---------------------------------------------------------------------- */
358
359static int au_do_flush_dir(struct file *file, fl_owner_t id)
360{
361 int err;
362 aufs_bindex_t bindex, bbot;
363 struct file *h_file;
364
365 err = 0;
366 bbot = au_fbbot_dir(file);
367 for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
368 h_file = au_hf_dir(file, bindex);
369 if (h_file)
370 err = vfsub_flush(h_file, id);
371 }
372 return err;
373}
374
375static int aufs_flush_dir(struct file *file, fl_owner_t id)
376{
377 return au_do_flush(file, id, au_do_flush_dir);
378}
379
380/* ---------------------------------------------------------------------- */
381
382static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
383{
384 int err;
385 aufs_bindex_t bbot, bindex;
386 struct inode *inode;
387 struct super_block *sb;
388
389 err = 0;
390 sb = dentry->d_sb;
391 inode = d_inode(dentry);
392 IMustLock(inode);
393 bbot = au_dbbot(dentry);
394 for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) {
395 struct path h_path;
396
397 if (au_test_ro(sb, bindex, inode))
398 continue;
399 h_path.dentry = au_h_dptr(dentry, bindex);
400 if (!h_path.dentry)
401 continue;
402
403 h_path.mnt = au_sbr_mnt(sb, bindex);
404 err = vfsub_fsync(NULL, &h_path, datasync);
405 }
406
407 return err;
408}
409
410static int au_do_fsync_dir(struct file *file, int datasync)
411{
412 int err;
413 aufs_bindex_t bbot, bindex;
414 struct file *h_file;
415 struct super_block *sb;
416 struct inode *inode;
417
418 err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
419 if (unlikely(err))
420 goto out;
421
422 inode = file_inode(file);
423 sb = inode->i_sb;
424 bbot = au_fbbot_dir(file);
425 for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
426 h_file = au_hf_dir(file, bindex);
427 if (!h_file || au_test_ro(sb, bindex, inode))
428 continue;
429
430 err = vfsub_fsync(h_file, &h_file->f_path, datasync);
431 }
432
433out:
434 return err;
435}
436
437/*
438 * @file may be NULL
439 */
440static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
441 int datasync)
442{
443 int err;
444 struct dentry *dentry;
445 struct inode *inode;
446 struct super_block *sb;
447
448 err = 0;
449 dentry = file->f_path.dentry;
450 inode = d_inode(dentry);
451 inode_lock(inode);
452 sb = dentry->d_sb;
453 si_noflush_read_lock(sb);
454 if (file)
455 err = au_do_fsync_dir(file, datasync);
456 else {
457 di_write_lock_child(dentry);
458 err = au_do_fsync_dir_no_file(dentry, datasync);
459 }
460 au_cpup_attr_timesizes(inode);
461 di_write_unlock(dentry);
462 if (file)
463 fi_write_unlock(file);
464
465 si_read_unlock(sb);
466 inode_unlock(inode);
467 return err;
468}
469
470/* ---------------------------------------------------------------------- */
471
472static int aufs_iterate_shared(struct file *file, struct dir_context *ctx)
473{
474 int err;
475 struct dentry *dentry;
476 struct inode *inode, *h_inode;
477 struct super_block *sb;
478
479 AuDbg("%pD, ctx{%pf, %llu}\n", file, ctx->actor, ctx->pos);
480
481 dentry = file->f_path.dentry;
482 inode = d_inode(dentry);
483 IMustLock(inode);
484
485 sb = dentry->d_sb;
486 si_read_lock(sb, AuLock_FLUSH);
487 err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1, /*fi_lsc*/0);
488 if (unlikely(err))
489 goto out;
490 err = au_alive_dir(dentry);
491 if (!err)
492 err = au_vdir_init(file);
493 di_downgrade_lock(dentry, AuLock_IR);
494 if (unlikely(err))
495 goto out_unlock;
496
497 h_inode = au_h_iptr(inode, au_ibtop(inode));
498 if (!au_test_nfsd()) {
499 err = au_vdir_fill_de(file, ctx);
500 fsstack_copy_attr_atime(inode, h_inode);
501 } else {
502 /*
503 * nfsd filldir may call lookup_one_len(), vfs_getattr(),
504 * encode_fh() and others.
505 */
506 atomic_inc(&h_inode->i_count);
507 di_read_unlock(dentry, AuLock_IR);
508 si_read_unlock(sb);
509 err = au_vdir_fill_de(file, ctx);
510 fsstack_copy_attr_atime(inode, h_inode);
511 fi_write_unlock(file);
512 iput(h_inode);
513
514 AuTraceErr(err);
515 return err;
516 }
517
518out_unlock:
519 di_read_unlock(dentry, AuLock_IR);
520 fi_write_unlock(file);
521out:
522 si_read_unlock(sb);
523 return err;
524}
525
526/* ---------------------------------------------------------------------- */
527
528#define AuTestEmpty_WHONLY 1
529#define AuTestEmpty_CALLED (1 << 1)
530#define AuTestEmpty_SHWH (1 << 2)
531#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
532#define au_fset_testempty(flags, name) \
533 do { (flags) |= AuTestEmpty_##name; } while (0)
534#define au_fclr_testempty(flags, name) \
535 do { (flags) &= ~AuTestEmpty_##name; } while (0)
536
537#ifndef CONFIG_AUFS_SHWH
538#undef AuTestEmpty_SHWH
539#define AuTestEmpty_SHWH 0
540#endif
541
542struct test_empty_arg {
543 struct dir_context ctx;
544 struct au_nhash *whlist;
545 unsigned int flags;
546 int err;
547 aufs_bindex_t bindex;
548};
549
550static int test_empty_cb(struct dir_context *ctx, const char *__name,
551 int namelen, loff_t offset __maybe_unused, u64 ino,
552 unsigned int d_type)
553{
554 struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg,
555 ctx);
556 char *name = (void *)__name;
557
558 arg->err = 0;
559 au_fset_testempty(arg->flags, CALLED);
560 /* smp_mb(); */
561 if (name[0] == '.'
562 && (namelen == 1 || (name[1] == '.' && namelen == 2)))
563 goto out; /* success */
564
565 if (namelen <= AUFS_WH_PFX_LEN
566 || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
567 if (au_ftest_testempty(arg->flags, WHONLY)
568 && !au_nhash_test_known_wh(arg->whlist, name, namelen))
569 arg->err = -ENOTEMPTY;
570 goto out;
571 }
572
573 name += AUFS_WH_PFX_LEN;
574 namelen -= AUFS_WH_PFX_LEN;
575 if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
576 arg->err = au_nhash_append_wh
577 (arg->whlist, name, namelen, ino, d_type, arg->bindex,
578 au_ftest_testempty(arg->flags, SHWH));
579
580out:
581 /* smp_mb(); */
582 AuTraceErr(arg->err);
583 return arg->err;
584}
585
586static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
587{
588 int err;
589 struct file *h_file;
590
591 h_file = au_h_open(dentry, arg->bindex,
592 O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
593 /*file*/NULL, /*force_wr*/0);
594 err = PTR_ERR(h_file);
595 if (IS_ERR(h_file))
596 goto out;
597
598 err = 0;
599 if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
600 && !file_inode(h_file)->i_nlink)
601 goto out_put;
602
603 do {
604 arg->err = 0;
605 au_fclr_testempty(arg->flags, CALLED);
606 /* smp_mb(); */
607 err = vfsub_iterate_dir(h_file, &arg->ctx);
608 if (err >= 0)
609 err = arg->err;
610 } while (!err && au_ftest_testempty(arg->flags, CALLED));
611
612out_put:
613 fput(h_file);
614 au_sbr_put(dentry->d_sb, arg->bindex);
615out:
616 return err;
617}
618
619struct do_test_empty_args {
620 int *errp;
621 struct dentry *dentry;
622 struct test_empty_arg *arg;
623};
624
625static void call_do_test_empty(void *args)
626{
627 struct do_test_empty_args *a = args;
628 *a->errp = do_test_empty(a->dentry, a->arg);
629}
630
631static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
632{
633 int err, wkq_err;
634 struct dentry *h_dentry;
635 struct inode *h_inode;
636
637 h_dentry = au_h_dptr(dentry, arg->bindex);
638 h_inode = d_inode(h_dentry);
639 /* todo: i_mode changes anytime? */
640 vfsub_inode_lock_shared_nested(h_inode, AuLsc_I_CHILD);
641 err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
642 inode_unlock_shared(h_inode);
643 if (!err)
644 err = do_test_empty(dentry, arg);
645 else {
646 struct do_test_empty_args args = {
647 .errp = &err,
648 .dentry = dentry,
649 .arg = arg
650 };
651 unsigned int flags = arg->flags;
652
653 wkq_err = au_wkq_wait(call_do_test_empty, &args);
654 if (unlikely(wkq_err))
655 err = wkq_err;
656 arg->flags = flags;
657 }
658
659 return err;
660}
661
662int au_test_empty_lower(struct dentry *dentry)
663{
664 int err;
665 unsigned int rdhash;
666 aufs_bindex_t bindex, btop, btail;
667 struct au_nhash whlist;
668 struct test_empty_arg arg = {
669 .ctx = {
670 .actor = test_empty_cb
671 }
672 };
673 int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg);
674
675 SiMustAnyLock(dentry->d_sb);
676
677 rdhash = au_sbi(dentry->d_sb)->si_rdhash;
678 if (!rdhash)
679 rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
680 err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
681 if (unlikely(err))
682 goto out;
683
684 arg.flags = 0;
685 arg.whlist = &whlist;
686 btop = au_dbtop(dentry);
687 if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
688 au_fset_testempty(arg.flags, SHWH);
689 test_empty = do_test_empty;
690 if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1))
691 test_empty = sio_test_empty;
692 arg.bindex = btop;
693 err = test_empty(dentry, &arg);
694 if (unlikely(err))
695 goto out_whlist;
696
697 au_fset_testempty(arg.flags, WHONLY);
698 btail = au_dbtaildir(dentry);
699 for (bindex = btop + 1; !err && bindex <= btail; bindex++) {
700 struct dentry *h_dentry;
701
702 h_dentry = au_h_dptr(dentry, bindex);
703 if (h_dentry && d_is_positive(h_dentry)) {
704 arg.bindex = bindex;
705 err = test_empty(dentry, &arg);
706 }
707 }
708
709out_whlist:
710 au_nhash_wh_free(&whlist);
711out:
712 return err;
713}
714
715int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
716{
717 int err;
718 struct test_empty_arg arg = {
719 .ctx = {
720 .actor = test_empty_cb
721 }
722 };
723 aufs_bindex_t bindex, btail;
724
725 err = 0;
726 arg.whlist = whlist;
727 arg.flags = AuTestEmpty_WHONLY;
728 if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
729 au_fset_testempty(arg.flags, SHWH);
730 btail = au_dbtaildir(dentry);
731 for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) {
732 struct dentry *h_dentry;
733
734 h_dentry = au_h_dptr(dentry, bindex);
735 if (h_dentry && d_is_positive(h_dentry)) {
736 arg.bindex = bindex;
737 err = sio_test_empty(dentry, &arg);
738 }
739 }
740
741 return err;
742}
743
744/* ---------------------------------------------------------------------- */
745
746const struct file_operations aufs_dir_fop = {
747 .owner = THIS_MODULE,
748 .llseek = default_llseek,
749 .read = generic_read_dir,
750 .iterate_shared = aufs_iterate_shared,
751 .unlocked_ioctl = aufs_ioctl_dir,
752#ifdef CONFIG_COMPAT
753 .compat_ioctl = aufs_compat_ioctl_dir,
754#endif
755 .open = aufs_open_dir,
756 .release = aufs_release_dir,
757 .flush = aufs_flush_dir,
758 .fsync = aufs_fsync_dir
759};