@@ -223,3 +223,243 @@ static __init int init_dynamic_event(void)
223
223
return 0 ;
224
224
}
225
225
fs_initcall (init_dynamic_event );
226
+
227
+ /**
228
+ * dynevent_arg_add - Add an arg to a dynevent_cmd
229
+ * @cmd: A pointer to the dynevent_cmd struct representing the new event cmd
230
+ * @arg: The argument to append to the current cmd
231
+ *
232
+ * Append an argument to a dynevent_cmd. The argument string will be
233
+ * appended to the current cmd string, followed by a separator, if
234
+ * applicable. Before the argument is added, the check_arg()
235
+ * function, if defined, is called.
236
+ *
237
+ * The cmd string, separator, and check_arg() function should be set
238
+ * using the dynevent_arg_init() before any arguments are added using
239
+ * this function.
240
+ *
241
+ * Return: 0 if successful, error otherwise.
242
+ */
243
+ int dynevent_arg_add (struct dynevent_cmd * cmd ,
244
+ struct dynevent_arg * arg )
245
+ {
246
+ int ret = 0 ;
247
+ int delta ;
248
+ char * q ;
249
+
250
+ if (arg -> check_arg ) {
251
+ ret = arg -> check_arg (arg );
252
+ if (ret )
253
+ return ret ;
254
+ }
255
+
256
+ q = cmd -> buf + (cmd -> maxlen - cmd -> remaining );
257
+
258
+ delta = snprintf (q , cmd -> remaining , " %s%c" , arg -> str , arg -> separator );
259
+ if (delta >= cmd -> remaining ) {
260
+ pr_err ("String is too long: %s\n" , arg -> str );
261
+ return - E2BIG ;
262
+ }
263
+ cmd -> remaining -= delta ;
264
+
265
+ return ret ;
266
+ }
267
+
268
+ /**
269
+ * dynevent_arg_pair_add - Add an arg pair to a dynevent_cmd
270
+ * @cmd: A pointer to the dynevent_cmd struct representing the new event cmd
271
+ * @arg_pair: The argument pair to append to the current cmd
272
+ *
273
+ * Append an argument pair to a dynevent_cmd. An argument pair
274
+ * consists of a left-hand-side argument and a right-hand-side
275
+ * argument separated by an operator, which can be whitespace, all
276
+ * followed by a separator, if applicable. This can be used to add
277
+ * arguments of the form 'type variable_name;' or 'x+y'.
278
+ *
279
+ * The lhs argument string will be appended to the current cmd string,
280
+ * followed by an operator, if applicable, followd by the rhs string,
281
+ * followed finally by a separator, if applicable. Before anything is
282
+ * added, the check_arg() function, if defined, is called.
283
+ *
284
+ * The cmd strings, operator, separator, and check_arg() function
285
+ * should be set using the dynevent_arg_pair_init() before any arguments
286
+ * are added using this function.
287
+ *
288
+ * Return: 0 if successful, error otherwise.
289
+ */
290
+ int dynevent_arg_pair_add (struct dynevent_cmd * cmd ,
291
+ struct dynevent_arg_pair * arg_pair )
292
+ {
293
+ int ret = 0 ;
294
+ int delta ;
295
+ char * q ;
296
+
297
+ if (arg_pair -> check_arg ) {
298
+ ret = arg_pair -> check_arg (arg_pair );
299
+ if (ret )
300
+ return ret ;
301
+ }
302
+
303
+ q = cmd -> buf + (cmd -> maxlen - cmd -> remaining );
304
+
305
+ delta = snprintf (q , cmd -> remaining , " %s%c" , arg_pair -> lhs ,
306
+ arg_pair -> operator );
307
+ if (delta >= cmd -> remaining ) {
308
+ pr_err ("field string is too long: %s\n" , arg_pair -> lhs );
309
+ return - E2BIG ;
310
+ }
311
+ cmd -> remaining -= delta ; q += delta ;
312
+
313
+ delta = snprintf (q , cmd -> remaining , "%s%c" , arg_pair -> rhs ,
314
+ arg_pair -> separator );
315
+ if (delta >= cmd -> remaining ) {
316
+ pr_err ("field string is too long: %s\n" , arg_pair -> rhs );
317
+ return - E2BIG ;
318
+ }
319
+ cmd -> remaining -= delta ; q += delta ;
320
+
321
+ return ret ;
322
+ }
323
+
324
+ /**
325
+ * dynevent_str_add - Add a string to a dynevent_cmd
326
+ * @cmd: A pointer to the dynevent_cmd struct representing the new event cmd
327
+ * @str: The string to append to the current cmd
328
+ *
329
+ * Append a string to a dynevent_cmd. The string will be appended to
330
+ * the current cmd string as-is, with nothing prepended or appended.
331
+ *
332
+ * Return: 0 if successful, error otherwise.
333
+ */
334
+ int dynevent_str_add (struct dynevent_cmd * cmd , const char * str )
335
+ {
336
+ int ret = 0 ;
337
+ int delta ;
338
+ char * q ;
339
+
340
+ q = cmd -> buf + (cmd -> maxlen - cmd -> remaining );
341
+
342
+ delta = snprintf (q , cmd -> remaining , "%s" , str );
343
+ if (delta >= cmd -> remaining ) {
344
+ pr_err ("String is too long: %s\n" , str );
345
+ return - E2BIG ;
346
+ }
347
+ cmd -> remaining -= delta ;
348
+
349
+ return ret ;
350
+ }
351
+
352
+ /**
353
+ * dynevent_cmd_init - Initialize a dynevent_cmd object
354
+ * @cmd: A pointer to the dynevent_cmd struct representing the cmd
355
+ * @buf: A pointer to the buffer to generate the command into
356
+ * @maxlen: The length of the buffer the command will be generated into
357
+ * @type: The type of the cmd, checked against further operations
358
+ * @run_command: The type-specific function that will actually run the command
359
+ *
360
+ * Initialize a dynevent_cmd. A dynevent_cmd is used to build up and
361
+ * run dynamic event creation commands, such as commands for creating
362
+ * synthetic and kprobe events. Before calling any of the functions
363
+ * used to build the command, a dynevent_cmd object should be
364
+ * instantiated and initialized using this function.
365
+ *
366
+ * The initialization sets things up by saving a pointer to the
367
+ * user-supplied buffer and its length via the @buf and @maxlen
368
+ * params, and by saving the cmd-specific @type and @run_command
369
+ * params which are used to check subsequent dynevent_cmd operations
370
+ * and actually run the command when complete.
371
+ */
372
+ void dynevent_cmd_init (struct dynevent_cmd * cmd , char * buf , int maxlen ,
373
+ enum dynevent_type type ,
374
+ dynevent_create_fn_t run_command )
375
+ {
376
+ memset (cmd , '\0' , sizeof (* cmd ));
377
+
378
+ cmd -> buf = buf ;
379
+ cmd -> maxlen = maxlen ;
380
+ cmd -> remaining = cmd -> maxlen ;
381
+ cmd -> type = type ;
382
+ cmd -> run_command = run_command ;
383
+ }
384
+
385
+ /**
386
+ * dynevent_arg_init - Initialize a dynevent_arg object
387
+ * @arg: A pointer to the dynevent_arg struct representing the arg
388
+ * @check_arg: An (optional) pointer to a function checking arg sanity
389
+ * @separator: An (optional) separator, appended after adding the arg
390
+ *
391
+ * Initialize a dynevent_arg object. A dynevent_arg represents an
392
+ * object used to append single arguments to the current command
393
+ * string. The @check_arg function, if present, will be used to check
394
+ * the sanity of the current arg string (which is directly set by the
395
+ * caller). After the arg string is successfully appended to the
396
+ * command string, the optional @separator is appended. If no
397
+ * separator was specified when initializing the arg, a space will be
398
+ * appended.
399
+ */
400
+ void dynevent_arg_init (struct dynevent_arg * arg ,
401
+ dynevent_check_arg_fn_t check_arg ,
402
+ char separator )
403
+ {
404
+ memset (arg , '\0' , sizeof (* arg ));
405
+
406
+ if (!separator )
407
+ separator = ' ' ;
408
+ arg -> separator = separator ;
409
+
410
+ arg -> check_arg = check_arg ;
411
+ }
412
+
413
+ /**
414
+ * dynevent_arg_pair_init - Initialize a dynevent_arg_pair object
415
+ * @arg_pair: A pointer to the dynevent_arg_pair struct representing the arg
416
+ * @check_arg: An (optional) pointer to a function checking arg sanity
417
+ * @operator: An (optional) operator, appended after adding the first arg
418
+ * @separator: An (optional) separator, appended after adding the second arg
419
+ *
420
+ * Initialize a dynevent_arg_pair object. A dynevent_arg_pair
421
+ * represents an object used to append argument pairs such as 'type
422
+ * variable_name;' or 'x+y' to the current command string. An
423
+ * argument pair consists of a left-hand-side argument and a
424
+ * right-hand-side argument separated by an operator, which can be
425
+ * whitespace, all followed by a separator, if applicable. The
426
+ * @check_arg function, if present, will be used to check the sanity
427
+ * of the current arg strings (which is directly set by the caller).
428
+ * After the first arg string is successfully appended to the command
429
+ * string, the optional @operator is appended, followed by the second
430
+ * arg and and optional @separator. If no separator was specified
431
+ * when initializing the arg, a space will be appended.
432
+ */
433
+ void dynevent_arg_pair_init (struct dynevent_arg_pair * arg_pair ,
434
+ dynevent_check_arg_fn_t check_arg ,
435
+ char operator , char separator )
436
+ {
437
+ memset (arg_pair , '\0' , sizeof (* arg_pair ));
438
+
439
+ if (!operator )
440
+ operator = ' ' ;
441
+ arg_pair -> operator = operator ;
442
+
443
+ if (!separator )
444
+ separator = ' ' ;
445
+ arg_pair -> separator = separator ;
446
+
447
+ arg_pair -> check_arg = check_arg ;
448
+ }
449
+
450
+ /**
451
+ * dynevent_create - Create the dynamic event contained in dynevent_cmd
452
+ * @cmd: The dynevent_cmd object containing the dynamic event creation command
453
+ *
454
+ * Once a dynevent_cmd object has been successfully built up via the
455
+ * dynevent_cmd_init(), dynevent_arg_add() and dynevent_arg_pair_add()
456
+ * functions, this function runs the final command to actually create
457
+ * the event.
458
+ *
459
+ * Return: 0 if the event was successfully created, error otherwise.
460
+ */
461
+ int dynevent_create (struct dynevent_cmd * cmd )
462
+ {
463
+ return cmd -> run_command (cmd );
464
+ }
465
+ EXPORT_SYMBOL_GPL (dynevent_create );
0 commit comments