send uevent from fs/ext4 driver - linux-kernel

looking fs/ext4/super.c, I see this function
static void ext4_handle_error(struct super_block *sb)
I need have a kobj if I want to send an uevent inside ext4_handle_error function using
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp_ext[])
Question: is there a way to get *kobj from super_block *sb?

struct ext4_sb_info *sbi = EXT4_SB(sb); sbi->s_kobj; is this good?

Related

C++11 Call virtual member function

I`m trying to implement something like this using C++11.
class Proto{
public:
virtual void fu() = 0;
};
class Impl: public Proto{
public:
void fu();
};
void Impl::fu(){
LOG_INFO("im fu");
}
class Inv{
public:
void useFu(void (Proto::*)());
};
void Inv::useFu(void (Proto::*fu)()){
//fu();
};
void main(){
Impl impl;
Inv inv;
//inv.useFu(impl.fu);
}
useFu(void (Proto::*)()) must be declared in this way because, fu() uses some specific to Proto functionality's
I have two places were things going wrong.
First is fu() call itself and second how to pass fu as parameter inv.useFu(impl.fu).
Edit after bipll answer
The suggested usage of inv.useFu() solves the second problem of my question.
inv.useFu(static_cast<void (Proto::*)(void)>(&Impl::fu));
But I still need to call fu as a pointer to member function;
The way your useFu is declared now, it should be called as
inv.useFu(static_cast<void (Proto::*)(void)>(&Impl::fu));
But I guess that's not what you wanted. It should rather be
template<class F> void useFu(F &&f) { std::invoke(std::forward<F>(f)); }
or simply
void useFu(std::function<void()> f) { std::invoke(std::move(f)); }
and called as
useFu([&]{ impl.fu(); });
(Rather than using a lambda you can bind the method to the object with std::bind in the latter call but almost nobody ever does that.)

Periodically hid_hw_raw_request in kernel module, how to?

I'm writing a kernel module that need to ask an hid raw device periodically.
I tried hrtimer and a simple timer and each time I call hid_hw_raw_request I got a "BUG: scheduling while atomic".
If I try the same function outside my timer function (eg in the init), it works fine (no bug).
How could periodically call this function without generating any bug ?
You need to use a work queue to issue your hid_hw_raw_request as deferred work. This can be done as in the following example module:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
static void hid_work_handler(struct work_struct *hid_work);
static struct workqueue_struct *hid_workqueue;
static DECLARE_WORK(hid_work, hid_work_handler);
static void hid_work_handler(struct work_struct *hid_work)
{
...
hid_hw_raw_request(...);
...
}
static int __init hid_work_init(void)
{
if (!hid_workqueue)
hid_workqueue = create_singlethread_workqueue("hid_workqueue");
if (hid_workqueue)
queue_work(hid_workqueue, &hid_work);
return 0;
}
static void __exit hid_work_exit(void)
{
if (hid_workqueue) {
flush_workqueue(hid_workqueue);
destroy_workqueue(hid_workqueue);
}
}
module_init(hid_work_init);
module_exit(hid_work_exit);
MODULE_DESCRIPTION("hid_work_test");
MODULE_LICENSE("GPL");
Note that for the real implementation you'll need to create your own data struct with an included struct work_struct to be queued. This data struct will likely contain the hiddev, buffer, etc. that the hid_work_handler needs to do the actual transfer. See LDD3 Chapter 7 for more details (albeit syntax of calls is outdated, the basic explanation still applies).

How I can use std::bind to bind class member function as function pointer?

I have Base and Dervided classes. In the Base class I have a typedef for specific function pointer (I think this is function pointer, im not sure):
typedef void (responseHandler)(BaseClass* instance,int resultCode, char* resultString);
And in the same base class I have several functions which accepts this typedef:
unsigned sendDescribeCommand(responseHandler* responseHandler, Authenticator* authenticator = NULL);
In my custom derived class from this Base class I have my response handler function, like this:
void continueAfterDESCRIBE(RTSPClient* rtspClient, int resultCode, char* resultString);
How I can use this method as input for sendDescribeCommand?
I tried this:
DerivedClass->sendDescribeCommand(DerivedCLass->continueAfterDescribe, MyAuth), but this did not build with error:
"error C3867: 'DerivedClass::continueAfterDESCRIBE': non-standard syntax; use '&' to create a pointer to member"
I also tried to use std::bind:
auto responseCallback = std::bind(&DerivedClass::continueAfterDESCRIBE, DerivedClassInstance);
DerivedClass->sendDescribeCommand(responseCallback, ourAuthenticator);
It also give me an error: no suitable conversion from std::bind to my response handler.
I know there is a way to make my method static, but Im curious if there is another way?

No call to CWinThread:ExitInstance

In my dialog based application, in CWinApp::InitInstance I create class that has framed window v1:
creating modHolder
CWinThread* pThread= AfxBeginThread(RUNTIME_CLASS(modHolder));
declaring modHolder
class modHolder : public CWinThread
{
DECLARE_DYNCREATE(modHolder)
protected:
modHolder(); // protected constructor used by dynamic creation
virtual ~modHolder();
public:
CMainWindow * v1;
virtual BOOL InitInstance();
virtual int ExitInstance();
protected:
DECLARE_MESSAGE_MAP()
};
During application close I expect to get call to modHolder::ExitInstance()
Unfortunately I have no this function. What might be problem? I think, that CWinThread modHolder should terminate automatically. Am I wrong?
CWinThread::ExitInstance is called when CWinThread::Run finishes.
You have the source code!

Sysfs to export device attributes

I've successfully added a device attribute to my device driver, but in all the examples that I found the attribute is used to inject data to the kernel, while my goal would be to export some data from kernel to make it visible in user space. Which is the right way to write to that file from kernel-space? So that data can be retrieved from user-space?
To read data from the kernel, just return it in the show handler:
static ssize_t show_myvalue(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct my_device *mydev = ...dev...;
return sprintf(buf, "%d\n", mydev->myvalue);
}
static DEVICE_ATTR(myvalue, S_IRUGO, show_myvalue, NULL);
If you must notify user space of changes, use sysfs_notify.

Resources