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