Reputation: 515
I'm currently writing a simple "multicaster" module.
Only one process can open a proc filesystem file for writing, and the rest can open it for reading. To do so i use the inode_operation .permission callback, I check the operation and when i detect someone open a file for writing I set a flag ON.
i need a way to detect if a process that opened a file for writing has decided to close the file so i can set the flag OFF, so someone else can open for writing.
Currently in case someone is open for writing i save the current->pid of that process and when the .close callback is called I check if that process is the one I saved earlier.
Is there a better way to do that? Without saving the pid, perhaps checking the files that the current process has opened and it's permission...
Thanks!
Upvotes: 0
Views: 1572
Reputation: 239031
No, it's not safe. Consider a few scenarios:
Process A opens the file for writing, and then fork()
s, creating process B. Now both A and B have the file open for writing. When Process A closes it, you set the flag to 0 but process B still has it open for writing.
Process A has multiple threads. Thread X opens the file for writing, but Thread Y closes it. Now the flag is stuck at 1. (Remember that ->pid
in kernel space is actually the userspace thread ID).
Rather than doing things at the inode level, you should be doing things in the .open
and .release
methods of your file_operations
struct.
Your inode's private data should contain a struct file *current_writer;
, initialised to NULL
. In the file_operations.open
method, if it's being opened for write then check the current_writer
; if it's NULL, set it to the struct file *
being opened, otherwise fail the open with EPERM
. In the file_operations.release
method, check if the struct file *
being released is equal to the inode's current_writer
- if so, set current_writer
back to NULL
.
PS: Bandan is also correct that you need locking, but the using the inode's existing i_mutex
should suffice to protect the current_writer
.
Upvotes: 2
Reputation: 596
I hope I understood your question correctly: When someone wants to write to your proc file, you set a variable called flag to 1 and also save the current->pid in a global variable. Then, when any close() entry point is called, you check current->pid of the close() instance and compare that with your saved value. If that matches, you turn flag to off. Right ?
Consider this situation : Process A wants to write to your proc resource, and so you check the permission callback. You see that flag is 0, so you can set it to 1 for process A. But at that moment, the scheduler finds out process A has used up its time share and chooses a different process to run(flag is still o!). After sometime, process B comes up wanting to write to your proc resource also, checks that the flag is 0, sets it to 1, and then goes about writing to the file. Unfortunately at this moment, process A gets scheduled to run again and since, it thinks that flag is 0 (remember, before the scheduler pre-empted it, flag was 0) and so sets it to 1 and goes about writing to the file. End result : data in your proc resource goes corrupt.
You should use a good locking mechanism provided by the kernel for this type of operation and based on your requirement, I think RCU is the best : Have a look at RCU locking mechanism
Upvotes: 0