I'd like to make my filesystem be able to do file creation and opening
atomically. This is needed for filesystems which cannot separate
checking open permission from the actual open operation.
Usually any filesystem served from userspace by an unprivileged (no
CAP_DAC_OVERRIDE) process will be such (ftp, sftp, etc.).
With nameidata->intent.open.* it is possible to do the actual open
from ->lookup() or ->create(). However there's no easy way to
associate the 'struct file *' returned by dentry_open() with the
filesystem's private file object. Also if there's some error after
the file has been opened but before a successful return of the file
pointer, the filesystem has no way to know that it should destroy the
private file object.
The following patch makes this possible through a new file pointer
field in the open intent data, through which the filesystem can pass
an opened file to be returned by filp_open().
The filesystem can call dentry_open() from ->lookup() or ->create(),
and it in with it's private file data. If there's an error the file
can be properly destroyed through f_op->release().
There's one question on which I'm not sure what is the best solution:
The filesystem needs to know whether it's f_op->open() method was
called from lookup/create, or from the filp_open(), because in the
first case it need not do anything (the private file object will be
created outside dentry_open()), but in the second case it must
actually prepare the private file object.
Two solutions come to mind:
1) pass a special open flag to dentry_open() which will be passed on
to f_op->open() in filp->f_flags
2) create a new 'dentry_open_noopen()' variant, which doesn't call
f_op->open()
Does one sound better? Or something else?
Comments are welcome.
Thanks,
Miklos
Index: linux/include/linux/namei.h
===================================================================
--- linux.orig/include/linux/namei.h 2005-06-17 21:48:29.000000000 +0200
+++ linux/include/linux/namei.h 2005-08-06 17:12:55.000000000 +0200
@@ -8,6 +8,10 @@ struct vfsmount;
struct open_intent {
int flags;
int create_mode;
+ int orig_flags;
+
+ /* Fs may want to do dentry_open() in ->lookup(), or in ->create() */
+ struct file *file;
};
enum { MAX_NESTED_LINKS = 5 };
Index: linux/fs/open.c
===================================================================
--- linux.orig/fs/open.c 2005-08-06 12:34:14.000000000 +0200
+++ linux/fs/open.c 2005-08-08 13:03:08.000000000 +0200
@@ -762,9 +762,22 @@ struct file *filp_open(const char * file
if (namei_flags & O_TRUNC)
namei_flags |= 2;
+ /* Fill in the open() intent data */
+ nd.intent.open.flags = namei_flags;
+ nd.intent.open.create_mode = mode;
+ nd.intent.open.orig_flags = flags;
+ nd.intent.open.file = NULL;
+
error = open_namei(filename, namei_flags, mode, &nd);
- if (!error)
- return dentry_open(nd.dentry, nd.mnt, flags);
+ if (!error) {
+ if (nd.intent.open.file)
+ return nd.intent.open.file;
+ else
+ return dentry_open(nd.dentry, nd.mnt, flags);
+ }
+
+ if (nd.intent.open.file && !IS_ERR(nd.intent.open.file))
+ fput(nd.intent.open.file);
return ERR_PTR(error);
}
Index: linux/fs/namei.c
===================================================================
--- linux.orig/fs/namei.c 2005-08-06 12:35:59.000000000 +0200
+++ linux/fs/namei.c 2005-08-06 17:12:55.000000000 +0200
@@ -1423,10 +1423,6 @@ int open_namei(const char * pathname, in
if (flag & O_APPEND)
acc_mode |= MAY_APPEND;
- /* Fill in the open() intent data */
- nd->intent.open.flags = flag;
- nd->intent.open.create_mode = mode;
-
/*
* The simplest case - just a plain lookup.
*/
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
|
|