]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blame - fs/aufs/dir.c
Revert "UBUNTU: SAUCE: aufs -- Convert to use xattr handlers"
[mirror_ubuntu-zesty-kernel.git] / fs / aufs / dir.c
CommitLineData
5b88fdd9
SF
1/*
2 * Copyright (C) 2005-2016 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 au_delayed_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 au_delayed_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 au_delayed_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 int execed, delayed;
329
330 delayed = (current->flags & PF_KTHREAD) || in_interrupt();
331 finfo = au_fi(file);
332 fidir = finfo->fi_hdir;
333 if (fidir) {
334 au_sphl_del(&finfo->fi_hlist,
335 &au_sbi(file->f_path.dentry->d_sb)->si_files);
336 vdir_cache = fidir->fd_vdir_cache; /* lock-free */
337 if (vdir_cache)
338 au_vdir_free(vdir_cache, delayed);
339
340 bindex = finfo->fi_btop;
341 if (bindex >= 0) {
342 execed = vfsub_file_execed(file);
343 hf = fidir->fd_hfile + bindex;
344 /*
345 * calls fput() instead of filp_close(),
346 * since no dnotify or lock for the lower file.
347 */
348 bbot = fidir->fd_bbot;
349 for (; bindex <= bbot; bindex++, hf++)
350 if (hf->hf_file)
351 au_hfput(hf, execed);
352 }
353 au_delayed_kfree(fidir);
354 finfo->fi_hdir = NULL;
355 }
356 au_finfo_fin(file, delayed);
357 return 0;
358}
359
360/* ---------------------------------------------------------------------- */
361
362static int au_do_flush_dir(struct file *file, fl_owner_t id)
363{
364 int err;
365 aufs_bindex_t bindex, bbot;
366 struct file *h_file;
367
368 err = 0;
369 bbot = au_fbbot_dir(file);
370 for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
371 h_file = au_hf_dir(file, bindex);
372 if (h_file)
373 err = vfsub_flush(h_file, id);
374 }
375 return err;
376}
377
378static int aufs_flush_dir(struct file *file, fl_owner_t id)
379{
380 return au_do_flush(file, id, au_do_flush_dir);
381}
382
383/* ---------------------------------------------------------------------- */
384
385static int au_do_fsync_dir_no_file(struct dentry *dentry, int datasync)
386{
387 int err;
388 aufs_bindex_t bbot, bindex;
389 struct inode *inode;
390 struct super_block *sb;
391
392 err = 0;
393 sb = dentry->d_sb;
394 inode = d_inode(dentry);
395 IMustLock(inode);
396 bbot = au_dbbot(dentry);
397 for (bindex = au_dbtop(dentry); !err && bindex <= bbot; bindex++) {
398 struct path h_path;
399
400 if (au_test_ro(sb, bindex, inode))
401 continue;
402 h_path.dentry = au_h_dptr(dentry, bindex);
403 if (!h_path.dentry)
404 continue;
405
406 h_path.mnt = au_sbr_mnt(sb, bindex);
407 err = vfsub_fsync(NULL, &h_path, datasync);
408 }
409
410 return err;
411}
412
413static int au_do_fsync_dir(struct file *file, int datasync)
414{
415 int err;
416 aufs_bindex_t bbot, bindex;
417 struct file *h_file;
418 struct super_block *sb;
419 struct inode *inode;
420
421 err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
422 if (unlikely(err))
423 goto out;
424
425 inode = file_inode(file);
426 sb = inode->i_sb;
427 bbot = au_fbbot_dir(file);
428 for (bindex = au_fbtop(file); !err && bindex <= bbot; bindex++) {
429 h_file = au_hf_dir(file, bindex);
430 if (!h_file || au_test_ro(sb, bindex, inode))
431 continue;
432
433 err = vfsub_fsync(h_file, &h_file->f_path, datasync);
434 }
435
436out:
437 return err;
438}
439
440/*
441 * @file may be NULL
442 */
443static int aufs_fsync_dir(struct file *file, loff_t start, loff_t end,
444 int datasync)
445{
446 int err;
447 struct dentry *dentry;
448 struct inode *inode;
449 struct super_block *sb;
450
451 err = 0;
452 dentry = file->f_path.dentry;
453 inode = d_inode(dentry);
454 inode_lock(inode);
455 sb = dentry->d_sb;
456 si_noflush_read_lock(sb);
457 if (file)
458 err = au_do_fsync_dir(file, datasync);
459 else {
460 di_write_lock_child(dentry);
461 err = au_do_fsync_dir_no_file(dentry, datasync);
462 }
463 au_cpup_attr_timesizes(inode);
464 di_write_unlock(dentry);
465 if (file)
466 fi_write_unlock(file);
467
468 si_read_unlock(sb);
469 inode_unlock(inode);
470 return err;
471}
472
473/* ---------------------------------------------------------------------- */
474
475static int aufs_iterate_shared(struct file *file, struct dir_context *ctx)
476{
477 int err;
478 struct dentry *dentry;
479 struct inode *inode, *h_inode;
480 struct super_block *sb;
481
482 AuDbg("%pD, ctx{%pf, %llu}\n", file, ctx->actor, ctx->pos);
483
484 dentry = file->f_path.dentry;
485 inode = d_inode(dentry);
486 IMustLock(inode);
487
488 sb = dentry->d_sb;
489 si_read_lock(sb, AuLock_FLUSH);
490 err = au_reval_and_lock_fdi(file, reopen_dir, /*wlock*/1);
491 if (unlikely(err))
492 goto out;
493 err = au_alive_dir(dentry);
494 if (!err)
495 err = au_vdir_init(file);
496 di_downgrade_lock(dentry, AuLock_IR);
497 if (unlikely(err))
498 goto out_unlock;
499
500 h_inode = au_h_iptr(inode, au_ibtop(inode));
501 if (!au_test_nfsd()) {
502 err = au_vdir_fill_de(file, ctx);
503 fsstack_copy_attr_atime(inode, h_inode);
504 } else {
505 /*
506 * nfsd filldir may call lookup_one_len(), vfs_getattr(),
507 * encode_fh() and others.
508 */
509 atomic_inc(&h_inode->i_count);
510 di_read_unlock(dentry, AuLock_IR);
511 si_read_unlock(sb);
512 err = au_vdir_fill_de(file, ctx);
513 fsstack_copy_attr_atime(inode, h_inode);
514 fi_write_unlock(file);
515 iput(h_inode);
516
517 AuTraceErr(err);
518 return err;
519 }
520
521out_unlock:
522 di_read_unlock(dentry, AuLock_IR);
523 fi_write_unlock(file);
524out:
525 si_read_unlock(sb);
526 return err;
527}
528
529/* ---------------------------------------------------------------------- */
530
531#define AuTestEmpty_WHONLY 1
532#define AuTestEmpty_CALLED (1 << 1)
533#define AuTestEmpty_SHWH (1 << 2)
534#define au_ftest_testempty(flags, name) ((flags) & AuTestEmpty_##name)
535#define au_fset_testempty(flags, name) \
536 do { (flags) |= AuTestEmpty_##name; } while (0)
537#define au_fclr_testempty(flags, name) \
538 do { (flags) &= ~AuTestEmpty_##name; } while (0)
539
540#ifndef CONFIG_AUFS_SHWH
541#undef AuTestEmpty_SHWH
542#define AuTestEmpty_SHWH 0
543#endif
544
545struct test_empty_arg {
546 struct dir_context ctx;
547 struct au_nhash *whlist;
548 unsigned int flags;
549 int err;
550 aufs_bindex_t bindex;
551};
552
553static int test_empty_cb(struct dir_context *ctx, const char *__name,
554 int namelen, loff_t offset __maybe_unused, u64 ino,
555 unsigned int d_type)
556{
557 struct test_empty_arg *arg = container_of(ctx, struct test_empty_arg,
558 ctx);
559 char *name = (void *)__name;
560
561 arg->err = 0;
562 au_fset_testempty(arg->flags, CALLED);
563 /* smp_mb(); */
564 if (name[0] == '.'
565 && (namelen == 1 || (name[1] == '.' && namelen == 2)))
566 goto out; /* success */
567
568 if (namelen <= AUFS_WH_PFX_LEN
569 || memcmp(name, AUFS_WH_PFX, AUFS_WH_PFX_LEN)) {
570 if (au_ftest_testempty(arg->flags, WHONLY)
571 && !au_nhash_test_known_wh(arg->whlist, name, namelen))
572 arg->err = -ENOTEMPTY;
573 goto out;
574 }
575
576 name += AUFS_WH_PFX_LEN;
577 namelen -= AUFS_WH_PFX_LEN;
578 if (!au_nhash_test_known_wh(arg->whlist, name, namelen))
579 arg->err = au_nhash_append_wh
580 (arg->whlist, name, namelen, ino, d_type, arg->bindex,
581 au_ftest_testempty(arg->flags, SHWH));
582
583out:
584 /* smp_mb(); */
585 AuTraceErr(arg->err);
586 return arg->err;
587}
588
589static int do_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
590{
591 int err;
592 struct file *h_file;
593
594 h_file = au_h_open(dentry, arg->bindex,
595 O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_LARGEFILE,
596 /*file*/NULL, /*force_wr*/0);
597 err = PTR_ERR(h_file);
598 if (IS_ERR(h_file))
599 goto out;
600
601 err = 0;
602 if (!au_opt_test(au_mntflags(dentry->d_sb), UDBA_NONE)
603 && !file_inode(h_file)->i_nlink)
604 goto out_put;
605
606 do {
607 arg->err = 0;
608 au_fclr_testempty(arg->flags, CALLED);
609 /* smp_mb(); */
610 err = vfsub_iterate_dir(h_file, &arg->ctx);
611 if (err >= 0)
612 err = arg->err;
613 } while (!err && au_ftest_testempty(arg->flags, CALLED));
614
615out_put:
616 fput(h_file);
617 au_sbr_put(dentry->d_sb, arg->bindex);
618out:
619 return err;
620}
621
622struct do_test_empty_args {
623 int *errp;
624 struct dentry *dentry;
625 struct test_empty_arg *arg;
626};
627
628static void call_do_test_empty(void *args)
629{
630 struct do_test_empty_args *a = args;
631 *a->errp = do_test_empty(a->dentry, a->arg);
632}
633
634static int sio_test_empty(struct dentry *dentry, struct test_empty_arg *arg)
635{
636 int err, wkq_err;
637 struct dentry *h_dentry;
638 struct inode *h_inode;
639
640 h_dentry = au_h_dptr(dentry, arg->bindex);
641 h_inode = d_inode(h_dentry);
642 /* todo: i_mode changes anytime? */
643 inode_lock_nested(h_inode, AuLsc_I_CHILD);
644 err = au_test_h_perm_sio(h_inode, MAY_EXEC | MAY_READ);
645 inode_unlock(h_inode);
646 if (!err)
647 err = do_test_empty(dentry, arg);
648 else {
649 struct do_test_empty_args args = {
650 .errp = &err,
651 .dentry = dentry,
652 .arg = arg
653 };
654 unsigned int flags = arg->flags;
655
656 wkq_err = au_wkq_wait(call_do_test_empty, &args);
657 if (unlikely(wkq_err))
658 err = wkq_err;
659 arg->flags = flags;
660 }
661
662 return err;
663}
664
665int au_test_empty_lower(struct dentry *dentry)
666{
667 int err;
668 unsigned int rdhash;
669 aufs_bindex_t bindex, btop, btail;
670 struct au_nhash whlist;
671 struct test_empty_arg arg = {
672 .ctx = {
673 .actor = test_empty_cb
674 }
675 };
676 int (*test_empty)(struct dentry *dentry, struct test_empty_arg *arg);
677
678 SiMustAnyLock(dentry->d_sb);
679
680 rdhash = au_sbi(dentry->d_sb)->si_rdhash;
681 if (!rdhash)
682 rdhash = au_rdhash_est(au_dir_size(/*file*/NULL, dentry));
683 err = au_nhash_alloc(&whlist, rdhash, GFP_NOFS);
684 if (unlikely(err))
685 goto out;
686
687 arg.flags = 0;
688 arg.whlist = &whlist;
689 btop = au_dbtop(dentry);
690 if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
691 au_fset_testempty(arg.flags, SHWH);
692 test_empty = do_test_empty;
693 if (au_opt_test(au_mntflags(dentry->d_sb), DIRPERM1))
694 test_empty = sio_test_empty;
695 arg.bindex = btop;
696 err = test_empty(dentry, &arg);
697 if (unlikely(err))
698 goto out_whlist;
699
700 au_fset_testempty(arg.flags, WHONLY);
701 btail = au_dbtaildir(dentry);
702 for (bindex = btop + 1; !err && bindex <= btail; bindex++) {
703 struct dentry *h_dentry;
704
705 h_dentry = au_h_dptr(dentry, bindex);
706 if (h_dentry && d_is_positive(h_dentry)) {
707 arg.bindex = bindex;
708 err = test_empty(dentry, &arg);
709 }
710 }
711
712out_whlist:
713 au_nhash_wh_free(&whlist);
714out:
715 return err;
716}
717
718int au_test_empty(struct dentry *dentry, struct au_nhash *whlist)
719{
720 int err;
721 struct test_empty_arg arg = {
722 .ctx = {
723 .actor = test_empty_cb
724 }
725 };
726 aufs_bindex_t bindex, btail;
727
728 err = 0;
729 arg.whlist = whlist;
730 arg.flags = AuTestEmpty_WHONLY;
731 if (au_opt_test(au_mntflags(dentry->d_sb), SHWH))
732 au_fset_testempty(arg.flags, SHWH);
733 btail = au_dbtaildir(dentry);
734 for (bindex = au_dbtop(dentry); !err && bindex <= btail; bindex++) {
735 struct dentry *h_dentry;
736
737 h_dentry = au_h_dptr(dentry, bindex);
738 if (h_dentry && d_is_positive(h_dentry)) {
739 arg.bindex = bindex;
740 err = sio_test_empty(dentry, &arg);
741 }
742 }
743
744 return err;
745}
746
747/* ---------------------------------------------------------------------- */
748
749const struct file_operations aufs_dir_fop = {
750 .owner = THIS_MODULE,
751 .llseek = default_llseek,
752 .read = generic_read_dir,
753 .iterate_shared = aufs_iterate_shared,
754 .unlocked_ioctl = aufs_ioctl_dir,
755#ifdef CONFIG_COMPAT
756 .compat_ioctl = aufs_compat_ioctl_dir,
757#endif
758 .open = aufs_open_dir,
759 .release = aufs_release_dir,
760 .flush = aufs_flush_dir,
761 .fsync = aufs_fsync_dir
762};