- if (!inode->i_nlink && !is_bad_inode(inode))
- deleteme = 1;
- truncate_inode_pages(&inode->i_data, 0);
- end_writeback(inode);
-
- if (deleteme && obj) {
- dev = obj->my_dev;
- yaffs_gross_lock(dev);
- yaffs_del_obj(obj);
- yaffs_gross_unlock(dev);
- }
- if (obj) {
- dev = obj->my_dev;
- yaffs_gross_lock(dev);
- yaffs_unstitch_obj(inode, obj);
- yaffs_gross_unlock(dev);
- }
-
-}
-
-static int yaffs_file_flush(struct file *file, fl_owner_t id)
-{
- struct yaffs_obj *obj = yaffs_dentry_to_obj(file->f_dentry);
-
- struct yaffs_dev *dev = obj->my_dev;
-
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_file_flush object %d (%s)\n"), obj->obj_id,
- obj->dirty ? "dirty" : "clean"));
-
- yaffs_gross_lock(dev);
-
- yaffs_flush_file(obj, 1, 0);
-
- yaffs_gross_unlock(dev);
-
- return 0;
-}
-
-static int yaffs_readpage_nolock(struct file *f, struct page *pg)
-{
- /* Lifted from jffs2 */
-
- struct yaffs_obj *obj;
- unsigned char *pg_buf;
- int ret;
-
- struct yaffs_dev *dev;
-
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_readpage_nolock at %08x, size %08x\n"),
- (unsigned)(pg->index << PAGE_CACHE_SHIFT),
- (unsigned)PAGE_CACHE_SIZE));
-
- obj = yaffs_dentry_to_obj(f->f_dentry);
-
- dev = obj->my_dev;
-
- BUG_ON(!PageLocked(pg));
-
- pg_buf = kmap(pg);
- /* FIXME: Can kmap fail? */
-
- yaffs_gross_lock(dev);
-
- ret = yaffs_file_rd(obj, pg_buf,
- pg->index << PAGE_CACHE_SHIFT, PAGE_CACHE_SIZE);
-
- yaffs_gross_unlock(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, (TSTR("yaffs_readpage_nolock 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)
-{
- int ret;
-
- T(YAFFS_TRACE_OS, (TSTR("yaffs_readpage\n")));
- ret = yaffs_readpage_unlock(f, pg);
- T(YAFFS_TRACE_OS, (TSTR("yaffs_readpage done\n")));
- return ret;
-}
-
-/* writepage inspired by/stolen from smbfs */
-
-static int yaffs_writepage(struct page *page, struct writeback_control *wbc)
-{
- struct yaffs_dev *dev;
- struct address_space *mapping = page->mapping;
- struct inode *inode;
- unsigned long end_index;
- char *buffer;
- struct yaffs_obj *obj;
- int n_written = 0;
- unsigned n_bytes;
- loff_t i_size;
-
- if (!mapping)
- BUG();
- inode = mapping->host;
- if (!inode)
- BUG();
- i_size = i_size_read(inode);
-
- end_index = i_size >> PAGE_CACHE_SHIFT;
-
- if (page->index < end_index)
- n_bytes = PAGE_CACHE_SIZE;
- else {
- n_bytes = i_size & (PAGE_CACHE_SIZE - 1);
-
- if (page->index > end_index || !n_bytes) {
- T(YAFFS_TRACE_OS,
- (TSTR
- ("yaffs_writepage at %08x, inode size = %08x!!!\n"),
- (unsigned)(page->index << PAGE_CACHE_SHIFT),
- (unsigned)inode->i_size));
- T(YAFFS_TRACE_OS,
- (TSTR(" -> don't care!!\n")));
-
- zero_user_segment(page, 0, PAGE_CACHE_SIZE);
- set_page_writeback(page);
- unlock_page(page);
- end_page_writeback(page);
- return 0;
- }
- }
-
- if (n_bytes != PAGE_CACHE_SIZE)
- zero_user_segment(page, n_bytes, PAGE_CACHE_SIZE);
-
- get_page(page);
-
- buffer = kmap(page);
-
- obj = yaffs_inode_to_obj(inode);
- dev = obj->my_dev;
- yaffs_gross_lock(dev);
-
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_writepage at %08x, size %08x\n"),
- (unsigned)(page->index << PAGE_CACHE_SHIFT), n_bytes));
- T(YAFFS_TRACE_OS,
- (TSTR("writepag0: obj = %05x, ino = %05x\n"),
- (int)obj->variant.file_variant.file_size, (int)inode->i_size));
-
- n_written = yaffs_wr_file(obj, buffer,
- page->index << PAGE_CACHE_SHIFT, n_bytes, 0);
-
- yaffs_touch_super(dev);
-
- T(YAFFS_TRACE_OS,
- (TSTR("writepag1: obj = %05x, ino = %05x\n"),
- (int)obj->variant.file_variant.file_size, (int)inode->i_size));
-
- yaffs_gross_unlock(dev);
-
- kunmap(page);
- set_page_writeback(page);
- unlock_page(page);
- end_page_writeback(page);
- put_page(page);
-
- return (n_written == n_bytes) ? 0 : -ENOSPC;
-}
-
-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;
-
- int ret = 0;
- int space_held = 0;
-
- /* Get a page */
- pg = grab_cache_page_write_begin(mapping, index, flags);
-
- *pagep = pg;
- if (!pg) {
- ret = -ENOMEM;
- goto out;
- }
- T(YAFFS_TRACE_OS,
- (TSTR("start yaffs_write_begin index %d(%x) uptodate %d\n"),
- (int)index, (int)index, Page_Uptodate(pg) ? 1 : 0));
-
- /* Get fs space */
- space_held = yaffs_hold_space(filp);
-
- if (!space_held) {
- ret = -ENOSPC;
- goto out;
- }
-
- /* Update page if required */
-
- if (!Page_Uptodate(pg))
- ret = yaffs_readpage_nolock(filp, pg);
-
- if (ret)
- goto out;
-
- /* Happy path return */
- T(YAFFS_TRACE_OS, (TSTR("end yaffs_write_begin - ok\n")));
-
- return 0;
-
-out:
- T(YAFFS_TRACE_OS,
- (TSTR("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;
-}
-
-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 %p pos %x n_bytes %d\n",
- addr, (unsigned)pos, copied));
-
- ret = yaffs_file_write(filp, addr, copied, &pos);
-
- if (ret != copied) {
- T(YAFFS_TRACE_OS,
- (TSTR("yaffs_write_end not same size ret %d copied %d\n"),
- ret, copied));
- SetPageError(pg);
- } else {
- /* Nothing */
- }
-
- kunmap(pg);
-
- yaffs_release_space(filp);
- unlock_page(pg);
- page_cache_release(pg);
- return ret;
-}
-
-static void yaffs_fill_inode_from_obj(struct inode *inode,
- struct yaffs_obj *obj)
-{
- if (inode && obj) {
-
- /* Check mode against the variant type and attempt to repair if broken. */
- u32 mode = obj->yst_mode;
- switch (obj->variant_type) {
- 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->obj_id;
- inode->i_mode = obj->yst_mode;
- inode->i_uid = obj->yst_uid;
- inode->i_gid = obj->yst_gid;
-
- 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;
- inode->i_size = yaffs_get_obj_length(obj);
- inode->i_blocks = (inode->i_size + 511) >> 9;
-
- inode->i_nlink = yaffs_get_obj_link_count(obj);
-
- T(YAFFS_TRACE_OS,
- (TSTR
- ("yaffs_fill_inode 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 */
- init_special_inode(inode, obj->yst_mode,
- old_decode_dev(obj->yst_rdev));
- 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;
- }