⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 marker.c

📁 Kernel code of linux kernel
💻 C
📖 第 1 页 / 共 2 页
字号:
{	struct hlist_head *head;	struct hlist_node *node;	struct marker_entry *e;	int found = 0;	size_t len = strlen(name) + 1;	u32 hash = jhash(name, len-1, 0);	head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];	hlist_for_each_entry(e, node, head, hlist) {		if (!strcmp(name, e->name)) {			found = 1;			break;		}	}	if (!found)		return -ENOENT;	if (e->single.func != __mark_empty_function)		return -EBUSY;	hlist_del(&e->hlist);	/* Make sure the call_rcu has been executed */	if (e->rcu_pending)		rcu_barrier_sched();	kfree(e);	return 0;}/* * Set the mark_entry format to the format found in the element. */static int marker_set_format(struct marker_entry **entry, const char *format){	struct marker_entry *e;	size_t name_len = strlen((*entry)->name) + 1;	size_t format_len = strlen(format) + 1;	e = kmalloc(sizeof(struct marker_entry) + name_len + format_len,			GFP_KERNEL);	if (!e)		return -ENOMEM;	memcpy(&e->name[0], (*entry)->name, name_len);	e->format = &e->name[name_len];	memcpy(e->format, format, format_len);	if (strcmp(e->format, MARK_NOARGS) == 0)		e->call = marker_probe_cb_noarg;	else		e->call = marker_probe_cb;	e->single = (*entry)->single;	e->multi = (*entry)->multi;	e->ptype = (*entry)->ptype;	e->refcount = (*entry)->refcount;	e->rcu_pending = 0;	hlist_add_before(&e->hlist, &(*entry)->hlist);	hlist_del(&(*entry)->hlist);	/* Make sure the call_rcu has been executed */	if ((*entry)->rcu_pending)		rcu_barrier_sched();	kfree(*entry);	*entry = e;	trace_mark(core_marker_format, "name %s format %s",			e->name, e->format);	return 0;}/* * Sets the probe callback corresponding to one marker. */static int set_marker(struct marker_entry **entry, struct marker *elem,		int active){	int ret;	WARN_ON(strcmp((*entry)->name, elem->name) != 0);	if ((*entry)->format) {		if (strcmp((*entry)->format, elem->format) != 0) {			printk(KERN_NOTICE				"Format mismatch for probe %s "				"(%s), marker (%s)\n",				(*entry)->name,				(*entry)->format,				elem->format);			return -EPERM;		}	} else {		ret = marker_set_format(entry, elem->format);		if (ret)			return ret;	}	/*	 * probe_cb setup (statically known) is done here. It is	 * asynchronous with the rest of execution, therefore we only	 * pass from a "safe" callback (with argument) to an "unsafe"	 * callback (does not set arguments).	 */	elem->call = (*entry)->call;	/*	 * Sanity check :	 * We only update the single probe private data when the ptr is	 * set to a _non_ single probe! (0 -> 1 and N -> 1, N != 1)	 */	WARN_ON(elem->single.func != __mark_empty_function		&& elem->single.probe_private		!= (*entry)->single.probe_private &&		!elem->ptype);	elem->single.probe_private = (*entry)->single.probe_private;	/*	 * Make sure the private data is valid when we update the	 * single probe ptr.	 */	smp_wmb();	elem->single.func = (*entry)->single.func;	/*	 * We also make sure that the new probe callbacks array is consistent	 * before setting a pointer to it.	 */	rcu_assign_pointer(elem->multi, (*entry)->multi);	/*	 * Update the function or multi probe array pointer before setting the	 * ptype.	 */	smp_wmb();	elem->ptype = (*entry)->ptype;	elem->state = active;	return 0;}/* * Disable a marker and its probe callback. * Note: only waiting an RCU period after setting elem->call to the empty * function insures that the original callback is not used anymore. This insured * by preempt_disable around the call site. */static void disable_marker(struct marker *elem){	/* leave "call" as is. It is known statically. */	elem->state = 0;	elem->single.func = __mark_empty_function;	/* Update the function before setting the ptype */	smp_wmb();	elem->ptype = 0;	/* single probe */	/*	 * Leave the private data and id there, because removal is racy and	 * should be done only after an RCU period. These are never used until	 * the next initialization anyway.	 */}/** * marker_update_probe_range - Update a probe range * @begin: beginning of the range * @end: end of the range * * Updates the probe callback corresponding to a range of markers. */void marker_update_probe_range(struct marker *begin,	struct marker *end){	struct marker *iter;	struct marker_entry *mark_entry;	mutex_lock(&markers_mutex);	for (iter = begin; iter < end; iter++) {		mark_entry = get_marker(iter->name);		if (mark_entry) {			set_marker(&mark_entry, iter,					!!mark_entry->refcount);			/*			 * ignore error, continue			 */		} else {			disable_marker(iter);		}	}	mutex_unlock(&markers_mutex);}/* * Update probes, removing the faulty probes. * * Internal callback only changed before the first probe is connected to it. * Single probe private data can only be changed on 0 -> 1 and 2 -> 1 * transitions.  All other transitions will leave the old private data valid. * This makes the non-atomicity of the callback/private data updates valid. * * "special case" updates : * 0 -> 1 callback * 1 -> 0 callback * 1 -> 2 callbacks * 2 -> 1 callbacks * Other updates all behave the same, just like the 2 -> 3 or 3 -> 2 updates. * Site effect : marker_set_format may delete the marker entry (creating a * replacement). */static void marker_update_probes(void){	/* Core kernel markers */	marker_update_probe_range(__start___markers, __stop___markers);	/* Markers in modules. */	module_update_markers();}/** * marker_probe_register -  Connect a probe to a marker * @name: marker name * @format: format string * @probe: probe handler * @probe_private: probe private data * * private data must be a valid allocated memory address, or NULL. * Returns 0 if ok, error value on error. * The probe address must at least be aligned on the architecture pointer size. */int marker_probe_register(const char *name, const char *format,			marker_probe_func *probe, void *probe_private){	struct marker_entry *entry;	int ret = 0;	struct marker_probe_closure *old;	mutex_lock(&markers_mutex);	entry = get_marker(name);	if (!entry) {		entry = add_marker(name, format);		if (IS_ERR(entry)) {			ret = PTR_ERR(entry);			goto end;		}	}	/*	 * If we detect that a call_rcu is pending for this marker,	 * make sure it's executed now.	 */	if (entry->rcu_pending)		rcu_barrier_sched();	old = marker_entry_add_probe(entry, probe, probe_private);	if (IS_ERR(old)) {		ret = PTR_ERR(old);		goto end;	}	mutex_unlock(&markers_mutex);	marker_update_probes();		/* may update entry */	mutex_lock(&markers_mutex);	entry = get_marker(name);	WARN_ON(!entry);	entry->oldptr = old;	entry->rcu_pending = 1;	/* write rcu_pending before calling the RCU callback */	smp_wmb();	call_rcu_sched(&entry->rcu, free_old_closure);end:	mutex_unlock(&markers_mutex);	return ret;}EXPORT_SYMBOL_GPL(marker_probe_register);/** * marker_probe_unregister -  Disconnect a probe from a marker * @name: marker name * @probe: probe function pointer * @probe_private: probe private data * * Returns the private data given to marker_probe_register, or an ERR_PTR(). * We do not need to call a synchronize_sched to make sure the probes have * finished running before doing a module unload, because the module unload * itself uses stop_machine(), which insures that every preempt disabled section * have finished. */int marker_probe_unregister(const char *name,	marker_probe_func *probe, void *probe_private){	struct marker_entry *entry;	struct marker_probe_closure *old;	int ret = -ENOENT;	mutex_lock(&markers_mutex);	entry = get_marker(name);	if (!entry)		goto end;	if (entry->rcu_pending)		rcu_barrier_sched();	old = marker_entry_remove_probe(entry, probe, probe_private);	mutex_unlock(&markers_mutex);	marker_update_probes();		/* may update entry */	mutex_lock(&markers_mutex);	entry = get_marker(name);	if (!entry)		goto end;	entry->oldptr = old;	entry->rcu_pending = 1;	/* write rcu_pending before calling the RCU callback */	smp_wmb();	call_rcu_sched(&entry->rcu, free_old_closure);	remove_marker(name);	/* Ignore busy error message */	ret = 0;end:	mutex_unlock(&markers_mutex);	return ret;}EXPORT_SYMBOL_GPL(marker_probe_unregister);static struct marker_entry *get_marker_from_private_data(marker_probe_func *probe, void *probe_private){	struct marker_entry *entry;	unsigned int i;	struct hlist_head *head;	struct hlist_node *node;	for (i = 0; i < MARKER_TABLE_SIZE; i++) {		head = &marker_table[i];		hlist_for_each_entry(entry, node, head, hlist) {			if (!entry->ptype) {				if (entry->single.func == probe						&& entry->single.probe_private						== probe_private)					return entry;			} else {				struct marker_probe_closure *closure;				closure = entry->multi;				for (i = 0; closure[i].func; i++) {					if (closure[i].func == probe &&							closure[i].probe_private							== probe_private)						return entry;				}			}		}	}	return NULL;}/** * marker_probe_unregister_private_data -  Disconnect a probe from a marker * @probe: probe function * @probe_private: probe private data * * Unregister a probe by providing the registered private data. * Only removes the first marker found in hash table. * Return 0 on success or error value. * We do not need to call a synchronize_sched to make sure the probes have * finished running before doing a module unload, because the module unload * itself uses stop_machine(), which insures that every preempt disabled section * have finished. */int marker_probe_unregister_private_data(marker_probe_func *probe,		void *probe_private){	struct marker_entry *entry;	int ret = 0;	struct marker_probe_closure *old;	mutex_lock(&markers_mutex);	entry = get_marker_from_private_data(probe, probe_private);	if (!entry) {		ret = -ENOENT;		goto end;	}	if (entry->rcu_pending)		rcu_barrier_sched();	old = marker_entry_remove_probe(entry, NULL, probe_private);	mutex_unlock(&markers_mutex);	marker_update_probes();		/* may update entry */	mutex_lock(&markers_mutex);	entry = get_marker_from_private_data(probe, probe_private);	WARN_ON(!entry);	entry->oldptr = old;	entry->rcu_pending = 1;	/* write rcu_pending before calling the RCU callback */	smp_wmb();	call_rcu_sched(&entry->rcu, free_old_closure);	remove_marker(entry->name);	/* Ignore busy error message */end:	mutex_unlock(&markers_mutex);	return ret;}EXPORT_SYMBOL_GPL(marker_probe_unregister_private_data);/** * marker_get_private_data - Get a marker's probe private data * @name: marker name * @probe: probe to match * @num: get the nth matching probe's private data * * Returns the nth private data pointer (starting from 0) matching, or an * ERR_PTR. * Returns the private data pointer, or an ERR_PTR. * The private data pointer should _only_ be dereferenced if the caller is the * owner of the data, or its content could vanish. This is mostly used to * confirm that a caller is the owner of a registered probe. */void *marker_get_private_data(const char *name, marker_probe_func *probe,		int num){	struct hlist_head *head;	struct hlist_node *node;	struct marker_entry *e;	size_t name_len = strlen(name) + 1;	u32 hash = jhash(name, name_len-1, 0);	int i;	head = &marker_table[hash & ((1 << MARKER_HASH_BITS)-1)];	hlist_for_each_entry(e, node, head, hlist) {		if (!strcmp(name, e->name)) {			if (!e->ptype) {				if (num == 0 && e->single.func == probe)					return e->single.probe_private;				else					break;			} else {				struct marker_probe_closure *closure;				int match = 0;				closure = e->multi;				for (i = 0; closure[i].func; i++) {					if (closure[i].func != probe)						continue;					if (match++ == num)						return closure[i].probe_private;				}			}		}	}	return ERR_PTR(-ENOENT);}EXPORT_SYMBOL_GPL(marker_get_private_data);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -