Merge tag 'compat-ioctl-5.5' of git://git.kernel.org:/pub/scm/linux/kernel/git/arnd...
[linux-2.6-block.git] / fs / f2fs / file.c
index 57d82f2d2ebd509ba4e942e574d7d21d9759ed72..85af112e868d18bd9c9f77b31349d8901f481206 100644 (file)
@@ -681,7 +681,7 @@ int f2fs_truncate(struct inode *inode)
        trace_f2fs_truncate(inode);
 
        if (time_to_inject(F2FS_I_SB(inode), FAULT_TRUNCATE)) {
-               f2fs_show_injection_info(FAULT_TRUNCATE);
+               f2fs_show_injection_info(F2FS_I_SB(inode), FAULT_TRUNCATE);
                return -EIO;
        }
 
@@ -726,11 +726,14 @@ int f2fs_getattr(const struct path *path, struct kstat *stat,
                stat->attributes |= STATX_ATTR_IMMUTABLE;
        if (flags & F2FS_NODUMP_FL)
                stat->attributes |= STATX_ATTR_NODUMP;
+       if (IS_VERITY(inode))
+               stat->attributes |= STATX_ATTR_VERITY;
 
        stat->attributes_mask |= (STATX_ATTR_APPEND |
                                  STATX_ATTR_ENCRYPTED |
                                  STATX_ATTR_IMMUTABLE |
-                                 STATX_ATTR_NODUMP);
+                                 STATX_ATTR_NODUMP |
+                                 STATX_ATTR_VERITY);
 
        generic_fillattr(inode, stat);
 
@@ -1139,7 +1142,7 @@ static int __clone_blkaddrs(struct inode *src_inode, struct inode *dst_inode,
                                }
                                dn.ofs_in_node++;
                                i++;
-                               new_size = (dst + i) << PAGE_SHIFT;
+                               new_size = (loff_t)(dst + i) << PAGE_SHIFT;
                                if (dst_inode->i_size < new_size)
                                        f2fs_i_size_write(dst_inode, new_size);
                        } while (--ilen && (do_replace[i] || blkaddr[i] == NULL_ADDR));
@@ -1545,12 +1548,44 @@ static int expand_inode_data(struct inode *inode, loff_t offset,
        if (off_end)
                map.m_len++;
 
-       if (f2fs_is_pinned_file(inode))
-               map.m_seg_type = CURSEG_COLD_DATA;
+       if (!map.m_len)
+               return 0;
+
+       if (f2fs_is_pinned_file(inode)) {
+               block_t len = (map.m_len >> sbi->log_blocks_per_seg) <<
+                                       sbi->log_blocks_per_seg;
+               block_t done = 0;
+
+               if (map.m_len % sbi->blocks_per_seg)
+                       len += sbi->blocks_per_seg;
+
+               map.m_len = sbi->blocks_per_seg;
+next_alloc:
+               if (has_not_enough_free_secs(sbi, 0,
+                       GET_SEC_FROM_SEG(sbi, overprovision_segments(sbi)))) {
+                       mutex_lock(&sbi->gc_mutex);
+                       err = f2fs_gc(sbi, true, false, NULL_SEGNO);
+                       if (err && err != -ENODATA && err != -EAGAIN)
+                               goto out_err;
+               }
+
+               down_write(&sbi->pin_sem);
+               map.m_seg_type = CURSEG_COLD_DATA_PINNED;
+               f2fs_allocate_new_segments(sbi, CURSEG_COLD_DATA);
+               err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_DIO);
+               up_write(&sbi->pin_sem);
 
-       err = f2fs_map_blocks(inode, &map, 1, (f2fs_is_pinned_file(inode) ?
-                                               F2FS_GET_BLOCK_PRE_DIO :
-                                               F2FS_GET_BLOCK_PRE_AIO));
+               done += map.m_len;
+               len -= map.m_len;
+               map.m_lblk += map.m_len;
+               if (!err && len)
+                       goto next_alloc;
+
+               map.m_len = done;
+       } else {
+               err = f2fs_map_blocks(inode, &map, 1, F2FS_GET_BLOCK_PRE_AIO);
+       }
+out_err:
        if (err) {
                pgoff_t last_off;
 
@@ -1890,6 +1925,7 @@ static int f2fs_ioc_start_atomic_write(struct file *filp)
        spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
        if (list_empty(&fi->inmem_ilist))
                list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]);
+       sbi->atomic_files++;
        spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
 
        /* add inode in inmem_list first and set atomic_file */