/** * wakeup function of logging process * @param __data : super block */ void rfs_log_wakeup(unsigned long __data) { struct super_block *sb = (struct super_block *) __data; struct task_struct *p = RFS_SB(sb)->sleep_proc; mod_timer(&RFS_SB(sb)->timer, DATA_EXPIRES(jiffies)); if (p->state == TASK_UNINTERRUPTIBLE) wake_up_process(p); }
/** * read dir entry in specified directory * @param inode specified directory inode * @param bh buffer head to read dir entries * @param ppos entry position to read * @param[out] dir_info to save dir entry info * @return return 0 on success, errno on failure */ static int internal_readdir(struct inode *inode, struct buffer_head **bh, loff_t *ppos, struct rfs_dir_info *dir_info) { #ifdef CONFIG_RFS_VFAT unsigned short uname[UNICODE_NAME_LENGTH]; #endif struct rfs_dir_entry *ep = NULL; loff_t index = *ppos; unsigned long ino; unsigned int type; int err; while (1) { ep = get_entry(inode, (u32) index, bh); if (IS_ERR(ep)) return PTR_ERR(ep); index++; type = entry_type(ep); dir_info->type = type; if (type == TYPE_UNUSED) return -INTERNAL_EOF; /* not error case */ if ((type == TYPE_DELETED) || (type == TYPE_EXTEND) || (type == TYPE_VOLUME)) continue; #ifdef CONFIG_RFS_VFAT uname[0] = 0x0; get_uname_from_entry(inode, index - 1, uname); if (uname[0] == 0x0 || !IS_VFAT(RFS_SB(inode->i_sb))) convert_dosname_to_cstring(dir_info->name, ep->name, ep->sysid); else convert_uname_to_cstring(dir_info->name, uname, RFS_SB(inode->i_sb)->nls_disk); #else convert_dosname_to_cstring(dir_info->name, ep->name, ep->sysid); #endif err = rfs_iunique(inode, index - 1, &ino); if (err) return err; dir_info->ino = ino; *ppos = index; return 0; } return 0; }
/** * rfs_direct_IO - directly read/write from/to user space buffers without cache * @param rw read/write type * @param inode inode * @param iobuf iobuf * @param blocknr number of blocks * @param blocksize block size * @return write/read size on success, errno on failure */ int rfs_direct_IO(int rw, struct inode *inode, struct kiobuf *iobuf, unsigned long blocknr, int blocksize) { struct super_block *sb = inode->i_sb; loff_t offset, old_size = inode->i_size; unsigned int alloc_clus = 0; int zerofilled = FALSE, ret; offset = blocknr << sb->s_blocksize_bits; if (rw == WRITE) { unsigned int clu_size, clu_bits; unsigned int req_clus, free_clus; clu_size = RFS_SB(sb)->cluster_size; clu_bits = RFS_SB(sb)->cluster_bits; /* compare the number of required clusters with free clusters */ alloc_clus = (inode->i_size + clu_size - 1) >> clu_bits; req_clus = (offset + iobuf->length + clu_size - 1) >> clu_bits; if (req_clus > alloc_clus) req_clus -= alloc_clus; /* required clusters */ else req_clus = 0; if (rfs_log_start(inode->i_sb, RFS_LOG_WRITE, inode)) return -EIO; free_clus = GET_FREE_CLUS(RFS_SB(sb)); if (req_clus > free_clus) { DEBUG(DL1, "req_clus = %d free_clus = %d \n", req_clus, free_clus); ret = -ENOSPC; goto end_log; } /* lseek case in direct IO */ if (offset > old_size) { /* * NOTE: In spite of direc IO, * we use page cache for extend_with_zeorfill */ ret = extend_with_zerofill(inode, (u32) old_size, (u32) offset); if (ret) goto end_log; inode->i_size = offset; set_mmu_private(inode, offset); zerofilled = TRUE; } }