/* nothing else could have found us thanks to the dnotify_groups
mark_mutex */ if (dn_mark->dn == NULL) {
fsnotify_detach_mark(fsn_mark);
free = true;
}
fsnotify_group_unlock(dnotify_group);
if (free)
fsnotify_free_mark(fsn_mark);
fsnotify_put_mark(fsn_mark);
}
/* this conversion is done only at watch creation */ static __u32 convert_arg(unsignedint arg)
{
__u32 new_mask = FS_EVENT_ON_CHILD;
if (arg & DN_MULTISHOT)
new_mask |= FS_DN_MULTISHOT; if (arg & DN_DELETE)
new_mask |= (FS_DELETE | FS_MOVED_FROM); if (arg & DN_MODIFY)
new_mask |= FS_MODIFY; if (arg & DN_ACCESS)
new_mask |= FS_ACCESS; if (arg & DN_ATTRIB)
new_mask |= FS_ATTRIB; if (arg & DN_RENAME)
new_mask |= FS_RENAME; if (arg & DN_CREATE)
new_mask |= (FS_CREATE | FS_MOVED_TO);
error = security_path_notify(&filp->f_path, mask,
FSNOTIFY_OBJ_TYPE_INODE); if (error) goto out_err;
/* expect most fcntl to add new rather than augment old */
dn = kmem_cache_alloc(dnotify_struct_cache, GFP_KERNEL); if (!dn) {
error = -ENOMEM; goto out_err;
}
error = file_f_owner_allocate(filp); if (error) goto out_err;
/* new fsnotify mark, we expect most fcntl calls to add a new mark */
new_dn_mark = kmem_cache_alloc(dnotify_mark_cache, GFP_KERNEL); if (!new_dn_mark) {
error = -ENOMEM; goto out_err;
}
/* set up the new_fsn_mark and new_dn_mark */
new_fsn_mark = &new_dn_mark->fsn_mark;
fsnotify_init_mark(new_fsn_mark, dnotify_group);
new_fsn_mark->mask = mask;
new_dn_mark->dn = NULL;
/* this is needed to prevent the fcntl/close race described below */
fsnotify_group_lock(dnotify_group);
/* add the new_fsn_mark or find an old one. */
fsn_mark = fsnotify_find_inode_mark(inode, dnotify_group); if (fsn_mark) {
dn_mark = container_of(fsn_mark, struct dnotify_mark, fsn_mark);
spin_lock(&fsn_mark->lock);
} else {
error = fsnotify_add_inode_mark_locked(new_fsn_mark, inode, 0); if (error) {
fsnotify_group_unlock(dnotify_group); goto out_err;
}
spin_lock(&new_fsn_mark->lock);
fsn_mark = new_fsn_mark;
dn_mark = new_dn_mark; /* we used new_fsn_mark, so don't free it */
new_fsn_mark = NULL;
}
f = fget_raw(fd);
/* if (f != filp) means that we lost a race and another task/thread *actuallyclosedthefdwearestillplayingwithbeforewegrabbed *thednotify_groupsmark_mutexandfsn_mark->lock.Sinceclosingthe *fdistheonlytimewecleanupthemarksweneedtogetourmark
* off the list. */ if (f != filp) { /* if we added ourselves, shoot ourselves, it's possible that *theflushactuallydidshootthisfsn_mark.That'sfinetoo *sincemultiplecallstodestroy_markisperfectlysafe,if *wefoundadn_markalreadyattachedtotheinode,justsod *offsilentlyastheflushatclosetimedealtwithit.
*/ if (dn_mark == new_dn_mark)
destroy = 1;
error = 0; goto out;
}
error = attach_dn(dn, dn_mark, id, fd, filp, mask); /* !error means that we attached the dn to the dn_mark, so don't free it */ if (!error)
dn = NULL; /* -EEXIST means that we didn't add this new dn and used an old one.
* that isn't an error (and the unused dn should be freed) */ elseif (error == -EEXIST)
error = 0;
if (destroy)
fsnotify_detach_mark(fsn_mark);
fsnotify_group_unlock(dnotify_group); if (destroy)
fsnotify_free_mark(fsn_mark);
fsnotify_put_mark(fsn_mark);
out_err: if (new_fsn_mark)
fsnotify_put_mark(new_fsn_mark); if (dn)
kmem_cache_free(dnotify_struct_cache, dn); if (f)
fput(f); return error;
}
dnotify_group = fsnotify_alloc_group(&dnotify_fsnotify_ops, 0); if (IS_ERR(dnotify_group))
panic("unable to allocate fsnotify group for dnotify\n");
dnotify_sysctl_init(); return0;
}
module_init(dnotify_init)
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-09-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.