11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds * JFFS2 -- Journalling Flash File System, Version 2.
31da177e4SLinus Torvalds *
4c00c310eSDavid Woodhouse * Copyright © 2001-2007 Red Hat, Inc.
56088c058SDavid Woodhouse * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
61da177e4SLinus Torvalds *
71da177e4SLinus Torvalds * Created by David Woodhouse <dwmw2@infradead.org>
81da177e4SLinus Torvalds *
91da177e4SLinus Torvalds * For licensing information, see the file 'LICENCE' in this directory.
101da177e4SLinus Torvalds *
111da177e4SLinus Torvalds */
121da177e4SLinus Torvalds
135a528957SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
145a528957SJoe Perches
1516f7e0feSRandy Dunlap #include <linux/capability.h>
161da177e4SLinus Torvalds #include <linux/kernel.h>
171da177e4SLinus Torvalds #include <linux/sched.h>
185b825c3aSIngo Molnar #include <linux/cred.h>
191da177e4SLinus Torvalds #include <linux/fs.h>
20ec10a24fSDavid Howells #include <linux/fs_context.h>
211da177e4SLinus Torvalds #include <linux/list.h>
221da177e4SLinus Torvalds #include <linux/mtd/mtd.h>
231da177e4SLinus Torvalds #include <linux/pagemap.h>
241da177e4SLinus Torvalds #include <linux/slab.h>
251da177e4SLinus Torvalds #include <linux/vmalloc.h>
261da177e4SLinus Torvalds #include <linux/vfs.h>
271da177e4SLinus Torvalds #include <linux/crc32.h>
281da177e4SLinus Torvalds #include "nodelist.h"
291da177e4SLinus Torvalds
301da177e4SLinus Torvalds static int jffs2_flash_setup(struct jffs2_sb_info *c);
311da177e4SLinus Torvalds
jffs2_do_setattr(struct inode * inode,struct iattr * iattr)329ed437c5SDavid Woodhouse int jffs2_do_setattr (struct inode *inode, struct iattr *iattr)
331da177e4SLinus Torvalds {
341da177e4SLinus Torvalds struct jffs2_full_dnode *old_metadata, *new_metadata;
351da177e4SLinus Torvalds struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
361da177e4SLinus Torvalds struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
371da177e4SLinus Torvalds struct jffs2_raw_inode *ri;
38aef9ab47SDavid Woodhouse union jffs2_device_node dev;
391da177e4SLinus Torvalds unsigned char *mdata = NULL;
401da177e4SLinus Torvalds int mdatalen = 0;
411da177e4SLinus Torvalds unsigned int ivalid;
429fe4854cSDavid Woodhouse uint32_t alloclen;
431da177e4SLinus Torvalds int ret;
44dd919660SDavid Woodhouse int alloc_type = ALLOC_NORMAL;
459ed437c5SDavid Woodhouse
469c261b33SJoe Perches jffs2_dbg(1, "%s(): ino #%lu\n", __func__, inode->i_ino);
471da177e4SLinus Torvalds
481da177e4SLinus Torvalds /* Special cases - we don't want more than one data node
491da177e4SLinus Torvalds for these types on the medium at any time. So setattr
501da177e4SLinus Torvalds must read the original data associated with the node
511da177e4SLinus Torvalds (i.e. the device numbers or the target name) and write
521da177e4SLinus Torvalds it out again with the appropriate data attached */
531da177e4SLinus Torvalds if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
541da177e4SLinus Torvalds /* For these, we don't actually need to read the old node */
55aef9ab47SDavid Woodhouse mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
561da177e4SLinus Torvalds mdata = (char *)&dev;
579c261b33SJoe Perches jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t\n",
589c261b33SJoe Perches __func__, mdatalen);
591da177e4SLinus Torvalds } else if (S_ISLNK(inode->i_mode)) {
60ced22070SDavid Woodhouse mutex_lock(&f->sem);
611da177e4SLinus Torvalds mdatalen = f->metadata->size;
621da177e4SLinus Torvalds mdata = kmalloc(f->metadata->size, GFP_USER);
63422138ddSDmitry Bazhenov if (!mdata) {
64ced22070SDavid Woodhouse mutex_unlock(&f->sem);
651da177e4SLinus Torvalds return -ENOMEM;
66422138ddSDmitry Bazhenov }
671da177e4SLinus Torvalds ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen);
681da177e4SLinus Torvalds if (ret) {
69ced22070SDavid Woodhouse mutex_unlock(&f->sem);
701da177e4SLinus Torvalds kfree(mdata);
711da177e4SLinus Torvalds return ret;
721da177e4SLinus Torvalds }
73ced22070SDavid Woodhouse mutex_unlock(&f->sem);
749c261b33SJoe Perches jffs2_dbg(1, "%s(): Writing %d bytes of symlink target\n",
759c261b33SJoe Perches __func__, mdatalen);
761da177e4SLinus Torvalds }
771da177e4SLinus Torvalds
781da177e4SLinus Torvalds ri = jffs2_alloc_raw_inode();
791da177e4SLinus Torvalds if (!ri) {
801da177e4SLinus Torvalds if (S_ISLNK(inode->i_mode))
811da177e4SLinus Torvalds kfree(mdata);
821da177e4SLinus Torvalds return -ENOMEM;
831da177e4SLinus Torvalds }
841da177e4SLinus Torvalds
859fe4854cSDavid Woodhouse ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen,
86e631ddbaSFerenc Havasi ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
871da177e4SLinus Torvalds if (ret) {
881da177e4SLinus Torvalds jffs2_free_raw_inode(ri);
8961effb51SAl Viro if (S_ISLNK(inode->i_mode))
901da177e4SLinus Torvalds kfree(mdata);
911da177e4SLinus Torvalds return ret;
921da177e4SLinus Torvalds }
93ced22070SDavid Woodhouse mutex_lock(&f->sem);
941da177e4SLinus Torvalds ivalid = iattr->ia_valid;
951da177e4SLinus Torvalds
961da177e4SLinus Torvalds ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
971da177e4SLinus Torvalds ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE);
981da177e4SLinus Torvalds ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen);
991da177e4SLinus Torvalds ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
1001da177e4SLinus Torvalds
1011da177e4SLinus Torvalds ri->ino = cpu_to_je32(inode->i_ino);
1021da177e4SLinus Torvalds ri->version = cpu_to_je32(++f->highest_version);
1031da177e4SLinus Torvalds
1040cfe53d3SEric W. Biederman ri->uid = cpu_to_je16((ivalid & ATTR_UID)?
1050cfe53d3SEric W. Biederman from_kuid(&init_user_ns, iattr->ia_uid):i_uid_read(inode));
1060cfe53d3SEric W. Biederman ri->gid = cpu_to_je16((ivalid & ATTR_GID)?
1070cfe53d3SEric W. Biederman from_kgid(&init_user_ns, iattr->ia_gid):i_gid_read(inode));
1081da177e4SLinus Torvalds
1091da177e4SLinus Torvalds if (ivalid & ATTR_MODE)
1101da177e4SLinus Torvalds ri->mode = cpu_to_jemode(iattr->ia_mode);
1111da177e4SLinus Torvalds else
1121da177e4SLinus Torvalds ri->mode = cpu_to_jemode(inode->i_mode);
1131da177e4SLinus Torvalds
1141da177e4SLinus Torvalds
1151da177e4SLinus Torvalds ri->isize = cpu_to_je32((ivalid & ATTR_SIZE)?iattr->ia_size:inode->i_size);
1161da177e4SLinus Torvalds ri->atime = cpu_to_je32(I_SEC((ivalid & ATTR_ATIME)?iattr->ia_atime:inode->i_atime));
1171da177e4SLinus Torvalds ri->mtime = cpu_to_je32(I_SEC((ivalid & ATTR_MTIME)?iattr->ia_mtime:inode->i_mtime));
118*d8b23c61SJeff Layton ri->ctime = cpu_to_je32(I_SEC((ivalid & ATTR_CTIME)?iattr->ia_ctime:inode_get_ctime(inode)));
1191da177e4SLinus Torvalds
1201da177e4SLinus Torvalds ri->offset = cpu_to_je32(0);
1211da177e4SLinus Torvalds ri->csize = ri->dsize = cpu_to_je32(mdatalen);
1221da177e4SLinus Torvalds ri->compr = JFFS2_COMPR_NONE;
1231da177e4SLinus Torvalds if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
1241da177e4SLinus Torvalds /* It's an extension. Make it a hole node */
1251da177e4SLinus Torvalds ri->compr = JFFS2_COMPR_ZERO;
1261da177e4SLinus Torvalds ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size);
1271da177e4SLinus Torvalds ri->offset = cpu_to_je32(inode->i_size);
128dd919660SDavid Woodhouse } else if (ivalid & ATTR_SIZE && !iattr->ia_size) {
129dd919660SDavid Woodhouse /* For truncate-to-zero, treat it as deletion because
130dd919660SDavid Woodhouse it'll always be obsoleting all previous nodes */
131dd919660SDavid Woodhouse alloc_type = ALLOC_DELETION;
1321da177e4SLinus Torvalds }
1331da177e4SLinus Torvalds ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
1341da177e4SLinus Torvalds if (mdatalen)
1351da177e4SLinus Torvalds ri->data_crc = cpu_to_je32(crc32(0, mdata, mdatalen));
1361da177e4SLinus Torvalds else
1371da177e4SLinus Torvalds ri->data_crc = cpu_to_je32(0);
1381da177e4SLinus Torvalds
139dd919660SDavid Woodhouse new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type);
1401da177e4SLinus Torvalds if (S_ISLNK(inode->i_mode))
1411da177e4SLinus Torvalds kfree(mdata);
1421da177e4SLinus Torvalds
1431da177e4SLinus Torvalds if (IS_ERR(new_metadata)) {
1441da177e4SLinus Torvalds jffs2_complete_reservation(c);
1451da177e4SLinus Torvalds jffs2_free_raw_inode(ri);
146ced22070SDavid Woodhouse mutex_unlock(&f->sem);
1471da177e4SLinus Torvalds return PTR_ERR(new_metadata);
1481da177e4SLinus Torvalds }
1491da177e4SLinus Torvalds /* It worked. Update the inode */
150c4592b9cSArnd Bergmann inode->i_atime = ITIME(je32_to_cpu(ri->atime));
151*d8b23c61SJeff Layton inode_set_ctime_to_ts(inode, ITIME(je32_to_cpu(ri->ctime)));
152c4592b9cSArnd Bergmann inode->i_mtime = ITIME(je32_to_cpu(ri->mtime));
1531da177e4SLinus Torvalds inode->i_mode = jemode_to_cpu(ri->mode);
1540cfe53d3SEric W. Biederman i_uid_write(inode, je16_to_cpu(ri->uid));
1550cfe53d3SEric W. Biederman i_gid_write(inode, je16_to_cpu(ri->gid));
1561da177e4SLinus Torvalds
1571da177e4SLinus Torvalds
1581da177e4SLinus Torvalds old_metadata = f->metadata;
1591da177e4SLinus Torvalds
1601da177e4SLinus Torvalds if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size)
161f302cd02SArtem B. Bityutskiy jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size);
1621da177e4SLinus Torvalds
1631da177e4SLinus Torvalds if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) {
1641da177e4SLinus Torvalds jffs2_add_full_dnode_to_inode(c, f, new_metadata);
1651da177e4SLinus Torvalds inode->i_size = iattr->ia_size;
166b28ba9faSDavid Woodhouse inode->i_blocks = (inode->i_size + 511) >> 9;
1671da177e4SLinus Torvalds f->metadata = NULL;
1681da177e4SLinus Torvalds } else {
1691da177e4SLinus Torvalds f->metadata = new_metadata;
1701da177e4SLinus Torvalds }
1711da177e4SLinus Torvalds if (old_metadata) {
1721da177e4SLinus Torvalds jffs2_mark_node_obsolete(c, old_metadata->raw);
1731da177e4SLinus Torvalds jffs2_free_full_dnode(old_metadata);
1741da177e4SLinus Torvalds }
1751da177e4SLinus Torvalds jffs2_free_raw_inode(ri);
1761da177e4SLinus Torvalds
177ced22070SDavid Woodhouse mutex_unlock(&f->sem);
1781da177e4SLinus Torvalds jffs2_complete_reservation(c);
1791da177e4SLinus Torvalds
1802c27c65eSChristoph Hellwig /* We have to do the truncate_setsize() without f->sem held, since
18175a47803SMatthew Wilcox (Oracle) some pages may be locked and waiting for it in read_folio().
1821da177e4SLinus Torvalds We are protected from a simultaneous write() extending i_size
1831da177e4SLinus Torvalds back past iattr->ia_size, because do_truncate() holds the
1841da177e4SLinus Torvalds generic inode semaphore. */
185b28ba9faSDavid Woodhouse if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
1862c27c65eSChristoph Hellwig truncate_setsize(inode, iattr->ia_size);
187b28ba9faSDavid Woodhouse inode->i_blocks = (inode->i_size + 511) >> 9;
188b28ba9faSDavid Woodhouse }
1891da177e4SLinus Torvalds
1901da177e4SLinus Torvalds return 0;
1911da177e4SLinus Torvalds }
1921da177e4SLinus Torvalds
jffs2_setattr(struct mnt_idmap * idmap,struct dentry * dentry,struct iattr * iattr)193c1632a0fSChristian Brauner int jffs2_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
194549c7297SChristian Brauner struct iattr *iattr)
1951da177e4SLinus Torvalds {
1962b0143b5SDavid Howells struct inode *inode = d_inode(dentry);
197aa98d7cfSKaiGai Kohei int rc;
198aa98d7cfSKaiGai Kohei
199c1632a0fSChristian Brauner rc = setattr_prepare(&nop_mnt_idmap, dentry, iattr);
2009ed437c5SDavid Woodhouse if (rc)
2019ed437c5SDavid Woodhouse return rc;
2029ed437c5SDavid Woodhouse
203f2963d45SChristoph Hellwig rc = jffs2_do_setattr(inode, iattr);
204aa98d7cfSKaiGai Kohei if (!rc && (iattr->ia_valid & ATTR_MODE))
20513e83a49SChristian Brauner rc = posix_acl_chmod(&nop_mnt_idmap, dentry, inode->i_mode);
2069ed437c5SDavid Woodhouse
207aa98d7cfSKaiGai Kohei return rc;
2081da177e4SLinus Torvalds }
2091da177e4SLinus Torvalds
jffs2_statfs(struct dentry * dentry,struct kstatfs * buf)210726c3342SDavid Howells int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf)
2111da177e4SLinus Torvalds {
212726c3342SDavid Howells struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb);
2131da177e4SLinus Torvalds unsigned long avail;
2141da177e4SLinus Torvalds
2151da177e4SLinus Torvalds buf->f_type = JFFS2_SUPER_MAGIC;
2161da177e4SLinus Torvalds buf->f_bsize = 1 << PAGE_SHIFT;
2171da177e4SLinus Torvalds buf->f_blocks = c->flash_size >> PAGE_SHIFT;
2181da177e4SLinus Torvalds buf->f_files = 0;
2191da177e4SLinus Torvalds buf->f_ffree = 0;
2201da177e4SLinus Torvalds buf->f_namelen = JFFS2_MAX_NAME_LEN;
22175caf6b5SDavid Woodhouse buf->f_fsid.val[0] = JFFS2_SUPER_MAGIC;
22275caf6b5SDavid Woodhouse buf->f_fsid.val[1] = c->mtd->index;
2231da177e4SLinus Torvalds
2241da177e4SLinus Torvalds spin_lock(&c->erase_completion_lock);
2251da177e4SLinus Torvalds avail = c->dirty_size + c->free_size;
2261da177e4SLinus Torvalds if (avail > c->sector_size * c->resv_blocks_write)
2271da177e4SLinus Torvalds avail -= c->sector_size * c->resv_blocks_write;
2281da177e4SLinus Torvalds else
2291da177e4SLinus Torvalds avail = 0;
230e0c8e42fSArtem B. Bityutskiy spin_unlock(&c->erase_completion_lock);
2311da177e4SLinus Torvalds
2321da177e4SLinus Torvalds buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT;
2331da177e4SLinus Torvalds
2341da177e4SLinus Torvalds return 0;
2351da177e4SLinus Torvalds }
2361da177e4SLinus Torvalds
2371da177e4SLinus Torvalds
jffs2_evict_inode(struct inode * inode)238b57922d9SAl Viro void jffs2_evict_inode (struct inode *inode)
2391da177e4SLinus Torvalds {
2401da177e4SLinus Torvalds /* We can forget about this inode for now - drop all
2411da177e4SLinus Torvalds * the nodelists associated with it, etc.
2421da177e4SLinus Torvalds */
2431da177e4SLinus Torvalds struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb);
2441da177e4SLinus Torvalds struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
2451da177e4SLinus Torvalds
2469c261b33SJoe Perches jffs2_dbg(1, "%s(): ino #%lu mode %o\n",
2479c261b33SJoe Perches __func__, inode->i_ino, inode->i_mode);
24891b0abe3SJohannes Weiner truncate_inode_pages_final(&inode->i_data);
249dbd5768fSJan Kara clear_inode(inode);
2501da177e4SLinus Torvalds jffs2_do_clear_inode(c, f);
2511da177e4SLinus Torvalds }
2521da177e4SLinus Torvalds
jffs2_iget(struct super_block * sb,unsigned long ino)2535451f79fSDavid Howells struct inode *jffs2_iget(struct super_block *sb, unsigned long ino)
2541da177e4SLinus Torvalds {
2551da177e4SLinus Torvalds struct jffs2_inode_info *f;
2561da177e4SLinus Torvalds struct jffs2_sb_info *c;
2571da177e4SLinus Torvalds struct jffs2_raw_inode latest_node;
258aef9ab47SDavid Woodhouse union jffs2_device_node jdev;
2595451f79fSDavid Howells struct inode *inode;
260aef9ab47SDavid Woodhouse dev_t rdev = 0;
2611da177e4SLinus Torvalds int ret;
2621da177e4SLinus Torvalds
2639c261b33SJoe Perches jffs2_dbg(1, "%s(): ino == %lu\n", __func__, ino);
2645451f79fSDavid Howells
2655451f79fSDavid Howells inode = iget_locked(sb, ino);
2665451f79fSDavid Howells if (!inode)
2675451f79fSDavid Howells return ERR_PTR(-ENOMEM);
2685451f79fSDavid Howells if (!(inode->i_state & I_NEW))
2695451f79fSDavid Howells return inode;
2701da177e4SLinus Torvalds
2711da177e4SLinus Torvalds f = JFFS2_INODE_INFO(inode);
2721da177e4SLinus Torvalds c = JFFS2_SB_INFO(inode->i_sb);
2731da177e4SLinus Torvalds
2741da177e4SLinus Torvalds jffs2_init_inode_info(f);
275ced22070SDavid Woodhouse mutex_lock(&f->sem);
2761da177e4SLinus Torvalds
2771da177e4SLinus Torvalds ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node);
2787aaea760SBrian Norris if (ret)
2797aaea760SBrian Norris goto error;
2801da177e4SLinus Torvalds
2811da177e4SLinus Torvalds inode->i_mode = jemode_to_cpu(latest_node.mode);
2820cfe53d3SEric W. Biederman i_uid_write(inode, je16_to_cpu(latest_node.uid));
2830cfe53d3SEric W. Biederman i_gid_write(inode, je16_to_cpu(latest_node.gid));
2841da177e4SLinus Torvalds inode->i_size = je32_to_cpu(latest_node.isize);
285c4592b9cSArnd Bergmann inode->i_atime = ITIME(je32_to_cpu(latest_node.atime));
286c4592b9cSArnd Bergmann inode->i_mtime = ITIME(je32_to_cpu(latest_node.mtime));
287*d8b23c61SJeff Layton inode_set_ctime_to_ts(inode, ITIME(je32_to_cpu(latest_node.ctime)));
2881da177e4SLinus Torvalds
289bfe86848SMiklos Szeredi set_nlink(inode, f->inocache->pino_nlink);
2901da177e4SLinus Torvalds
2911da177e4SLinus Torvalds inode->i_blocks = (inode->i_size + 511) >> 9;
2921da177e4SLinus Torvalds
2931da177e4SLinus Torvalds switch (inode->i_mode & S_IFMT) {
2941da177e4SLinus Torvalds
2951da177e4SLinus Torvalds case S_IFLNK:
2961da177e4SLinus Torvalds inode->i_op = &jffs2_symlink_inode_operations;
297a8db149fSAl Viro inode->i_link = f->target;
2981da177e4SLinus Torvalds break;
2991da177e4SLinus Torvalds
3001da177e4SLinus Torvalds case S_IFDIR:
3011da177e4SLinus Torvalds {
3021da177e4SLinus Torvalds struct jffs2_full_dirent *fd;
303bfe86848SMiklos Szeredi set_nlink(inode, 2); /* parent and '.' */
3041da177e4SLinus Torvalds
3051da177e4SLinus Torvalds for (fd=f->dents; fd; fd = fd->next) {
3061da177e4SLinus Torvalds if (fd->type == DT_DIR && fd->ino)
307d8c76e6fSDave Hansen inc_nlink(inode);
3081da177e4SLinus Torvalds }
3091da177e4SLinus Torvalds /* Root dir gets i_nlink 3 for some reason */
3101da177e4SLinus Torvalds if (inode->i_ino == 1)
311d8c76e6fSDave Hansen inc_nlink(inode);
3121da177e4SLinus Torvalds
3131da177e4SLinus Torvalds inode->i_op = &jffs2_dir_inode_operations;
3141da177e4SLinus Torvalds inode->i_fop = &jffs2_dir_operations;
3151da177e4SLinus Torvalds break;
3161da177e4SLinus Torvalds }
3171da177e4SLinus Torvalds case S_IFREG:
3181da177e4SLinus Torvalds inode->i_op = &jffs2_file_inode_operations;
3191da177e4SLinus Torvalds inode->i_fop = &jffs2_file_operations;
3201da177e4SLinus Torvalds inode->i_mapping->a_ops = &jffs2_file_address_operations;
3211da177e4SLinus Torvalds inode->i_mapping->nrpages = 0;
3221da177e4SLinus Torvalds break;
3231da177e4SLinus Torvalds
3241da177e4SLinus Torvalds case S_IFBLK:
3251da177e4SLinus Torvalds case S_IFCHR:
3261da177e4SLinus Torvalds /* Read the device numbers from the media */
32791f80266SAndrew Morton if (f->metadata->size != sizeof(jdev.old_id) &&
32891f80266SAndrew Morton f->metadata->size != sizeof(jdev.new_id)) {
329da320f05SJoe Perches pr_notice("Device node has strange size %d\n",
330da320f05SJoe Perches f->metadata->size);
3315451f79fSDavid Howells goto error_io;
332aef9ab47SDavid Woodhouse }
3339c261b33SJoe Perches jffs2_dbg(1, "Reading device numbers from flash\n");
3345451f79fSDavid Howells ret = jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size);
3355451f79fSDavid Howells if (ret < 0) {
3361da177e4SLinus Torvalds /* Eep */
337da320f05SJoe Perches pr_notice("Read device numbers for inode %lu failed\n",
338da320f05SJoe Perches (unsigned long)inode->i_ino);
3395451f79fSDavid Howells goto error;
3401da177e4SLinus Torvalds }
34191f80266SAndrew Morton if (f->metadata->size == sizeof(jdev.old_id))
34291f80266SAndrew Morton rdev = old_decode_dev(je16_to_cpu(jdev.old_id));
343aef9ab47SDavid Woodhouse else
34491f80266SAndrew Morton rdev = new_decode_dev(je32_to_cpu(jdev.new_id));
345df561f66SGustavo A. R. Silva fallthrough;
3461da177e4SLinus Torvalds
3471da177e4SLinus Torvalds case S_IFSOCK:
3481da177e4SLinus Torvalds case S_IFIFO:
3491da177e4SLinus Torvalds inode->i_op = &jffs2_file_inode_operations;
350aef9ab47SDavid Woodhouse init_special_inode(inode, inode->i_mode, rdev);
3511da177e4SLinus Torvalds break;
3521da177e4SLinus Torvalds
3531da177e4SLinus Torvalds default:
354da320f05SJoe Perches pr_warn("%s(): Bogus i_mode %o for ino %lu\n",
355da320f05SJoe Perches __func__, inode->i_mode, (unsigned long)inode->i_ino);
3561da177e4SLinus Torvalds }
3571da177e4SLinus Torvalds
358ced22070SDavid Woodhouse mutex_unlock(&f->sem);
3591da177e4SLinus Torvalds
3609c261b33SJoe Perches jffs2_dbg(1, "jffs2_read_inode() returning\n");
3615451f79fSDavid Howells unlock_new_inode(inode);
3625451f79fSDavid Howells return inode;
3635451f79fSDavid Howells
3645451f79fSDavid Howells error_io:
3655451f79fSDavid Howells ret = -EIO;
3665451f79fSDavid Howells error:
367ced22070SDavid Woodhouse mutex_unlock(&f->sem);
3685451f79fSDavid Howells iget_failed(inode);
3695451f79fSDavid Howells return ERR_PTR(ret);
3701da177e4SLinus Torvalds }
3711da177e4SLinus Torvalds
jffs2_dirty_inode(struct inode * inode,int flags)372aa385729SChristoph Hellwig void jffs2_dirty_inode(struct inode *inode, int flags)
3731da177e4SLinus Torvalds {
3741da177e4SLinus Torvalds struct iattr iattr;
3751da177e4SLinus Torvalds
3761da177e4SLinus Torvalds if (!(inode->i_state & I_DIRTY_DATASYNC)) {
3779c261b33SJoe Perches jffs2_dbg(2, "%s(): not calling setattr() for ino #%lu\n",
3789c261b33SJoe Perches __func__, inode->i_ino);
3791da177e4SLinus Torvalds return;
3801da177e4SLinus Torvalds }
3811da177e4SLinus Torvalds
3829c261b33SJoe Perches jffs2_dbg(1, "%s(): calling setattr() for ino #%lu\n",
3839c261b33SJoe Perches __func__, inode->i_ino);
3841da177e4SLinus Torvalds
3851da177e4SLinus Torvalds iattr.ia_valid = ATTR_MODE|ATTR_UID|ATTR_GID|ATTR_ATIME|ATTR_MTIME|ATTR_CTIME;
3861da177e4SLinus Torvalds iattr.ia_mode = inode->i_mode;
3871da177e4SLinus Torvalds iattr.ia_uid = inode->i_uid;
3881da177e4SLinus Torvalds iattr.ia_gid = inode->i_gid;
3891da177e4SLinus Torvalds iattr.ia_atime = inode->i_atime;
3901da177e4SLinus Torvalds iattr.ia_mtime = inode->i_mtime;
391*d8b23c61SJeff Layton iattr.ia_ctime = inode_get_ctime(inode);
3921da177e4SLinus Torvalds
3931da177e4SLinus Torvalds jffs2_do_setattr(inode, &iattr);
3941da177e4SLinus Torvalds }
3951da177e4SLinus Torvalds
jffs2_do_remount_fs(struct super_block * sb,struct fs_context * fc)396ec10a24fSDavid Howells int jffs2_do_remount_fs(struct super_block *sb, struct fs_context *fc)
3971da177e4SLinus Torvalds {
3981da177e4SLinus Torvalds struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
3991da177e4SLinus Torvalds
400bc98a42cSDavid Howells if (c->flags & JFFS2_SB_FLAG_RO && !sb_rdonly(sb))
4011da177e4SLinus Torvalds return -EROFS;
4021da177e4SLinus Torvalds
4031da177e4SLinus Torvalds /* We stop if it was running, then restart if it needs to.
4041da177e4SLinus Torvalds This also catches the case where it was stopped and this
4051da177e4SLinus Torvalds is just a remount to restart it.
4067198c9c0SYu Zhe Flush the writebuffer, if necessary, else we loose it */
407bc98a42cSDavid Howells if (!sb_rdonly(sb)) {
4081da177e4SLinus Torvalds jffs2_stop_garbage_collect_thread(c);
409ced22070SDavid Woodhouse mutex_lock(&c->alloc_sem);
4101da177e4SLinus Torvalds jffs2_flush_wbuf_pad(c);
411ced22070SDavid Woodhouse mutex_unlock(&c->alloc_sem);
4121da177e4SLinus Torvalds }
4131da177e4SLinus Torvalds
414ec10a24fSDavid Howells if (!(fc->sb_flags & SB_RDONLY))
4151da177e4SLinus Torvalds jffs2_start_garbage_collect_thread(c);
4161da177e4SLinus Torvalds
417ec10a24fSDavid Howells fc->sb_flags |= SB_NOATIME;
4181da177e4SLinus Torvalds return 0;
4191da177e4SLinus Torvalds }
4201da177e4SLinus Torvalds
4211da177e4SLinus Torvalds /* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
4221da177e4SLinus Torvalds fill in the raw_inode while you're at it. */
jffs2_new_inode(struct inode * dir_i,umode_t mode,struct jffs2_raw_inode * ri)423d3fb6120SAl Viro struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_raw_inode *ri)
4241da177e4SLinus Torvalds {
4251da177e4SLinus Torvalds struct inode *inode;
4261da177e4SLinus Torvalds struct super_block *sb = dir_i->i_sb;
4271da177e4SLinus Torvalds struct jffs2_sb_info *c;
4281da177e4SLinus Torvalds struct jffs2_inode_info *f;
4291da177e4SLinus Torvalds int ret;
4301da177e4SLinus Torvalds
4319c261b33SJoe Perches jffs2_dbg(1, "%s(): dir_i %ld, mode 0x%x\n",
4329c261b33SJoe Perches __func__, dir_i->i_ino, mode);
4331da177e4SLinus Torvalds
4341da177e4SLinus Torvalds c = JFFS2_SB_INFO(sb);
4351da177e4SLinus Torvalds
4361da177e4SLinus Torvalds inode = new_inode(sb);
4371da177e4SLinus Torvalds
4381da177e4SLinus Torvalds if (!inode)
4391da177e4SLinus Torvalds return ERR_PTR(-ENOMEM);
4401da177e4SLinus Torvalds
4411da177e4SLinus Torvalds f = JFFS2_INODE_INFO(inode);
4421da177e4SLinus Torvalds jffs2_init_inode_info(f);
443ced22070SDavid Woodhouse mutex_lock(&f->sem);
4441da177e4SLinus Torvalds
4451da177e4SLinus Torvalds memset(ri, 0, sizeof(*ri));
4461da177e4SLinus Torvalds /* Set OS-specific defaults for new inodes */
4470cfe53d3SEric W. Biederman ri->uid = cpu_to_je16(from_kuid(&init_user_ns, current_fsuid()));
4481da177e4SLinus Torvalds
4491da177e4SLinus Torvalds if (dir_i->i_mode & S_ISGID) {
4500cfe53d3SEric W. Biederman ri->gid = cpu_to_je16(i_gid_read(dir_i));
4511da177e4SLinus Torvalds if (S_ISDIR(mode))
4521da177e4SLinus Torvalds mode |= S_ISGID;
4531da177e4SLinus Torvalds } else {
4540cfe53d3SEric W. Biederman ri->gid = cpu_to_je16(from_kgid(&init_user_ns, current_fsgid()));
4551da177e4SLinus Torvalds }
4569ed437c5SDavid Woodhouse
4579ed437c5SDavid Woodhouse /* POSIX ACLs have to be processed now, at least partly.
4589ed437c5SDavid Woodhouse The umask is only applied if there's no default ACL */
459cfc8dc6fSKaiGai Kohei ret = jffs2_init_acl_pre(dir_i, inode, &mode);
460cfc8dc6fSKaiGai Kohei if (ret) {
46101887a3aSWang Guoli mutex_unlock(&f->sem);
4629ed437c5SDavid Woodhouse make_bad_inode(inode);
4639ed437c5SDavid Woodhouse iput(inode);
464cfc8dc6fSKaiGai Kohei return ERR_PTR(ret);
4659ed437c5SDavid Woodhouse }
4661da177e4SLinus Torvalds ret = jffs2_do_new_inode (c, f, mode, ri);
4671da177e4SLinus Torvalds if (ret) {
46801887a3aSWang Guoli mutex_unlock(&f->sem);
4691da177e4SLinus Torvalds make_bad_inode(inode);
4701da177e4SLinus Torvalds iput(inode);
4711da177e4SLinus Torvalds return ERR_PTR(ret);
4721da177e4SLinus Torvalds }
473bfe86848SMiklos Szeredi set_nlink(inode, 1);
4741da177e4SLinus Torvalds inode->i_ino = je32_to_cpu(ri->ino);
4751da177e4SLinus Torvalds inode->i_mode = jemode_to_cpu(ri->mode);
4760cfe53d3SEric W. Biederman i_gid_write(inode, je16_to_cpu(ri->gid));
4770cfe53d3SEric W. Biederman i_uid_write(inode, je16_to_cpu(ri->uid));
478*d8b23c61SJeff Layton inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode);
4791da177e4SLinus Torvalds ri->atime = ri->mtime = ri->ctime = cpu_to_je32(I_SEC(inode->i_mtime));
4801da177e4SLinus Torvalds
4811da177e4SLinus Torvalds inode->i_blocks = 0;
4821da177e4SLinus Torvalds inode->i_size = 0;
4831da177e4SLinus Torvalds
484e72e6497SDavid Woodhouse if (insert_inode_locked(inode) < 0) {
48501887a3aSWang Guoli mutex_unlock(&f->sem);
486e72e6497SDavid Woodhouse make_bad_inode(inode);
487e72e6497SDavid Woodhouse iput(inode);
488e72e6497SDavid Woodhouse return ERR_PTR(-EINVAL);
489e72e6497SDavid Woodhouse }
4901da177e4SLinus Torvalds
4911da177e4SLinus Torvalds return inode;
4921da177e4SLinus Torvalds }
4931da177e4SLinus Torvalds
calculate_inocache_hashsize(uint32_t flash_size)49465e5a0e1SDaniel Drake static int calculate_inocache_hashsize(uint32_t flash_size)
49565e5a0e1SDaniel Drake {
49665e5a0e1SDaniel Drake /*
49765e5a0e1SDaniel Drake * Pick a inocache hash size based on the size of the medium.
49865e5a0e1SDaniel Drake * Count how many megabytes we're dealing with, apply a hashsize twice
49965e5a0e1SDaniel Drake * that size, but rounding down to the usual big powers of 2. And keep
50065e5a0e1SDaniel Drake * to sensible bounds.
50165e5a0e1SDaniel Drake */
50265e5a0e1SDaniel Drake
50365e5a0e1SDaniel Drake int size_mb = flash_size / 1024 / 1024;
50465e5a0e1SDaniel Drake int hashsize = (size_mb * 2) & ~0x3f;
50565e5a0e1SDaniel Drake
50665e5a0e1SDaniel Drake if (hashsize < INOCACHE_HASHSIZE_MIN)
50765e5a0e1SDaniel Drake return INOCACHE_HASHSIZE_MIN;
50865e5a0e1SDaniel Drake if (hashsize > INOCACHE_HASHSIZE_MAX)
50965e5a0e1SDaniel Drake return INOCACHE_HASHSIZE_MAX;
51065e5a0e1SDaniel Drake
51165e5a0e1SDaniel Drake return hashsize;
51265e5a0e1SDaniel Drake }
5131da177e4SLinus Torvalds
jffs2_do_fill_super(struct super_block * sb,struct fs_context * fc)514ec10a24fSDavid Howells int jffs2_do_fill_super(struct super_block *sb, struct fs_context *fc)
5151da177e4SLinus Torvalds {
5161da177e4SLinus Torvalds struct jffs2_sb_info *c;
5171da177e4SLinus Torvalds struct inode *root_i;
5181da177e4SLinus Torvalds int ret;
5191da177e4SLinus Torvalds size_t blocks;
5201da177e4SLinus Torvalds
5211da177e4SLinus Torvalds c = JFFS2_SB_INFO(sb);
5221da177e4SLinus Torvalds
523e104f1e9SHuang Shijie /* Do not support the MLC nand */
524e104f1e9SHuang Shijie if (c->mtd->type == MTD_MLCNANDFLASH)
525e104f1e9SHuang Shijie return -EINVAL;
526e104f1e9SHuang Shijie
5272f82ce1eSAndrew Victor #ifndef CONFIG_JFFS2_FS_WRITEBUFFER
5281da177e4SLinus Torvalds if (c->mtd->type == MTD_NANDFLASH) {
529ec10a24fSDavid Howells errorf(fc, "Cannot operate on NAND flash unless jffs2 NAND support is compiled in");
5301da177e4SLinus Torvalds return -EINVAL;
5311da177e4SLinus Torvalds }
5328f15fd55SAndrew Victor if (c->mtd->type == MTD_DATAFLASH) {
533ec10a24fSDavid Howells errorf(fc, "Cannot operate on DataFlash unless jffs2 DataFlash support is compiled in");
5348f15fd55SAndrew Victor return -EINVAL;
5358f15fd55SAndrew Victor }
5368f15fd55SAndrew Victor #endif
5371da177e4SLinus Torvalds
5381da177e4SLinus Torvalds c->flash_size = c->mtd->size;
5391da177e4SLinus Torvalds c->sector_size = c->mtd->erasesize;
5401da177e4SLinus Torvalds blocks = c->flash_size / c->sector_size;
5411da177e4SLinus Torvalds
5421da177e4SLinus Torvalds /*
5431da177e4SLinus Torvalds * Size alignment check
5441da177e4SLinus Torvalds */
5451da177e4SLinus Torvalds if ((c->sector_size * blocks) != c->flash_size) {
5461da177e4SLinus Torvalds c->flash_size = c->sector_size * blocks;
547ec10a24fSDavid Howells infof(fc, "Flash size not aligned to erasesize, reducing to %dKiB",
5481da177e4SLinus Torvalds c->flash_size / 1024);
5491da177e4SLinus Torvalds }
5501da177e4SLinus Torvalds
5511da177e4SLinus Torvalds if (c->flash_size < 5*c->sector_size) {
552ec10a24fSDavid Howells errorf(fc, "Too few erase blocks (%d)",
553da320f05SJoe Perches c->flash_size / c->sector_size);
5541da177e4SLinus Torvalds return -EINVAL;
5551da177e4SLinus Torvalds }
5561da177e4SLinus Torvalds
5571da177e4SLinus Torvalds c->cleanmarker_size = sizeof(struct jffs2_unknown_node);
5581da177e4SLinus Torvalds
5591da177e4SLinus Torvalds /* NAND (or other bizarre) flash... do setup accordingly */
5601da177e4SLinus Torvalds ret = jffs2_flash_setup(c);
5611da177e4SLinus Torvalds if (ret)
5621da177e4SLinus Torvalds return ret;
5631da177e4SLinus Torvalds
56465e5a0e1SDaniel Drake c->inocache_hashsize = calculate_inocache_hashsize(c->flash_size);
56565e5a0e1SDaniel Drake c->inocache_list = kcalloc(c->inocache_hashsize, sizeof(struct jffs2_inode_cache *), GFP_KERNEL);
5661da177e4SLinus Torvalds if (!c->inocache_list) {
5671da177e4SLinus Torvalds ret = -ENOMEM;
5681da177e4SLinus Torvalds goto out_wbuf;
5691da177e4SLinus Torvalds }
5701da177e4SLinus Torvalds
571aa98d7cfSKaiGai Kohei jffs2_init_xattr_subsystem(c);
572aa98d7cfSKaiGai Kohei
5731da177e4SLinus Torvalds if ((ret = jffs2_do_mount_fs(c)))
5741da177e4SLinus Torvalds goto out_inohash;
5751da177e4SLinus Torvalds
5769c261b33SJoe Perches jffs2_dbg(1, "%s(): Getting root inode\n", __func__);
5775451f79fSDavid Howells root_i = jffs2_iget(sb, 1);
5785451f79fSDavid Howells if (IS_ERR(root_i)) {
5799c261b33SJoe Perches jffs2_dbg(1, "get root inode failed\n");
5805451f79fSDavid Howells ret = PTR_ERR(root_i);
5815451f79fSDavid Howells goto out_root;
5821da177e4SLinus Torvalds }
5831da177e4SLinus Torvalds
5845451f79fSDavid Howells ret = -ENOMEM;
5855451f79fSDavid Howells
586623ff773SLinus Torvalds jffs2_dbg(1, "%s(): d_make_root()\n", __func__);
58748fde701SAl Viro sb->s_root = d_make_root(root_i);
5881da177e4SLinus Torvalds if (!sb->s_root)
58948fde701SAl Viro goto out_root;
5901da177e4SLinus Torvalds
5911da177e4SLinus Torvalds sb->s_maxbytes = 0xFFFFFFFF;
59209cbfeafSKirill A. Shutemov sb->s_blocksize = PAGE_SIZE;
59309cbfeafSKirill A. Shutemov sb->s_blocksize_bits = PAGE_SHIFT;
5941da177e4SLinus Torvalds sb->s_magic = JFFS2_SUPER_MAGIC;
59522b13969SDeepa Dinamani sb->s_time_min = 0;
59622b13969SDeepa Dinamani sb->s_time_max = U32_MAX;
59722b13969SDeepa Dinamani
598bc98a42cSDavid Howells if (!sb_rdonly(sb))
5991da177e4SLinus Torvalds jffs2_start_garbage_collect_thread(c);
6001da177e4SLinus Torvalds return 0;
6011da177e4SLinus Torvalds
6025451f79fSDavid Howells out_root:
6031da177e4SLinus Torvalds jffs2_free_ino_caches(c);
6041da177e4SLinus Torvalds jffs2_free_raw_node_refs(c);
6051d5cfdb0STetsuo Handa kvfree(c->blocks);
606aa98d7cfSKaiGai Kohei jffs2_clear_xattr_subsystem(c);
607c14adb1cSBaokun Li jffs2_sum_exit(c);
6084c7c44eeSBaokun Li out_inohash:
6091da177e4SLinus Torvalds kfree(c->inocache_list);
6101da177e4SLinus Torvalds out_wbuf:
6111da177e4SLinus Torvalds jffs2_flash_cleanup(c);
6121da177e4SLinus Torvalds
6131da177e4SLinus Torvalds return ret;
6141da177e4SLinus Torvalds }
6151da177e4SLinus Torvalds
jffs2_gc_release_inode(struct jffs2_sb_info * c,struct jffs2_inode_info * f)6161da177e4SLinus Torvalds void jffs2_gc_release_inode(struct jffs2_sb_info *c,
6171da177e4SLinus Torvalds struct jffs2_inode_info *f)
6181da177e4SLinus Torvalds {
6191da177e4SLinus Torvalds iput(OFNI_EDONI_2SFFJ(f));
6201da177e4SLinus Torvalds }
6211da177e4SLinus Torvalds
jffs2_gc_fetch_inode(struct jffs2_sb_info * c,int inum,int unlinked)6221da177e4SLinus Torvalds struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c,
6231b690b48SDavid Woodhouse int inum, int unlinked)
6241da177e4SLinus Torvalds {
6251da177e4SLinus Torvalds struct inode *inode;
6261da177e4SLinus Torvalds struct jffs2_inode_cache *ic;
6271b690b48SDavid Woodhouse
6281b690b48SDavid Woodhouse if (unlinked) {
6291da177e4SLinus Torvalds /* The inode has zero nlink but its nodes weren't yet marked
6301da177e4SLinus Torvalds obsolete. This has to be because we're still waiting for
6311da177e4SLinus Torvalds the final (close() and) iput() to happen.
6321da177e4SLinus Torvalds
6331da177e4SLinus Torvalds There's a possibility that the final iput() could have
6341da177e4SLinus Torvalds happened while we were contemplating. In order to ensure
6351da177e4SLinus Torvalds that we don't cause a new read_inode() (which would fail)
6361da177e4SLinus Torvalds for the inode in question, we use ilookup() in this case
6371da177e4SLinus Torvalds instead of iget().
6381da177e4SLinus Torvalds
6391da177e4SLinus Torvalds The nlink can't _become_ zero at this point because we're
6401da177e4SLinus Torvalds holding the alloc_sem, and jffs2_do_unlink() would also
6411da177e4SLinus Torvalds need that while decrementing nlink on any inode.
6421da177e4SLinus Torvalds */
6431da177e4SLinus Torvalds inode = ilookup(OFNI_BS_2SFFJ(c), inum);
6441da177e4SLinus Torvalds if (!inode) {
6459c261b33SJoe Perches jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted.\n",
6469c261b33SJoe Perches inum);
6471da177e4SLinus Torvalds
6481da177e4SLinus Torvalds spin_lock(&c->inocache_lock);
6491da177e4SLinus Torvalds ic = jffs2_get_ino_cache(c, inum);
6501da177e4SLinus Torvalds if (!ic) {
6519c261b33SJoe Perches jffs2_dbg(1, "Inode cache for ino #%u is gone\n",
6529c261b33SJoe Perches inum);
6531da177e4SLinus Torvalds spin_unlock(&c->inocache_lock);
6541da177e4SLinus Torvalds return NULL;
6551da177e4SLinus Torvalds }
6561da177e4SLinus Torvalds if (ic->state != INO_STATE_CHECKEDABSENT) {
6571da177e4SLinus Torvalds /* Wait for progress. Don't just loop */
6589c261b33SJoe Perches jffs2_dbg(1, "Waiting for ino #%u in state %d\n",
6599c261b33SJoe Perches ic->ino, ic->state);
6601da177e4SLinus Torvalds sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
6611da177e4SLinus Torvalds } else {
6621da177e4SLinus Torvalds spin_unlock(&c->inocache_lock);
6631da177e4SLinus Torvalds }
6641da177e4SLinus Torvalds
6651da177e4SLinus Torvalds return NULL;
6661da177e4SLinus Torvalds }
6671da177e4SLinus Torvalds } else {
6681da177e4SLinus Torvalds /* Inode has links to it still; they're not going away because
6691da177e4SLinus Torvalds jffs2_do_unlink() would need the alloc_sem and we have it.
6701da177e4SLinus Torvalds Just iget() it, and if read_inode() is necessary that's OK.
6711da177e4SLinus Torvalds */
6725451f79fSDavid Howells inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum);
6735451f79fSDavid Howells if (IS_ERR(inode))
6745451f79fSDavid Howells return ERR_CAST(inode);
6751da177e4SLinus Torvalds }
6761da177e4SLinus Torvalds if (is_bad_inode(inode)) {
677da320f05SJoe Perches pr_notice("Eep. read_inode() failed for ino #%u. unlinked %d\n",
6781b690b48SDavid Woodhouse inum, unlinked);
6791da177e4SLinus Torvalds /* NB. This will happen again. We need to do something appropriate here. */
6801da177e4SLinus Torvalds iput(inode);
6811da177e4SLinus Torvalds return ERR_PTR(-EIO);
6821da177e4SLinus Torvalds }
6831da177e4SLinus Torvalds
6841da177e4SLinus Torvalds return JFFS2_INODE_INFO(inode);
6851da177e4SLinus Torvalds }
6861da177e4SLinus Torvalds
jffs2_flash_setup(struct jffs2_sb_info * c)6871da177e4SLinus Torvalds static int jffs2_flash_setup(struct jffs2_sb_info *c) {
6881da177e4SLinus Torvalds int ret = 0;
6891da177e4SLinus Torvalds
6901da177e4SLinus Torvalds if (jffs2_cleanmarker_oob(c)) {
6911da177e4SLinus Torvalds /* NAND flash... do setup accordingly */
6921da177e4SLinus Torvalds ret = jffs2_nand_flash_setup(c);
6931da177e4SLinus Torvalds if (ret)
6941da177e4SLinus Torvalds return ret;
6951da177e4SLinus Torvalds }
6961da177e4SLinus Torvalds
6978f15fd55SAndrew Victor /* and Dataflash */
6988f15fd55SAndrew Victor if (jffs2_dataflash(c)) {
6998f15fd55SAndrew Victor ret = jffs2_dataflash_setup(c);
7008f15fd55SAndrew Victor if (ret)
7018f15fd55SAndrew Victor return ret;
7028f15fd55SAndrew Victor }
7038f15fd55SAndrew Victor
70459da721aSNicolas Pitre /* and Intel "Sibley" flash */
70559da721aSNicolas Pitre if (jffs2_nor_wbuf_flash(c)) {
70659da721aSNicolas Pitre ret = jffs2_nor_wbuf_flash_setup(c);
70759da721aSNicolas Pitre if (ret)
70859da721aSNicolas Pitre return ret;
70959da721aSNicolas Pitre }
71059da721aSNicolas Pitre
7110029da3bSArtem Bityutskiy /* and an UBI volume */
7120029da3bSArtem Bityutskiy if (jffs2_ubivol(c)) {
7130029da3bSArtem Bityutskiy ret = jffs2_ubivol_setup(c);
7140029da3bSArtem Bityutskiy if (ret)
7150029da3bSArtem Bityutskiy return ret;
7160029da3bSArtem Bityutskiy }
7170029da3bSArtem Bityutskiy
7181da177e4SLinus Torvalds return ret;
7191da177e4SLinus Torvalds }
7201da177e4SLinus Torvalds
jffs2_flash_cleanup(struct jffs2_sb_info * c)7211da177e4SLinus Torvalds void jffs2_flash_cleanup(struct jffs2_sb_info *c) {
7221da177e4SLinus Torvalds
7231da177e4SLinus Torvalds if (jffs2_cleanmarker_oob(c)) {
7241da177e4SLinus Torvalds jffs2_nand_flash_cleanup(c);
7251da177e4SLinus Torvalds }
7261da177e4SLinus Torvalds
7278f15fd55SAndrew Victor /* and DataFlash */
7288f15fd55SAndrew Victor if (jffs2_dataflash(c)) {
7298f15fd55SAndrew Victor jffs2_dataflash_cleanup(c);
7308f15fd55SAndrew Victor }
73159da721aSNicolas Pitre
73259da721aSNicolas Pitre /* and Intel "Sibley" flash */
73359da721aSNicolas Pitre if (jffs2_nor_wbuf_flash(c)) {
73459da721aSNicolas Pitre jffs2_nor_wbuf_flash_cleanup(c);
73559da721aSNicolas Pitre }
7360029da3bSArtem Bityutskiy
7370029da3bSArtem Bityutskiy /* and an UBI volume */
7380029da3bSArtem Bityutskiy if (jffs2_ubivol(c)) {
7390029da3bSArtem Bityutskiy jffs2_ubivol_cleanup(c);
7400029da3bSArtem Bityutskiy }
7411da177e4SLinus Torvalds }
742