18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * JFFS2 -- Journalling Flash File System, Version 2. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright © 2001-2007 Red Hat, Inc. 58c2ecf20Sopenharmony_ci * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Created by David Woodhouse <dwmw2@infradead.org> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * For licensing information, see the file 'LICENCE' in this directory. 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci */ 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/capability.h> 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <linux/sched.h> 188c2ecf20Sopenharmony_ci#include <linux/cred.h> 198c2ecf20Sopenharmony_ci#include <linux/fs.h> 208c2ecf20Sopenharmony_ci#include <linux/fs_context.h> 218c2ecf20Sopenharmony_ci#include <linux/list.h> 228c2ecf20Sopenharmony_ci#include <linux/mtd/mtd.h> 238c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 248c2ecf20Sopenharmony_ci#include <linux/slab.h> 258c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 268c2ecf20Sopenharmony_ci#include <linux/vfs.h> 278c2ecf20Sopenharmony_ci#include <linux/crc32.h> 288c2ecf20Sopenharmony_ci#include "nodelist.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic int jffs2_flash_setup(struct jffs2_sb_info *c); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ciint jffs2_do_setattr (struct inode *inode, struct iattr *iattr) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci struct jffs2_full_dnode *old_metadata, *new_metadata; 358c2ecf20Sopenharmony_ci struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 368c2ecf20Sopenharmony_ci struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 378c2ecf20Sopenharmony_ci struct jffs2_raw_inode *ri; 388c2ecf20Sopenharmony_ci union jffs2_device_node dev; 398c2ecf20Sopenharmony_ci unsigned char *mdata = NULL; 408c2ecf20Sopenharmony_ci int mdatalen = 0; 418c2ecf20Sopenharmony_ci unsigned int ivalid; 428c2ecf20Sopenharmony_ci uint32_t alloclen; 438c2ecf20Sopenharmony_ci int ret; 448c2ecf20Sopenharmony_ci int alloc_type = ALLOC_NORMAL; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): ino #%lu\n", __func__, inode->i_ino); 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci /* Special cases - we don't want more than one data node 498c2ecf20Sopenharmony_ci for these types on the medium at any time. So setattr 508c2ecf20Sopenharmony_ci must read the original data associated with the node 518c2ecf20Sopenharmony_ci (i.e. the device numbers or the target name) and write 528c2ecf20Sopenharmony_ci it out again with the appropriate data attached */ 538c2ecf20Sopenharmony_ci if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { 548c2ecf20Sopenharmony_ci /* For these, we don't actually need to read the old node */ 558c2ecf20Sopenharmony_ci mdatalen = jffs2_encode_dev(&dev, inode->i_rdev); 568c2ecf20Sopenharmony_ci mdata = (char *)&dev; 578c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t\n", 588c2ecf20Sopenharmony_ci __func__, mdatalen); 598c2ecf20Sopenharmony_ci } else if (S_ISLNK(inode->i_mode)) { 608c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 618c2ecf20Sopenharmony_ci mdatalen = f->metadata->size; 628c2ecf20Sopenharmony_ci mdata = kmalloc(f->metadata->size, GFP_USER); 638c2ecf20Sopenharmony_ci if (!mdata) { 648c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 658c2ecf20Sopenharmony_ci return -ENOMEM; 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_ci ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen); 688c2ecf20Sopenharmony_ci if (ret) { 698c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 708c2ecf20Sopenharmony_ci kfree(mdata); 718c2ecf20Sopenharmony_ci return ret; 728c2ecf20Sopenharmony_ci } 738c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 748c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): Writing %d bytes of symlink target\n", 758c2ecf20Sopenharmony_ci __func__, mdatalen); 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci ri = jffs2_alloc_raw_inode(); 798c2ecf20Sopenharmony_ci if (!ri) { 808c2ecf20Sopenharmony_ci if (S_ISLNK(inode->i_mode)) 818c2ecf20Sopenharmony_ci kfree(mdata); 828c2ecf20Sopenharmony_ci return -ENOMEM; 838c2ecf20Sopenharmony_ci } 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen, 868c2ecf20Sopenharmony_ci ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); 878c2ecf20Sopenharmony_ci if (ret) { 888c2ecf20Sopenharmony_ci jffs2_free_raw_inode(ri); 898c2ecf20Sopenharmony_ci if (S_ISLNK(inode->i_mode)) 908c2ecf20Sopenharmony_ci kfree(mdata); 918c2ecf20Sopenharmony_ci return ret; 928c2ecf20Sopenharmony_ci } 938c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 948c2ecf20Sopenharmony_ci ivalid = iattr->ia_valid; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); 978c2ecf20Sopenharmony_ci ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); 988c2ecf20Sopenharmony_ci ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen); 998c2ecf20Sopenharmony_ci ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4)); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci ri->ino = cpu_to_je32(inode->i_ino); 1028c2ecf20Sopenharmony_ci ri->version = cpu_to_je32(++f->highest_version); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci ri->uid = cpu_to_je16((ivalid & ATTR_UID)? 1058c2ecf20Sopenharmony_ci from_kuid(&init_user_ns, iattr->ia_uid):i_uid_read(inode)); 1068c2ecf20Sopenharmony_ci ri->gid = cpu_to_je16((ivalid & ATTR_GID)? 1078c2ecf20Sopenharmony_ci from_kgid(&init_user_ns, iattr->ia_gid):i_gid_read(inode)); 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci if (ivalid & ATTR_MODE) 1108c2ecf20Sopenharmony_ci ri->mode = cpu_to_jemode(iattr->ia_mode); 1118c2ecf20Sopenharmony_ci else 1128c2ecf20Sopenharmony_ci ri->mode = cpu_to_jemode(inode->i_mode); 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size); 1168c2ecf20Sopenharmony_ci ri->atime = cpu_to_je32(I_SEC((ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime)); 1178c2ecf20Sopenharmony_ci ri->mtime = cpu_to_je32(I_SEC((ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime)); 1188c2ecf20Sopenharmony_ci ri->ctime = cpu_to_je32(I_SEC((ivalid & ATTR_CTIME)?iattr->ia_ctime:inode->i_ctime)); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci ri->offset = cpu_to_je32(0); 1218c2ecf20Sopenharmony_ci ri->csize = ri->dsize = cpu_to_je32(mdatalen); 1228c2ecf20Sopenharmony_ci ri->compr = JFFS2_COMPR_NONE; 1238c2ecf20Sopenharmony_ci if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { 1248c2ecf20Sopenharmony_ci /* It's an extension. Make it a hole node */ 1258c2ecf20Sopenharmony_ci ri->compr = JFFS2_COMPR_ZERO; 1268c2ecf20Sopenharmony_ci ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size); 1278c2ecf20Sopenharmony_ci ri->offset = cpu_to_je32(inode->i_size); 1288c2ecf20Sopenharmony_ci } else if (ivalid & ATTR_SIZE && !iattr->ia_size) { 1298c2ecf20Sopenharmony_ci /* For truncate-to-zero, treat it as deletion because 1308c2ecf20Sopenharmony_ci it'll always be obsoleting all previous nodes */ 1318c2ecf20Sopenharmony_ci alloc_type = ALLOC_DELETION; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); 1348c2ecf20Sopenharmony_ci if (mdatalen) 1358c2ecf20Sopenharmony_ci ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); 1368c2ecf20Sopenharmony_ci else 1378c2ecf20Sopenharmony_ci ri->data_crc = cpu_to_je32(0); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type); 1408c2ecf20Sopenharmony_ci if (S_ISLNK(inode->i_mode)) 1418c2ecf20Sopenharmony_ci kfree(mdata); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci if (IS_ERR(new_metadata)) { 1448c2ecf20Sopenharmony_ci jffs2_complete_reservation(c); 1458c2ecf20Sopenharmony_ci jffs2_free_raw_inode(ri); 1468c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 1478c2ecf20Sopenharmony_ci return PTR_ERR(new_metadata); 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci /* It worked. Update the inode */ 1508c2ecf20Sopenharmony_ci inode->i_atime = ITIME(je32_to_cpu(ri->atime)); 1518c2ecf20Sopenharmony_ci inode->i_ctime = ITIME(je32_to_cpu(ri->ctime)); 1528c2ecf20Sopenharmony_ci inode->i_mtime = ITIME(je32_to_cpu(ri->mtime)); 1538c2ecf20Sopenharmony_ci inode->i_mode = jemode_to_cpu(ri->mode); 1548c2ecf20Sopenharmony_ci i_uid_write(inode, je16_to_cpu(ri->uid)); 1558c2ecf20Sopenharmony_ci i_gid_write(inode, je16_to_cpu(ri->gid)); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci old_metadata = f->metadata; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) 1618c2ecf20Sopenharmony_ci jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size); 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { 1648c2ecf20Sopenharmony_ci jffs2_add_full_dnode_to_inode(c, f, new_metadata); 1658c2ecf20Sopenharmony_ci inode->i_size = iattr->ia_size; 1668c2ecf20Sopenharmony_ci inode->i_blocks = (inode->i_size + 511) >> 9; 1678c2ecf20Sopenharmony_ci f->metadata = NULL; 1688c2ecf20Sopenharmony_ci } else { 1698c2ecf20Sopenharmony_ci f->metadata = new_metadata; 1708c2ecf20Sopenharmony_ci } 1718c2ecf20Sopenharmony_ci if (old_metadata) { 1728c2ecf20Sopenharmony_ci jffs2_mark_node_obsolete(c, old_metadata->raw); 1738c2ecf20Sopenharmony_ci jffs2_free_full_dnode(old_metadata); 1748c2ecf20Sopenharmony_ci } 1758c2ecf20Sopenharmony_ci jffs2_free_raw_inode(ri); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 1788c2ecf20Sopenharmony_ci jffs2_complete_reservation(c); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* We have to do the truncate_setsize() without f->sem held, since 1818c2ecf20Sopenharmony_ci some pages may be locked and waiting for it in readpage(). 1828c2ecf20Sopenharmony_ci We are protected from a simultaneous write() extending i_size 1838c2ecf20Sopenharmony_ci back past iattr->ia_size, because do_truncate() holds the 1848c2ecf20Sopenharmony_ci generic inode semaphore. */ 1858c2ecf20Sopenharmony_ci if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) { 1868c2ecf20Sopenharmony_ci truncate_setsize(inode, iattr->ia_size); 1878c2ecf20Sopenharmony_ci inode->i_blocks = (inode->i_size + 511) >> 9; 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return 0; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciint jffs2_setattr(struct dentry *dentry, struct iattr *iattr) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci struct inode *inode = d_inode(dentry); 1968c2ecf20Sopenharmony_ci int rc; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci rc = setattr_prepare(dentry, iattr); 1998c2ecf20Sopenharmony_ci if (rc) 2008c2ecf20Sopenharmony_ci return rc; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci rc = jffs2_do_setattr(inode, iattr); 2038c2ecf20Sopenharmony_ci if (!rc && (iattr->ia_valid & ATTR_MODE)) 2048c2ecf20Sopenharmony_ci rc = posix_acl_chmod(inode, inode->i_mode); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci return rc; 2078c2ecf20Sopenharmony_ci} 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ciint jffs2_statfs(struct dentry *dentry, struct kstatfs *buf) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb); 2128c2ecf20Sopenharmony_ci unsigned long avail; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci buf->f_type = JFFS2_SUPER_MAGIC; 2158c2ecf20Sopenharmony_ci buf->f_bsize = 1 << PAGE_SHIFT; 2168c2ecf20Sopenharmony_ci buf->f_blocks = c->flash_size >> PAGE_SHIFT; 2178c2ecf20Sopenharmony_ci buf->f_files = 0; 2188c2ecf20Sopenharmony_ci buf->f_ffree = 0; 2198c2ecf20Sopenharmony_ci buf->f_namelen = JFFS2_MAX_NAME_LEN; 2208c2ecf20Sopenharmony_ci buf->f_fsid.val[0] = JFFS2_SUPER_MAGIC; 2218c2ecf20Sopenharmony_ci buf->f_fsid.val[1] = c->mtd->index; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci spin_lock(&c->erase_completion_lock); 2248c2ecf20Sopenharmony_ci avail = c->dirty_size + c->free_size; 2258c2ecf20Sopenharmony_ci if (avail > c->sector_size * c->resv_blocks_write) 2268c2ecf20Sopenharmony_ci avail -= c->sector_size * c->resv_blocks_write; 2278c2ecf20Sopenharmony_ci else 2288c2ecf20Sopenharmony_ci avail = 0; 2298c2ecf20Sopenharmony_ci spin_unlock(&c->erase_completion_lock); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci return 0; 2348c2ecf20Sopenharmony_ci} 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_civoid jffs2_evict_inode (struct inode *inode) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci /* We can forget about this inode for now - drop all 2408c2ecf20Sopenharmony_ci * the nodelists associated with it, etc. 2418c2ecf20Sopenharmony_ci */ 2428c2ecf20Sopenharmony_ci struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); 2438c2ecf20Sopenharmony_ci struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): ino #%lu mode %o\n", 2468c2ecf20Sopenharmony_ci __func__, inode->i_ino, inode->i_mode); 2478c2ecf20Sopenharmony_ci truncate_inode_pages_final(&inode->i_data); 2488c2ecf20Sopenharmony_ci clear_inode(inode); 2498c2ecf20Sopenharmony_ci jffs2_do_clear_inode(c, f); 2508c2ecf20Sopenharmony_ci} 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_cistruct inode *jffs2_iget(struct super_block *sb, unsigned long ino) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci struct jffs2_inode_info *f; 2558c2ecf20Sopenharmony_ci struct jffs2_sb_info *c; 2568c2ecf20Sopenharmony_ci struct jffs2_raw_inode latest_node; 2578c2ecf20Sopenharmony_ci union jffs2_device_node jdev; 2588c2ecf20Sopenharmony_ci struct inode *inode; 2598c2ecf20Sopenharmony_ci dev_t rdev = 0; 2608c2ecf20Sopenharmony_ci int ret; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): ino == %lu\n", __func__, ino); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci inode = iget_locked(sb, ino); 2658c2ecf20Sopenharmony_ci if (!inode) 2668c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 2678c2ecf20Sopenharmony_ci if (!(inode->i_state & I_NEW)) 2688c2ecf20Sopenharmony_ci return inode; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci f = JFFS2_INODE_INFO(inode); 2718c2ecf20Sopenharmony_ci c = JFFS2_SB_INFO(inode->i_sb); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci jffs2_init_inode_info(f); 2748c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); 2778c2ecf20Sopenharmony_ci if (ret) 2788c2ecf20Sopenharmony_ci goto error; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci inode->i_mode = jemode_to_cpu(latest_node.mode); 2818c2ecf20Sopenharmony_ci i_uid_write(inode, je16_to_cpu(latest_node.uid)); 2828c2ecf20Sopenharmony_ci i_gid_write(inode, je16_to_cpu(latest_node.gid)); 2838c2ecf20Sopenharmony_ci inode->i_size = je32_to_cpu(latest_node.isize); 2848c2ecf20Sopenharmony_ci inode->i_atime = ITIME(je32_to_cpu(latest_node.atime)); 2858c2ecf20Sopenharmony_ci inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime)); 2868c2ecf20Sopenharmony_ci inode->i_ctime = ITIME(je32_to_cpu(latest_node.ctime)); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci set_nlink(inode, f->inocache->pino_nlink); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci inode->i_blocks = (inode->i_size + 511) >> 9; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci switch (inode->i_mode & S_IFMT) { 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci case S_IFLNK: 2958c2ecf20Sopenharmony_ci inode->i_op = &jffs2_symlink_inode_operations; 2968c2ecf20Sopenharmony_ci inode->i_link = f->target; 2978c2ecf20Sopenharmony_ci break; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci case S_IFDIR: 3008c2ecf20Sopenharmony_ci { 3018c2ecf20Sopenharmony_ci struct jffs2_full_dirent *fd; 3028c2ecf20Sopenharmony_ci set_nlink(inode, 2); /* parent and '.' */ 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci for (fd=f->dents; fd; fd = fd->next) { 3058c2ecf20Sopenharmony_ci if (fd->type == DT_DIR && fd->ino) 3068c2ecf20Sopenharmony_ci inc_nlink(inode); 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci /* Root dir gets i_nlink 3 for some reason */ 3098c2ecf20Sopenharmony_ci if (inode->i_ino == 1) 3108c2ecf20Sopenharmony_ci inc_nlink(inode); 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci inode->i_op = &jffs2_dir_inode_operations; 3138c2ecf20Sopenharmony_ci inode->i_fop = &jffs2_dir_operations; 3148c2ecf20Sopenharmony_ci break; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci case S_IFREG: 3178c2ecf20Sopenharmony_ci inode->i_op = &jffs2_file_inode_operations; 3188c2ecf20Sopenharmony_ci inode->i_fop = &jffs2_file_operations; 3198c2ecf20Sopenharmony_ci inode->i_mapping->a_ops = &jffs2_file_address_operations; 3208c2ecf20Sopenharmony_ci inode->i_mapping->nrpages = 0; 3218c2ecf20Sopenharmony_ci break; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci case S_IFBLK: 3248c2ecf20Sopenharmony_ci case S_IFCHR: 3258c2ecf20Sopenharmony_ci /* Read the device numbers from the media */ 3268c2ecf20Sopenharmony_ci if (f->metadata->size != sizeof(jdev.old_id) && 3278c2ecf20Sopenharmony_ci f->metadata->size != sizeof(jdev.new_id)) { 3288c2ecf20Sopenharmony_ci pr_notice("Device node has strange size %d\n", 3298c2ecf20Sopenharmony_ci f->metadata->size); 3308c2ecf20Sopenharmony_ci goto error_io; 3318c2ecf20Sopenharmony_ci } 3328c2ecf20Sopenharmony_ci jffs2_dbg(1, "Reading device numbers from flash\n"); 3338c2ecf20Sopenharmony_ci ret = jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size); 3348c2ecf20Sopenharmony_ci if (ret < 0) { 3358c2ecf20Sopenharmony_ci /* Eep */ 3368c2ecf20Sopenharmony_ci pr_notice("Read device numbers for inode %lu failed\n", 3378c2ecf20Sopenharmony_ci (unsigned long)inode->i_ino); 3388c2ecf20Sopenharmony_ci goto error; 3398c2ecf20Sopenharmony_ci } 3408c2ecf20Sopenharmony_ci if (f->metadata->size == sizeof(jdev.old_id)) 3418c2ecf20Sopenharmony_ci rdev = old_decode_dev(je16_to_cpu(jdev.old_id)); 3428c2ecf20Sopenharmony_ci else 3438c2ecf20Sopenharmony_ci rdev = new_decode_dev(je32_to_cpu(jdev.new_id)); 3448c2ecf20Sopenharmony_ci fallthrough; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci case S_IFSOCK: 3478c2ecf20Sopenharmony_ci case S_IFIFO: 3488c2ecf20Sopenharmony_ci inode->i_op = &jffs2_file_inode_operations; 3498c2ecf20Sopenharmony_ci init_special_inode(inode, inode->i_mode, rdev); 3508c2ecf20Sopenharmony_ci break; 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci default: 3538c2ecf20Sopenharmony_ci pr_warn("%s(): Bogus i_mode %o for ino %lu\n", 3548c2ecf20Sopenharmony_ci __func__, inode->i_mode, (unsigned long)inode->i_ino); 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci jffs2_dbg(1, "jffs2_read_inode() returning\n"); 3608c2ecf20Sopenharmony_ci unlock_new_inode(inode); 3618c2ecf20Sopenharmony_ci return inode; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cierror_io: 3648c2ecf20Sopenharmony_ci ret = -EIO; 3658c2ecf20Sopenharmony_cierror: 3668c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 3678c2ecf20Sopenharmony_ci iget_failed(inode); 3688c2ecf20Sopenharmony_ci return ERR_PTR(ret); 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_civoid jffs2_dirty_inode(struct inode *inode, int flags) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci struct iattr iattr; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci if (!(inode->i_state & I_DIRTY_DATASYNC)) { 3768c2ecf20Sopenharmony_ci jffs2_dbg(2, "%s(): not calling setattr() for ino #%lu\n", 3778c2ecf20Sopenharmony_ci __func__, inode->i_ino); 3788c2ecf20Sopenharmony_ci return; 3798c2ecf20Sopenharmony_ci } 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): calling setattr() for ino #%lu\n", 3828c2ecf20Sopenharmony_ci __func__, inode->i_ino); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci iattr.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_MTIME|ATTR_CTIME; 3858c2ecf20Sopenharmony_ci iattr.ia_mode = inode->i_mode; 3868c2ecf20Sopenharmony_ci iattr.ia_uid = inode->i_uid; 3878c2ecf20Sopenharmony_ci iattr.ia_gid = inode->i_gid; 3888c2ecf20Sopenharmony_ci iattr.ia_atime = inode->i_atime; 3898c2ecf20Sopenharmony_ci iattr.ia_mtime = inode->i_mtime; 3908c2ecf20Sopenharmony_ci iattr.ia_ctime = inode->i_ctime; 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci jffs2_do_setattr(inode, &iattr); 3938c2ecf20Sopenharmony_ci} 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ciint jffs2_do_remount_fs(struct super_block *sb, struct fs_context *fc) 3968c2ecf20Sopenharmony_ci{ 3978c2ecf20Sopenharmony_ci struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci if (c->flags & JFFS2_SB_FLAG_RO && !sb_rdonly(sb)) 4008c2ecf20Sopenharmony_ci return -EROFS; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci /* We stop if it was running, then restart if it needs to. 4038c2ecf20Sopenharmony_ci This also catches the case where it was stopped and this 4048c2ecf20Sopenharmony_ci is just a remount to restart it. 4058c2ecf20Sopenharmony_ci Flush the writebuffer, if neccecary, else we loose it */ 4068c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) { 4078c2ecf20Sopenharmony_ci jffs2_stop_garbage_collect_thread(c); 4088c2ecf20Sopenharmony_ci mutex_lock(&c->alloc_sem); 4098c2ecf20Sopenharmony_ci jffs2_flush_wbuf_pad(c); 4108c2ecf20Sopenharmony_ci mutex_unlock(&c->alloc_sem); 4118c2ecf20Sopenharmony_ci } 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci if (!(fc->sb_flags & SB_RDONLY)) 4148c2ecf20Sopenharmony_ci jffs2_start_garbage_collect_thread(c); 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci fc->sb_flags |= SB_NOATIME; 4178c2ecf20Sopenharmony_ci return 0; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash, 4218c2ecf20Sopenharmony_ci fill in the raw_inode while you're at it. */ 4228c2ecf20Sopenharmony_cistruct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_raw_inode *ri) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci struct inode *inode; 4258c2ecf20Sopenharmony_ci struct super_block *sb = dir_i->i_sb; 4268c2ecf20Sopenharmony_ci struct jffs2_sb_info *c; 4278c2ecf20Sopenharmony_ci struct jffs2_inode_info *f; 4288c2ecf20Sopenharmony_ci int ret; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): dir_i %ld, mode 0x%x\n", 4318c2ecf20Sopenharmony_ci __func__, dir_i->i_ino, mode); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci c = JFFS2_SB_INFO(sb); 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_ci inode = new_inode(sb); 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci if (!inode) 4388c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci f = JFFS2_INODE_INFO(inode); 4418c2ecf20Sopenharmony_ci jffs2_init_inode_info(f); 4428c2ecf20Sopenharmony_ci mutex_lock(&f->sem); 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci memset(ri, 0, sizeof(*ri)); 4458c2ecf20Sopenharmony_ci /* Set OS-specific defaults for new inodes */ 4468c2ecf20Sopenharmony_ci ri->uid = cpu_to_je16(from_kuid(&init_user_ns, current_fsuid())); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci if (dir_i->i_mode & S_ISGID) { 4498c2ecf20Sopenharmony_ci ri->gid = cpu_to_je16(i_gid_read(dir_i)); 4508c2ecf20Sopenharmony_ci if (S_ISDIR(mode)) 4518c2ecf20Sopenharmony_ci mode |= S_ISGID; 4528c2ecf20Sopenharmony_ci } else { 4538c2ecf20Sopenharmony_ci ri->gid = cpu_to_je16(from_kgid(&init_user_ns, current_fsgid())); 4548c2ecf20Sopenharmony_ci } 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci /* POSIX ACLs have to be processed now, at least partly. 4578c2ecf20Sopenharmony_ci The umask is only applied if there's no default ACL */ 4588c2ecf20Sopenharmony_ci ret = jffs2_init_acl_pre(dir_i, inode, &mode); 4598c2ecf20Sopenharmony_ci if (ret) { 4608c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 4618c2ecf20Sopenharmony_ci make_bad_inode(inode); 4628c2ecf20Sopenharmony_ci iput(inode); 4638c2ecf20Sopenharmony_ci return ERR_PTR(ret); 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci ret = jffs2_do_new_inode (c, f, mode, ri); 4668c2ecf20Sopenharmony_ci if (ret) { 4678c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 4688c2ecf20Sopenharmony_ci make_bad_inode(inode); 4698c2ecf20Sopenharmony_ci iput(inode); 4708c2ecf20Sopenharmony_ci return ERR_PTR(ret); 4718c2ecf20Sopenharmony_ci } 4728c2ecf20Sopenharmony_ci set_nlink(inode, 1); 4738c2ecf20Sopenharmony_ci inode->i_ino = je32_to_cpu(ri->ino); 4748c2ecf20Sopenharmony_ci inode->i_mode = jemode_to_cpu(ri->mode); 4758c2ecf20Sopenharmony_ci i_gid_write(inode, je16_to_cpu(ri->gid)); 4768c2ecf20Sopenharmony_ci i_uid_write(inode, je16_to_cpu(ri->uid)); 4778c2ecf20Sopenharmony_ci inode->i_atime = inode->i_ctime = inode->i_mtime = current_time(inode); 4788c2ecf20Sopenharmony_ci ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime)); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci inode->i_blocks = 0; 4818c2ecf20Sopenharmony_ci inode->i_size = 0; 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci if (insert_inode_locked(inode) < 0) { 4848c2ecf20Sopenharmony_ci mutex_unlock(&f->sem); 4858c2ecf20Sopenharmony_ci make_bad_inode(inode); 4868c2ecf20Sopenharmony_ci iput(inode); 4878c2ecf20Sopenharmony_ci return ERR_PTR(-EINVAL); 4888c2ecf20Sopenharmony_ci } 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci return inode; 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic int calculate_inocache_hashsize(uint32_t flash_size) 4948c2ecf20Sopenharmony_ci{ 4958c2ecf20Sopenharmony_ci /* 4968c2ecf20Sopenharmony_ci * Pick a inocache hash size based on the size of the medium. 4978c2ecf20Sopenharmony_ci * Count how many megabytes we're dealing with, apply a hashsize twice 4988c2ecf20Sopenharmony_ci * that size, but rounding down to the usual big powers of 2. And keep 4998c2ecf20Sopenharmony_ci * to sensible bounds. 5008c2ecf20Sopenharmony_ci */ 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci int size_mb = flash_size / 1024 / 1024; 5038c2ecf20Sopenharmony_ci int hashsize = (size_mb * 2) & ~0x3f; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci if (hashsize < INOCACHE_HASHSIZE_MIN) 5068c2ecf20Sopenharmony_ci return INOCACHE_HASHSIZE_MIN; 5078c2ecf20Sopenharmony_ci if (hashsize > INOCACHE_HASHSIZE_MAX) 5088c2ecf20Sopenharmony_ci return INOCACHE_HASHSIZE_MAX; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci return hashsize; 5118c2ecf20Sopenharmony_ci} 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ciint jffs2_do_fill_super(struct super_block *sb, struct fs_context *fc) 5148c2ecf20Sopenharmony_ci{ 5158c2ecf20Sopenharmony_ci struct jffs2_sb_info *c; 5168c2ecf20Sopenharmony_ci struct inode *root_i; 5178c2ecf20Sopenharmony_ci int ret; 5188c2ecf20Sopenharmony_ci size_t blocks; 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci c = JFFS2_SB_INFO(sb); 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci /* Do not support the MLC nand */ 5238c2ecf20Sopenharmony_ci if (c->mtd->type == MTD_MLCNANDFLASH) 5248c2ecf20Sopenharmony_ci return -EINVAL; 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci#ifndef CONFIG_JFFS2_FS_WRITEBUFFER 5278c2ecf20Sopenharmony_ci if (c->mtd->type == MTD_NANDFLASH) { 5288c2ecf20Sopenharmony_ci errorf(fc, "Cannot operate on NAND flash unless jffs2 NAND support is compiled in"); 5298c2ecf20Sopenharmony_ci return -EINVAL; 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci if (c->mtd->type == MTD_DATAFLASH) { 5328c2ecf20Sopenharmony_ci errorf(fc, "Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in"); 5338c2ecf20Sopenharmony_ci return -EINVAL; 5348c2ecf20Sopenharmony_ci } 5358c2ecf20Sopenharmony_ci#endif 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci c->flash_size = c->mtd->size; 5388c2ecf20Sopenharmony_ci c->sector_size = c->mtd->erasesize; 5398c2ecf20Sopenharmony_ci blocks = c->flash_size / c->sector_size; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci /* 5428c2ecf20Sopenharmony_ci * Size alignment check 5438c2ecf20Sopenharmony_ci */ 5448c2ecf20Sopenharmony_ci if ((c->sector_size * blocks) != c->flash_size) { 5458c2ecf20Sopenharmony_ci c->flash_size = c->sector_size * blocks; 5468c2ecf20Sopenharmony_ci infof(fc, "Flash size not aligned to erasesize, reducing to %dKiB", 5478c2ecf20Sopenharmony_ci c->flash_size / 1024); 5488c2ecf20Sopenharmony_ci } 5498c2ecf20Sopenharmony_ci 5508c2ecf20Sopenharmony_ci if (c->flash_size < 5*c->sector_size) { 5518c2ecf20Sopenharmony_ci errorf(fc, "Too few erase blocks (%d)", 5528c2ecf20Sopenharmony_ci c->flash_size / c->sector_size); 5538c2ecf20Sopenharmony_ci return -EINVAL; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci c->cleanmarker_size = sizeof(struct jffs2_unknown_node); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci /* NAND (or other bizarre) flash... do setup accordingly */ 5598c2ecf20Sopenharmony_ci ret = jffs2_flash_setup(c); 5608c2ecf20Sopenharmony_ci if (ret) 5618c2ecf20Sopenharmony_ci return ret; 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size); 5648c2ecf20Sopenharmony_ci c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL); 5658c2ecf20Sopenharmony_ci if (!c->inocache_list) { 5668c2ecf20Sopenharmony_ci ret = -ENOMEM; 5678c2ecf20Sopenharmony_ci goto out_wbuf; 5688c2ecf20Sopenharmony_ci } 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ci jffs2_init_xattr_subsystem(c); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci if ((ret = jffs2_do_mount_fs(c))) 5738c2ecf20Sopenharmony_ci goto out_inohash; 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): Getting root inode\n", __func__); 5768c2ecf20Sopenharmony_ci root_i = jffs2_iget(sb, 1); 5778c2ecf20Sopenharmony_ci if (IS_ERR(root_i)) { 5788c2ecf20Sopenharmony_ci jffs2_dbg(1, "get root inode failed\n"); 5798c2ecf20Sopenharmony_ci ret = PTR_ERR(root_i); 5808c2ecf20Sopenharmony_ci goto out_root; 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci ret = -ENOMEM; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci jffs2_dbg(1, "%s(): d_make_root()\n", __func__); 5868c2ecf20Sopenharmony_ci sb->s_root = d_make_root(root_i); 5878c2ecf20Sopenharmony_ci if (!sb->s_root) 5888c2ecf20Sopenharmony_ci goto out_root; 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci sb->s_maxbytes = 0xFFFFFFFF; 5918c2ecf20Sopenharmony_ci sb->s_blocksize = PAGE_SIZE; 5928c2ecf20Sopenharmony_ci sb->s_blocksize_bits = PAGE_SHIFT; 5938c2ecf20Sopenharmony_ci sb->s_magic = JFFS2_SUPER_MAGIC; 5948c2ecf20Sopenharmony_ci sb->s_time_min = 0; 5958c2ecf20Sopenharmony_ci sb->s_time_max = U32_MAX; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci if (!sb_rdonly(sb)) 5988c2ecf20Sopenharmony_ci jffs2_start_garbage_collect_thread(c); 5998c2ecf20Sopenharmony_ci return 0; 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ciout_root: 6028c2ecf20Sopenharmony_ci jffs2_free_ino_caches(c); 6038c2ecf20Sopenharmony_ci jffs2_free_raw_node_refs(c); 6048c2ecf20Sopenharmony_ci kvfree(c->blocks); 6058c2ecf20Sopenharmony_ci jffs2_clear_xattr_subsystem(c); 6068c2ecf20Sopenharmony_ci jffs2_sum_exit(c); 6078c2ecf20Sopenharmony_ci out_inohash: 6088c2ecf20Sopenharmony_ci kfree(c->inocache_list); 6098c2ecf20Sopenharmony_ci out_wbuf: 6108c2ecf20Sopenharmony_ci jffs2_flash_cleanup(c); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci return ret; 6138c2ecf20Sopenharmony_ci} 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_civoid jffs2_gc_release_inode(struct jffs2_sb_info *c, 6168c2ecf20Sopenharmony_ci struct jffs2_inode_info *f) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci iput(OFNI_EDONI_2SFFJ(f)); 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_cistruct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, 6228c2ecf20Sopenharmony_ci int inum, int unlinked) 6238c2ecf20Sopenharmony_ci{ 6248c2ecf20Sopenharmony_ci struct inode *inode; 6258c2ecf20Sopenharmony_ci struct jffs2_inode_cache *ic; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci if (unlinked) { 6288c2ecf20Sopenharmony_ci /* The inode has zero nlink but its nodes weren't yet marked 6298c2ecf20Sopenharmony_ci obsolete. This has to be because we're still waiting for 6308c2ecf20Sopenharmony_ci the final (close() and) iput() to happen. 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci There's a possibility that the final iput() could have 6338c2ecf20Sopenharmony_ci happened while we were contemplating. In order to ensure 6348c2ecf20Sopenharmony_ci that we don't cause a new read_inode() (which would fail) 6358c2ecf20Sopenharmony_ci for the inode in question, we use ilookup() in this case 6368c2ecf20Sopenharmony_ci instead of iget(). 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci The nlink can't _become_ zero at this point because we're 6398c2ecf20Sopenharmony_ci holding the alloc_sem, and jffs2_do_unlink() would also 6408c2ecf20Sopenharmony_ci need that while decrementing nlink on any inode. 6418c2ecf20Sopenharmony_ci */ 6428c2ecf20Sopenharmony_ci inode = ilookup(OFNI_BS_2SFFJ(c), inum); 6438c2ecf20Sopenharmony_ci if (!inode) { 6448c2ecf20Sopenharmony_ci jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted.\n", 6458c2ecf20Sopenharmony_ci inum); 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci spin_lock(&c->inocache_lock); 6488c2ecf20Sopenharmony_ci ic = jffs2_get_ino_cache(c, inum); 6498c2ecf20Sopenharmony_ci if (!ic) { 6508c2ecf20Sopenharmony_ci jffs2_dbg(1, "Inode cache for ino #%u is gone\n", 6518c2ecf20Sopenharmony_ci inum); 6528c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 6538c2ecf20Sopenharmony_ci return NULL; 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci if (ic->state != INO_STATE_CHECKEDABSENT) { 6568c2ecf20Sopenharmony_ci /* Wait for progress. Don't just loop */ 6578c2ecf20Sopenharmony_ci jffs2_dbg(1, "Waiting for ino #%u in state %d\n", 6588c2ecf20Sopenharmony_ci ic->ino, ic->state); 6598c2ecf20Sopenharmony_ci sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); 6608c2ecf20Sopenharmony_ci } else { 6618c2ecf20Sopenharmony_ci spin_unlock(&c->inocache_lock); 6628c2ecf20Sopenharmony_ci } 6638c2ecf20Sopenharmony_ci 6648c2ecf20Sopenharmony_ci return NULL; 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci } else { 6678c2ecf20Sopenharmony_ci /* Inode has links to it still; they're not going away because 6688c2ecf20Sopenharmony_ci jffs2_do_unlink() would need the alloc_sem and we have it. 6698c2ecf20Sopenharmony_ci Just iget() it, and if read_inode() is necessary that's OK. 6708c2ecf20Sopenharmony_ci */ 6718c2ecf20Sopenharmony_ci inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum); 6728c2ecf20Sopenharmony_ci if (IS_ERR(inode)) 6738c2ecf20Sopenharmony_ci return ERR_CAST(inode); 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci if (is_bad_inode(inode)) { 6768c2ecf20Sopenharmony_ci pr_notice("Eep. read_inode() failed for ino #%u. unlinked %d\n", 6778c2ecf20Sopenharmony_ci inum, unlinked); 6788c2ecf20Sopenharmony_ci /* NB. This will happen again. We need to do something appropriate here. */ 6798c2ecf20Sopenharmony_ci iput(inode); 6808c2ecf20Sopenharmony_ci return ERR_PTR(-EIO); 6818c2ecf20Sopenharmony_ci } 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_ci return JFFS2_INODE_INFO(inode); 6848c2ecf20Sopenharmony_ci} 6858c2ecf20Sopenharmony_ci 6868c2ecf20Sopenharmony_cistatic int jffs2_flash_setup(struct jffs2_sb_info *c) { 6878c2ecf20Sopenharmony_ci int ret = 0; 6888c2ecf20Sopenharmony_ci 6898c2ecf20Sopenharmony_ci if (jffs2_cleanmarker_oob(c)) { 6908c2ecf20Sopenharmony_ci /* NAND flash... do setup accordingly */ 6918c2ecf20Sopenharmony_ci ret = jffs2_nand_flash_setup(c); 6928c2ecf20Sopenharmony_ci if (ret) 6938c2ecf20Sopenharmony_ci return ret; 6948c2ecf20Sopenharmony_ci } 6958c2ecf20Sopenharmony_ci 6968c2ecf20Sopenharmony_ci /* and Dataflash */ 6978c2ecf20Sopenharmony_ci if (jffs2_dataflash(c)) { 6988c2ecf20Sopenharmony_ci ret = jffs2_dataflash_setup(c); 6998c2ecf20Sopenharmony_ci if (ret) 7008c2ecf20Sopenharmony_ci return ret; 7018c2ecf20Sopenharmony_ci } 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci /* and Intel "Sibley" flash */ 7048c2ecf20Sopenharmony_ci if (jffs2_nor_wbuf_flash(c)) { 7058c2ecf20Sopenharmony_ci ret = jffs2_nor_wbuf_flash_setup(c); 7068c2ecf20Sopenharmony_ci if (ret) 7078c2ecf20Sopenharmony_ci return ret; 7088c2ecf20Sopenharmony_ci } 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci /* and an UBI volume */ 7118c2ecf20Sopenharmony_ci if (jffs2_ubivol(c)) { 7128c2ecf20Sopenharmony_ci ret = jffs2_ubivol_setup(c); 7138c2ecf20Sopenharmony_ci if (ret) 7148c2ecf20Sopenharmony_ci return ret; 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci 7178c2ecf20Sopenharmony_ci return ret; 7188c2ecf20Sopenharmony_ci} 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_civoid jffs2_flash_cleanup(struct jffs2_sb_info *c) { 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci if (jffs2_cleanmarker_oob(c)) { 7238c2ecf20Sopenharmony_ci jffs2_nand_flash_cleanup(c); 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci /* and DataFlash */ 7278c2ecf20Sopenharmony_ci if (jffs2_dataflash(c)) { 7288c2ecf20Sopenharmony_ci jffs2_dataflash_cleanup(c); 7298c2ecf20Sopenharmony_ci } 7308c2ecf20Sopenharmony_ci 7318c2ecf20Sopenharmony_ci /* and Intel "Sibley" flash */ 7328c2ecf20Sopenharmony_ci if (jffs2_nor_wbuf_flash(c)) { 7338c2ecf20Sopenharmony_ci jffs2_nor_wbuf_flash_cleanup(c); 7348c2ecf20Sopenharmony_ci } 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci /* and an UBI volume */ 7378c2ecf20Sopenharmony_ci if (jffs2_ubivol(c)) { 7388c2ecf20Sopenharmony_ci jffs2_ubivol_cleanup(c); 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci} 741