static int au_hfsn_handle_event(struct fsnotify_group *group, struct fsnotify_mark *inode_mark, struct fsnotify_mark *vfsmount_mark, struct fsnotify_event *event) { int err; struct au_hnotify *hnotify; struct inode *h_dir, *h_inode; __u32 mask; struct qstr h_child_qstr = { .name = event->file_name, .len = event->name_len }; AuDebugOn(event->data_type != FSNOTIFY_EVENT_INODE); err = 0; /* if FS_UNMOUNT happens, there must be another bug */ mask = event->mask; AuDebugOn(mask & FS_UNMOUNT); if (mask & (FS_IN_IGNORED | FS_UNMOUNT)) goto out; h_dir = event->to_tell; h_inode = event->inode; #ifdef AuDbgHnotify au_debug(1); if (1 || h_child_qstr.len != sizeof(AUFS_XINO_FNAME) - 1 || strncmp(h_child_qstr.name, AUFS_XINO_FNAME, h_child_qstr.len)) { AuDbg("i%lu, mask 0x%x %s, hcname %.*s, hi%lu\n", h_dir->i_ino, mask, au_hfsn_name(mask), AuLNPair(&h_child_qstr), h_inode ? h_inode->i_ino : 0); /* WARN_ON(1); */ } au_debug(0); #endif AuDebugOn(!inode_mark); hnotify = container_of(inode_mark, struct au_hnotify, hn_mark); err = au_hnotify(h_dir, hnotify, mask, &h_child_qstr, h_inode); out: return err; } /* isn't it waste to ask every registered 'group'? */ /* copied from linux/fs/notify/inotify/inotify_fsnotiry.c */ /* it should be exported to modules */ static bool au_hfsn_should_send_event(struct fsnotify_group *group, struct inode *h_inode, struct fsnotify_mark *inode_mark, struct fsnotify_mark *vfsmount_mark, __u32 mask, void *data, int data_type) { mask = (mask & ~FS_EVENT_ON_CHILD); return inode_mark->mask & mask; }
/* * returns a negative dentry whose name is unique and temporary. */ struct dentry *au_whtmp_lkup(struct dentry *h_parent, struct au_branch *br, struct qstr *prefix) { struct dentry *dentry; int i; char defname[NAME_MAX - AUFS_MAX_NAMELEN + DNAME_INLINE_LEN + 1], *name, *p; /* strict atomic_t is unnecessary here */ static unsigned short cnt; struct qstr qs; BUILD_BUG_ON(sizeof(cnt) * 2 > AUFS_WH_TMP_LEN); name = defname; qs.len = sizeof(defname) - DNAME_INLINE_LEN + prefix->len - 1; if (unlikely(prefix->len > DNAME_INLINE_LEN)) { dentry = ERR_PTR(-ENAMETOOLONG); if (unlikely(qs.len > NAME_MAX)) goto out; dentry = ERR_PTR(-ENOMEM); name = kmalloc(qs.len + 1, GFP_NOFS); if (unlikely(!name)) goto out; } /* doubly whiteout-ed */ memcpy(name, AUFS_WH_PFX AUFS_WH_PFX, AUFS_WH_PFX_LEN * 2); p = name + AUFS_WH_PFX_LEN * 2; memcpy(p, prefix->name, prefix->len); p += prefix->len; *p++ = '.'; AuDebugOn(name + qs.len + 1 - p <= AUFS_WH_TMP_LEN); qs.name = name; for (i = 0; i < 3; i++) { sprintf(p, "%.*x", AUFS_WH_TMP_LEN, cnt++); dentry = au_sio_lkup_one(&qs, h_parent, br); if (IS_ERR(dentry) || !dentry->d_inode) goto out_name; dput(dentry); } /* pr_warn("could not get random name\n"); */ dentry = ERR_PTR(-EEXIST); AuDbg("%.*s\n", AuLNPair(&qs)); BUG(); out_name: if (name != defname) kfree(name); out: AuTraceErrPtr(dentry); return dentry; }
struct dentry *vfsub__lookup_hash(struct qstr *name, struct dentry *parent, struct nameidata *nd) { struct dentry *d; LKTRTrace("%.*s/%.*s, nd %d\n", AuDLNPair(parent), AuLNPair(name), !!nd); if (nd) LKTRTrace("nd{0x%x}\n", nd->flags); IMustLock(parent->d_inode); d = __lookup_hash(name, parent, nd); if (!IS_ERR(d)) au_update_fuse_h_inode(NULL, d); /*ignore*/ return d; }