static int test_overlap(struct super_block *sb, struct dentry *h_adding, struct dentry *h_root) { if (unlikely(h_adding == h_root || au_test_loopback_overlap(sb, h_adding))) return 1; if (h_adding->d_sb != h_root->d_sb) return 0; return au_test_subdir(h_adding, h_root) || au_test_subdir(h_root, h_adding); }
/* * test if two lower dentries have overlapping branches. */ int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding) { struct super_block *h_sb; struct file *backing_file; if (unlikely(!backing_file_func)) { /* don't load "loop" module here */ backing_file_func = symbol_get(loop_backing_file); if (unlikely(!backing_file_func)) /* "loop" module is not loaded */ return 0; } h_sb = h_adding->d_sb; backing_file = backing_file_func(h_sb); if (!backing_file) return 0; h_adding = backing_file->f_path.dentry; /* * h_adding can be local NFS. * in this case aufs cannot detect the loop. */ if (unlikely(h_adding->d_sb == sb)) return 1; return !!au_test_subdir(h_adding, sb->s_root); }
void di_write_lock2_parent(struct dentry *d1, struct dentry *d2, int isdir) { AuDebugOn(d1 == d2 || d1->d_inode == d2->d_inode || d1->d_sb != d2->d_sb); if (isdir && au_test_subdir(d1, d2)) { di_write_lock_parent(d1); di_write_lock_parent2(d2); } else { /* there should be no races */ di_write_lock_parent(d2); di_write_lock_parent2(d1); } }
/* * test if two lower dentries have overlapping branches. */ int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_d1, struct dentry *h_d2) { struct inode *h_inode; struct loop_device *l; h_inode = h_d1->d_inode; if (MAJOR(h_inode->i_sb->s_dev) != LOOP_MAJOR) return 0; l = h_inode->i_sb->s_bdev->bd_disk->private_data; h_d1 = l->lo_backing_file->f_dentry; /* h_d1 can be local NFS. in this case aufs cannot detect the loop */ if (unlikely(h_d1->d_sb == sb)) return 1; return au_test_subdir(h_d1, h_d2); }
/* * test if two lower dentries have overlapping branches. */ int au_test_loopback_overlap(struct super_block *sb, struct dentry *h_adding) { struct super_block *h_sb; struct loop_device *l; h_sb = h_adding->d_sb; if (MAJOR(h_sb->s_dev) != LOOP_MAJOR) return 0; l = h_sb->s_bdev->bd_disk->private_data; h_adding = l->lo_backing_file->f_dentry; /* * h_adding can be local NFS. * in this case aufs cannot detect the loop. */ if (unlikely(h_adding->d_sb == sb)) return 1; return !!au_test_subdir(h_adding, sb->s_root); }