]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - fs/f2fs/data.c
Merge remote-tracking branch 'f2fs/dev'
[karo-tx-linux.git] / fs / f2fs / data.c
index 883b6499841f1ad2c979b9a77bcd9e46212ee09b..972eab7ac07193da485df3efc6b6c11c99dacd97 100644 (file)
@@ -275,7 +275,8 @@ int f2fs_get_block(struct dnode_of_data *dn, pgoff_t index)
        return f2fs_reserve_block(dn, index);
 }
 
-struct page *get_read_data_page(struct inode *inode, pgoff_t index, int rw)
+struct page *get_read_data_page(struct inode *inode, pgoff_t index,
+                                               int rw, bool for_write)
 {
        struct address_space *mapping = inode->i_mapping;
        struct dnode_of_data dn;
@@ -292,7 +293,7 @@ struct page *get_read_data_page(struct inode *inode, pgoff_t index, int rw)
        if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
                return read_mapping_page(mapping, index, NULL);
 
-       page = grab_cache_page(mapping, index);
+       page = f2fs_grab_cache_page(mapping, index, for_write);
        if (!page)
                return ERR_PTR(-ENOMEM);
 
@@ -352,7 +353,7 @@ struct page *find_data_page(struct inode *inode, pgoff_t index)
                return page;
        f2fs_put_page(page, 0);
 
-       page = get_read_data_page(inode, index, READ_SYNC);
+       page = get_read_data_page(inode, index, READ_SYNC, false);
        if (IS_ERR(page))
                return page;
 
@@ -372,12 +373,13 @@ struct page *find_data_page(struct inode *inode, pgoff_t index)
  * Because, the callers, functions in dir.c and GC, should be able to know
  * whether this page exists or not.
  */
-struct page *get_lock_data_page(struct inode *inode, pgoff_t index)
+struct page *get_lock_data_page(struct inode *inode, pgoff_t index,
+                                                       bool for_write)
 {
        struct address_space *mapping = inode->i_mapping;
        struct page *page;
 repeat:
-       page = get_read_data_page(inode, index, READ_SYNC);
+       page = get_read_data_page(inode, index, READ_SYNC, for_write);
        if (IS_ERR(page))
                return page;
 
@@ -411,7 +413,7 @@ struct page *get_new_data_page(struct inode *inode,
        struct dnode_of_data dn;
        int err;
 repeat:
-       page = grab_cache_page(mapping, index);
+       page = f2fs_grab_cache_page(mapping, index, true);
        if (!page) {
                /*
                 * before exiting, we should make sure ipage will be released
@@ -439,7 +441,7 @@ repeat:
        } else {
                f2fs_put_page(page, 1);
 
-               page = get_read_data_page(inode, index, READ_SYNC);
+               page = get_read_data_page(inode, index, READ_SYNC, true);
                if (IS_ERR(page))
                        goto repeat;
 
@@ -524,6 +526,9 @@ static void __allocate_data_blocks(struct inode *inode, loff_t offset,
                while (dn.ofs_in_node < end_offset && len) {
                        block_t blkaddr;
 
+                       if (unlikely(f2fs_cp_error(sbi)))
+                               goto sync_out;
+
                        blkaddr = datablock_addr(dn.node_page, dn.ofs_in_node);
                        if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) {
                                if (__allocate_data_block(&dn))
@@ -566,6 +571,7 @@ static int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
 {
        unsigned int maxblocks = map->m_len;
        struct dnode_of_data dn;
+       struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
        int mode = create ? ALLOC_NODE : LOOKUP_NODE_RA;
        pgoff_t pgofs, end_offset;
        int err = 0, ofs = 1;
@@ -599,6 +605,10 @@ static int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map,
 
        if (dn.data_blkaddr == NEW_ADDR || dn.data_blkaddr == NULL_ADDR) {
                if (create) {
+                       if (unlikely(f2fs_cp_error(sbi))) {
+                               err = -EIO;
+                               goto put_out;
+                       }
                        err = __allocate_data_block(&dn);
                        if (err)
                                goto put_out;
@@ -652,6 +662,10 @@ get_next:
 
                if (blkaddr == NEW_ADDR || blkaddr == NULL_ADDR) {
                        if (create) {
+                               if (unlikely(f2fs_cp_error(sbi))) {
+                                       err = -EIO;
+                                       goto sync_out;
+                               }
                                err = __allocate_data_block(&dn);
                                if (err)
                                        goto sync_out;
@@ -757,6 +771,12 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
        if (ret)
                return ret;
 
+       if (f2fs_has_inline_data(inode)) {
+               ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len);
+               if (ret != -EAGAIN)
+                       return ret;
+       }
+
        mutex_lock(&inode->i_mutex);
 
        if (len >= isize) {
@@ -908,7 +928,8 @@ static int f2fs_mpage_readpages(struct address_space *mapping,
                        map.m_lblk = block_in_file;
                        map.m_len = last_block - block_in_file;
 
-                       if (f2fs_map_blocks(inode, &map, 0, false))
+                       if (f2fs_map_blocks(inode, &map, 0,
+                                                       F2FS_GET_BLOCK_READ))
                                goto set_error_page;
                }
 got_it:
@@ -941,21 +962,14 @@ submit_and_realloc:
 
                        if (f2fs_encrypted_inode(inode) &&
                                        S_ISREG(inode->i_mode)) {
-                               struct page *cpage;
 
                                ctx = f2fs_get_crypto_ctx(inode);
                                if (IS_ERR(ctx))
                                        goto set_error_page;
 
                                /* wait the page to be moved by cleaning */
-                               cpage = find_lock_page(
-                                               META_MAPPING(F2FS_I_SB(inode)),
-                                               block_nr);
-                               if (cpage) {
-                                       f2fs_wait_on_page_writeback(cpage,
-                                                                       DATA);
-                                       f2fs_put_page(cpage, 1);
-                               }
+                               f2fs_wait_on_encrypted_page_writeback(
+                                               F2FS_I_SB(inode), block_nr);
                        }
 
                        bio = bio_alloc(GFP_KERNEL,
@@ -1017,6 +1031,9 @@ static int f2fs_read_data_pages(struct file *file,
                        struct list_head *pages, unsigned nr_pages)
 {
        struct inode *inode = file->f_mapping->host;
+       struct page *page = list_entry(pages->prev, struct page, lru);
+
+       trace_f2fs_readpages(inode, page, nr_pages);
 
        /* If the file has inline data, skip readpages */
        if (f2fs_has_inline_data(inode))
@@ -1046,6 +1063,11 @@ int do_write_data_page(struct f2fs_io_info *fio)
        }
 
        if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode)) {
+
+               /* wait for GCed encrypted page writeback */
+               f2fs_wait_on_encrypted_page_writeback(F2FS_I_SB(inode),
+                                                       fio->blk_addr);
+
                fio->encrypted_page = f2fs_encrypt(inode, fio->page);
                if (IS_ERR(fio->encrypted_page)) {
                        err = PTR_ERR(fio->encrypted_page);
@@ -1434,6 +1456,10 @@ put_next:
 
        f2fs_wait_on_page_writeback(page, DATA);
 
+       /* wait for GCed encrypted page writeback */
+       if (f2fs_encrypted_inode(inode) && S_ISREG(inode->i_mode))
+               f2fs_wait_on_encrypted_page_writeback(sbi, dn.data_blkaddr);
+
        if (len == PAGE_CACHE_SIZE)
                goto out_update;
        if (PageUptodate(page))
@@ -1556,10 +1582,16 @@ static ssize_t f2fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 
        trace_f2fs_direct_IO_enter(inode, offset, count, iov_iter_rw(iter));
 
-       if (iov_iter_rw(iter) == WRITE)
+       if (iov_iter_rw(iter) == WRITE) {
                __allocate_data_blocks(inode, offset, count);
+               if (unlikely(f2fs_cp_error(F2FS_I_SB(inode)))) {
+                       err = -EIO;
+                       goto out;
+               }
+       }
 
        err = blockdev_direct_IO(iocb, inode, iter, offset, get_data_block_dio);
+out:
        if (err < 0 && iov_iter_rw(iter) == WRITE)
                f2fs_write_failed(mapping, offset + count);
 
@@ -1641,12 +1673,13 @@ static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
 {
        struct inode *inode = mapping->host;
 
-       /* we don't need to use inline_data strictly */
-       if (f2fs_has_inline_data(inode)) {
-               int err = f2fs_convert_inline_inode(inode);
-               if (err)
-                       return err;
-       }
+       if (f2fs_has_inline_data(inode))
+               return 0;
+
+       /* make sure allocating whole blocks */
+       if (mapping_tagged(mapping, PAGECACHE_TAG_DIRTY))
+               filemap_write_and_wait(mapping);
+
        return generic_block_bmap(mapping, block, get_data_block_bmap);
 }