Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[sfrench/cifs-2.6.git] / fs / f2fs / file.c
index 8ccbfe53c03c2a35216c603ab08c9319710f7a3f..a0e6d2c65a9ec013ed05a6a67ced7ca6995e9842 100644 (file)
 #include "trace.h"
 #include <trace/events/f2fs.h>
 
+static int f2fs_filemap_fault(struct vm_fault *vmf)
+{
+       struct inode *inode = file_inode(vmf->vma->vm_file);
+       int err;
+
+       down_read(&F2FS_I(inode)->i_mmap_sem);
+       err = filemap_fault(vmf);
+       up_read(&F2FS_I(inode)->i_mmap_sem);
+
+       return err;
+}
+
 static int f2fs_vm_page_mkwrite(struct vm_fault *vmf)
 {
        struct page *page = vmf->page;
@@ -59,13 +71,14 @@ static int f2fs_vm_page_mkwrite(struct vm_fault *vmf)
        f2fs_balance_fs(sbi, dn.node_changed);
 
        file_update_time(vmf->vma->vm_file);
+       down_read(&F2FS_I(inode)->i_mmap_sem);
        lock_page(page);
        if (unlikely(page->mapping != inode->i_mapping ||
                        page_offset(page) > i_size_read(inode) ||
                        !PageUptodate(page))) {
                unlock_page(page);
                err = -EFAULT;
-               goto out;
+               goto out_sem;
        }
 
        /*
@@ -94,6 +107,8 @@ mapped:
        if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
                f2fs_wait_on_encrypted_page_writeback(sbi, dn.data_blkaddr);
 
+out_sem:
+       up_read(&F2FS_I(inode)->i_mmap_sem);
 out:
        sb_end_pagefault(inode->i_sb);
        f2fs_update_time(sbi, REQ_TIME);
@@ -101,7 +116,7 @@ out:
 }
 
 static const struct vm_operations_struct f2fs_file_vm_ops = {
-       .fault          = filemap_fault,
+       .fault          = f2fs_filemap_fault,
        .map_pages      = filemap_map_pages,
        .page_mkwrite   = f2fs_vm_page_mkwrite,
 };
@@ -415,14 +430,6 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
        struct inode *inode = file_inode(file);
        int err;
 
-       if (f2fs_encrypted_inode(inode)) {
-               err = fscrypt_get_encryption_info(inode);
-               if (err)
-                       return 0;
-               if (!f2fs_encrypted_inode(inode))
-                       return -ENOKEY;
-       }
-
        /* we don't need to use inline_data strictly */
        err = f2fs_convert_inline_inode(inode);
        if (err)
@@ -435,11 +442,10 @@ static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma)
 
 static int f2fs_file_open(struct inode *inode, struct file *filp)
 {
-       int ret = generic_file_open(inode, filp);
        struct dentry *dir;
 
-       if (!ret && f2fs_encrypted_inode(inode)) {
-               ret = fscrypt_get_encryption_info(inode);
+       if (f2fs_encrypted_inode(inode)) {
+               int ret = fscrypt_get_encryption_info(inode);
                if (ret)
                        return -EACCES;
                if (!fscrypt_has_encryption_key(inode))
@@ -452,7 +458,7 @@ static int f2fs_file_open(struct inode *inode, struct file *filp)
                return -EPERM;
        }
        dput(dir);
-       return ret;
+       return dquot_file_open(inode, filp);
 }
 
 int truncate_data_blocks_range(struct dnode_of_data *dn, int count)
@@ -527,8 +533,10 @@ static int truncate_partial_data_page(struct inode *inode, u64 from,
 truncate_out:
        f2fs_wait_on_page_writeback(page, DATA, true);
        zero_user(page, offset, PAGE_SIZE - offset);
-       if (!cache_only || !f2fs_encrypted_inode(inode) ||
-                                       !S_ISREG(inode->i_mode))
+
+       /* An encrypted inode should have a key and truncate the last page. */
+       f2fs_bug_on(F2FS_I_SB(inode), cache_only && f2fs_encrypted_inode(inode));
+       if (!cache_only)
                set_page_dirty(page);
        f2fs_put_page(page, 1);
        return 0;
@@ -658,7 +666,6 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
                                  STATX_ATTR_NODUMP);
 
        generic_fillattr(inode, stat);
-       stat->blocks <<= 3;
        return 0;
 }
 
@@ -702,14 +709,34 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
        if (err)
                return err;
 
