/* Special cases - we don't want more than one data node forthesetypesonthemediumatanytime.Sosetattr mustreadtheoriginaldataassociatedwiththenode (i.e.thedevicenumbersorthetargetname)andwrite
it out again with the appropriate data attached */ if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { /* For these, we don't actually need to read the old node */
mdatalen = jffs2_encode_dev(&dev, inode->i_rdev);
mdata = (char *)&dev;
jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t\n",
__func__, mdatalen);
} elseif (S_ISLNK(inode->i_mode)) {
mutex_lock(&f->sem);
mdatalen = f->metadata->size;
mdata = kmalloc(f->metadata->size, GFP_USER); if (!mdata) {
mutex_unlock(&f->sem); return -ENOMEM;
}
ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen); if (ret) {
mutex_unlock(&f->sem);
kfree(mdata); return ret;
}
mutex_unlock(&f->sem);
jffs2_dbg(1, "%s(): Writing %d bytes of symlink target\n",
__func__, mdatalen);
}
ri = jffs2_alloc_raw_inode(); if (!ri) { if (S_ISLNK(inode->i_mode))
kfree(mdata); return -ENOMEM;
}
ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen,
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) {
jffs2_free_raw_inode(ri); if (S_ISLNK(inode->i_mode))
kfree(mdata); return ret;
}
mutex_lock(&f->sem);
ivalid = iattr->ia_valid;
/* We have to do the truncate_setsize() without f->sem held, since somepagesmaybelockedandwaitingforitinread_folio(). Weareprotectedfromasimultaneouswrite()extendingi_size backpastiattr->ia_size,becausedo_truncate()holdsthe
generic inode semaphore. */ if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) {
truncate_setsize(inode, iattr->ia_size);
inode->i_blocks = (inode->i_size + 511) >> 9;
}
return0;
}
int jffs2_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *iattr)
{ struct inode *inode = d_inode(dentry); int rc;
rc = setattr_prepare(&nop_mnt_idmap, dentry, iattr); if (rc) return rc;
void jffs2_evict_inode (struct inode *inode)
{ /* We can forget about this inode for now - drop all *thenodelistsassociatedwithit,etc.
*/ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode);
case S_IFLNK:
inode->i_op = &jffs2_symlink_inode_operations;
inode->i_link = f->target; break;
case S_IFDIR:
{ struct jffs2_full_dirent *fd;
set_nlink(inode, 2); /* parent and '.' */
for (fd=f->dents; fd; fd = fd->next) { if (fd->type == DT_DIR && fd->ino)
inc_nlink(inode);
} /* Root dir gets i_nlink 3 for some reason */ if (inode->i_ino == 1)
inc_nlink(inode);
if (c->flags & JFFS2_SB_FLAG_RO && !sb_rdonly(sb)) return -EROFS;
/* We stop if it was running, then restart if it needs to. Thisalsocatchesthecasewhereitwasstoppedandthis isjustaremounttorestartit.
Flush the writebuffer, if necessary, else we loose it */ if (!sb_rdonly(sb)) {
jffs2_stop_garbage_collect_thread(c);
mutex_lock(&c->alloc_sem);
jffs2_flush_wbuf_pad(c);
mutex_unlock(&c->alloc_sem);
}
if (!(fc->sb_flags & SB_RDONLY))
jffs2_start_garbage_collect_thread(c);
fc->sb_flags |= SB_NOATIME; return0;
}
/* jffs2_new_inode: allocate a new inode and inocache, add it to the hash,
fill in the raw_inode while you're at it. */ struct inode *jffs2_new_inode (struct inode *dir_i, umode_t mode, struct jffs2_raw_inode *ri)
{ struct inode *inode; struct super_block *sb = dir_i->i_sb; struct jffs2_sb_info *c; struct jffs2_inode_info *f; int ret;
struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, int inum, int unlinked)
{ struct inode *inode; struct jffs2_inode_cache *ic;
if (unlinked) { /* The inode has zero nlink but its nodes weren't yet marked obsolete.Thishastobebecausewe'restillwaitingfor thefinal(close()and)iput()tohappen.
Thenlinkcan't_become_zeroatthispointbecausewe're holdingthealloc_sem,andjffs2_do_unlink()wouldalso needthatwhiledecrementingnlinkonanyinode.
*/
inode = ilookup(OFNI_BS_2SFFJ(c), inum); if (!inode) {
jffs2_dbg(1, "ilookup() failed for ino #%u; inode is probably deleted.\n",
inum);
spin_lock(&c->inocache_lock);
ic = jffs2_get_ino_cache(c, inum); if (!ic) {
jffs2_dbg(1, "Inode cache for ino #%u is gone\n",
inum);
spin_unlock(&c->inocache_lock); return NULL;
} if (ic->state != INO_STATE_CHECKEDABSENT) { /* Wait for progress. Don't just loop */
jffs2_dbg(1, "Waiting for ino #%u in state %d\n",
ic->ino, ic->state);
sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock);
} else {
spin_unlock(&c->inocache_lock);
}
return NULL;
}
} else { /* Inode has links to it still; they're not going away because jffs2_do_unlink()wouldneedthealloc_semandwehaveit. Justiget()it,andifread_inode()isnecessarythat'sOK.
*/
inode = jffs2_iget(OFNI_BS_2SFFJ(c), inum); if (IS_ERR(inode)) return ERR_CAST(inode);
} if (is_bad_inode(inode)) {
pr_notice("Eep. read_inode() failed for ino #%u. unlinked %d\n",
inum, unlinked); /* NB. This will happen again. We need to do something appropriate here. */
iput(inode); return ERR_PTR(-EIO);
}
return JFFS2_INODE_INFO(inode);
}
staticint jffs2_flash_setup(struct jffs2_sb_info *c) { int ret = 0;
if (jffs2_cleanmarker_oob(c)) { /* NAND flash... do setup accordingly */
ret = jffs2_nand_flash_setup(c); if (ret) return ret;
}
/* and Dataflash */ if (jffs2_dataflash(c)) {
ret = jffs2_dataflash_setup(c); if (ret) return ret;
}
/* and Intel "Sibley" flash */ if (jffs2_nor_wbuf_flash(c)) {
ret = jffs2_nor_wbuf_flash_setup(c); if (ret) return ret;
}
/* and an UBI volume */ if (jffs2_ubivol(c)) {
ret = jffs2_ubivol_setup(c); if (ret) return ret;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.