162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * This file is part of UBIFS. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2006-2008 Nokia Corporation. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Authors: Artem Bityutskiy (Битюцкий Артём) 862306a36Sopenharmony_ci * Adrian Hunter 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* 1262306a36Sopenharmony_ci * This file implements VFS file and inode operations for regular files, device 1362306a36Sopenharmony_ci * nodes and symlinks as well as address space operations. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * UBIFS uses 2 page flags: @PG_private and @PG_checked. @PG_private is set if 1662306a36Sopenharmony_ci * the page is dirty and is used for optimization purposes - dirty pages are 1762306a36Sopenharmony_ci * not budgeted so the flag shows that 'ubifs_write_end()' should not release 1862306a36Sopenharmony_ci * the budget for this page. The @PG_checked flag is set if full budgeting is 1962306a36Sopenharmony_ci * required for the page e.g., when it corresponds to a file hole or it is 2062306a36Sopenharmony_ci * beyond the file size. The budgeting is done in 'ubifs_write_begin()', because 2162306a36Sopenharmony_ci * it is OK to fail in this function, and the budget is released in 2262306a36Sopenharmony_ci * 'ubifs_write_end()'. So the @PG_private and @PG_checked flags carry 2362306a36Sopenharmony_ci * information about how the page was budgeted, to make it possible to release 2462306a36Sopenharmony_ci * the budget properly. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * A thing to keep in mind: inode @i_mutex is locked in most VFS operations we 2762306a36Sopenharmony_ci * implement. However, this is not true for 'ubifs_writepage()', which may be 2862306a36Sopenharmony_ci * called with @i_mutex unlocked. For example, when flusher thread is doing 2962306a36Sopenharmony_ci * background write-back, it calls 'ubifs_writepage()' with unlocked @i_mutex. 3062306a36Sopenharmony_ci * At "normal" work-paths the @i_mutex is locked in 'ubifs_writepage()', e.g. 3162306a36Sopenharmony_ci * in the "sys_write -> alloc_pages -> direct reclaim path". So, in 3262306a36Sopenharmony_ci * 'ubifs_writepage()' we are only guaranteed that the page is locked. 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci * Similarly, @i_mutex is not always locked in 'ubifs_read_folio()', e.g., the 3562306a36Sopenharmony_ci * read-ahead path does not lock it ("sys_read -> generic_file_aio_read -> 3662306a36Sopenharmony_ci * ondemand_readahead -> read_folio"). In case of readahead, @I_SYNC flag is not 3762306a36Sopenharmony_ci * set as well. However, UBIFS disables readahead. 3862306a36Sopenharmony_ci */ 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#include "ubifs.h" 4162306a36Sopenharmony_ci#include <linux/mount.h> 4262306a36Sopenharmony_ci#include <linux/slab.h> 4362306a36Sopenharmony_ci#include <linux/migrate.h> 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic int read_block(struct inode *inode, void *addr, unsigned int block, 4662306a36Sopenharmony_ci struct ubifs_data_node *dn) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 4962306a36Sopenharmony_ci int err, len, out_len; 5062306a36Sopenharmony_ci union ubifs_key key; 5162306a36Sopenharmony_ci unsigned int dlen; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci data_key_init(c, &key, inode->i_ino, block); 5462306a36Sopenharmony_ci err = ubifs_tnc_lookup(c, &key, dn); 5562306a36Sopenharmony_ci if (err) { 5662306a36Sopenharmony_ci if (err == -ENOENT) 5762306a36Sopenharmony_ci /* Not found, so it must be a hole */ 5862306a36Sopenharmony_ci memset(addr, 0, UBIFS_BLOCK_SIZE); 5962306a36Sopenharmony_ci return err; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci ubifs_assert(c, le64_to_cpu(dn->ch.sqnum) > 6362306a36Sopenharmony_ci ubifs_inode(inode)->creat_sqnum); 6462306a36Sopenharmony_ci len = le32_to_cpu(dn->size); 6562306a36Sopenharmony_ci if (len <= 0 || len > UBIFS_BLOCK_SIZE) 6662306a36Sopenharmony_ci goto dump; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci if (IS_ENCRYPTED(inode)) { 7162306a36Sopenharmony_ci err = ubifs_decrypt(inode, dn, &dlen, block); 7262306a36Sopenharmony_ci if (err) 7362306a36Sopenharmony_ci goto dump; 7462306a36Sopenharmony_ci } 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci out_len = UBIFS_BLOCK_SIZE; 7762306a36Sopenharmony_ci err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len, 7862306a36Sopenharmony_ci le16_to_cpu(dn->compr_type)); 7962306a36Sopenharmony_ci if (err || len != out_len) 8062306a36Sopenharmony_ci goto dump; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* 8362306a36Sopenharmony_ci * Data length can be less than a full block, even for blocks that are 8462306a36Sopenharmony_ci * not the last in the file (e.g., as a result of making a hole and 8562306a36Sopenharmony_ci * appending data). Ensure that the remainder is zeroed out. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci if (len < UBIFS_BLOCK_SIZE) 8862306a36Sopenharmony_ci memset(addr + len, 0, UBIFS_BLOCK_SIZE - len); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci return 0; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cidump: 9362306a36Sopenharmony_ci ubifs_err(c, "bad data node (block %u, inode %lu)", 9462306a36Sopenharmony_ci block, inode->i_ino); 9562306a36Sopenharmony_ci ubifs_dump_node(c, dn, UBIFS_MAX_DATA_NODE_SZ); 9662306a36Sopenharmony_ci return -EINVAL; 9762306a36Sopenharmony_ci} 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistatic int do_readpage(struct page *page) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci void *addr; 10262306a36Sopenharmony_ci int err = 0, i; 10362306a36Sopenharmony_ci unsigned int block, beyond; 10462306a36Sopenharmony_ci struct ubifs_data_node *dn; 10562306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 10662306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 10762306a36Sopenharmony_ci loff_t i_size = i_size_read(inode); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx", 11062306a36Sopenharmony_ci inode->i_ino, page->index, i_size, page->flags); 11162306a36Sopenharmony_ci ubifs_assert(c, !PageChecked(page)); 11262306a36Sopenharmony_ci ubifs_assert(c, !PagePrivate(page)); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci addr = kmap(page); 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT; 11762306a36Sopenharmony_ci beyond = (i_size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT; 11862306a36Sopenharmony_ci if (block >= beyond) { 11962306a36Sopenharmony_ci /* Reading beyond inode */ 12062306a36Sopenharmony_ci SetPageChecked(page); 12162306a36Sopenharmony_ci memset(addr, 0, PAGE_SIZE); 12262306a36Sopenharmony_ci goto out; 12362306a36Sopenharmony_ci } 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci dn = kmalloc(UBIFS_MAX_DATA_NODE_SZ, GFP_NOFS); 12662306a36Sopenharmony_ci if (!dn) { 12762306a36Sopenharmony_ci err = -ENOMEM; 12862306a36Sopenharmony_ci goto error; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci i = 0; 13262306a36Sopenharmony_ci while (1) { 13362306a36Sopenharmony_ci int ret; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (block >= beyond) { 13662306a36Sopenharmony_ci /* Reading beyond inode */ 13762306a36Sopenharmony_ci err = -ENOENT; 13862306a36Sopenharmony_ci memset(addr, 0, UBIFS_BLOCK_SIZE); 13962306a36Sopenharmony_ci } else { 14062306a36Sopenharmony_ci ret = read_block(inode, addr, block, dn); 14162306a36Sopenharmony_ci if (ret) { 14262306a36Sopenharmony_ci err = ret; 14362306a36Sopenharmony_ci if (err != -ENOENT) 14462306a36Sopenharmony_ci break; 14562306a36Sopenharmony_ci } else if (block + 1 == beyond) { 14662306a36Sopenharmony_ci int dlen = le32_to_cpu(dn->size); 14762306a36Sopenharmony_ci int ilen = i_size & (UBIFS_BLOCK_SIZE - 1); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci if (ilen && ilen < dlen) 15062306a36Sopenharmony_ci memset(addr + ilen, 0, dlen - ilen); 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci } 15362306a36Sopenharmony_ci if (++i >= UBIFS_BLOCKS_PER_PAGE) 15462306a36Sopenharmony_ci break; 15562306a36Sopenharmony_ci block += 1; 15662306a36Sopenharmony_ci addr += UBIFS_BLOCK_SIZE; 15762306a36Sopenharmony_ci } 15862306a36Sopenharmony_ci if (err) { 15962306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 16062306a36Sopenharmony_ci if (err == -ENOENT) { 16162306a36Sopenharmony_ci /* Not found, so it must be a hole */ 16262306a36Sopenharmony_ci SetPageChecked(page); 16362306a36Sopenharmony_ci dbg_gen("hole"); 16462306a36Sopenharmony_ci goto out_free; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci ubifs_err(c, "cannot read page %lu of inode %lu, error %d", 16762306a36Sopenharmony_ci page->index, inode->i_ino, err); 16862306a36Sopenharmony_ci goto error; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ciout_free: 17262306a36Sopenharmony_ci kfree(dn); 17362306a36Sopenharmony_ciout: 17462306a36Sopenharmony_ci SetPageUptodate(page); 17562306a36Sopenharmony_ci ClearPageError(page); 17662306a36Sopenharmony_ci flush_dcache_page(page); 17762306a36Sopenharmony_ci kunmap(page); 17862306a36Sopenharmony_ci return 0; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cierror: 18162306a36Sopenharmony_ci kfree(dn); 18262306a36Sopenharmony_ci ClearPageUptodate(page); 18362306a36Sopenharmony_ci SetPageError(page); 18462306a36Sopenharmony_ci flush_dcache_page(page); 18562306a36Sopenharmony_ci kunmap(page); 18662306a36Sopenharmony_ci return err; 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_ci/** 19062306a36Sopenharmony_ci * release_new_page_budget - release budget of a new page. 19162306a36Sopenharmony_ci * @c: UBIFS file-system description object 19262306a36Sopenharmony_ci * 19362306a36Sopenharmony_ci * This is a helper function which releases budget corresponding to the budget 19462306a36Sopenharmony_ci * of one new page of data. 19562306a36Sopenharmony_ci */ 19662306a36Sopenharmony_cistatic void release_new_page_budget(struct ubifs_info *c) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci struct ubifs_budget_req req = { .recalculate = 1, .new_page = 1 }; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci ubifs_release_budget(c, &req); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci/** 20462306a36Sopenharmony_ci * release_existing_page_budget - release budget of an existing page. 20562306a36Sopenharmony_ci * @c: UBIFS file-system description object 20662306a36Sopenharmony_ci * 20762306a36Sopenharmony_ci * This is a helper function which releases budget corresponding to the budget 20862306a36Sopenharmony_ci * of changing one page of data which already exists on the flash media. 20962306a36Sopenharmony_ci */ 21062306a36Sopenharmony_cistatic void release_existing_page_budget(struct ubifs_info *c) 21162306a36Sopenharmony_ci{ 21262306a36Sopenharmony_ci struct ubifs_budget_req req = { .dd_growth = c->bi.page_budget}; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci ubifs_release_budget(c, &req); 21562306a36Sopenharmony_ci} 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_cistatic int write_begin_slow(struct address_space *mapping, 21862306a36Sopenharmony_ci loff_t pos, unsigned len, struct page **pagep) 21962306a36Sopenharmony_ci{ 22062306a36Sopenharmony_ci struct inode *inode = mapping->host; 22162306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 22262306a36Sopenharmony_ci pgoff_t index = pos >> PAGE_SHIFT; 22362306a36Sopenharmony_ci struct ubifs_budget_req req = { .new_page = 1 }; 22462306a36Sopenharmony_ci int err, appending = !!(pos + len > inode->i_size); 22562306a36Sopenharmony_ci struct page *page; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci dbg_gen("ino %lu, pos %llu, len %u, i_size %lld", 22862306a36Sopenharmony_ci inode->i_ino, pos, len, inode->i_size); 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci /* 23162306a36Sopenharmony_ci * At the slow path we have to budget before locking the page, because 23262306a36Sopenharmony_ci * budgeting may force write-back, which would wait on locked pages and 23362306a36Sopenharmony_ci * deadlock if we had the page locked. At this point we do not know 23462306a36Sopenharmony_ci * anything about the page, so assume that this is a new page which is 23562306a36Sopenharmony_ci * written to a hole. This corresponds to largest budget. Later the 23662306a36Sopenharmony_ci * budget will be amended if this is not true. 23762306a36Sopenharmony_ci */ 23862306a36Sopenharmony_ci if (appending) 23962306a36Sopenharmony_ci /* We are appending data, budget for inode change */ 24062306a36Sopenharmony_ci req.dirtied_ino = 1; 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci err = ubifs_budget_space(c, &req); 24362306a36Sopenharmony_ci if (unlikely(err)) 24462306a36Sopenharmony_ci return err; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci page = grab_cache_page_write_begin(mapping, index); 24762306a36Sopenharmony_ci if (unlikely(!page)) { 24862306a36Sopenharmony_ci ubifs_release_budget(c, &req); 24962306a36Sopenharmony_ci return -ENOMEM; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci if (!PageUptodate(page)) { 25362306a36Sopenharmony_ci if (!(pos & ~PAGE_MASK) && len == PAGE_SIZE) 25462306a36Sopenharmony_ci SetPageChecked(page); 25562306a36Sopenharmony_ci else { 25662306a36Sopenharmony_ci err = do_readpage(page); 25762306a36Sopenharmony_ci if (err) { 25862306a36Sopenharmony_ci unlock_page(page); 25962306a36Sopenharmony_ci put_page(page); 26062306a36Sopenharmony_ci ubifs_release_budget(c, &req); 26162306a36Sopenharmony_ci return err; 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci } 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci if (PagePrivate(page)) 26762306a36Sopenharmony_ci /* 26862306a36Sopenharmony_ci * The page is dirty, which means it was budgeted twice: 26962306a36Sopenharmony_ci * o first time the budget was allocated by the task which 27062306a36Sopenharmony_ci * made the page dirty and set the PG_private flag; 27162306a36Sopenharmony_ci * o and then we budgeted for it for the second time at the 27262306a36Sopenharmony_ci * very beginning of this function. 27362306a36Sopenharmony_ci * 27462306a36Sopenharmony_ci * So what we have to do is to release the page budget we 27562306a36Sopenharmony_ci * allocated. 27662306a36Sopenharmony_ci */ 27762306a36Sopenharmony_ci release_new_page_budget(c); 27862306a36Sopenharmony_ci else if (!PageChecked(page)) 27962306a36Sopenharmony_ci /* 28062306a36Sopenharmony_ci * We are changing a page which already exists on the media. 28162306a36Sopenharmony_ci * This means that changing the page does not make the amount 28262306a36Sopenharmony_ci * of indexing information larger, and this part of the budget 28362306a36Sopenharmony_ci * which we have already acquired may be released. 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ci ubifs_convert_page_budget(c); 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci if (appending) { 28862306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci /* 29162306a36Sopenharmony_ci * 'ubifs_write_end()' is optimized from the fast-path part of 29262306a36Sopenharmony_ci * 'ubifs_write_begin()' and expects the @ui_mutex to be locked 29362306a36Sopenharmony_ci * if data is appended. 29462306a36Sopenharmony_ci */ 29562306a36Sopenharmony_ci mutex_lock(&ui->ui_mutex); 29662306a36Sopenharmony_ci if (ui->dirty) 29762306a36Sopenharmony_ci /* 29862306a36Sopenharmony_ci * The inode is dirty already, so we may free the 29962306a36Sopenharmony_ci * budget we allocated. 30062306a36Sopenharmony_ci */ 30162306a36Sopenharmony_ci ubifs_release_dirty_inode_budget(c, ui); 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci *pagep = page; 30562306a36Sopenharmony_ci return 0; 30662306a36Sopenharmony_ci} 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci/** 30962306a36Sopenharmony_ci * allocate_budget - allocate budget for 'ubifs_write_begin()'. 31062306a36Sopenharmony_ci * @c: UBIFS file-system description object 31162306a36Sopenharmony_ci * @page: page to allocate budget for 31262306a36Sopenharmony_ci * @ui: UBIFS inode object the page belongs to 31362306a36Sopenharmony_ci * @appending: non-zero if the page is appended 31462306a36Sopenharmony_ci * 31562306a36Sopenharmony_ci * This is a helper function for 'ubifs_write_begin()' which allocates budget 31662306a36Sopenharmony_ci * for the operation. The budget is allocated differently depending on whether 31762306a36Sopenharmony_ci * this is appending, whether the page is dirty or not, and so on. This 31862306a36Sopenharmony_ci * function leaves the @ui->ui_mutex locked in case of appending. Returns zero 31962306a36Sopenharmony_ci * in case of success and %-ENOSPC in case of failure. 32062306a36Sopenharmony_ci */ 32162306a36Sopenharmony_cistatic int allocate_budget(struct ubifs_info *c, struct page *page, 32262306a36Sopenharmony_ci struct ubifs_inode *ui, int appending) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci struct ubifs_budget_req req = { .fast = 1 }; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci if (PagePrivate(page)) { 32762306a36Sopenharmony_ci if (!appending) 32862306a36Sopenharmony_ci /* 32962306a36Sopenharmony_ci * The page is dirty and we are not appending, which 33062306a36Sopenharmony_ci * means no budget is needed at all. 33162306a36Sopenharmony_ci */ 33262306a36Sopenharmony_ci return 0; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci mutex_lock(&ui->ui_mutex); 33562306a36Sopenharmony_ci if (ui->dirty) 33662306a36Sopenharmony_ci /* 33762306a36Sopenharmony_ci * The page is dirty and we are appending, so the inode 33862306a36Sopenharmony_ci * has to be marked as dirty. However, it is already 33962306a36Sopenharmony_ci * dirty, so we do not need any budget. We may return, 34062306a36Sopenharmony_ci * but @ui->ui_mutex hast to be left locked because we 34162306a36Sopenharmony_ci * should prevent write-back from flushing the inode 34262306a36Sopenharmony_ci * and freeing the budget. The lock will be released in 34362306a36Sopenharmony_ci * 'ubifs_write_end()'. 34462306a36Sopenharmony_ci */ 34562306a36Sopenharmony_ci return 0; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* 34862306a36Sopenharmony_ci * The page is dirty, we are appending, the inode is clean, so 34962306a36Sopenharmony_ci * we need to budget the inode change. 35062306a36Sopenharmony_ci */ 35162306a36Sopenharmony_ci req.dirtied_ino = 1; 35262306a36Sopenharmony_ci } else { 35362306a36Sopenharmony_ci if (PageChecked(page)) 35462306a36Sopenharmony_ci /* 35562306a36Sopenharmony_ci * The page corresponds to a hole and does not 35662306a36Sopenharmony_ci * exist on the media. So changing it makes 35762306a36Sopenharmony_ci * make the amount of indexing information 35862306a36Sopenharmony_ci * larger, and we have to budget for a new 35962306a36Sopenharmony_ci * page. 36062306a36Sopenharmony_ci */ 36162306a36Sopenharmony_ci req.new_page = 1; 36262306a36Sopenharmony_ci else 36362306a36Sopenharmony_ci /* 36462306a36Sopenharmony_ci * Not a hole, the change will not add any new 36562306a36Sopenharmony_ci * indexing information, budget for page 36662306a36Sopenharmony_ci * change. 36762306a36Sopenharmony_ci */ 36862306a36Sopenharmony_ci req.dirtied_page = 1; 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_ci if (appending) { 37162306a36Sopenharmony_ci mutex_lock(&ui->ui_mutex); 37262306a36Sopenharmony_ci if (!ui->dirty) 37362306a36Sopenharmony_ci /* 37462306a36Sopenharmony_ci * The inode is clean but we will have to mark 37562306a36Sopenharmony_ci * it as dirty because we are appending. This 37662306a36Sopenharmony_ci * needs a budget. 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_ci req.dirtied_ino = 1; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci return ubifs_budget_space(c, &req); 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci/* 38662306a36Sopenharmony_ci * This function is called when a page of data is going to be written. Since 38762306a36Sopenharmony_ci * the page of data will not necessarily go to the flash straight away, UBIFS 38862306a36Sopenharmony_ci * has to reserve space on the media for it, which is done by means of 38962306a36Sopenharmony_ci * budgeting. 39062306a36Sopenharmony_ci * 39162306a36Sopenharmony_ci * This is the hot-path of the file-system and we are trying to optimize it as 39262306a36Sopenharmony_ci * much as possible. For this reasons it is split on 2 parts - slow and fast. 39362306a36Sopenharmony_ci * 39462306a36Sopenharmony_ci * There many budgeting cases: 39562306a36Sopenharmony_ci * o a new page is appended - we have to budget for a new page and for 39662306a36Sopenharmony_ci * changing the inode; however, if the inode is already dirty, there is 39762306a36Sopenharmony_ci * no need to budget for it; 39862306a36Sopenharmony_ci * o an existing clean page is changed - we have budget for it; if the page 39962306a36Sopenharmony_ci * does not exist on the media (a hole), we have to budget for a new 40062306a36Sopenharmony_ci * page; otherwise, we may budget for changing an existing page; the 40162306a36Sopenharmony_ci * difference between these cases is that changing an existing page does 40262306a36Sopenharmony_ci * not introduce anything new to the FS indexing information, so it does 40362306a36Sopenharmony_ci * not grow, and smaller budget is acquired in this case; 40462306a36Sopenharmony_ci * o an existing dirty page is changed - no need to budget at all, because 40562306a36Sopenharmony_ci * the page budget has been acquired by earlier, when the page has been 40662306a36Sopenharmony_ci * marked dirty. 40762306a36Sopenharmony_ci * 40862306a36Sopenharmony_ci * UBIFS budgeting sub-system may force write-back if it thinks there is no 40962306a36Sopenharmony_ci * space to reserve. This imposes some locking restrictions and makes it 41062306a36Sopenharmony_ci * impossible to take into account the above cases, and makes it impossible to 41162306a36Sopenharmony_ci * optimize budgeting. 41262306a36Sopenharmony_ci * 41362306a36Sopenharmony_ci * The solution for this is that the fast path of 'ubifs_write_begin()' assumes 41462306a36Sopenharmony_ci * there is a plenty of flash space and the budget will be acquired quickly, 41562306a36Sopenharmony_ci * without forcing write-back. The slow path does not make this assumption. 41662306a36Sopenharmony_ci */ 41762306a36Sopenharmony_cistatic int ubifs_write_begin(struct file *file, struct address_space *mapping, 41862306a36Sopenharmony_ci loff_t pos, unsigned len, 41962306a36Sopenharmony_ci struct page **pagep, void **fsdata) 42062306a36Sopenharmony_ci{ 42162306a36Sopenharmony_ci struct inode *inode = mapping->host; 42262306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 42362306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 42462306a36Sopenharmony_ci pgoff_t index = pos >> PAGE_SHIFT; 42562306a36Sopenharmony_ci int err, appending = !!(pos + len > inode->i_size); 42662306a36Sopenharmony_ci int skipped_read = 0; 42762306a36Sopenharmony_ci struct page *page; 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci ubifs_assert(c, ubifs_inode(inode)->ui_size == inode->i_size); 43062306a36Sopenharmony_ci ubifs_assert(c, !c->ro_media && !c->ro_mount); 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci if (unlikely(c->ro_error)) 43362306a36Sopenharmony_ci return -EROFS; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci /* Try out the fast-path part first */ 43662306a36Sopenharmony_ci page = grab_cache_page_write_begin(mapping, index); 43762306a36Sopenharmony_ci if (unlikely(!page)) 43862306a36Sopenharmony_ci return -ENOMEM; 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci if (!PageUptodate(page)) { 44162306a36Sopenharmony_ci /* The page is not loaded from the flash */ 44262306a36Sopenharmony_ci if (!(pos & ~PAGE_MASK) && len == PAGE_SIZE) { 44362306a36Sopenharmony_ci /* 44462306a36Sopenharmony_ci * We change whole page so no need to load it. But we 44562306a36Sopenharmony_ci * do not know whether this page exists on the media or 44662306a36Sopenharmony_ci * not, so we assume the latter because it requires 44762306a36Sopenharmony_ci * larger budget. The assumption is that it is better 44862306a36Sopenharmony_ci * to budget a bit more than to read the page from the 44962306a36Sopenharmony_ci * media. Thus, we are setting the @PG_checked flag 45062306a36Sopenharmony_ci * here. 45162306a36Sopenharmony_ci */ 45262306a36Sopenharmony_ci SetPageChecked(page); 45362306a36Sopenharmony_ci skipped_read = 1; 45462306a36Sopenharmony_ci } else { 45562306a36Sopenharmony_ci err = do_readpage(page); 45662306a36Sopenharmony_ci if (err) { 45762306a36Sopenharmony_ci unlock_page(page); 45862306a36Sopenharmony_ci put_page(page); 45962306a36Sopenharmony_ci return err; 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci } 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci err = allocate_budget(c, page, ui, appending); 46562306a36Sopenharmony_ci if (unlikely(err)) { 46662306a36Sopenharmony_ci ubifs_assert(c, err == -ENOSPC); 46762306a36Sopenharmony_ci /* 46862306a36Sopenharmony_ci * If we skipped reading the page because we were going to 46962306a36Sopenharmony_ci * write all of it, then it is not up to date. 47062306a36Sopenharmony_ci */ 47162306a36Sopenharmony_ci if (skipped_read) 47262306a36Sopenharmony_ci ClearPageChecked(page); 47362306a36Sopenharmony_ci /* 47462306a36Sopenharmony_ci * Budgeting failed which means it would have to force 47562306a36Sopenharmony_ci * write-back but didn't, because we set the @fast flag in the 47662306a36Sopenharmony_ci * request. Write-back cannot be done now, while we have the 47762306a36Sopenharmony_ci * page locked, because it would deadlock. Unlock and free 47862306a36Sopenharmony_ci * everything and fall-back to slow-path. 47962306a36Sopenharmony_ci */ 48062306a36Sopenharmony_ci if (appending) { 48162306a36Sopenharmony_ci ubifs_assert(c, mutex_is_locked(&ui->ui_mutex)); 48262306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 48362306a36Sopenharmony_ci } 48462306a36Sopenharmony_ci unlock_page(page); 48562306a36Sopenharmony_ci put_page(page); 48662306a36Sopenharmony_ci 48762306a36Sopenharmony_ci return write_begin_slow(mapping, pos, len, pagep); 48862306a36Sopenharmony_ci } 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_ci /* 49162306a36Sopenharmony_ci * Whee, we acquired budgeting quickly - without involving 49262306a36Sopenharmony_ci * garbage-collection, committing or forcing write-back. We return 49362306a36Sopenharmony_ci * with @ui->ui_mutex locked if we are appending pages, and unlocked 49462306a36Sopenharmony_ci * otherwise. This is an optimization (slightly hacky though). 49562306a36Sopenharmony_ci */ 49662306a36Sopenharmony_ci *pagep = page; 49762306a36Sopenharmony_ci return 0; 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci/** 50262306a36Sopenharmony_ci * cancel_budget - cancel budget. 50362306a36Sopenharmony_ci * @c: UBIFS file-system description object 50462306a36Sopenharmony_ci * @page: page to cancel budget for 50562306a36Sopenharmony_ci * @ui: UBIFS inode object the page belongs to 50662306a36Sopenharmony_ci * @appending: non-zero if the page is appended 50762306a36Sopenharmony_ci * 50862306a36Sopenharmony_ci * This is a helper function for a page write operation. It unlocks the 50962306a36Sopenharmony_ci * @ui->ui_mutex in case of appending. 51062306a36Sopenharmony_ci */ 51162306a36Sopenharmony_cistatic void cancel_budget(struct ubifs_info *c, struct page *page, 51262306a36Sopenharmony_ci struct ubifs_inode *ui, int appending) 51362306a36Sopenharmony_ci{ 51462306a36Sopenharmony_ci if (appending) { 51562306a36Sopenharmony_ci if (!ui->dirty) 51662306a36Sopenharmony_ci ubifs_release_dirty_inode_budget(c, ui); 51762306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 51862306a36Sopenharmony_ci } 51962306a36Sopenharmony_ci if (!PagePrivate(page)) { 52062306a36Sopenharmony_ci if (PageChecked(page)) 52162306a36Sopenharmony_ci release_new_page_budget(c); 52262306a36Sopenharmony_ci else 52362306a36Sopenharmony_ci release_existing_page_budget(c); 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci} 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_cistatic int ubifs_write_end(struct file *file, struct address_space *mapping, 52862306a36Sopenharmony_ci loff_t pos, unsigned len, unsigned copied, 52962306a36Sopenharmony_ci struct page *page, void *fsdata) 53062306a36Sopenharmony_ci{ 53162306a36Sopenharmony_ci struct inode *inode = mapping->host; 53262306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 53362306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 53462306a36Sopenharmony_ci loff_t end_pos = pos + len; 53562306a36Sopenharmony_ci int appending = !!(end_pos > inode->i_size); 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci dbg_gen("ino %lu, pos %llu, pg %lu, len %u, copied %d, i_size %lld", 53862306a36Sopenharmony_ci inode->i_ino, pos, page->index, len, copied, inode->i_size); 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci if (unlikely(copied < len && len == PAGE_SIZE)) { 54162306a36Sopenharmony_ci /* 54262306a36Sopenharmony_ci * VFS copied less data to the page that it intended and 54362306a36Sopenharmony_ci * declared in its '->write_begin()' call via the @len 54462306a36Sopenharmony_ci * argument. If the page was not up-to-date, and @len was 54562306a36Sopenharmony_ci * @PAGE_SIZE, the 'ubifs_write_begin()' function did 54662306a36Sopenharmony_ci * not load it from the media (for optimization reasons). This 54762306a36Sopenharmony_ci * means that part of the page contains garbage. So read the 54862306a36Sopenharmony_ci * page now. 54962306a36Sopenharmony_ci */ 55062306a36Sopenharmony_ci dbg_gen("copied %d instead of %d, read page and repeat", 55162306a36Sopenharmony_ci copied, len); 55262306a36Sopenharmony_ci cancel_budget(c, page, ui, appending); 55362306a36Sopenharmony_ci ClearPageChecked(page); 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci /* 55662306a36Sopenharmony_ci * Return 0 to force VFS to repeat the whole operation, or the 55762306a36Sopenharmony_ci * error code if 'do_readpage()' fails. 55862306a36Sopenharmony_ci */ 55962306a36Sopenharmony_ci copied = do_readpage(page); 56062306a36Sopenharmony_ci goto out; 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (len == PAGE_SIZE) 56462306a36Sopenharmony_ci SetPageUptodate(page); 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_ci if (!PagePrivate(page)) { 56762306a36Sopenharmony_ci attach_page_private(page, (void *)1); 56862306a36Sopenharmony_ci atomic_long_inc(&c->dirty_pg_cnt); 56962306a36Sopenharmony_ci __set_page_dirty_nobuffers(page); 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci if (appending) { 57362306a36Sopenharmony_ci i_size_write(inode, end_pos); 57462306a36Sopenharmony_ci ui->ui_size = end_pos; 57562306a36Sopenharmony_ci /* 57662306a36Sopenharmony_ci * Note, we do not set @I_DIRTY_PAGES (which means that the 57762306a36Sopenharmony_ci * inode has dirty pages), this has been done in 57862306a36Sopenharmony_ci * '__set_page_dirty_nobuffers()'. 57962306a36Sopenharmony_ci */ 58062306a36Sopenharmony_ci __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 58162306a36Sopenharmony_ci ubifs_assert(c, mutex_is_locked(&ui->ui_mutex)); 58262306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 58362306a36Sopenharmony_ci } 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ciout: 58662306a36Sopenharmony_ci unlock_page(page); 58762306a36Sopenharmony_ci put_page(page); 58862306a36Sopenharmony_ci return copied; 58962306a36Sopenharmony_ci} 59062306a36Sopenharmony_ci 59162306a36Sopenharmony_ci/** 59262306a36Sopenharmony_ci * populate_page - copy data nodes into a page for bulk-read. 59362306a36Sopenharmony_ci * @c: UBIFS file-system description object 59462306a36Sopenharmony_ci * @page: page 59562306a36Sopenharmony_ci * @bu: bulk-read information 59662306a36Sopenharmony_ci * @n: next zbranch slot 59762306a36Sopenharmony_ci * 59862306a36Sopenharmony_ci * This function returns %0 on success and a negative error code on failure. 59962306a36Sopenharmony_ci */ 60062306a36Sopenharmony_cistatic int populate_page(struct ubifs_info *c, struct page *page, 60162306a36Sopenharmony_ci struct bu_info *bu, int *n) 60262306a36Sopenharmony_ci{ 60362306a36Sopenharmony_ci int i = 0, nn = *n, offs = bu->zbranch[0].offs, hole = 0, read = 0; 60462306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 60562306a36Sopenharmony_ci loff_t i_size = i_size_read(inode); 60662306a36Sopenharmony_ci unsigned int page_block; 60762306a36Sopenharmony_ci void *addr, *zaddr; 60862306a36Sopenharmony_ci pgoff_t end_index; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx", 61162306a36Sopenharmony_ci inode->i_ino, page->index, i_size, page->flags); 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci addr = zaddr = kmap(page); 61462306a36Sopenharmony_ci 61562306a36Sopenharmony_ci end_index = (i_size - 1) >> PAGE_SHIFT; 61662306a36Sopenharmony_ci if (!i_size || page->index > end_index) { 61762306a36Sopenharmony_ci hole = 1; 61862306a36Sopenharmony_ci memset(addr, 0, PAGE_SIZE); 61962306a36Sopenharmony_ci goto out_hole; 62062306a36Sopenharmony_ci } 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci page_block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT; 62362306a36Sopenharmony_ci while (1) { 62462306a36Sopenharmony_ci int err, len, out_len, dlen; 62562306a36Sopenharmony_ci 62662306a36Sopenharmony_ci if (nn >= bu->cnt) { 62762306a36Sopenharmony_ci hole = 1; 62862306a36Sopenharmony_ci memset(addr, 0, UBIFS_BLOCK_SIZE); 62962306a36Sopenharmony_ci } else if (key_block(c, &bu->zbranch[nn].key) == page_block) { 63062306a36Sopenharmony_ci struct ubifs_data_node *dn; 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_ci dn = bu->buf + (bu->zbranch[nn].offs - offs); 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_ci ubifs_assert(c, le64_to_cpu(dn->ch.sqnum) > 63562306a36Sopenharmony_ci ubifs_inode(inode)->creat_sqnum); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci len = le32_to_cpu(dn->size); 63862306a36Sopenharmony_ci if (len <= 0 || len > UBIFS_BLOCK_SIZE) 63962306a36Sopenharmony_ci goto out_err; 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci dlen = le32_to_cpu(dn->ch.len) - UBIFS_DATA_NODE_SZ; 64262306a36Sopenharmony_ci out_len = UBIFS_BLOCK_SIZE; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci if (IS_ENCRYPTED(inode)) { 64562306a36Sopenharmony_ci err = ubifs_decrypt(inode, dn, &dlen, page_block); 64662306a36Sopenharmony_ci if (err) 64762306a36Sopenharmony_ci goto out_err; 64862306a36Sopenharmony_ci } 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci err = ubifs_decompress(c, &dn->data, dlen, addr, &out_len, 65162306a36Sopenharmony_ci le16_to_cpu(dn->compr_type)); 65262306a36Sopenharmony_ci if (err || len != out_len) 65362306a36Sopenharmony_ci goto out_err; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci if (len < UBIFS_BLOCK_SIZE) 65662306a36Sopenharmony_ci memset(addr + len, 0, UBIFS_BLOCK_SIZE - len); 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci nn += 1; 65962306a36Sopenharmony_ci read = (i << UBIFS_BLOCK_SHIFT) + len; 66062306a36Sopenharmony_ci } else if (key_block(c, &bu->zbranch[nn].key) < page_block) { 66162306a36Sopenharmony_ci nn += 1; 66262306a36Sopenharmony_ci continue; 66362306a36Sopenharmony_ci } else { 66462306a36Sopenharmony_ci hole = 1; 66562306a36Sopenharmony_ci memset(addr, 0, UBIFS_BLOCK_SIZE); 66662306a36Sopenharmony_ci } 66762306a36Sopenharmony_ci if (++i >= UBIFS_BLOCKS_PER_PAGE) 66862306a36Sopenharmony_ci break; 66962306a36Sopenharmony_ci addr += UBIFS_BLOCK_SIZE; 67062306a36Sopenharmony_ci page_block += 1; 67162306a36Sopenharmony_ci } 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci if (end_index == page->index) { 67462306a36Sopenharmony_ci int len = i_size & (PAGE_SIZE - 1); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci if (len && len < read) 67762306a36Sopenharmony_ci memset(zaddr + len, 0, read - len); 67862306a36Sopenharmony_ci } 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ciout_hole: 68162306a36Sopenharmony_ci if (hole) { 68262306a36Sopenharmony_ci SetPageChecked(page); 68362306a36Sopenharmony_ci dbg_gen("hole"); 68462306a36Sopenharmony_ci } 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_ci SetPageUptodate(page); 68762306a36Sopenharmony_ci ClearPageError(page); 68862306a36Sopenharmony_ci flush_dcache_page(page); 68962306a36Sopenharmony_ci kunmap(page); 69062306a36Sopenharmony_ci *n = nn; 69162306a36Sopenharmony_ci return 0; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ciout_err: 69462306a36Sopenharmony_ci ClearPageUptodate(page); 69562306a36Sopenharmony_ci SetPageError(page); 69662306a36Sopenharmony_ci flush_dcache_page(page); 69762306a36Sopenharmony_ci kunmap(page); 69862306a36Sopenharmony_ci ubifs_err(c, "bad data node (block %u, inode %lu)", 69962306a36Sopenharmony_ci page_block, inode->i_ino); 70062306a36Sopenharmony_ci return -EINVAL; 70162306a36Sopenharmony_ci} 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci/** 70462306a36Sopenharmony_ci * ubifs_do_bulk_read - do bulk-read. 70562306a36Sopenharmony_ci * @c: UBIFS file-system description object 70662306a36Sopenharmony_ci * @bu: bulk-read information 70762306a36Sopenharmony_ci * @page1: first page to read 70862306a36Sopenharmony_ci * 70962306a36Sopenharmony_ci * This function returns %1 if the bulk-read is done, otherwise %0 is returned. 71062306a36Sopenharmony_ci */ 71162306a36Sopenharmony_cistatic int ubifs_do_bulk_read(struct ubifs_info *c, struct bu_info *bu, 71262306a36Sopenharmony_ci struct page *page1) 71362306a36Sopenharmony_ci{ 71462306a36Sopenharmony_ci pgoff_t offset = page1->index, end_index; 71562306a36Sopenharmony_ci struct address_space *mapping = page1->mapping; 71662306a36Sopenharmony_ci struct inode *inode = mapping->host; 71762306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 71862306a36Sopenharmony_ci int err, page_idx, page_cnt, ret = 0, n = 0; 71962306a36Sopenharmony_ci int allocate = bu->buf ? 0 : 1; 72062306a36Sopenharmony_ci loff_t isize; 72162306a36Sopenharmony_ci gfp_t ra_gfp_mask = readahead_gfp_mask(mapping) & ~__GFP_FS; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci err = ubifs_tnc_get_bu_keys(c, bu); 72462306a36Sopenharmony_ci if (err) 72562306a36Sopenharmony_ci goto out_warn; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci if (bu->eof) { 72862306a36Sopenharmony_ci /* Turn off bulk-read at the end of the file */ 72962306a36Sopenharmony_ci ui->read_in_a_row = 1; 73062306a36Sopenharmony_ci ui->bulk_read = 0; 73162306a36Sopenharmony_ci } 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci page_cnt = bu->blk_cnt >> UBIFS_BLOCKS_PER_PAGE_SHIFT; 73462306a36Sopenharmony_ci if (!page_cnt) { 73562306a36Sopenharmony_ci /* 73662306a36Sopenharmony_ci * This happens when there are multiple blocks per page and the 73762306a36Sopenharmony_ci * blocks for the first page we are looking for, are not 73862306a36Sopenharmony_ci * together. If all the pages were like this, bulk-read would 73962306a36Sopenharmony_ci * reduce performance, so we turn it off for a while. 74062306a36Sopenharmony_ci */ 74162306a36Sopenharmony_ci goto out_bu_off; 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci if (bu->cnt) { 74562306a36Sopenharmony_ci if (allocate) { 74662306a36Sopenharmony_ci /* 74762306a36Sopenharmony_ci * Allocate bulk-read buffer depending on how many data 74862306a36Sopenharmony_ci * nodes we are going to read. 74962306a36Sopenharmony_ci */ 75062306a36Sopenharmony_ci bu->buf_len = bu->zbranch[bu->cnt - 1].offs + 75162306a36Sopenharmony_ci bu->zbranch[bu->cnt - 1].len - 75262306a36Sopenharmony_ci bu->zbranch[0].offs; 75362306a36Sopenharmony_ci ubifs_assert(c, bu->buf_len > 0); 75462306a36Sopenharmony_ci ubifs_assert(c, bu->buf_len <= c->leb_size); 75562306a36Sopenharmony_ci bu->buf = kmalloc(bu->buf_len, GFP_NOFS | __GFP_NOWARN); 75662306a36Sopenharmony_ci if (!bu->buf) 75762306a36Sopenharmony_ci goto out_bu_off; 75862306a36Sopenharmony_ci } 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci err = ubifs_tnc_bulk_read(c, bu); 76162306a36Sopenharmony_ci if (err) 76262306a36Sopenharmony_ci goto out_warn; 76362306a36Sopenharmony_ci } 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci err = populate_page(c, page1, bu, &n); 76662306a36Sopenharmony_ci if (err) 76762306a36Sopenharmony_ci goto out_warn; 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci unlock_page(page1); 77062306a36Sopenharmony_ci ret = 1; 77162306a36Sopenharmony_ci 77262306a36Sopenharmony_ci isize = i_size_read(inode); 77362306a36Sopenharmony_ci if (isize == 0) 77462306a36Sopenharmony_ci goto out_free; 77562306a36Sopenharmony_ci end_index = ((isize - 1) >> PAGE_SHIFT); 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci for (page_idx = 1; page_idx < page_cnt; page_idx++) { 77862306a36Sopenharmony_ci pgoff_t page_offset = offset + page_idx; 77962306a36Sopenharmony_ci struct page *page; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci if (page_offset > end_index) 78262306a36Sopenharmony_ci break; 78362306a36Sopenharmony_ci page = pagecache_get_page(mapping, page_offset, 78462306a36Sopenharmony_ci FGP_LOCK|FGP_ACCESSED|FGP_CREAT|FGP_NOWAIT, 78562306a36Sopenharmony_ci ra_gfp_mask); 78662306a36Sopenharmony_ci if (!page) 78762306a36Sopenharmony_ci break; 78862306a36Sopenharmony_ci if (!PageUptodate(page)) 78962306a36Sopenharmony_ci err = populate_page(c, page, bu, &n); 79062306a36Sopenharmony_ci unlock_page(page); 79162306a36Sopenharmony_ci put_page(page); 79262306a36Sopenharmony_ci if (err) 79362306a36Sopenharmony_ci break; 79462306a36Sopenharmony_ci } 79562306a36Sopenharmony_ci 79662306a36Sopenharmony_ci ui->last_page_read = offset + page_idx - 1; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ciout_free: 79962306a36Sopenharmony_ci if (allocate) 80062306a36Sopenharmony_ci kfree(bu->buf); 80162306a36Sopenharmony_ci return ret; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ciout_warn: 80462306a36Sopenharmony_ci ubifs_warn(c, "ignoring error %d and skipping bulk-read", err); 80562306a36Sopenharmony_ci goto out_free; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ciout_bu_off: 80862306a36Sopenharmony_ci ui->read_in_a_row = ui->bulk_read = 0; 80962306a36Sopenharmony_ci goto out_free; 81062306a36Sopenharmony_ci} 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci/** 81362306a36Sopenharmony_ci * ubifs_bulk_read - determine whether to bulk-read and, if so, do it. 81462306a36Sopenharmony_ci * @page: page from which to start bulk-read. 81562306a36Sopenharmony_ci * 81662306a36Sopenharmony_ci * Some flash media are capable of reading sequentially at faster rates. UBIFS 81762306a36Sopenharmony_ci * bulk-read facility is designed to take advantage of that, by reading in one 81862306a36Sopenharmony_ci * go consecutive data nodes that are also located consecutively in the same 81962306a36Sopenharmony_ci * LEB. This function returns %1 if a bulk-read is done and %0 otherwise. 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_cistatic int ubifs_bulk_read(struct page *page) 82262306a36Sopenharmony_ci{ 82362306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 82462306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 82562306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 82662306a36Sopenharmony_ci pgoff_t index = page->index, last_page_read = ui->last_page_read; 82762306a36Sopenharmony_ci struct bu_info *bu; 82862306a36Sopenharmony_ci int err = 0, allocated = 0; 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci ui->last_page_read = index; 83162306a36Sopenharmony_ci if (!c->bulk_read) 83262306a36Sopenharmony_ci return 0; 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci /* 83562306a36Sopenharmony_ci * Bulk-read is protected by @ui->ui_mutex, but it is an optimization, 83662306a36Sopenharmony_ci * so don't bother if we cannot lock the mutex. 83762306a36Sopenharmony_ci */ 83862306a36Sopenharmony_ci if (!mutex_trylock(&ui->ui_mutex)) 83962306a36Sopenharmony_ci return 0; 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_ci if (index != last_page_read + 1) { 84262306a36Sopenharmony_ci /* Turn off bulk-read if we stop reading sequentially */ 84362306a36Sopenharmony_ci ui->read_in_a_row = 1; 84462306a36Sopenharmony_ci if (ui->bulk_read) 84562306a36Sopenharmony_ci ui->bulk_read = 0; 84662306a36Sopenharmony_ci goto out_unlock; 84762306a36Sopenharmony_ci } 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci if (!ui->bulk_read) { 85062306a36Sopenharmony_ci ui->read_in_a_row += 1; 85162306a36Sopenharmony_ci if (ui->read_in_a_row < 3) 85262306a36Sopenharmony_ci goto out_unlock; 85362306a36Sopenharmony_ci /* Three reads in a row, so switch on bulk-read */ 85462306a36Sopenharmony_ci ui->bulk_read = 1; 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci /* 85862306a36Sopenharmony_ci * If possible, try to use pre-allocated bulk-read information, which 85962306a36Sopenharmony_ci * is protected by @c->bu_mutex. 86062306a36Sopenharmony_ci */ 86162306a36Sopenharmony_ci if (mutex_trylock(&c->bu_mutex)) 86262306a36Sopenharmony_ci bu = &c->bu; 86362306a36Sopenharmony_ci else { 86462306a36Sopenharmony_ci bu = kmalloc(sizeof(struct bu_info), GFP_NOFS | __GFP_NOWARN); 86562306a36Sopenharmony_ci if (!bu) 86662306a36Sopenharmony_ci goto out_unlock; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci bu->buf = NULL; 86962306a36Sopenharmony_ci allocated = 1; 87062306a36Sopenharmony_ci } 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci bu->buf_len = c->max_bu_buf_len; 87362306a36Sopenharmony_ci data_key_init(c, &bu->key, inode->i_ino, 87462306a36Sopenharmony_ci page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT); 87562306a36Sopenharmony_ci err = ubifs_do_bulk_read(c, bu, page); 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci if (!allocated) 87862306a36Sopenharmony_ci mutex_unlock(&c->bu_mutex); 87962306a36Sopenharmony_ci else 88062306a36Sopenharmony_ci kfree(bu); 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ciout_unlock: 88362306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 88462306a36Sopenharmony_ci return err; 88562306a36Sopenharmony_ci} 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_cistatic int ubifs_read_folio(struct file *file, struct folio *folio) 88862306a36Sopenharmony_ci{ 88962306a36Sopenharmony_ci struct page *page = &folio->page; 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci if (ubifs_bulk_read(page)) 89262306a36Sopenharmony_ci return 0; 89362306a36Sopenharmony_ci do_readpage(page); 89462306a36Sopenharmony_ci folio_unlock(folio); 89562306a36Sopenharmony_ci return 0; 89662306a36Sopenharmony_ci} 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_cistatic int do_writepage(struct page *page, int len) 89962306a36Sopenharmony_ci{ 90062306a36Sopenharmony_ci int err = 0, i, blen; 90162306a36Sopenharmony_ci unsigned int block; 90262306a36Sopenharmony_ci void *addr; 90362306a36Sopenharmony_ci union ubifs_key key; 90462306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 90562306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 90662306a36Sopenharmony_ci 90762306a36Sopenharmony_ci#ifdef UBIFS_DEBUG 90862306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 90962306a36Sopenharmony_ci spin_lock(&ui->ui_lock); 91062306a36Sopenharmony_ci ubifs_assert(c, page->index <= ui->synced_i_size >> PAGE_SHIFT); 91162306a36Sopenharmony_ci spin_unlock(&ui->ui_lock); 91262306a36Sopenharmony_ci#endif 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci /* Update radix tree tags */ 91562306a36Sopenharmony_ci set_page_writeback(page); 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci addr = kmap(page); 91862306a36Sopenharmony_ci block = page->index << UBIFS_BLOCKS_PER_PAGE_SHIFT; 91962306a36Sopenharmony_ci i = 0; 92062306a36Sopenharmony_ci while (len) { 92162306a36Sopenharmony_ci blen = min_t(int, len, UBIFS_BLOCK_SIZE); 92262306a36Sopenharmony_ci data_key_init(c, &key, inode->i_ino, block); 92362306a36Sopenharmony_ci err = ubifs_jnl_write_data(c, inode, &key, addr, blen); 92462306a36Sopenharmony_ci if (err) 92562306a36Sopenharmony_ci break; 92662306a36Sopenharmony_ci if (++i >= UBIFS_BLOCKS_PER_PAGE) 92762306a36Sopenharmony_ci break; 92862306a36Sopenharmony_ci block += 1; 92962306a36Sopenharmony_ci addr += blen; 93062306a36Sopenharmony_ci len -= blen; 93162306a36Sopenharmony_ci } 93262306a36Sopenharmony_ci if (err) { 93362306a36Sopenharmony_ci SetPageError(page); 93462306a36Sopenharmony_ci ubifs_err(c, "cannot write page %lu of inode %lu, error %d", 93562306a36Sopenharmony_ci page->index, inode->i_ino, err); 93662306a36Sopenharmony_ci ubifs_ro_mode(c, err); 93762306a36Sopenharmony_ci } 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci ubifs_assert(c, PagePrivate(page)); 94062306a36Sopenharmony_ci if (PageChecked(page)) 94162306a36Sopenharmony_ci release_new_page_budget(c); 94262306a36Sopenharmony_ci else 94362306a36Sopenharmony_ci release_existing_page_budget(c); 94462306a36Sopenharmony_ci 94562306a36Sopenharmony_ci atomic_long_dec(&c->dirty_pg_cnt); 94662306a36Sopenharmony_ci detach_page_private(page); 94762306a36Sopenharmony_ci ClearPageChecked(page); 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci kunmap(page); 95062306a36Sopenharmony_ci unlock_page(page); 95162306a36Sopenharmony_ci end_page_writeback(page); 95262306a36Sopenharmony_ci return err; 95362306a36Sopenharmony_ci} 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci/* 95662306a36Sopenharmony_ci * When writing-back dirty inodes, VFS first writes-back pages belonging to the 95762306a36Sopenharmony_ci * inode, then the inode itself. For UBIFS this may cause a problem. Consider a 95862306a36Sopenharmony_ci * situation when a we have an inode with size 0, then a megabyte of data is 95962306a36Sopenharmony_ci * appended to the inode, then write-back starts and flushes some amount of the 96062306a36Sopenharmony_ci * dirty pages, the journal becomes full, commit happens and finishes, and then 96162306a36Sopenharmony_ci * an unclean reboot happens. When the file system is mounted next time, the 96262306a36Sopenharmony_ci * inode size would still be 0, but there would be many pages which are beyond 96362306a36Sopenharmony_ci * the inode size, they would be indexed and consume flash space. Because the 96462306a36Sopenharmony_ci * journal has been committed, the replay would not be able to detect this 96562306a36Sopenharmony_ci * situation and correct the inode size. This means UBIFS would have to scan 96662306a36Sopenharmony_ci * whole index and correct all inode sizes, which is long an unacceptable. 96762306a36Sopenharmony_ci * 96862306a36Sopenharmony_ci * To prevent situations like this, UBIFS writes pages back only if they are 96962306a36Sopenharmony_ci * within the last synchronized inode size, i.e. the size which has been 97062306a36Sopenharmony_ci * written to the flash media last time. Otherwise, UBIFS forces inode 97162306a36Sopenharmony_ci * write-back, thus making sure the on-flash inode contains current inode size, 97262306a36Sopenharmony_ci * and then keeps writing pages back. 97362306a36Sopenharmony_ci * 97462306a36Sopenharmony_ci * Some locking issues explanation. 'ubifs_writepage()' first is called with 97562306a36Sopenharmony_ci * the page locked, and it locks @ui_mutex. However, write-back does take inode 97662306a36Sopenharmony_ci * @i_mutex, which means other VFS operations may be run on this inode at the 97762306a36Sopenharmony_ci * same time. And the problematic one is truncation to smaller size, from where 97862306a36Sopenharmony_ci * we have to call 'truncate_setsize()', which first changes @inode->i_size, 97962306a36Sopenharmony_ci * then drops the truncated pages. And while dropping the pages, it takes the 98062306a36Sopenharmony_ci * page lock. This means that 'do_truncation()' cannot call 'truncate_setsize()' 98162306a36Sopenharmony_ci * with @ui_mutex locked, because it would deadlock with 'ubifs_writepage()'. 98262306a36Sopenharmony_ci * This means that @inode->i_size is changed while @ui_mutex is unlocked. 98362306a36Sopenharmony_ci * 98462306a36Sopenharmony_ci * XXX(truncate): with the new truncate sequence this is not true anymore, 98562306a36Sopenharmony_ci * and the calls to truncate_setsize can be move around freely. They should 98662306a36Sopenharmony_ci * be moved to the very end of the truncate sequence. 98762306a36Sopenharmony_ci * 98862306a36Sopenharmony_ci * But in 'ubifs_writepage()' we have to guarantee that we do not write beyond 98962306a36Sopenharmony_ci * inode size. How do we do this if @inode->i_size may became smaller while we 99062306a36Sopenharmony_ci * are in the middle of 'ubifs_writepage()'? The UBIFS solution is the 99162306a36Sopenharmony_ci * @ui->ui_isize "shadow" field which UBIFS uses instead of @inode->i_size 99262306a36Sopenharmony_ci * internally and updates it under @ui_mutex. 99362306a36Sopenharmony_ci * 99462306a36Sopenharmony_ci * Q: why we do not worry that if we race with truncation, we may end up with a 99562306a36Sopenharmony_ci * situation when the inode is truncated while we are in the middle of 99662306a36Sopenharmony_ci * 'do_writepage()', so we do write beyond inode size? 99762306a36Sopenharmony_ci * A: If we are in the middle of 'do_writepage()', truncation would be locked 99862306a36Sopenharmony_ci * on the page lock and it would not write the truncated inode node to the 99962306a36Sopenharmony_ci * journal before we have finished. 100062306a36Sopenharmony_ci */ 100162306a36Sopenharmony_cistatic int ubifs_writepage(struct page *page, struct writeback_control *wbc) 100262306a36Sopenharmony_ci{ 100362306a36Sopenharmony_ci struct inode *inode = page->mapping->host; 100462306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 100562306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 100662306a36Sopenharmony_ci loff_t i_size = i_size_read(inode), synced_i_size; 100762306a36Sopenharmony_ci pgoff_t end_index = i_size >> PAGE_SHIFT; 100862306a36Sopenharmony_ci int err, len = i_size & (PAGE_SIZE - 1); 100962306a36Sopenharmony_ci void *kaddr; 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci dbg_gen("ino %lu, pg %lu, pg flags %#lx", 101262306a36Sopenharmony_ci inode->i_ino, page->index, page->flags); 101362306a36Sopenharmony_ci ubifs_assert(c, PagePrivate(page)); 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci /* Is the page fully outside @i_size? (truncate in progress) */ 101662306a36Sopenharmony_ci if (page->index > end_index || (page->index == end_index && !len)) { 101762306a36Sopenharmony_ci err = 0; 101862306a36Sopenharmony_ci goto out_unlock; 101962306a36Sopenharmony_ci } 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci spin_lock(&ui->ui_lock); 102262306a36Sopenharmony_ci synced_i_size = ui->synced_i_size; 102362306a36Sopenharmony_ci spin_unlock(&ui->ui_lock); 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci /* Is the page fully inside @i_size? */ 102662306a36Sopenharmony_ci if (page->index < end_index) { 102762306a36Sopenharmony_ci if (page->index >= synced_i_size >> PAGE_SHIFT) { 102862306a36Sopenharmony_ci err = inode->i_sb->s_op->write_inode(inode, NULL); 102962306a36Sopenharmony_ci if (err) 103062306a36Sopenharmony_ci goto out_redirty; 103162306a36Sopenharmony_ci /* 103262306a36Sopenharmony_ci * The inode has been written, but the write-buffer has 103362306a36Sopenharmony_ci * not been synchronized, so in case of an unclean 103462306a36Sopenharmony_ci * reboot we may end up with some pages beyond inode 103562306a36Sopenharmony_ci * size, but they would be in the journal (because 103662306a36Sopenharmony_ci * commit flushes write buffers) and recovery would deal 103762306a36Sopenharmony_ci * with this. 103862306a36Sopenharmony_ci */ 103962306a36Sopenharmony_ci } 104062306a36Sopenharmony_ci return do_writepage(page, PAGE_SIZE); 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci /* 104462306a36Sopenharmony_ci * The page straddles @i_size. It must be zeroed out on each and every 104562306a36Sopenharmony_ci * writepage invocation because it may be mmapped. "A file is mapped 104662306a36Sopenharmony_ci * in multiples of the page size. For a file that is not a multiple of 104762306a36Sopenharmony_ci * the page size, the remaining memory is zeroed when mapped, and 104862306a36Sopenharmony_ci * writes to that region are not written out to the file." 104962306a36Sopenharmony_ci */ 105062306a36Sopenharmony_ci kaddr = kmap_atomic(page); 105162306a36Sopenharmony_ci memset(kaddr + len, 0, PAGE_SIZE - len); 105262306a36Sopenharmony_ci flush_dcache_page(page); 105362306a36Sopenharmony_ci kunmap_atomic(kaddr); 105462306a36Sopenharmony_ci 105562306a36Sopenharmony_ci if (i_size > synced_i_size) { 105662306a36Sopenharmony_ci err = inode->i_sb->s_op->write_inode(inode, NULL); 105762306a36Sopenharmony_ci if (err) 105862306a36Sopenharmony_ci goto out_redirty; 105962306a36Sopenharmony_ci } 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci return do_writepage(page, len); 106262306a36Sopenharmony_ciout_redirty: 106362306a36Sopenharmony_ci /* 106462306a36Sopenharmony_ci * redirty_page_for_writepage() won't call ubifs_dirty_inode() because 106562306a36Sopenharmony_ci * it passes I_DIRTY_PAGES flag while calling __mark_inode_dirty(), so 106662306a36Sopenharmony_ci * there is no need to do space budget for dirty inode. 106762306a36Sopenharmony_ci */ 106862306a36Sopenharmony_ci redirty_page_for_writepage(wbc, page); 106962306a36Sopenharmony_ciout_unlock: 107062306a36Sopenharmony_ci unlock_page(page); 107162306a36Sopenharmony_ci return err; 107262306a36Sopenharmony_ci} 107362306a36Sopenharmony_ci 107462306a36Sopenharmony_ci/** 107562306a36Sopenharmony_ci * do_attr_changes - change inode attributes. 107662306a36Sopenharmony_ci * @inode: inode to change attributes for 107762306a36Sopenharmony_ci * @attr: describes attributes to change 107862306a36Sopenharmony_ci */ 107962306a36Sopenharmony_cistatic void do_attr_changes(struct inode *inode, const struct iattr *attr) 108062306a36Sopenharmony_ci{ 108162306a36Sopenharmony_ci if (attr->ia_valid & ATTR_UID) 108262306a36Sopenharmony_ci inode->i_uid = attr->ia_uid; 108362306a36Sopenharmony_ci if (attr->ia_valid & ATTR_GID) 108462306a36Sopenharmony_ci inode->i_gid = attr->ia_gid; 108562306a36Sopenharmony_ci if (attr->ia_valid & ATTR_ATIME) 108662306a36Sopenharmony_ci inode->i_atime = attr->ia_atime; 108762306a36Sopenharmony_ci if (attr->ia_valid & ATTR_MTIME) 108862306a36Sopenharmony_ci inode->i_mtime = attr->ia_mtime; 108962306a36Sopenharmony_ci if (attr->ia_valid & ATTR_CTIME) 109062306a36Sopenharmony_ci inode_set_ctime_to_ts(inode, attr->ia_ctime); 109162306a36Sopenharmony_ci if (attr->ia_valid & ATTR_MODE) { 109262306a36Sopenharmony_ci umode_t mode = attr->ia_mode; 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) 109562306a36Sopenharmony_ci mode &= ~S_ISGID; 109662306a36Sopenharmony_ci inode->i_mode = mode; 109762306a36Sopenharmony_ci } 109862306a36Sopenharmony_ci} 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci/** 110162306a36Sopenharmony_ci * do_truncation - truncate an inode. 110262306a36Sopenharmony_ci * @c: UBIFS file-system description object 110362306a36Sopenharmony_ci * @inode: inode to truncate 110462306a36Sopenharmony_ci * @attr: inode attribute changes description 110562306a36Sopenharmony_ci * 110662306a36Sopenharmony_ci * This function implements VFS '->setattr()' call when the inode is truncated 110762306a36Sopenharmony_ci * to a smaller size. Returns zero in case of success and a negative error code 110862306a36Sopenharmony_ci * in case of failure. 110962306a36Sopenharmony_ci */ 111062306a36Sopenharmony_cistatic int do_truncation(struct ubifs_info *c, struct inode *inode, 111162306a36Sopenharmony_ci const struct iattr *attr) 111262306a36Sopenharmony_ci{ 111362306a36Sopenharmony_ci int err; 111462306a36Sopenharmony_ci struct ubifs_budget_req req; 111562306a36Sopenharmony_ci loff_t old_size = inode->i_size, new_size = attr->ia_size; 111662306a36Sopenharmony_ci int offset = new_size & (UBIFS_BLOCK_SIZE - 1), budgeted = 1; 111762306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci dbg_gen("ino %lu, size %lld -> %lld", inode->i_ino, old_size, new_size); 112062306a36Sopenharmony_ci memset(&req, 0, sizeof(struct ubifs_budget_req)); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci /* 112362306a36Sopenharmony_ci * If this is truncation to a smaller size, and we do not truncate on a 112462306a36Sopenharmony_ci * block boundary, budget for changing one data block, because the last 112562306a36Sopenharmony_ci * block will be re-written. 112662306a36Sopenharmony_ci */ 112762306a36Sopenharmony_ci if (new_size & (UBIFS_BLOCK_SIZE - 1)) 112862306a36Sopenharmony_ci req.dirtied_page = 1; 112962306a36Sopenharmony_ci 113062306a36Sopenharmony_ci req.dirtied_ino = 1; 113162306a36Sopenharmony_ci /* A funny way to budget for truncation node */ 113262306a36Sopenharmony_ci req.dirtied_ino_d = UBIFS_TRUN_NODE_SZ; 113362306a36Sopenharmony_ci err = ubifs_budget_space(c, &req); 113462306a36Sopenharmony_ci if (err) { 113562306a36Sopenharmony_ci /* 113662306a36Sopenharmony_ci * Treat truncations to zero as deletion and always allow them, 113762306a36Sopenharmony_ci * just like we do for '->unlink()'. 113862306a36Sopenharmony_ci */ 113962306a36Sopenharmony_ci if (new_size || err != -ENOSPC) 114062306a36Sopenharmony_ci return err; 114162306a36Sopenharmony_ci budgeted = 0; 114262306a36Sopenharmony_ci } 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci truncate_setsize(inode, new_size); 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci if (offset) { 114762306a36Sopenharmony_ci pgoff_t index = new_size >> PAGE_SHIFT; 114862306a36Sopenharmony_ci struct page *page; 114962306a36Sopenharmony_ci 115062306a36Sopenharmony_ci page = find_lock_page(inode->i_mapping, index); 115162306a36Sopenharmony_ci if (page) { 115262306a36Sopenharmony_ci if (PageDirty(page)) { 115362306a36Sopenharmony_ci /* 115462306a36Sopenharmony_ci * 'ubifs_jnl_truncate()' will try to truncate 115562306a36Sopenharmony_ci * the last data node, but it contains 115662306a36Sopenharmony_ci * out-of-date data because the page is dirty. 115762306a36Sopenharmony_ci * Write the page now, so that 115862306a36Sopenharmony_ci * 'ubifs_jnl_truncate()' will see an already 115962306a36Sopenharmony_ci * truncated (and up to date) data node. 116062306a36Sopenharmony_ci */ 116162306a36Sopenharmony_ci ubifs_assert(c, PagePrivate(page)); 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_ci clear_page_dirty_for_io(page); 116462306a36Sopenharmony_ci if (UBIFS_BLOCKS_PER_PAGE_SHIFT) 116562306a36Sopenharmony_ci offset = new_size & 116662306a36Sopenharmony_ci (PAGE_SIZE - 1); 116762306a36Sopenharmony_ci err = do_writepage(page, offset); 116862306a36Sopenharmony_ci put_page(page); 116962306a36Sopenharmony_ci if (err) 117062306a36Sopenharmony_ci goto out_budg; 117162306a36Sopenharmony_ci /* 117262306a36Sopenharmony_ci * We could now tell 'ubifs_jnl_truncate()' not 117362306a36Sopenharmony_ci * to read the last block. 117462306a36Sopenharmony_ci */ 117562306a36Sopenharmony_ci } else { 117662306a36Sopenharmony_ci /* 117762306a36Sopenharmony_ci * We could 'kmap()' the page and pass the data 117862306a36Sopenharmony_ci * to 'ubifs_jnl_truncate()' to save it from 117962306a36Sopenharmony_ci * having to read it. 118062306a36Sopenharmony_ci */ 118162306a36Sopenharmony_ci unlock_page(page); 118262306a36Sopenharmony_ci put_page(page); 118362306a36Sopenharmony_ci } 118462306a36Sopenharmony_ci } 118562306a36Sopenharmony_ci } 118662306a36Sopenharmony_ci 118762306a36Sopenharmony_ci mutex_lock(&ui->ui_mutex); 118862306a36Sopenharmony_ci ui->ui_size = inode->i_size; 118962306a36Sopenharmony_ci /* Truncation changes inode [mc]time */ 119062306a36Sopenharmony_ci inode->i_mtime = inode_set_ctime_current(inode); 119162306a36Sopenharmony_ci /* Other attributes may be changed at the same time as well */ 119262306a36Sopenharmony_ci do_attr_changes(inode, attr); 119362306a36Sopenharmony_ci err = ubifs_jnl_truncate(c, inode, old_size, new_size); 119462306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ciout_budg: 119762306a36Sopenharmony_ci if (budgeted) 119862306a36Sopenharmony_ci ubifs_release_budget(c, &req); 119962306a36Sopenharmony_ci else { 120062306a36Sopenharmony_ci c->bi.nospace = c->bi.nospace_rp = 0; 120162306a36Sopenharmony_ci smp_wmb(); 120262306a36Sopenharmony_ci } 120362306a36Sopenharmony_ci return err; 120462306a36Sopenharmony_ci} 120562306a36Sopenharmony_ci 120662306a36Sopenharmony_ci/** 120762306a36Sopenharmony_ci * do_setattr - change inode attributes. 120862306a36Sopenharmony_ci * @c: UBIFS file-system description object 120962306a36Sopenharmony_ci * @inode: inode to change attributes for 121062306a36Sopenharmony_ci * @attr: inode attribute changes description 121162306a36Sopenharmony_ci * 121262306a36Sopenharmony_ci * This function implements VFS '->setattr()' call for all cases except 121362306a36Sopenharmony_ci * truncations to smaller size. Returns zero in case of success and a negative 121462306a36Sopenharmony_ci * error code in case of failure. 121562306a36Sopenharmony_ci */ 121662306a36Sopenharmony_cistatic int do_setattr(struct ubifs_info *c, struct inode *inode, 121762306a36Sopenharmony_ci const struct iattr *attr) 121862306a36Sopenharmony_ci{ 121962306a36Sopenharmony_ci int err, release; 122062306a36Sopenharmony_ci loff_t new_size = attr->ia_size; 122162306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 122262306a36Sopenharmony_ci struct ubifs_budget_req req = { .dirtied_ino = 1, 122362306a36Sopenharmony_ci .dirtied_ino_d = ALIGN(ui->data_len, 8) }; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci err = ubifs_budget_space(c, &req); 122662306a36Sopenharmony_ci if (err) 122762306a36Sopenharmony_ci return err; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci if (attr->ia_valid & ATTR_SIZE) { 123062306a36Sopenharmony_ci dbg_gen("size %lld -> %lld", inode->i_size, new_size); 123162306a36Sopenharmony_ci truncate_setsize(inode, new_size); 123262306a36Sopenharmony_ci } 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci mutex_lock(&ui->ui_mutex); 123562306a36Sopenharmony_ci if (attr->ia_valid & ATTR_SIZE) { 123662306a36Sopenharmony_ci /* Truncation changes inode [mc]time */ 123762306a36Sopenharmony_ci inode->i_mtime = inode_set_ctime_current(inode); 123862306a36Sopenharmony_ci /* 'truncate_setsize()' changed @i_size, update @ui_size */ 123962306a36Sopenharmony_ci ui->ui_size = inode->i_size; 124062306a36Sopenharmony_ci } 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci do_attr_changes(inode, attr); 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci release = ui->dirty; 124562306a36Sopenharmony_ci if (attr->ia_valid & ATTR_SIZE) 124662306a36Sopenharmony_ci /* 124762306a36Sopenharmony_ci * Inode length changed, so we have to make sure 124862306a36Sopenharmony_ci * @I_DIRTY_DATASYNC is set. 124962306a36Sopenharmony_ci */ 125062306a36Sopenharmony_ci __mark_inode_dirty(inode, I_DIRTY_DATASYNC); 125162306a36Sopenharmony_ci else 125262306a36Sopenharmony_ci mark_inode_dirty_sync(inode); 125362306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci if (release) 125662306a36Sopenharmony_ci ubifs_release_budget(c, &req); 125762306a36Sopenharmony_ci if (IS_SYNC(inode)) 125862306a36Sopenharmony_ci err = inode->i_sb->s_op->write_inode(inode, NULL); 125962306a36Sopenharmony_ci return err; 126062306a36Sopenharmony_ci} 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ciint ubifs_setattr(struct mnt_idmap *idmap, struct dentry *dentry, 126362306a36Sopenharmony_ci struct iattr *attr) 126462306a36Sopenharmony_ci{ 126562306a36Sopenharmony_ci int err; 126662306a36Sopenharmony_ci struct inode *inode = d_inode(dentry); 126762306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_ci dbg_gen("ino %lu, mode %#x, ia_valid %#x", 127062306a36Sopenharmony_ci inode->i_ino, inode->i_mode, attr->ia_valid); 127162306a36Sopenharmony_ci err = setattr_prepare(&nop_mnt_idmap, dentry, attr); 127262306a36Sopenharmony_ci if (err) 127362306a36Sopenharmony_ci return err; 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_ci err = dbg_check_synced_i_size(c, inode); 127662306a36Sopenharmony_ci if (err) 127762306a36Sopenharmony_ci return err; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci err = fscrypt_prepare_setattr(dentry, attr); 128062306a36Sopenharmony_ci if (err) 128162306a36Sopenharmony_ci return err; 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci if ((attr->ia_valid & ATTR_SIZE) && attr->ia_size < inode->i_size) 128462306a36Sopenharmony_ci /* Truncation to a smaller size */ 128562306a36Sopenharmony_ci err = do_truncation(c, inode, attr); 128662306a36Sopenharmony_ci else 128762306a36Sopenharmony_ci err = do_setattr(c, inode, attr); 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci return err; 129062306a36Sopenharmony_ci} 129162306a36Sopenharmony_ci 129262306a36Sopenharmony_cistatic void ubifs_invalidate_folio(struct folio *folio, size_t offset, 129362306a36Sopenharmony_ci size_t length) 129462306a36Sopenharmony_ci{ 129562306a36Sopenharmony_ci struct inode *inode = folio->mapping->host; 129662306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci ubifs_assert(c, folio_test_private(folio)); 129962306a36Sopenharmony_ci if (offset || length < folio_size(folio)) 130062306a36Sopenharmony_ci /* Partial folio remains dirty */ 130162306a36Sopenharmony_ci return; 130262306a36Sopenharmony_ci 130362306a36Sopenharmony_ci if (folio_test_checked(folio)) 130462306a36Sopenharmony_ci release_new_page_budget(c); 130562306a36Sopenharmony_ci else 130662306a36Sopenharmony_ci release_existing_page_budget(c); 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci atomic_long_dec(&c->dirty_pg_cnt); 130962306a36Sopenharmony_ci folio_detach_private(folio); 131062306a36Sopenharmony_ci folio_clear_checked(folio); 131162306a36Sopenharmony_ci} 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ciint ubifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) 131462306a36Sopenharmony_ci{ 131562306a36Sopenharmony_ci struct inode *inode = file->f_mapping->host; 131662306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 131762306a36Sopenharmony_ci int err; 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_ci dbg_gen("syncing inode %lu", inode->i_ino); 132062306a36Sopenharmony_ci 132162306a36Sopenharmony_ci if (c->ro_mount) 132262306a36Sopenharmony_ci /* 132362306a36Sopenharmony_ci * For some really strange reasons VFS does not filter out 132462306a36Sopenharmony_ci * 'fsync()' for R/O mounted file-systems as per 2.6.39. 132562306a36Sopenharmony_ci */ 132662306a36Sopenharmony_ci return 0; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci err = file_write_and_wait_range(file, start, end); 132962306a36Sopenharmony_ci if (err) 133062306a36Sopenharmony_ci return err; 133162306a36Sopenharmony_ci inode_lock(inode); 133262306a36Sopenharmony_ci 133362306a36Sopenharmony_ci /* Synchronize the inode unless this is a 'datasync()' call. */ 133462306a36Sopenharmony_ci if (!datasync || (inode->i_state & I_DIRTY_DATASYNC)) { 133562306a36Sopenharmony_ci err = inode->i_sb->s_op->write_inode(inode, NULL); 133662306a36Sopenharmony_ci if (err) 133762306a36Sopenharmony_ci goto out; 133862306a36Sopenharmony_ci } 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci /* 134162306a36Sopenharmony_ci * Nodes related to this inode may still sit in a write-buffer. Flush 134262306a36Sopenharmony_ci * them. 134362306a36Sopenharmony_ci */ 134462306a36Sopenharmony_ci err = ubifs_sync_wbufs_by_inode(c, inode); 134562306a36Sopenharmony_ciout: 134662306a36Sopenharmony_ci inode_unlock(inode); 134762306a36Sopenharmony_ci return err; 134862306a36Sopenharmony_ci} 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci/** 135162306a36Sopenharmony_ci * mctime_update_needed - check if mtime or ctime update is needed. 135262306a36Sopenharmony_ci * @inode: the inode to do the check for 135362306a36Sopenharmony_ci * @now: current time 135462306a36Sopenharmony_ci * 135562306a36Sopenharmony_ci * This helper function checks if the inode mtime/ctime should be updated or 135662306a36Sopenharmony_ci * not. If current values of the time-stamps are within the UBIFS inode time 135762306a36Sopenharmony_ci * granularity, they are not updated. This is an optimization. 135862306a36Sopenharmony_ci */ 135962306a36Sopenharmony_cistatic inline int mctime_update_needed(const struct inode *inode, 136062306a36Sopenharmony_ci const struct timespec64 *now) 136162306a36Sopenharmony_ci{ 136262306a36Sopenharmony_ci struct timespec64 ctime = inode_get_ctime(inode); 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci if (!timespec64_equal(&inode->i_mtime, now) || 136562306a36Sopenharmony_ci !timespec64_equal(&ctime, now)) 136662306a36Sopenharmony_ci return 1; 136762306a36Sopenharmony_ci return 0; 136862306a36Sopenharmony_ci} 136962306a36Sopenharmony_ci 137062306a36Sopenharmony_ci/** 137162306a36Sopenharmony_ci * ubifs_update_time - update time of inode. 137262306a36Sopenharmony_ci * @inode: inode to update 137362306a36Sopenharmony_ci * 137462306a36Sopenharmony_ci * This function updates time of the inode. 137562306a36Sopenharmony_ci */ 137662306a36Sopenharmony_ciint ubifs_update_time(struct inode *inode, int flags) 137762306a36Sopenharmony_ci{ 137862306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 137962306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 138062306a36Sopenharmony_ci struct ubifs_budget_req req = { .dirtied_ino = 1, 138162306a36Sopenharmony_ci .dirtied_ino_d = ALIGN(ui->data_len, 8) }; 138262306a36Sopenharmony_ci int err, release; 138362306a36Sopenharmony_ci 138462306a36Sopenharmony_ci if (!IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT)) { 138562306a36Sopenharmony_ci generic_update_time(inode, flags); 138662306a36Sopenharmony_ci return 0; 138762306a36Sopenharmony_ci } 138862306a36Sopenharmony_ci 138962306a36Sopenharmony_ci err = ubifs_budget_space(c, &req); 139062306a36Sopenharmony_ci if (err) 139162306a36Sopenharmony_ci return err; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci mutex_lock(&ui->ui_mutex); 139462306a36Sopenharmony_ci inode_update_timestamps(inode, flags); 139562306a36Sopenharmony_ci release = ui->dirty; 139662306a36Sopenharmony_ci __mark_inode_dirty(inode, I_DIRTY_SYNC); 139762306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 139862306a36Sopenharmony_ci if (release) 139962306a36Sopenharmony_ci ubifs_release_budget(c, &req); 140062306a36Sopenharmony_ci return 0; 140162306a36Sopenharmony_ci} 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci/** 140462306a36Sopenharmony_ci * update_mctime - update mtime and ctime of an inode. 140562306a36Sopenharmony_ci * @inode: inode to update 140662306a36Sopenharmony_ci * 140762306a36Sopenharmony_ci * This function updates mtime and ctime of the inode if it is not equivalent to 140862306a36Sopenharmony_ci * current time. Returns zero in case of success and a negative error code in 140962306a36Sopenharmony_ci * case of failure. 141062306a36Sopenharmony_ci */ 141162306a36Sopenharmony_cistatic int update_mctime(struct inode *inode) 141262306a36Sopenharmony_ci{ 141362306a36Sopenharmony_ci struct timespec64 now = current_time(inode); 141462306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 141562306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 141662306a36Sopenharmony_ci 141762306a36Sopenharmony_ci if (mctime_update_needed(inode, &now)) { 141862306a36Sopenharmony_ci int err, release; 141962306a36Sopenharmony_ci struct ubifs_budget_req req = { .dirtied_ino = 1, 142062306a36Sopenharmony_ci .dirtied_ino_d = ALIGN(ui->data_len, 8) }; 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci err = ubifs_budget_space(c, &req); 142362306a36Sopenharmony_ci if (err) 142462306a36Sopenharmony_ci return err; 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci mutex_lock(&ui->ui_mutex); 142762306a36Sopenharmony_ci inode->i_mtime = inode_set_ctime_current(inode); 142862306a36Sopenharmony_ci release = ui->dirty; 142962306a36Sopenharmony_ci mark_inode_dirty_sync(inode); 143062306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 143162306a36Sopenharmony_ci if (release) 143262306a36Sopenharmony_ci ubifs_release_budget(c, &req); 143362306a36Sopenharmony_ci } 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci return 0; 143662306a36Sopenharmony_ci} 143762306a36Sopenharmony_ci 143862306a36Sopenharmony_cistatic ssize_t ubifs_write_iter(struct kiocb *iocb, struct iov_iter *from) 143962306a36Sopenharmony_ci{ 144062306a36Sopenharmony_ci int err = update_mctime(file_inode(iocb->ki_filp)); 144162306a36Sopenharmony_ci if (err) 144262306a36Sopenharmony_ci return err; 144362306a36Sopenharmony_ci 144462306a36Sopenharmony_ci return generic_file_write_iter(iocb, from); 144562306a36Sopenharmony_ci} 144662306a36Sopenharmony_ci 144762306a36Sopenharmony_cistatic bool ubifs_dirty_folio(struct address_space *mapping, 144862306a36Sopenharmony_ci struct folio *folio) 144962306a36Sopenharmony_ci{ 145062306a36Sopenharmony_ci bool ret; 145162306a36Sopenharmony_ci struct ubifs_info *c = mapping->host->i_sb->s_fs_info; 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci ret = filemap_dirty_folio(mapping, folio); 145462306a36Sopenharmony_ci /* 145562306a36Sopenharmony_ci * An attempt to dirty a page without budgeting for it - should not 145662306a36Sopenharmony_ci * happen. 145762306a36Sopenharmony_ci */ 145862306a36Sopenharmony_ci ubifs_assert(c, ret == false); 145962306a36Sopenharmony_ci return ret; 146062306a36Sopenharmony_ci} 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_cistatic bool ubifs_release_folio(struct folio *folio, gfp_t unused_gfp_flags) 146362306a36Sopenharmony_ci{ 146462306a36Sopenharmony_ci struct inode *inode = folio->mapping->host; 146562306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci if (folio_test_writeback(folio)) 146862306a36Sopenharmony_ci return false; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci /* 147162306a36Sopenharmony_ci * Page is private but not dirty, weird? There is one condition 147262306a36Sopenharmony_ci * making it happened. ubifs_writepage skipped the page because 147362306a36Sopenharmony_ci * page index beyonds isize (for example. truncated by other 147462306a36Sopenharmony_ci * process named A), then the page is invalidated by fadvise64 147562306a36Sopenharmony_ci * syscall before being truncated by process A. 147662306a36Sopenharmony_ci */ 147762306a36Sopenharmony_ci ubifs_assert(c, folio_test_private(folio)); 147862306a36Sopenharmony_ci if (folio_test_checked(folio)) 147962306a36Sopenharmony_ci release_new_page_budget(c); 148062306a36Sopenharmony_ci else 148162306a36Sopenharmony_ci release_existing_page_budget(c); 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci atomic_long_dec(&c->dirty_pg_cnt); 148462306a36Sopenharmony_ci folio_detach_private(folio); 148562306a36Sopenharmony_ci folio_clear_checked(folio); 148662306a36Sopenharmony_ci return true; 148762306a36Sopenharmony_ci} 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_ci/* 149062306a36Sopenharmony_ci * mmap()d file has taken write protection fault and is being made writable. 149162306a36Sopenharmony_ci * UBIFS must ensure page is budgeted for. 149262306a36Sopenharmony_ci */ 149362306a36Sopenharmony_cistatic vm_fault_t ubifs_vm_page_mkwrite(struct vm_fault *vmf) 149462306a36Sopenharmony_ci{ 149562306a36Sopenharmony_ci struct page *page = vmf->page; 149662306a36Sopenharmony_ci struct inode *inode = file_inode(vmf->vma->vm_file); 149762306a36Sopenharmony_ci struct ubifs_info *c = inode->i_sb->s_fs_info; 149862306a36Sopenharmony_ci struct timespec64 now = current_time(inode); 149962306a36Sopenharmony_ci struct ubifs_budget_req req = { .new_page = 1 }; 150062306a36Sopenharmony_ci int err, update_time; 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci dbg_gen("ino %lu, pg %lu, i_size %lld", inode->i_ino, page->index, 150362306a36Sopenharmony_ci i_size_read(inode)); 150462306a36Sopenharmony_ci ubifs_assert(c, !c->ro_media && !c->ro_mount); 150562306a36Sopenharmony_ci 150662306a36Sopenharmony_ci if (unlikely(c->ro_error)) 150762306a36Sopenharmony_ci return VM_FAULT_SIGBUS; /* -EROFS */ 150862306a36Sopenharmony_ci 150962306a36Sopenharmony_ci /* 151062306a36Sopenharmony_ci * We have not locked @page so far so we may budget for changing the 151162306a36Sopenharmony_ci * page. Note, we cannot do this after we locked the page, because 151262306a36Sopenharmony_ci * budgeting may cause write-back which would cause deadlock. 151362306a36Sopenharmony_ci * 151462306a36Sopenharmony_ci * At the moment we do not know whether the page is dirty or not, so we 151562306a36Sopenharmony_ci * assume that it is not and budget for a new page. We could look at 151662306a36Sopenharmony_ci * the @PG_private flag and figure this out, but we may race with write 151762306a36Sopenharmony_ci * back and the page state may change by the time we lock it, so this 151862306a36Sopenharmony_ci * would need additional care. We do not bother with this at the 151962306a36Sopenharmony_ci * moment, although it might be good idea to do. Instead, we allocate 152062306a36Sopenharmony_ci * budget for a new page and amend it later on if the page was in fact 152162306a36Sopenharmony_ci * dirty. 152262306a36Sopenharmony_ci * 152362306a36Sopenharmony_ci * The budgeting-related logic of this function is similar to what we 152462306a36Sopenharmony_ci * do in 'ubifs_write_begin()' and 'ubifs_write_end()'. Glance there 152562306a36Sopenharmony_ci * for more comments. 152662306a36Sopenharmony_ci */ 152762306a36Sopenharmony_ci update_time = mctime_update_needed(inode, &now); 152862306a36Sopenharmony_ci if (update_time) 152962306a36Sopenharmony_ci /* 153062306a36Sopenharmony_ci * We have to change inode time stamp which requires extra 153162306a36Sopenharmony_ci * budgeting. 153262306a36Sopenharmony_ci */ 153362306a36Sopenharmony_ci req.dirtied_ino = 1; 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci err = ubifs_budget_space(c, &req); 153662306a36Sopenharmony_ci if (unlikely(err)) { 153762306a36Sopenharmony_ci if (err == -ENOSPC) 153862306a36Sopenharmony_ci ubifs_warn(c, "out of space for mmapped file (inode number %lu)", 153962306a36Sopenharmony_ci inode->i_ino); 154062306a36Sopenharmony_ci return VM_FAULT_SIGBUS; 154162306a36Sopenharmony_ci } 154262306a36Sopenharmony_ci 154362306a36Sopenharmony_ci lock_page(page); 154462306a36Sopenharmony_ci if (unlikely(page->mapping != inode->i_mapping || 154562306a36Sopenharmony_ci page_offset(page) > i_size_read(inode))) { 154662306a36Sopenharmony_ci /* Page got truncated out from underneath us */ 154762306a36Sopenharmony_ci goto sigbus; 154862306a36Sopenharmony_ci } 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci if (PagePrivate(page)) 155162306a36Sopenharmony_ci release_new_page_budget(c); 155262306a36Sopenharmony_ci else { 155362306a36Sopenharmony_ci if (!PageChecked(page)) 155462306a36Sopenharmony_ci ubifs_convert_page_budget(c); 155562306a36Sopenharmony_ci attach_page_private(page, (void *)1); 155662306a36Sopenharmony_ci atomic_long_inc(&c->dirty_pg_cnt); 155762306a36Sopenharmony_ci __set_page_dirty_nobuffers(page); 155862306a36Sopenharmony_ci } 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci if (update_time) { 156162306a36Sopenharmony_ci int release; 156262306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci mutex_lock(&ui->ui_mutex); 156562306a36Sopenharmony_ci inode->i_mtime = inode_set_ctime_current(inode); 156662306a36Sopenharmony_ci release = ui->dirty; 156762306a36Sopenharmony_ci mark_inode_dirty_sync(inode); 156862306a36Sopenharmony_ci mutex_unlock(&ui->ui_mutex); 156962306a36Sopenharmony_ci if (release) 157062306a36Sopenharmony_ci ubifs_release_dirty_inode_budget(c, ui); 157162306a36Sopenharmony_ci } 157262306a36Sopenharmony_ci 157362306a36Sopenharmony_ci wait_for_stable_page(page); 157462306a36Sopenharmony_ci return VM_FAULT_LOCKED; 157562306a36Sopenharmony_ci 157662306a36Sopenharmony_cisigbus: 157762306a36Sopenharmony_ci unlock_page(page); 157862306a36Sopenharmony_ci ubifs_release_budget(c, &req); 157962306a36Sopenharmony_ci return VM_FAULT_SIGBUS; 158062306a36Sopenharmony_ci} 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_cistatic const struct vm_operations_struct ubifs_file_vm_ops = { 158362306a36Sopenharmony_ci .fault = filemap_fault, 158462306a36Sopenharmony_ci .map_pages = filemap_map_pages, 158562306a36Sopenharmony_ci .page_mkwrite = ubifs_vm_page_mkwrite, 158662306a36Sopenharmony_ci}; 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_cistatic int ubifs_file_mmap(struct file *file, struct vm_area_struct *vma) 158962306a36Sopenharmony_ci{ 159062306a36Sopenharmony_ci int err; 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci err = generic_file_mmap(file, vma); 159362306a36Sopenharmony_ci if (err) 159462306a36Sopenharmony_ci return err; 159562306a36Sopenharmony_ci vma->vm_ops = &ubifs_file_vm_ops; 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_UBIFS_ATIME_SUPPORT)) 159862306a36Sopenharmony_ci file_accessed(file); 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci return 0; 160162306a36Sopenharmony_ci} 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_cistatic const char *ubifs_get_link(struct dentry *dentry, 160462306a36Sopenharmony_ci struct inode *inode, 160562306a36Sopenharmony_ci struct delayed_call *done) 160662306a36Sopenharmony_ci{ 160762306a36Sopenharmony_ci struct ubifs_inode *ui = ubifs_inode(inode); 160862306a36Sopenharmony_ci 160962306a36Sopenharmony_ci if (!IS_ENCRYPTED(inode)) 161062306a36Sopenharmony_ci return ui->data; 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci if (!dentry) 161362306a36Sopenharmony_ci return ERR_PTR(-ECHILD); 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci return fscrypt_get_symlink(inode, ui->data, ui->data_len, done); 161662306a36Sopenharmony_ci} 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_cistatic int ubifs_symlink_getattr(struct mnt_idmap *idmap, 161962306a36Sopenharmony_ci const struct path *path, struct kstat *stat, 162062306a36Sopenharmony_ci u32 request_mask, unsigned int query_flags) 162162306a36Sopenharmony_ci{ 162262306a36Sopenharmony_ci ubifs_getattr(idmap, path, stat, request_mask, query_flags); 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci if (IS_ENCRYPTED(d_inode(path->dentry))) 162562306a36Sopenharmony_ci return fscrypt_symlink_getattr(path, stat); 162662306a36Sopenharmony_ci return 0; 162762306a36Sopenharmony_ci} 162862306a36Sopenharmony_ci 162962306a36Sopenharmony_ciconst struct address_space_operations ubifs_file_address_operations = { 163062306a36Sopenharmony_ci .read_folio = ubifs_read_folio, 163162306a36Sopenharmony_ci .writepage = ubifs_writepage, 163262306a36Sopenharmony_ci .write_begin = ubifs_write_begin, 163362306a36Sopenharmony_ci .write_end = ubifs_write_end, 163462306a36Sopenharmony_ci .invalidate_folio = ubifs_invalidate_folio, 163562306a36Sopenharmony_ci .dirty_folio = ubifs_dirty_folio, 163662306a36Sopenharmony_ci .migrate_folio = filemap_migrate_folio, 163762306a36Sopenharmony_ci .release_folio = ubifs_release_folio, 163862306a36Sopenharmony_ci}; 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ciconst struct inode_operations ubifs_file_inode_operations = { 164162306a36Sopenharmony_ci .setattr = ubifs_setattr, 164262306a36Sopenharmony_ci .getattr = ubifs_getattr, 164362306a36Sopenharmony_ci .listxattr = ubifs_listxattr, 164462306a36Sopenharmony_ci .update_time = ubifs_update_time, 164562306a36Sopenharmony_ci .fileattr_get = ubifs_fileattr_get, 164662306a36Sopenharmony_ci .fileattr_set = ubifs_fileattr_set, 164762306a36Sopenharmony_ci}; 164862306a36Sopenharmony_ci 164962306a36Sopenharmony_ciconst struct inode_operations ubifs_symlink_inode_operations = { 165062306a36Sopenharmony_ci .get_link = ubifs_get_link, 165162306a36Sopenharmony_ci .setattr = ubifs_setattr, 165262306a36Sopenharmony_ci .getattr = ubifs_symlink_getattr, 165362306a36Sopenharmony_ci .listxattr = ubifs_listxattr, 165462306a36Sopenharmony_ci .update_time = ubifs_update_time, 165562306a36Sopenharmony_ci}; 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ciconst struct file_operations ubifs_file_operations = { 165862306a36Sopenharmony_ci .llseek = generic_file_llseek, 165962306a36Sopenharmony_ci .read_iter = generic_file_read_iter, 166062306a36Sopenharmony_ci .write_iter = ubifs_write_iter, 166162306a36Sopenharmony_ci .mmap = ubifs_file_mmap, 166262306a36Sopenharmony_ci .fsync = ubifs_fsync, 166362306a36Sopenharmony_ci .unlocked_ioctl = ubifs_ioctl, 166462306a36Sopenharmony_ci .splice_read = filemap_splice_read, 166562306a36Sopenharmony_ci .splice_write = iter_file_splice_write, 166662306a36Sopenharmony_ci .open = fscrypt_file_open, 166762306a36Sopenharmony_ci#ifdef CONFIG_COMPAT 166862306a36Sopenharmony_ci .compat_ioctl = ubifs_compat_ioctl, 166962306a36Sopenharmony_ci#endif 167062306a36Sopenharmony_ci}; 1671