@@ -244,3 +244,194 @@ struct dentry *fault_create_debugfs_attr(const char *name,
244244EXPORT_SYMBOL_GPL (fault_create_debugfs_attr );
245245
246246#endif /* CONFIG_FAULT_INJECTION_DEBUG_FS */
247+
248+ #ifdef CONFIG_FAULT_INJECTION_CONFIGFS
249+
250+ /* These configfs attribute utilities are copied from drivers/block/null_blk/main.c */
251+
252+ static ssize_t fault_uint_attr_show (unsigned int val , char * page )
253+ {
254+ return snprintf (page , PAGE_SIZE , "%u\n" , val );
255+ }
256+
257+ static ssize_t fault_ulong_attr_show (unsigned long val , char * page )
258+ {
259+ return snprintf (page , PAGE_SIZE , "%lu\n" , val );
260+ }
261+
262+ static ssize_t fault_bool_attr_show (bool val , char * page )
263+ {
264+ return snprintf (page , PAGE_SIZE , "%u\n" , val );
265+ }
266+
267+ static ssize_t fault_atomic_t_attr_show (atomic_t val , char * page )
268+ {
269+ return snprintf (page , PAGE_SIZE , "%d\n" , atomic_read (& val ));
270+ }
271+
272+ static ssize_t fault_uint_attr_store (unsigned int * val , const char * page , size_t count )
273+ {
274+ unsigned int tmp ;
275+ int result ;
276+
277+ result = kstrtouint (page , 0 , & tmp );
278+ if (result < 0 )
279+ return result ;
280+
281+ * val = tmp ;
282+ return count ;
283+ }
284+
285+ static ssize_t fault_ulong_attr_store (unsigned long * val , const char * page , size_t count )
286+ {
287+ int result ;
288+ unsigned long tmp ;
289+
290+ result = kstrtoul (page , 0 , & tmp );
291+ if (result < 0 )
292+ return result ;
293+
294+ * val = tmp ;
295+ return count ;
296+ }
297+
298+ static ssize_t fault_bool_attr_store (bool * val , const char * page , size_t count )
299+ {
300+ bool tmp ;
301+ int result ;
302+
303+ result = kstrtobool (page , & tmp );
304+ if (result < 0 )
305+ return result ;
306+
307+ * val = tmp ;
308+ return count ;
309+ }
310+
311+ static ssize_t fault_atomic_t_attr_store (atomic_t * val , const char * page , size_t count )
312+ {
313+ int tmp ;
314+ int result ;
315+
316+ result = kstrtoint (page , 0 , & tmp );
317+ if (result < 0 )
318+ return result ;
319+
320+ atomic_set (val , tmp );
321+ return count ;
322+ }
323+
324+ #define CONFIGFS_ATTR_NAMED (_pfx , _name , _attr_name ) \
325+ static struct configfs_attribute _pfx##attr_##_name = { \
326+ .ca_name = _attr_name, \
327+ .ca_mode = 0644, \
328+ .ca_owner = THIS_MODULE, \
329+ .show = _pfx##_name##_show, \
330+ .store = _pfx##_name##_store, \
331+ }
332+
333+ static struct fault_config * to_fault_config (struct config_item * item )
334+ {
335+ return container_of (to_config_group (item ), struct fault_config , group );
336+ }
337+
338+ #define FAULT_CONFIGFS_ATTR_NAMED (NAME , ATTR_NAME , MEMBER , TYPE ) \
339+ static ssize_t fault_##NAME##_show(struct config_item *item, char *page) \
340+ { \
341+ return fault_##TYPE##_attr_show(to_fault_config(item)->attr.MEMBER, page); \
342+ } \
343+ static ssize_t fault_##NAME##_store(struct config_item *item, const char *page, size_t count) \
344+ { \
345+ struct fault_config *config = to_fault_config(item); \
346+ return fault_##TYPE##_attr_store(&config->attr.MEMBER, page, count); \
347+ } \
348+ CONFIGFS_ATTR_NAMED(fault_, NAME, ATTR_NAME)
349+
350+ #define FAULT_CONFIGFS_ATTR (NAME , TYPE ) \
351+ FAULT_CONFIGFS_ATTR_NAMED(NAME, __stringify(NAME), NAME, TYPE)
352+
353+ FAULT_CONFIGFS_ATTR (probability , ulong );
354+ FAULT_CONFIGFS_ATTR (interval , ulong );
355+ FAULT_CONFIGFS_ATTR (times , atomic_t );
356+ FAULT_CONFIGFS_ATTR (space , atomic_t );
357+ FAULT_CONFIGFS_ATTR (verbose , ulong );
358+ FAULT_CONFIGFS_ATTR_NAMED (ratelimit_interval , "verbose_ratelimit_interval_ms" ,
359+ ratelimit_state .interval , uint );
360+ FAULT_CONFIGFS_ATTR_NAMED (ratelimit_burst , "verbose_ratelimit_burst" ,
361+ ratelimit_state .burst , uint );
362+ FAULT_CONFIGFS_ATTR_NAMED (task_filter , "task-filter" , task_filter , bool );
363+
364+ #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
365+
366+ static ssize_t fault_stacktrace_depth_show (struct config_item * item , char * page )
367+ {
368+ return fault_ulong_attr_show (to_fault_config (item )-> attr .stacktrace_depth , page );
369+ }
370+
371+ static ssize_t fault_stacktrace_depth_store (struct config_item * item , const char * page ,
372+ size_t count )
373+ {
374+ int result ;
375+ unsigned long tmp ;
376+
377+ result = kstrtoul (page , 0 , & tmp );
378+ if (result < 0 )
379+ return result ;
380+
381+ to_fault_config (item )-> attr .stacktrace_depth =
382+ min_t (unsigned long , tmp , MAX_STACK_TRACE_DEPTH );
383+
384+ return count ;
385+ }
386+
387+ CONFIGFS_ATTR_NAMED (fault_ , stacktrace_depth , "stacktrace-depth" );
388+
389+ static ssize_t fault_xul_attr_show (unsigned long val , char * page )
390+ {
391+ return snprintf (page , PAGE_SIZE ,
392+ sizeof (val ) == sizeof (u32 ) ? "0x%08lx\n" : "0x%016lx\n" , val );
393+ }
394+
395+ static ssize_t fault_xul_attr_store (unsigned long * val , const char * page , size_t count )
396+ {
397+ return fault_ulong_attr_store (val , page , count );
398+ }
399+
400+ FAULT_CONFIGFS_ATTR_NAMED (require_start , "require-start" , require_start , xul );
401+ FAULT_CONFIGFS_ATTR_NAMED (require_end , "require-end" , require_end , xul );
402+ FAULT_CONFIGFS_ATTR_NAMED (reject_start , "reject-start" , reject_start , xul );
403+ FAULT_CONFIGFS_ATTR_NAMED (reject_end , "reject-end" , reject_end , xul );
404+
405+ #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
406+
407+ static struct configfs_attribute * fault_config_attrs [] = {
408+ & fault_attr_probability ,
409+ & fault_attr_interval ,
410+ & fault_attr_times ,
411+ & fault_attr_space ,
412+ & fault_attr_verbose ,
413+ & fault_attr_ratelimit_interval ,
414+ & fault_attr_ratelimit_burst ,
415+ & fault_attr_task_filter ,
416+ #ifdef CONFIG_FAULT_INJECTION_STACKTRACE_FILTER
417+ & fault_attr_stacktrace_depth ,
418+ & fault_attr_require_start ,
419+ & fault_attr_require_end ,
420+ & fault_attr_reject_start ,
421+ & fault_attr_reject_end ,
422+ #endif /* CONFIG_FAULT_INJECTION_STACKTRACE_FILTER */
423+ NULL ,
424+ };
425+
426+ static const struct config_item_type fault_config_type = {
427+ .ct_attrs = fault_config_attrs ,
428+ .ct_owner = THIS_MODULE ,
429+ };
430+
431+ void fault_config_init (struct fault_config * config , const char * name )
432+ {
433+ config_group_init_type_name (& config -> group , name , & fault_config_type );
434+ }
435+ EXPORT_SYMBOL_GPL (fault_config_init );
436+
437+ #endif /* CONFIG_FAULT_INJECTION_CONFIGFS */
0 commit comments