+       if (is_quota_modification(inode, attr)) {
+               err = dquot_initialize(inode);
+               if (err)
+                       return err;
+       }
+       if ((attr->ia_valid & ATTR_UID &&
+               !uid_eq(attr->ia_uid, inode->i_uid)) ||
+               (attr->ia_valid & ATTR_GID &&
+               !gid_eq(attr->ia_gid, inode->i_gid))) {
+               err = dquot_transfer(inode, attr);
+               if (err)
+                       return err;
+       }
+
        if (attr->ia_valid & ATTR_SIZE) {
-               if (f2fs_encrypted_inode(inode) &&
-                               fscrypt_get_encryption_info(inode))
-                       return -EACCES;
+               if (f2fs_encrypted_inode(inode)) {
+                       err = fscrypt_get_encryption_info(inode);
+                       if (err)
+                               return err;
+                       if (!fscrypt_has_encryption_key(inode))
+                               return -ENOKEY;
+               }
 
                if (attr->ia_size <= i_size_read(inode)) {
+                       down_write(&F2FS_I(inode)->i_mmap_sem);
                        truncate_setsize(inode, attr->ia_size);
                        err = f2fs_truncate(inode);
+                       up_write(&F2FS_I(inode)->i_mmap_sem);
                        if (err)
                                return err;
                } else {
@@ -717,7 +744,9 @@ int f2fs_setattr(struct dentry *dentry, struct iattr *attr)
                         * do not trim all blocks after i_size if target size is
                         * larger than i_size.
                         */
+                       down_write(&F2FS_I(inode)->i_mmap_sem);
                        truncate_setsize(inode, attr->ia_size);
+                       up_write(&F2FS_I(inode)->i_mmap_sem);
 
                        /* should convert inline inode here */
                        if (!f2fs_may_inline_data(inode)) {
@@ -860,12 +889,14 @@ static int punch_hole(struct inode *inode, loff_t offset, loff_t len)
 
                        blk_start = (loff_t)pg_start << PAGE_SHIFT;
                        blk_end = (loff_t)pg_end << PAGE_SHIFT;
+                       down_write(&F2FS_I(inode)->i_mmap_sem);
                        truncate_inode_pages_range(mapping, blk_start,
                                        blk_end - 1);
 
                        f2fs_lock_op(sbi);
                        ret = truncate_hole(inode, pg_start, pg_end);
                        f2fs_unlock_op(sbi);
+                       up_write(&F2FS_I(inode)->i_mmap_sem);
                }
        }
 
@@ -978,9 +1009,9 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
 
                                if (do_replace[i]) {
                                        f2fs_i_blocks_write(src_inode,
-                                                               1, false);
+                                                       1, false, false);
                                        f2fs_i_blocks_write(dst_inode,
-                                                               1, true);
+                                                       1, true, false);
                                        f2fs_replace_block(sbi, &dn, dn.data_blkaddr,
                                        blkaddr[i], ni.version, true, false);
 
@@ -1032,11 +1063,11 @@ static int __exchange_data_block(struct inode *src_inode,
        while (len) {
                olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len);
 
-               src_blkaddr = f2fs_kvzalloc(sizeof(block_t) * olen, GFP_KERNEL);
+               src_blkaddr = kvzalloc(sizeof(block_t) * olen, GFP_KERNEL);
                if (!src_blkaddr)
                        return -ENOMEM;
 
-               do_replace = f2fs_kvzalloc(sizeof(int) * olen, GFP_KERNEL);
+               do_replace = kvzalloc(sizeof(int) * olen, GFP_KERNEL);
                if (!do_replace) {
                        kvfree(src_blkaddr);
                        return -ENOMEM;
@@ -1104,16 +1135,17 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
        pg_start = offset >> PAGE_SHIFT;
        pg_end = (offset + len) >> PAGE_SHIFT;
 
+       down_write(&F2FS_I(inode)->i_mmap_sem);
        /* write out all dirty pages from offset */
        ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
        if (ret)
-               return ret;
+               goto out;
 
        truncate_pagecache(inode, offset);
 
        ret = f2fs_do_collapse(inode, pg_start, pg_end);
        if (ret)
-               return ret;
+               goto out;
 
        /* write out all moved pages, if possible */
        filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
@@ -1126,6 +1158,8 @@ static int f2fs_collapse_range(struct inode *inode, loff_t offset, loff_t len)
        if (!ret)
                f2fs_i_size_write(inode, new_size);
 
+out:
+       up_write(&F2FS_I(inode)->i_mmap_sem);
        return ret;
 }
 
@@ -1190,9 +1224,10 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
        if (ret)
                return ret;
 
+       down_write(&F2FS_I(inode)->i_mmap_sem);
        ret = filemap_write_and_wait_range(mapping, offset, offset + len - 1);
        if (ret)
-               return ret;
+               goto out_sem;
 
        truncate_pagecache_range(inode, offset, offset + len - 1);
 
@@ -1206,7 +1241,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
                ret = fill_zero(inode, pg_start, off_start,
                                                off_end - off_start);
                if (ret)
-                       return ret;
+                       goto out_sem;
 
                new_size = max_t(loff_t, new_size, offset + len);
        } else {
@@ -1214,7 +1249,7 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
                        ret = fill_zero(inode, pg_start++, off_start,
                                                PAGE_SIZE - off_start);
                        if (ret)
-                               return ret;
+                               goto out_sem;
 
                        new_size = max_t(loff_t, new_size,
                                        (loff_t)pg_start << PAGE_SHIFT);
@@ -1263,6 +1298,8 @@ static int f2fs_zero_range(struct inode *inode, loff_t offset, loff_t len,
 out:
        if (!(mode & FALLOC_FL_KEEP_SIZE) && i_size_read(inode) < new_size)
                f2fs_i_size_write(inode, new_size);
+out_sem:
+       up_write(&F2FS_I(inode)->i_mmap_sem);
 
        return ret;
 }
@@ -1292,14 +1329,15 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
 
        f2fs_balance_fs(sbi, true);
 
+       down_write(&F2FS_I(inode)->i_mmap_sem);
        ret = truncate_blocks(inode, i_size_read(inode), true);
        if (ret)
-               return ret;
+               goto out;
 
        /* write out all dirty pages from offset */
        ret = filemap_write_and_wait_range(inode->i_mapping, offset, LLONG_MAX);
        if (ret)
-               return ret;
+               goto out;
 
        truncate_pagecache(inode, offset);
 
@@ -1328,6 +1366,8 @@ static int f2fs_insert_range(struct inode *inode, loff_t offset, loff_t len)
 
        if (!ret)
                f2fs_i_size_write(inode, new_size);
+out:
+       up_write(&F2FS_I(inode)->i_mmap_sem);
        return ret;
 }
 
