📄 yaffs_fs.c
字号:
#endif/* clear is called to tell the fs to release any per-inode data it holds */static void yaffs_clear_inode(struct inode *inode){ yaffs_Object *obj; yaffs_Device *dev; obj = yaffs_InodeToObject(inode); T(YAFFS_TRACE_OS, ("yaffs_clear_inode: ino %d, count %d %s\n", (int)inode->i_ino, atomic_read(&inode->i_count), obj ? "object exists" : "null object")); if (obj) { dev = obj->myDev; yaffs_GrossLock(dev); /* Clear the association between the inode and * the yaffs_Object. */ obj->myInode = NULL; yaffs_InodeToObjectLV(inode) = NULL; /* If the object freeing was deferred, then the real * free happens now. * This should fix the inode inconsistency problem. */ yaffs_HandleDeferedFree(obj); yaffs_GrossUnlock(dev); }}/* delete is called when the link count is zero and the inode * is put (ie. nobody wants to know about it anymore, time to * delete the file). * NB Must call clear_inode() */static void yaffs_delete_inode(struct inode *inode){ yaffs_Object *obj = yaffs_InodeToObject(inode); yaffs_Device *dev; T(YAFFS_TRACE_OS, ("yaffs_delete_inode: ino %d, count %d %s\n", (int)inode->i_ino, atomic_read(&inode->i_count), obj ? "object exists" : "null object")); if (obj) { dev = obj->myDev; yaffs_GrossLock(dev); yaffs_DeleteObject(obj); yaffs_GrossUnlock(dev); }#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 13)) truncate_inode_pages(&inode->i_data, 0);#endif clear_inode(inode);}#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))static int yaffs_file_flush(struct file *file, fl_owner_t id)#elsestatic int yaffs_file_flush(struct file *file)#endif{ yaffs_Object *obj = yaffs_DentryToObject(file->f_dentry); yaffs_Device *dev = obj->myDev; T(YAFFS_TRACE_OS, ("yaffs_file_flush object %d (%s)\n", obj->objectId, obj->dirty ? "dirty" : "clean")); yaffs_GrossLock(dev); yaffs_FlushFile(obj, 1); yaffs_GrossUnlock(dev); return 0;}static int yaffs_readpage_nolock(struct file *f, struct page *pg){ /* Lifted from jffs2 */ yaffs_Object *obj; unsigned char *pg_buf; int ret; yaffs_Device *dev; T(YAFFS_TRACE_OS, ("yaffs_readpage at %08x, size %08x\n", (unsigned)(pg->index << PAGE_CACHE_SHIFT), (unsigned)PAGE_CACHE_SIZE)); obj = yaffs_DentryToObject(f->f_dentry); dev = obj->myDev;#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) BUG_ON(!PageLocked(pg));#else if (!PageLocked(pg)) PAGE_BUG(pg);#endif pg_buf = kmap(pg); /* FIXME: Can kmap fail? */ yaffs_GrossLock(dev); ret = yaffs_ReadDataFromFile(obj, pg_buf, pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE); yaffs_GrossUnlock(dev); if (ret >= 0) ret = 0; if (ret) { ClearPageUptodate(pg); SetPageError(pg); } else { SetPageUptodate(pg); ClearPageError(pg); } flush_dcache_page(pg); kunmap(pg); T(YAFFS_TRACE_OS, ("yaffs_readpage done\n")); return ret;}static int yaffs_readpage_unlock(struct file *f, struct page *pg){ int ret = yaffs_readpage_nolock(f, pg); UnlockPage(pg); return ret;}static int yaffs_readpage(struct file *f, struct page *pg){ return yaffs_readpage_unlock(f, pg);}/* writepage inspired by/stolen from smbfs */#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0))static int yaffs_writepage(struct page *page, struct writeback_control *wbc)#elsestatic int yaffs_writepage(struct page *page)#endif{ struct address_space *mapping = page->mapping; loff_t offset = (loff_t) page->index << PAGE_CACHE_SHIFT; struct inode *inode; unsigned long end_index; char *buffer; yaffs_Object *obj; int nWritten = 0; unsigned nBytes; if (!mapping) BUG(); inode = mapping->host; if (!inode) BUG(); if (offset > inode->i_size) { T(YAFFS_TRACE_OS, ("yaffs_writepage at %08x, inode size = %08x!!!\n", (unsigned)(page->index << PAGE_CACHE_SHIFT), (unsigned)inode->i_size)); T(YAFFS_TRACE_OS, (" -> don't care!!\n")); unlock_page(page); return 0; } end_index = inode->i_size >> PAGE_CACHE_SHIFT; /* easy case */ if (page->index < end_index) nBytes = PAGE_CACHE_SIZE; else nBytes = inode->i_size & (PAGE_CACHE_SIZE - 1); get_page(page); buffer = kmap(page); obj = yaffs_InodeToObject(inode); yaffs_GrossLock(obj->myDev); T(YAFFS_TRACE_OS, ("yaffs_writepage at %08x, size %08x\n", (unsigned)(page->index << PAGE_CACHE_SHIFT), nBytes)); T(YAFFS_TRACE_OS, ("writepag0: obj = %05x, ino = %05x\n", (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); nWritten = yaffs_WriteDataToFile(obj, buffer, page->index << PAGE_CACHE_SHIFT, nBytes, 0); T(YAFFS_TRACE_OS, ("writepag1: obj = %05x, ino = %05x\n", (int)obj->variant.fileVariant.fileSize, (int)inode->i_size)); yaffs_GrossUnlock(obj->myDev); kunmap(page); SetPageUptodate(page); UnlockPage(page); put_page(page); return (nWritten == nBytes) ? 0 : -ENOSPC;}#if (YAFFS_USE_WRITE_BEGIN_END > 0)static int yaffs_write_begin(struct file *filp, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata){ struct page *pg = NULL; pgoff_t index = pos >> PAGE_CACHE_SHIFT; uint32_t offset = pos & (PAGE_CACHE_SIZE - 1); uint32_t to = offset + len; int ret = 0; int space_held = 0; T(YAFFS_TRACE_OS, ("start yaffs_write_begin\n")); /* Get a page */#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 28) pg = grab_cache_page_write_begin(mapping, index, flags);#else pg = __grab_cache_page(mapping, index);#endif *pagep = pg; if (!pg) { ret = -ENOMEM; goto out; } /* Get fs space */ space_held = yaffs_hold_space(filp); if (!space_held) { ret = -ENOSPC; goto out; } /* Update page if required */ if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) ret = yaffs_readpage_nolock(filp, pg); if (ret) goto out; /* Happy path return */ T(YAFFS_TRACE_OS, ("end yaffs_write_begin - ok\n")); return 0;out: T(YAFFS_TRACE_OS, ("end yaffs_write_begin fail returning %d\n", ret)); if (space_held) yaffs_release_space(filp); if (pg) { unlock_page(pg); page_cache_release(pg); } return ret;}#elsestatic int yaffs_prepare_write(struct file *f, struct page *pg, unsigned offset, unsigned to){ T(YAFFS_TRACE_OS, ("yaffs_prepair_write\n")); if (!Page_Uptodate(pg) && (offset || to < PAGE_CACHE_SIZE)) return yaffs_readpage_nolock(f, pg); return 0;}#endif#if (YAFFS_USE_WRITE_BEGIN_END > 0)static int yaffs_write_end(struct file *filp, struct address_space *mapping, loff_t pos, unsigned len, unsigned copied, struct page *pg, void *fsdadata){ int ret = 0; void *addr, *kva; uint32_t offset_into_page = pos & (PAGE_CACHE_SIZE - 1); kva = kmap(pg); addr = kva + offset_into_page; T(YAFFS_TRACE_OS, ("yaffs_write_end addr %x pos %x nBytes %d\n", (unsigned) addr, (int)pos, copied)); ret = yaffs_file_write(filp, addr, copied, &pos); if (ret != copied) { T(YAFFS_TRACE_OS, ("yaffs_write_end not same size ret %d copied %d\n", ret, copied)); SetPageError(pg); ClearPageUptodate(pg); } else { SetPageUptodate(pg); } kunmap(pg); yaffs_release_space(filp); unlock_page(pg); page_cache_release(pg); return ret;}#elsestatic int yaffs_commit_write(struct file *f, struct page *pg, unsigned offset, unsigned to){ void *addr, *kva; loff_t pos = (((loff_t) pg->index) << PAGE_CACHE_SHIFT) + offset; int nBytes = to - offset; int nWritten; unsigned spos = pos; unsigned saddr; kva = kmap(pg); addr = kva + offset; saddr = (unsigned) addr; T(YAFFS_TRACE_OS, ("yaffs_commit_write addr %x pos %x nBytes %d\n", saddr, spos, nBytes)); nWritten = yaffs_file_write(f, addr, nBytes, &pos); if (nWritten != nBytes) { T(YAFFS_TRACE_OS, ("yaffs_commit_write not same size nWritten %d nBytes %d\n", nWritten, nBytes)); SetPageError(pg); ClearPageUptodate(pg); } else { SetPageUptodate(pg); } kunmap(pg); T(YAFFS_TRACE_OS, ("yaffs_commit_write returning %d\n", nWritten == nBytes ? 0 : nWritten)); return nWritten == nBytes ? 0 : nWritten;}#endifstatic void yaffs_FillInodeFromObject(struct inode *inode, yaffs_Object *obj){ if (inode && obj) { /* Check mode against the variant type and attempt to repair if broken. */ __u32 mode = obj->yst_mode; switch (obj->variantType) { case YAFFS_OBJECT_TYPE_FILE: if (!S_ISREG(mode)) { obj->yst_mode &= ~S_IFMT; obj->yst_mode |= S_IFREG; } break; case YAFFS_OBJECT_TYPE_SYMLINK: if (!S_ISLNK(mode)) { obj->yst_mode &= ~S_IFMT; obj->yst_mode |= S_IFLNK; } break; case YAFFS_OBJECT_TYPE_DIRECTORY: if (!S_ISDIR(mode)) { obj->yst_mode &= ~S_IFMT; obj->yst_mode |= S_IFDIR; } break; case YAFFS_OBJECT_TYPE_UNKNOWN: case YAFFS_OBJECT_TYPE_HARDLINK: case YAFFS_OBJECT_TYPE_SPECIAL: default: /* TODO? */ break; } inode->i_flags |= S_NOATIME; inode->i_ino = obj->objectId; inode->i_mode = obj->yst_mode; inode->i_uid = obj->yst_uid; inode->i_gid = obj->yst_gid;#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)) inode->i_blksize = inode->i_sb->s_blocksize;#endif#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) inode->i_rdev = old_decode_dev(obj->yst_rdev); inode->i_atime.tv_sec = (time_t) (obj->yst_atime); inode->i_atime.tv_nsec = 0; inode->i_mtime.tv_sec = (time_t) obj->yst_mtime; inode->i_mtime.tv_nsec = 0; inode->i_ctime.tv_sec = (time_t) obj->yst_ctime; inode->i_ctime.tv_nsec = 0;#else inode->i_rdev = obj->yst_rdev; inode->i_atime = obj->yst_atime; inode->i_mtime = obj->yst_mtime; inode->i_ctime = obj->yst_ctime;#endif inode->i_size = yaffs_GetObjectFileLength(obj); inode->i_blocks = (inode->i_size + 511) >> 9; inode->i_nlink = yaffs_GetObjectLinkCount(obj); T(YAFFS_TRACE_OS, ("yaffs_FillInode mode %x uid %d gid %d size %d count %d\n", inode->i_mode, inode->i_uid, inode->i_gid, (int)inode->i_size, atomic_read(&inode->i_count))); switch (obj->yst_mode & S_IFMT) { default: /* fifo, device or socket */#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 0)) init_special_inode(inode, obj->yst_mode, old_decode_dev(obj->yst_rdev));#else init_special_inode(inode, obj->yst_mode, (dev_t) (obj->yst_rdev));#endif break; case S_IFREG: /* file */ inode->i_op = &yaffs_file_inode_operations; inode->i_fop = &yaffs_file_operations; inode->i_mapping->a_ops = &yaffs_file_address_operations; break; case S_IFDIR: /* directory */ inode->i_op = &yaffs_dir_inode_operations; inode->i_fop = &yaffs_dir_operations; break; case S_IFLNK: /* symlink */ inode->i_op = &yaffs_symlink_inode_operations; break; } yaffs_InodeToObjectLV(inode) = obj; obj->myInode = inode; } else { T(YAFFS_TRACE_OS, ("yaffs_FileInode invalid parameters\n")); }}struct inode *yaffs_get_inode(struct super_block *sb, int mode, int dev, yaffs_Object *obj){ struct inode *inode; if (!sb) { T(YAFFS_TRACE_OS, ("yaffs_get_inode for NULL super_block!!\n")); return NULL; } if (!obj) { T(YAFFS_TRACE_OS, ("yaffs_get_inode for NULL object!!\n")); return NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -