mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 12:43:29 +02:00
vfs: don't unnecessarily clone write access for writable fds
There's no need for mnt_want_write_file() to increment mnt_writers when the file is already open for writing, provided that mnt_drop_write_file() is changed to conditionally decrement it. We seem to have ended up in the current situation because mnt_want_write_file() used to be paired with mnt_drop_write(), due to mnt_drop_write_file() not having been added yet. So originally mnt_want_write_file() had to always increment mnt_writers. But later mnt_drop_write_file() was added, and all callers of mnt_want_write_file() were paired with it. This makes the compatibility between mnt_want_write_file() and mnt_drop_write() no longer necessary. Therefore, make __mnt_want_write_file() and __mnt_drop_write_file() skip incrementing mnt_writers on files already open for writing. This removes the only caller of mnt_clone_write(), so remove that too. Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
@@ -865,3 +865,10 @@ no matter what. Everything is handled by the caller.
|
|||||||
|
|
||||||
clone_private_mount() returns a longterm mount now, so the proper destructor of
|
clone_private_mount() returns a longterm mount now, so the proper destructor of
|
||||||
its result is kern_unmount() or kern_unmount_array().
|
its result is kern_unmount() or kern_unmount_array().
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**mandatory**
|
||||||
|
|
||||||
|
mnt_want_write_file() can now only be paired with mnt_drop_write_file(),
|
||||||
|
whereas previously it could be paired with mnt_drop_write() as well.
|
||||||
|
@@ -359,51 +359,37 @@ int mnt_want_write(struct vfsmount *m)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mnt_want_write);
|
EXPORT_SYMBOL_GPL(mnt_want_write);
|
||||||
|
|
||||||
/**
|
|
||||||
* mnt_clone_write - get write access to a mount
|
|
||||||
* @mnt: the mount on which to take a write
|
|
||||||
*
|
|
||||||
* This is effectively like mnt_want_write, except
|
|
||||||
* it must only be used to take an extra write reference
|
|
||||||
* on a mountpoint that we already know has a write reference
|
|
||||||
* on it. This allows some optimisation.
|
|
||||||
*
|
|
||||||
* After finished, mnt_drop_write must be called as usual to
|
|
||||||
* drop the reference.
|
|
||||||
*/
|
|
||||||
int mnt_clone_write(struct vfsmount *mnt)
|
|
||||||
{
|
|
||||||
/* superblock may be r/o */
|
|
||||||
if (__mnt_is_readonly(mnt))
|
|
||||||
return -EROFS;
|
|
||||||
preempt_disable();
|
|
||||||
mnt_inc_writers(real_mount(mnt));
|
|
||||||
preempt_enable();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(mnt_clone_write);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __mnt_want_write_file - get write access to a file's mount
|
* __mnt_want_write_file - get write access to a file's mount
|
||||||
* @file: the file who's mount on which to take a write
|
* @file: the file who's mount on which to take a write
|
||||||
*
|
*
|
||||||
* This is like __mnt_want_write, but it takes a file and can
|
* This is like __mnt_want_write, but if the file is already open for writing it
|
||||||
* do some optimisations if the file is open for write already
|
* skips incrementing mnt_writers (since the open file already has a reference)
|
||||||
|
* and instead only does the check for emergency r/o remounts. This must be
|
||||||
|
* paired with __mnt_drop_write_file.
|
||||||
*/
|
*/
|
||||||
int __mnt_want_write_file(struct file *file)
|
int __mnt_want_write_file(struct file *file)
|
||||||
{
|
{
|
||||||
if (!(file->f_mode & FMODE_WRITER))
|
if (file->f_mode & FMODE_WRITER) {
|
||||||
return __mnt_want_write(file->f_path.mnt);
|
/*
|
||||||
else
|
* Superblock may have become readonly while there are still
|
||||||
return mnt_clone_write(file->f_path.mnt);
|
* writable fd's, e.g. due to a fs error with errors=remount-ro
|
||||||
|
*/
|
||||||
|
if (__mnt_is_readonly(file->f_path.mnt))
|
||||||
|
return -EROFS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return __mnt_want_write(file->f_path.mnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* mnt_want_write_file - get write access to a file's mount
|
* mnt_want_write_file - get write access to a file's mount
|
||||||
* @file: the file who's mount on which to take a write
|
* @file: the file who's mount on which to take a write
|
||||||
*
|
*
|
||||||
* This is like mnt_want_write, but it takes a file and can
|
* This is like mnt_want_write, but if the file is already open for writing it
|
||||||
* do some optimisations if the file is open for write already
|
* skips incrementing mnt_writers (since the open file already has a reference)
|
||||||
|
* and instead only does the freeze protection and the check for emergency r/o
|
||||||
|
* remounts. This must be paired with mnt_drop_write_file.
|
||||||
*/
|
*/
|
||||||
int mnt_want_write_file(struct file *file)
|
int mnt_want_write_file(struct file *file)
|
||||||
{
|
{
|
||||||
@@ -449,7 +435,8 @@ EXPORT_SYMBOL_GPL(mnt_drop_write);
|
|||||||
|
|
||||||
void __mnt_drop_write_file(struct file *file)
|
void __mnt_drop_write_file(struct file *file)
|
||||||
{
|
{
|
||||||
__mnt_drop_write(file->f_path.mnt);
|
if (!(file->f_mode & FMODE_WRITER))
|
||||||
|
__mnt_drop_write(file->f_path.mnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mnt_drop_write_file(struct file *file)
|
void mnt_drop_write_file(struct file *file)
|
||||||
|
@@ -79,7 +79,6 @@ struct path;
|
|||||||
|
|
||||||
extern int mnt_want_write(struct vfsmount *mnt);
|
extern int mnt_want_write(struct vfsmount *mnt);
|
||||||
extern int mnt_want_write_file(struct file *file);
|
extern int mnt_want_write_file(struct file *file);
|
||||||
extern int mnt_clone_write(struct vfsmount *mnt);
|
|
||||||
extern void mnt_drop_write(struct vfsmount *mnt);
|
extern void mnt_drop_write(struct vfsmount *mnt);
|
||||||
extern void mnt_drop_write_file(struct file *file);
|
extern void mnt_drop_write_file(struct file *file);
|
||||||
extern void mntput(struct vfsmount *mnt);
|
extern void mntput(struct vfsmount *mnt);
|
||||||
|
Reference in New Issue
Block a user