@@ -1496,6 +1536,13 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
 
        inode_lock(inode);
 
+       /* Is it quota file? Do not allow user to mess with it */
+       if (IS_NOQUOTA(inode)) {
+               inode_unlock(inode);
+               ret = -EPERM;
+               goto unlock_out;
+       }
+
        flags = f2fs_mask_flags(inode->i_mode, flags);
 
        oldflags = fi->i_flags;
@@ -1515,7 +1562,7 @@ static int f2fs_ioc_setflags(struct file *filp, unsigned long arg)
        inode->i_ctime = current_time(inode);
        f2fs_set_inode_flags(inode);
        f2fs_mark_inode_dirty_sync(inode, false);
-
+unlock_out:
        inode_unlock(inode);
 out:
        mnt_drop_write_file(filp);
@@ -1884,6 +1931,50 @@ out:
        return ret;
 }
 
+static int f2fs_ioc_gc_range(struct file *filp, unsigned long arg)
+{
+       struct inode *inode = file_inode(filp);
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
+       struct f2fs_gc_range range;
+       u64 end;
+       int ret;
+
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+
+       if (copy_from_user(&range, (struct f2fs_gc_range __user *)arg,
+                                                       sizeof(range)))
+               return -EFAULT;
+
+       if (f2fs_readonly(sbi->sb))
+               return -EROFS;
+
+       ret = mnt_want_write_file(filp);
+       if (ret)
+               return ret;
+
+       end = range.start + range.len;
+       if (range.start < MAIN_BLKADDR(sbi) || end >= MAX_BLKADDR(sbi))
+               return -EINVAL;
+do_more:
+       if (!range.sync) {
+               if (!mutex_trylock(&sbi->gc_mutex)) {
+                       ret = -EBUSY;
+                       goto out;
+               }
+       } else {
+               mutex_lock(&sbi->gc_mutex);
+       }
+
+       ret = f2fs_gc(sbi, range.sync, true, GET_SEGNO(sbi, range.start));
+       range.start += sbi->blocks_per_seg;
+       if (range.start <= end)
+               goto do_more;
+out:
+       mnt_drop_write_file(filp);
+       return ret;
+}
+
 static int f2fs_ioc_write_checkpoint(struct file *filp, unsigned long arg)
 {
        struct inode *inode = file_inode(filp);
@@ -2328,6 +2419,8 @@ long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
                return f2fs_ioc_get_encryption_pwsalt(filp, arg);
        case F2FS_IOC_GARBAGE_COLLECT:
                return f2fs_ioc_gc(filp, arg);
+       case F2FS_IOC_GARBAGE_COLLECT_RANGE:
+               return f2fs_ioc_gc_range(filp, arg);
        case F2FS_IOC_WRITE_CHECKPOINT:
                return f2fs_ioc_write_checkpoint(filp, arg);
        case F2FS_IOC_DEFRAGMENT:
@@ -2348,11 +2441,6 @@ static ssize_t f2fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from)
        struct blk_plug plug;
        ssize_t ret;
 
-       if (f2fs_encrypted_inode(inode) &&
-                               !fscrypt_has_encryption_key(inode) &&
-                               fscrypt_get_encryption_info(inode))
-               return -EACCES;
-
        inode_lock(inode);
        ret = generic_write_checks(iocb, from);
        if (ret > 0) {
@@ -2401,6 +2489,7 @@ long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case F2FS_IOC_GET_ENCRYPTION_PWSALT:
        case F2FS_IOC_GET_ENCRYPTION_POLICY:
        case F2FS_IOC_GARBAGE_COLLECT:
+       case F2FS_IOC_GARBAGE_COLLECT_RANGE:
        case F2FS_IOC_WRITE_CHECKPOINT:
        case F2FS_IOC_DEFRAGMENT:
        case F2FS_IOC_MOVE_RANGE: