Messages in this thread | | | From | Daeho Jeong <> | Date | Wed, 14 Oct 2020 11:27:30 +0900 | Subject | Re: [f2fs-dev] [PATCH 2/2] f2fs: add F2FS_IOC_SET_COMPRESS_OPTION ioctl |
| |
> f2fs_readonly() is redundant with mnt_want_write_file(). > > Also, shouldn't this require a writable file descriptor? As-is, this ioctl can > be called on a file owned by another user, as long as the caller has read > access. > > Note: if you change this to require a writable file descriptor, then > f2fs_readonly(), mnt_want_write_file(), and IS_IMMUTABLE() all would no longer > be needed.
I agree that f2fs_readonly() is redundant. But, sorry, I don't get the rest. I thought mnt_want_write_file() is a way to check whether the caller has a proper write permission or not. I think just using mnt_want_write_file() is enough for this ioctl. Am I missing something?
> What if f2fs_cops[options.algorithm] == NULL, e.g. COMPRESS_LZ4 without > CONFIG_F2FS_FS_LZ4? Shouldn't the caller get an error then?
Good point!
> I don't think the check for i_writecount == 1 accomplishes anything because it > just means there are no *other* writable file descriptors. It doesn't mean that > some other thread isn't concurrently trying to write to this same file > descriptor. So the lock needs to be enough. Is it?
This is to detect any possibility of other threads mmap-ing and writing the file. Using only inode lock is not enough to prevent them from making dirty pages.
2020년 10월 13일 (화) 오후 3:11, Eric Biggers <ebiggers@kernel.org>님이 작성: > > On Tue, Oct 13, 2020 at 11:24:29AM +0900, Daeho Jeong wrote: > > +static int f2fs_ioc_set_compress_option(struct file *filp, unsigned long arg) > > +{ > > + struct inode *inode = file_inode(filp); > > + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); > > + struct f2fs_comp_option option; > > + int ret; > > + int writecount; > > + > > + if (!f2fs_sb_has_compression(sbi)) > > + return -EOPNOTSUPP; > > + > > + if (!f2fs_compressed_file(inode) || IS_IMMUTABLE(inode)) > > + return -EINVAL; > > + > > + if (f2fs_readonly(sbi->sb)) > > + return -EROFS; >
> > > + > > + if (copy_from_user(&option, (struct f2fs_comp_option __user *)arg, > > + sizeof(option))) > > + return -EFAULT; > > + > > + if (option.log_cluster_size < MIN_COMPRESS_LOG_SIZE || > > + option.log_cluster_size > MAX_COMPRESS_LOG_SIZE || > > + option.algorithm >= COMPRESS_MAX) > > + return -EINVAL; > > What if f2fs_cops[options.algorithm] == NULL, e.g. COMPRESS_LZ4 without > CONFIG_F2FS_FS_LZ4? Shouldn't the caller get an error then? > > > + > > + ret = mnt_want_write_file(filp); > > + if (ret) > > + return ret; > > + > > + inode_lock(inode); > > + > > + writecount = atomic_read(&inode->i_writecount); > > + if ((filp->f_mode & FMODE_WRITE && writecount != 1) || > > + (!(filp->f_mode & FMODE_WRITE) && writecount)) { > > + ret = -EBUSY; > > + goto out; > > + } > > I don't think the check for i_writecount == 1 accomplishes anything because it > just means there are no *other* writable file descriptors. It doesn't mean that > some other thread isn't concurrently trying to write to this same file > descriptor. So the lock needs to be enough. Is it? > > - Eric
| |