s32 bdev_read(struct super_block *sb, u32 secno, struct buffer_head **bh, u32 num_secs, s32 read) { BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); #ifdef CONFIG_EXFAT_KERNEL_DEBUG struct exfat_sb_info *sbi = EXFAT_SB(sb); long flags = sbi->debug_flags; if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return FFS_MEDIAERR; #endif /* CONFIG_EXFAT_KERNEL_DEBUG */ if (!p_bd->opened) return FFS_MEDIAERR; if (*bh) __brelse(*bh); if (read) *bh = __bread(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits); else *bh = __getblk(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits); if (*bh) return FFS_SUCCESS; WARN(!p_fs->dev_ejected, "[EXFAT] No bh, device seems wrong or to be ejected.\n"); return FFS_MEDIAERR; }
UINT16 nls_upper(struct super_block *sb, UINT16 a) { FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); if (EXFAT_SB(sb)->options.casesensitive) return(a); if ((p_fs->vol_utbl)[get_col_index(a)] != NULL) return (p_fs->vol_utbl)[get_col_index(a)][get_row_index(a)]; else return a; }
s32 bdev_write(struct super_block *sb, u32 secno, struct buffer_head *bh, u32 num_secs, s32 sync) { s32 count; struct buffer_head *bh2; BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); #ifdef CONFIG_EXFAT_KERNEL_DEBUG struct exfat_sb_info *sbi = EXFAT_SB(sb); long flags = sbi->debug_flags; if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return FFS_MEDIAERR; #endif /* CONFIG_EXFAT_KERNEL_DEBUG */ if (!p_bd->opened) return FFS_MEDIAERR; if (secno == bh->b_blocknr) { lock_buffer(bh); set_buffer_uptodate(bh); mark_buffer_dirty(bh); unlock_buffer(bh); if (sync && (sync_dirty_buffer(bh) != 0)) return FFS_MEDIAERR; } else { count = num_secs << p_bd->sector_size_bits; bh2 = __getblk(sb->s_bdev, secno, count); if (bh2 == NULL) goto no_bh; lock_buffer(bh2); memcpy(bh2->b_data, bh->b_data, count); set_buffer_uptodate(bh2); mark_buffer_dirty(bh2); unlock_buffer(bh2); if (sync && (sync_dirty_buffer(bh2) != 0)) { __brelse(bh2); goto no_bh; } __brelse(bh2); } return FFS_SUCCESS; no_bh: WARN(!p_fs->dev_ejected, "[EXFAT] No bh, device seems wrong or to be ejected.\n"); return FFS_MEDIAERR; }
INT32 bdev_sync(struct super_block *sb) { BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); #if EXFAT_CONFIG_KERNEL_DEBUG struct exfat_sb_info *sbi = EXFAT_SB(sb); long flags = sbi->debug_flags; if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); #endif /* EXFAT_CONFIG_KERNEL_DEBUG */ if (!p_bd->opened) return(FFS_MEDIAERR); return sync_blockdev(sb->s_bdev); }
void nls_uniname_to_cstring(struct super_block *sb, u8 *p_cstring, UNI_NAME_T *p_uniname) { int i, j, len; u8 buf[MAX_CHARSET_SIZE]; u16 *uniname = p_uniname->name; struct nls_table *nls = EXFAT_SB(sb)->nls_io; if (nls == NULL) { len = utf16s_to_utf8s(uniname, MAX_NAME_LENGTH, UTF16_HOST_ENDIAN, p_cstring, MAX_NAME_LENGTH); p_cstring[len] = 0; return; } i = 0; while (i < (MAX_NAME_LENGTH-1)) { if (*uniname == (u16) '\0') break; len = convert_uni_to_ch(nls, buf, *uniname, NULL); if (len > 1) { for (j = 0; j < len; j++) *p_cstring++ = (char) *(buf+j); } else { /* len == 1 */ *p_cstring++ = (char) *buf; } uniname++; i++; } *p_cstring = '\0'; } /* end of nls_uniname_to_cstring */
void nls_uniname_to_cstring(struct super_block *sb, UINT8 *p_cstring, UNI_NAME_T *p_uniname) { INT32 i, j, len; UINT8 buf[MAX_CHARSET_SIZE]; UINT16 *uniname = p_uniname->name; struct nls_table *nls = EXFAT_SB(sb)->nls_io; i = 0; while (i < (MAX_NAME_LENGTH-1)) { if (*uniname == (UINT16) '\0') break; len = convert_uni_to_ch(nls, buf, *uniname, NULL); if (len > 1) { for (j = 0; j < len; j++) *p_cstring++ = (INT8) *(buf+j); } else { *p_cstring++ = (INT8) *buf; } uniname++; i++; } *p_cstring = '\0'; }
/* * Caller must be guarantee it have no race with truncate(). I.e. the * range of "iclusnr" and "iclusnr + len" must not be truncated. */ int exfat_get_cluster(struct inode *inode, u32 iclusnr, u32 clus_len, struct exfat_clus_map *cmap) { struct super_block *sb = inode->i_sb; struct exfat_sb_info *sbi = EXFAT_SB(sb); struct exfat_inode_info *exi = EXFAT_I(inode); struct exfat_cache_id cid; struct exfat_ent fatent; u32 clusnr; int err = 0, found_target; DEBUG0_ON(!exi->clusnr); if (exi->data_flag == EXFAT_DATA_CONTIGUOUS) { DEBUG_ON(clus_len > (i_size_read(inode) + (sbi->clus_size - 1)) >> sbi->clus_bits, "clus_len %u, i_size %lld, clus_size %lu\n", clus_len, i_size_read(inode), sbi->clus_size); /* FIXME: should check clus_len limit from i_size? */ cmap->iclusnr = iclusnr; cmap->clusnr = exi->clusnr + iclusnr; cmap->len = clus_len; printk("%s: contig: iclusnr %u, clusnr %u, len %u\n", __func__, cmap->iclusnr, cmap->clusnr, cmap->len); return 0; }
INT32 bdev_close(struct super_block *sb) { BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); if (!p_bd->opened) return(FFS_SUCCESS); p_bd->opened = FALSE; return(FFS_SUCCESS); }
void nls_cstring_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, UINT8 *p_cstring, INT32 *p_lossy) { INT32 i, j, lossy = FALSE; UINT8 *end_of_name; UINT8 upname[MAX_NAME_LENGTH * 2]; UINT16 *uniname = p_uniname->name; struct nls_table *nls = EXFAT_SB(sb)->nls_io; /* strip all trailing spaces */ end_of_name = p_cstring + STRLEN((INT8 *) p_cstring); while (*(--end_of_name) == ' ') { if (end_of_name < p_cstring) break; } *(++end_of_name) = '\0'; if (STRCMP((INT8 *) p_cstring, ".") && STRCMP((INT8 *) p_cstring, "..")) { /* strip all trailing periods */ while (*(--end_of_name) == '.') { if (end_of_name < p_cstring) break; } *(++end_of_name) = '\0'; } if (*p_cstring == '\0') lossy = TRUE; i = j = 0; while (j < (MAX_NAME_LENGTH-1)) { if (*(p_cstring+i) == '\0') break; i += convert_ch_to_uni(nls, uniname, (UINT8 *)(p_cstring+i), &lossy); if ((*uniname < 0x0020) || WSTRCHR(bad_uni_chars, *uniname)) lossy = TRUE; SET16_A(upname + j * 2, nls_upper(sb, *uniname)); uniname++; j++; } if (*(p_cstring+i) != '\0') lossy = TRUE; *uniname = (UINT16) '\0'; p_uniname->name_len = j; p_uniname->name_hash = calc_checksum_2byte((void *) upname, j<<1, 0, CS_DEFAULT); if (p_lossy != NULL) *p_lossy = lossy; } /* end of nls_cstring_to_uniname */
void nls_dosname_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) { int i = 0, j, n = 0; u8 buf[DOS_NAME_LENGTH+2]; u8 *dosname = p_dosname->name; u16 *uniname = p_uniname->name; struct nls_table *nls = EXFAT_SB(sb)->nls_disk; if (*dosname == 0x05) { *buf = 0xE5; i++; n++; } for (; i < 8; i++, n++) { if (*(dosname+i) == ' ') break; if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && (p_dosname->name_case & 0x08)) *(buf+n) = *(dosname+i) + ('a' - 'A'); else *(buf+n) = *(dosname+i); } if (*(dosname+8) != ' ') { *(buf+n) = '.'; n++; } for (i = 8; i < DOS_NAME_LENGTH; i++, n++) { if (*(dosname+i) == ' ') break; if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && (p_dosname->name_case & 0x10)) *(buf+n) = *(dosname+i) + ('a' - 'A'); else *(buf+n) = *(dosname+i); } *(buf+n) = '\0'; i = j = 0; while (j < (MAX_NAME_LENGTH-1)) { if (*(buf+i) == '\0') break; i += convert_ch_to_uni(nls, uniname, (buf+i), NULL); uniname++; j++; } *uniname = (u16) '\0'; } /* end of nls_dosname_to_uniname */
INT32 FsReleaseCache(struct super_block *sb) { FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); sm_P(&(fs_struct[p_fs->drv].v_sem)); FAT_release_all(sb); buf_release_all(sb); sm_V(&(fs_struct[p_fs->drv].v_sem)); return 0; }
INT32 FsSyncVol(struct super_block *sb, INT32 do_sync) { INT32 err; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsSyncVol(sb, do_sync); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
INT32 FsReadStat(struct inode *inode, DIR_ENTRY_T *info) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsGetStat(inode, info); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
INT32 FsSetAttr(struct inode *inode, UINT32 attr) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsSetAttr(inode, attr); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
/* FsSyncVol : synchronize a file system volume */ int FsSyncVol(struct super_block *sb, int do_sync) { int err; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); /* acquire the lock for file system critical section */ sm_P(&p_fs->v_sem); err = ffsSyncVol(sb, do_sync); /* release the lock for file system critical section */ sm_V(&p_fs->v_sem); return err; } /* end of FsSyncVol */
INT32 FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info) { INT32 err; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); if (info == NULL) return(FFS_ERROR); sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsGetVolInfo(sb, info); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
INT32 bdev_open(struct super_block *sb) { BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); if (p_bd->opened) return(FFS_SUCCESS); p_bd->sector_size = bdev_logical_block_size(sb->s_bdev); p_bd->sector_size_bits = my_log2(p_bd->sector_size); p_bd->sector_size_mask = p_bd->sector_size - 1; p_bd->num_sectors = i_size_read(sb->s_bdev->bd_inode) >> p_bd->sector_size_bits; p_bd->opened = TRUE; return(FFS_SUCCESS); }
/* FsReleaseCache: Release FAT & buf cache */ INT32 FsReleaseCache(struct super_block *sb) { FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); /* acquire the lock for file system critical section */ sm_P(&(fs_struct[p_fs->drv].v_sem)); FAT_release_all(sb); buf_release_all(sb); /* release the lock for file system critical section */ sm_V(&(fs_struct[p_fs->drv].v_sem)); return 0; } /* FsReleaseCache */
/* FsSyncVol : synchronize a file system volume */ INT32 FsSyncVol(struct super_block *sb, INT32 do_sync) { INT32 err; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); /* acquire the lock for file system critical section */ sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsSyncVol(sb, do_sync); /* release the lock for file system critical section */ sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); } /* end of FsSyncVol */
/* FsSetAttr : set the attribute of a given file */ int FsSetAttr(struct inode *inode, u32 attr) { int err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); /* acquire the lock for file system critical section */ sm_P(&p_fs->v_sem); err = ffsSetAttr(inode, attr); /* release the lock for file system critical section */ sm_V(&p_fs->v_sem); return err; } /* end of FsSetAttr */
INT32 FsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry) { INT32 err; struct super_block *sb = old_parent_inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); if (fid == NULL) return(FFS_INVALIDFID); sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsMoveFile(old_parent_inode, fid, new_parent_inode, new_dentry); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
INT32 FsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); if (clu == NULL) return(FFS_ERROR); sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsMapCluster(inode, clu_offset, clu); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
INT32 FsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); if (dir_entry == NULL) return(FFS_ERROR); sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsReadDir(inode, dir_entry); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
INT32 FsRemoveEntry(struct inode *inode, FILE_ID_T *fid) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); if (fid == NULL) return(FFS_INVALIDFID); sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsRemoveEntry(inode, fid); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
/* FsReadStat : get the information of a given file */ INT32 FsReadStat(struct inode *inode, DIR_ENTRY_T *info) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); /* acquire the lock for file system critical section */ sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsGetStat(inode, info); /* release the lock for file system critical section */ sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); } /* end of FsReadStat */
/* FsSetAttr : set the attribute of a given file */ INT32 FsSetAttr(struct inode *inode, UINT32 attr) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); /* acquire the lock for file system critical section */ sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsSetAttr(inode, attr); /* release the lock for file system critical section */ sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); } /* end of FsSetAttr */
INT32 FsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); if ((fid == NULL) || (path == NULL) || (STRLEN(path) == 0)) return(FFS_ERROR); sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsCreateDir(inode, path, fid); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
INT32 FsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); sm_P(&(fs_struct[p_fs->drv].v_sem)); PRINTK("FsTruncateFile entered (inode %p size %llu)\n", inode, new_size); err = ffsTruncateFile(inode, old_size, new_size); PRINTK("FsTruncateFile exitted (%d)\n", err); sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); }
INT32 FsWriteStat(struct inode *inode, DIR_ENTRY_T *info) { INT32 err; struct super_block *sb = inode->i_sb; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); sm_P(&(fs_struct[p_fs->drv].v_sem)); PRINTK("FsWriteStat entered (inode %p info %p\n", inode, info); err = ffsSetStat(inode, info); sm_V(&(fs_struct[p_fs->drv].v_sem)); PRINTK("FsWriteStat exited (%d)\n", err); return(err); }
/* FsGetVolInfo : get the information of a file system volume */ INT32 FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info) { INT32 err; FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); /* check the validity of pointer parameters */ if (info == NULL) return(FFS_ERROR); /* acquire the lock for file system critical section */ sm_P(&(fs_struct[p_fs->drv].v_sem)); err = ffsGetVolInfo(sb, info); /* release the lock for file system critical section */ sm_V(&(fs_struct[p_fs->drv].v_sem)); return(err); } /* end of FsGetVolInfo */