1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * linux/fs/ufs/util.h
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds * Copyright (C) 1998
61da177e4SLinus Torvalds * Daniel Pirkl <daniel.pirkl@email.cz>
71da177e4SLinus Torvalds * Charles University, Faculty of Mathematics and Physics
81da177e4SLinus Torvalds */
91da177e4SLinus Torvalds
101da177e4SLinus Torvalds #include <linux/buffer_head.h>
111da177e4SLinus Torvalds #include <linux/fs.h>
121da177e4SLinus Torvalds #include "swab.h"
131da177e4SLinus Torvalds
141da177e4SLinus Torvalds /*
159695ef16SEvgeniy Dushistov * functions used for retyping
161da177e4SLinus Torvalds */
UCPI_UBH(struct ufs_cg_private_info * cpi)179695ef16SEvgeniy Dushistov static inline struct ufs_buffer_head *UCPI_UBH(struct ufs_cg_private_info *cpi)
189695ef16SEvgeniy Dushistov {
199695ef16SEvgeniy Dushistov return &cpi->c_ubh;
209695ef16SEvgeniy Dushistov }
USPI_UBH(struct ufs_sb_private_info * spi)219695ef16SEvgeniy Dushistov static inline struct ufs_buffer_head *USPI_UBH(struct ufs_sb_private_info *spi)
229695ef16SEvgeniy Dushistov {
239695ef16SEvgeniy Dushistov return &spi->s_ubh;
249695ef16SEvgeniy Dushistov }
251da177e4SLinus Torvalds
261da177e4SLinus Torvalds
271da177e4SLinus Torvalds
281da177e4SLinus Torvalds /*
291da177e4SLinus Torvalds * macros used for accessing structures
301da177e4SLinus Torvalds */
311da177e4SLinus Torvalds static inline s32
ufs_get_fs_state(struct super_block * sb,struct ufs_super_block_first * usb1,struct ufs_super_block_third * usb3)321da177e4SLinus Torvalds ufs_get_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1,
331da177e4SLinus Torvalds struct ufs_super_block_third *usb3)
341da177e4SLinus Torvalds {
351da177e4SLinus Torvalds switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
36252e211eSMark Fortescue case UFS_ST_SUNOS:
37252e211eSMark Fortescue if (fs32_to_cpu(sb, usb3->fs_postblformat) == UFS_42POSTBLFMT)
38252e211eSMark Fortescue return fs32_to_cpu(sb, usb1->fs_u0.fs_sun.fs_state);
39*df561f66SGustavo A. R. Silva fallthrough; /* to UFS_ST_SUN */
401da177e4SLinus Torvalds case UFS_ST_SUN:
41647b7e87SEvgeniy Dushistov return fs32_to_cpu(sb, usb3->fs_un2.fs_sun.fs_state);
421da177e4SLinus Torvalds case UFS_ST_SUNx86:
431da177e4SLinus Torvalds return fs32_to_cpu(sb, usb1->fs_u1.fs_sunx86.fs_state);
441da177e4SLinus Torvalds case UFS_ST_44BSD:
451da177e4SLinus Torvalds default:
46647b7e87SEvgeniy Dushistov return fs32_to_cpu(sb, usb3->fs_un2.fs_44.fs_state);
471da177e4SLinus Torvalds }
481da177e4SLinus Torvalds }
491da177e4SLinus Torvalds
501da177e4SLinus Torvalds static inline void
ufs_set_fs_state(struct super_block * sb,struct ufs_super_block_first * usb1,struct ufs_super_block_third * usb3,s32 value)511da177e4SLinus Torvalds ufs_set_fs_state(struct super_block *sb, struct ufs_super_block_first *usb1,
521da177e4SLinus Torvalds struct ufs_super_block_third *usb3, s32 value)
531da177e4SLinus Torvalds {
541da177e4SLinus Torvalds switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
55252e211eSMark Fortescue case UFS_ST_SUNOS:
56f81e8a43SRoel Kluin if (fs32_to_cpu(sb, usb3->fs_postblformat) == UFS_42POSTBLFMT) {
57252e211eSMark Fortescue usb1->fs_u0.fs_sun.fs_state = cpu_to_fs32(sb, value);
58252e211eSMark Fortescue break;
59252e211eSMark Fortescue }
60*df561f66SGustavo A. R. Silva fallthrough; /* to UFS_ST_SUN */
611da177e4SLinus Torvalds case UFS_ST_SUN:
62647b7e87SEvgeniy Dushistov usb3->fs_un2.fs_sun.fs_state = cpu_to_fs32(sb, value);
631da177e4SLinus Torvalds break;
641da177e4SLinus Torvalds case UFS_ST_SUNx86:
651da177e4SLinus Torvalds usb1->fs_u1.fs_sunx86.fs_state = cpu_to_fs32(sb, value);
661da177e4SLinus Torvalds break;
671da177e4SLinus Torvalds case UFS_ST_44BSD:
68647b7e87SEvgeniy Dushistov usb3->fs_un2.fs_44.fs_state = cpu_to_fs32(sb, value);
691da177e4SLinus Torvalds break;
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds }
721da177e4SLinus Torvalds
731da177e4SLinus Torvalds static inline u32
ufs_get_fs_npsect(struct super_block * sb,struct ufs_super_block_first * usb1,struct ufs_super_block_third * usb3)741da177e4SLinus Torvalds ufs_get_fs_npsect(struct super_block *sb, struct ufs_super_block_first *usb1,
751da177e4SLinus Torvalds struct ufs_super_block_third *usb3)
761da177e4SLinus Torvalds {
771da177e4SLinus Torvalds if ((UFS_SB(sb)->s_flags & UFS_ST_MASK) == UFS_ST_SUNx86)
78647b7e87SEvgeniy Dushistov return fs32_to_cpu(sb, usb3->fs_un2.fs_sunx86.fs_npsect);
791da177e4SLinus Torvalds else
801da177e4SLinus Torvalds return fs32_to_cpu(sb, usb1->fs_u1.fs_sun.fs_npsect);
811da177e4SLinus Torvalds }
821da177e4SLinus Torvalds
831da177e4SLinus Torvalds static inline u64
ufs_get_fs_qbmask(struct super_block * sb,struct ufs_super_block_third * usb3)841da177e4SLinus Torvalds ufs_get_fs_qbmask(struct super_block *sb, struct ufs_super_block_third *usb3)
851da177e4SLinus Torvalds {
861da177e4SLinus Torvalds __fs64 tmp;
871da177e4SLinus Torvalds
881da177e4SLinus Torvalds switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
89252e211eSMark Fortescue case UFS_ST_SUNOS:
901da177e4SLinus Torvalds case UFS_ST_SUN:
91647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sun.fs_qbmask[0];
92647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sun.fs_qbmask[1];
931da177e4SLinus Torvalds break;
941da177e4SLinus Torvalds case UFS_ST_SUNx86:
95647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sunx86.fs_qbmask[0];
96647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sunx86.fs_qbmask[1];
971da177e4SLinus Torvalds break;
981da177e4SLinus Torvalds case UFS_ST_44BSD:
99647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_44.fs_qbmask[0];
100647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_44.fs_qbmask[1];
1011da177e4SLinus Torvalds break;
1021da177e4SLinus Torvalds }
1031da177e4SLinus Torvalds
1041da177e4SLinus Torvalds return fs64_to_cpu(sb, tmp);
1051da177e4SLinus Torvalds }
1061da177e4SLinus Torvalds
1071da177e4SLinus Torvalds static inline u64
ufs_get_fs_qfmask(struct super_block * sb,struct ufs_super_block_third * usb3)1081da177e4SLinus Torvalds ufs_get_fs_qfmask(struct super_block *sb, struct ufs_super_block_third *usb3)
1091da177e4SLinus Torvalds {
1101da177e4SLinus Torvalds __fs64 tmp;
1111da177e4SLinus Torvalds
1121da177e4SLinus Torvalds switch (UFS_SB(sb)->s_flags & UFS_ST_MASK) {
113252e211eSMark Fortescue case UFS_ST_SUNOS:
1141da177e4SLinus Torvalds case UFS_ST_SUN:
115647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sun.fs_qfmask[0];
116647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sun.fs_qfmask[1];
1171da177e4SLinus Torvalds break;
1181da177e4SLinus Torvalds case UFS_ST_SUNx86:
119647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_sunx86.fs_qfmask[0];
120647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_sunx86.fs_qfmask[1];
1211da177e4SLinus Torvalds break;
1221da177e4SLinus Torvalds case UFS_ST_44BSD:
123647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[0] = usb3->fs_un2.fs_44.fs_qfmask[0];
124647b7e87SEvgeniy Dushistov ((__fs32 *)&tmp)[1] = usb3->fs_un2.fs_44.fs_qfmask[1];
1251da177e4SLinus Torvalds break;
1261da177e4SLinus Torvalds }
1271da177e4SLinus Torvalds
1281da177e4SLinus Torvalds return fs64_to_cpu(sb, tmp);
1291da177e4SLinus Torvalds }
1301da177e4SLinus Torvalds
1311da177e4SLinus Torvalds static inline u16
ufs_get_de_namlen(struct super_block * sb,struct ufs_dir_entry * de)1321da177e4SLinus Torvalds ufs_get_de_namlen(struct super_block *sb, struct ufs_dir_entry *de)
1331da177e4SLinus Torvalds {
1341da177e4SLinus Torvalds if ((UFS_SB(sb)->s_flags & UFS_DE_MASK) == UFS_DE_OLD)
1351da177e4SLinus Torvalds return fs16_to_cpu(sb, de->d_u.d_namlen);
1361da177e4SLinus Torvalds else
1371da177e4SLinus Torvalds return de->d_u.d_44.d_namlen; /* XXX this seems wrong */
1381da177e4SLinus Torvalds }
1391da177e4SLinus Torvalds
1401da177e4SLinus Torvalds static inline void
ufs_set_de_namlen(struct super_block * sb,struct ufs_dir_entry * de,u16 value)1411da177e4SLinus Torvalds ufs_set_de_namlen(struct super_block *sb, struct ufs_dir_entry *de, u16 value)
1421da177e4SLinus Torvalds {
1431da177e4SLinus Torvalds if ((UFS_SB(sb)->s_flags & UFS_DE_MASK) == UFS_DE_OLD)
1441da177e4SLinus Torvalds de->d_u.d_namlen = cpu_to_fs16(sb, value);
1451da177e4SLinus Torvalds else
1461da177e4SLinus Torvalds de->d_u.d_44.d_namlen = value; /* XXX this seems wrong */
1471da177e4SLinus Torvalds }
1481da177e4SLinus Torvalds
1491da177e4SLinus Torvalds static inline void
ufs_set_de_type(struct super_block * sb,struct ufs_dir_entry * de,int mode)1501da177e4SLinus Torvalds ufs_set_de_type(struct super_block *sb, struct ufs_dir_entry *de, int mode)
1511da177e4SLinus Torvalds {
1521da177e4SLinus Torvalds if ((UFS_SB(sb)->s_flags & UFS_DE_MASK) != UFS_DE_44BSD)
1531da177e4SLinus Torvalds return;
1541da177e4SLinus Torvalds
1551da177e4SLinus Torvalds /*
1561da177e4SLinus Torvalds * TODO turn this into a table lookup
1571da177e4SLinus Torvalds */
1581da177e4SLinus Torvalds switch (mode & S_IFMT) {
1591da177e4SLinus Torvalds case S_IFSOCK:
1601da177e4SLinus Torvalds de->d_u.d_44.d_type = DT_SOCK;
1611da177e4SLinus Torvalds break;
1621da177e4SLinus Torvalds case S_IFLNK:
1631da177e4SLinus Torvalds de->d_u.d_44.d_type = DT_LNK;
1641da177e4SLinus Torvalds break;
1651da177e4SLinus Torvalds case S_IFREG:
1661da177e4SLinus Torvalds de->d_u.d_44.d_type = DT_REG;
1671da177e4SLinus Torvalds break;
1681da177e4SLinus Torvalds case S_IFBLK:
1691da177e4SLinus Torvalds de->d_u.d_44.d_type = DT_BLK;
1701da177e4SLinus Torvalds break;
1711da177e4SLinus Torvalds case S_IFDIR:
1721da177e4SLinus Torvalds de->d_u.d_44.d_type = DT_DIR;
1731da177e4SLinus Torvalds break;
1741da177e4SLinus Torvalds case S_IFCHR:
1751da177e4SLinus Torvalds de->d_u.d_44.d_type = DT_CHR;
1761da177e4SLinus Torvalds break;
1771da177e4SLinus Torvalds case S_IFIFO:
1781da177e4SLinus Torvalds de->d_u.d_44.d_type = DT_FIFO;
1791da177e4SLinus Torvalds break;
1801da177e4SLinus Torvalds default:
1811da177e4SLinus Torvalds de->d_u.d_44.d_type = DT_UNKNOWN;
1821da177e4SLinus Torvalds }
1831da177e4SLinus Torvalds }
1841da177e4SLinus Torvalds
1851da177e4SLinus Torvalds static inline u32
ufs_get_inode_uid(struct super_block * sb,struct ufs_inode * inode)1861da177e4SLinus Torvalds ufs_get_inode_uid(struct super_block *sb, struct ufs_inode *inode)
1871da177e4SLinus Torvalds {
1881da177e4SLinus Torvalds switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
1891da177e4SLinus Torvalds case UFS_UID_44BSD:
1901da177e4SLinus Torvalds return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_uid);
191252e211eSMark Fortescue case UFS_UID_EFT:
192252e211eSMark Fortescue if (inode->ui_u1.oldids.ui_suid == 0xFFFF)
193252e211eSMark Fortescue return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_uid);
194*df561f66SGustavo A. R. Silva fallthrough;
1951da177e4SLinus Torvalds default:
1961da177e4SLinus Torvalds return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_suid);
1971da177e4SLinus Torvalds }
1981da177e4SLinus Torvalds }
1991da177e4SLinus Torvalds
2001da177e4SLinus Torvalds static inline void
ufs_set_inode_uid(struct super_block * sb,struct ufs_inode * inode,u32 value)2011da177e4SLinus Torvalds ufs_set_inode_uid(struct super_block *sb, struct ufs_inode *inode, u32 value)
2021da177e4SLinus Torvalds {
2031da177e4SLinus Torvalds switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
2041da177e4SLinus Torvalds case UFS_UID_44BSD:
2051da177e4SLinus Torvalds inode->ui_u3.ui_44.ui_uid = cpu_to_fs32(sb, value);
206252e211eSMark Fortescue inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value);
207252e211eSMark Fortescue break;
208252e211eSMark Fortescue case UFS_UID_EFT:
209252e211eSMark Fortescue inode->ui_u3.ui_sun.ui_uid = cpu_to_fs32(sb, value);
210252e211eSMark Fortescue if (value > 0xFFFF)
211252e211eSMark Fortescue value = 0xFFFF;
212*df561f66SGustavo A. R. Silva fallthrough;
213252e211eSMark Fortescue default:
214252e211eSMark Fortescue inode->ui_u1.oldids.ui_suid = cpu_to_fs16(sb, value);
2151da177e4SLinus Torvalds break;
2161da177e4SLinus Torvalds }
2171da177e4SLinus Torvalds }
2181da177e4SLinus Torvalds
2191da177e4SLinus Torvalds static inline u32
ufs_get_inode_gid(struct super_block * sb,struct ufs_inode * inode)2201da177e4SLinus Torvalds ufs_get_inode_gid(struct super_block *sb, struct ufs_inode *inode)
2211da177e4SLinus Torvalds {
2221da177e4SLinus Torvalds switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
2231da177e4SLinus Torvalds case UFS_UID_44BSD:
2241da177e4SLinus Torvalds return fs32_to_cpu(sb, inode->ui_u3.ui_44.ui_gid);
225252e211eSMark Fortescue case UFS_UID_EFT:
2264e903604SAl Viro if (inode->ui_u1.oldids.ui_sgid == 0xFFFF)
227252e211eSMark Fortescue return fs32_to_cpu(sb, inode->ui_u3.ui_sun.ui_gid);
228*df561f66SGustavo A. R. Silva fallthrough;
2291da177e4SLinus Torvalds default:
2301da177e4SLinus Torvalds return fs16_to_cpu(sb, inode->ui_u1.oldids.ui_sgid);
2311da177e4SLinus Torvalds }
2321da177e4SLinus Torvalds }
2331da177e4SLinus Torvalds
2341da177e4SLinus Torvalds static inline void
ufs_set_inode_gid(struct super_block * sb,struct ufs_inode * inode,u32 value)2351da177e4SLinus Torvalds ufs_set_inode_gid(struct super_block *sb, struct ufs_inode *inode, u32 value)
2361da177e4SLinus Torvalds {
2371da177e4SLinus Torvalds switch (UFS_SB(sb)->s_flags & UFS_UID_MASK) {
2381da177e4SLinus Torvalds case UFS_UID_44BSD:
2391da177e4SLinus Torvalds inode->ui_u3.ui_44.ui_gid = cpu_to_fs32(sb, value);
240252e211eSMark Fortescue inode->ui_u1.oldids.ui_sgid = cpu_to_fs16(sb, value);
241252e211eSMark Fortescue break;
242252e211eSMark Fortescue case UFS_UID_EFT:
243252e211eSMark Fortescue inode->ui_u3.ui_sun.ui_gid = cpu_to_fs32(sb, value);
244252e211eSMark Fortescue if (value > 0xFFFF)
245252e211eSMark Fortescue value = 0xFFFF;
246*df561f66SGustavo A. R. Silva fallthrough;
247252e211eSMark Fortescue default:
248252e211eSMark Fortescue inode->ui_u1.oldids.ui_sgid = cpu_to_fs16(sb, value);
2491da177e4SLinus Torvalds break;
2501da177e4SLinus Torvalds }
2511da177e4SLinus Torvalds }
2521da177e4SLinus Torvalds
2531da177e4SLinus Torvalds extern dev_t ufs_get_inode_dev(struct super_block *, struct ufs_inode_info *);
2541da177e4SLinus Torvalds extern void ufs_set_inode_dev(struct super_block *, struct ufs_inode_info *, dev_t);
255f4e420dcSChristoph Hellwig extern int ufs_prepare_chunk(struct page *page, loff_t pos, unsigned len);
2561da177e4SLinus Torvalds
2571da177e4SLinus Torvalds /*
2581da177e4SLinus Torvalds * These functions manipulate ufs buffers
2591da177e4SLinus Torvalds */
2601da177e4SLinus Torvalds #define ubh_bread(sb,fragment,size) _ubh_bread_(uspi,sb,fragment,size)
2611da177e4SLinus Torvalds extern struct ufs_buffer_head * _ubh_bread_(struct ufs_sb_private_info *, struct super_block *, u64 , u64);
2621da177e4SLinus Torvalds extern struct ufs_buffer_head * ubh_bread_uspi(struct ufs_sb_private_info *, struct super_block *, u64, u64);
2631da177e4SLinus Torvalds extern void ubh_brelse (struct ufs_buffer_head *);
2641da177e4SLinus Torvalds extern void ubh_brelse_uspi (struct ufs_sb_private_info *);
2651da177e4SLinus Torvalds extern void ubh_mark_buffer_dirty (struct ufs_buffer_head *);
2661da177e4SLinus Torvalds extern void ubh_mark_buffer_uptodate (struct ufs_buffer_head *, int);
2679cb569d6SChristoph Hellwig extern void ubh_sync_block(struct ufs_buffer_head *);
2681da177e4SLinus Torvalds extern void ubh_bforget (struct ufs_buffer_head *);
2691da177e4SLinus Torvalds extern int ubh_buffer_dirty (struct ufs_buffer_head *);
2701da177e4SLinus Torvalds #define ubh_ubhcpymem(mem,ubh,size) _ubh_ubhcpymem_(uspi,mem,ubh,size)
2711da177e4SLinus Torvalds extern void _ubh_ubhcpymem_(struct ufs_sb_private_info *, unsigned char *, struct ufs_buffer_head *, unsigned);
2721da177e4SLinus Torvalds #define ubh_memcpyubh(ubh,mem,size) _ubh_memcpyubh_(uspi,ubh,mem,size)
2731da177e4SLinus Torvalds extern void _ubh_memcpyubh_(struct ufs_sb_private_info *, struct ufs_buffer_head *, unsigned char *, unsigned);
2741da177e4SLinus Torvalds
27510e5dce0SEvgeniy Dushistov /* This functions works with cache pages*/
27610e5dce0SEvgeniy Dushistov extern struct page *ufs_get_locked_page(struct address_space *mapping,
27710e5dce0SEvgeniy Dushistov pgoff_t index);
ufs_put_locked_page(struct page * page)27810e5dce0SEvgeniy Dushistov static inline void ufs_put_locked_page(struct page *page)
27910e5dce0SEvgeniy Dushistov {
28010e5dce0SEvgeniy Dushistov unlock_page(page);
28109cbfeafSKirill A. Shutemov put_page(page);
28210e5dce0SEvgeniy Dushistov }
2831da177e4SLinus Torvalds
2841da177e4SLinus Torvalds
2851da177e4SLinus Torvalds /*
2867b4ee73eSEvgeniy * macros and inline function to get important structures from ufs_sb_private_info
2871da177e4SLinus Torvalds */
2881da177e4SLinus Torvalds
get_usb_offset(struct ufs_sb_private_info * uspi,unsigned int offset)2897b4ee73eSEvgeniy static inline void *get_usb_offset(struct ufs_sb_private_info *uspi,
2907b4ee73eSEvgeniy unsigned int offset)
2917b4ee73eSEvgeniy {
2927b4ee73eSEvgeniy unsigned int index;
2931da177e4SLinus Torvalds
2947b4ee73eSEvgeniy index = offset >> uspi->s_fshift;
2957b4ee73eSEvgeniy offset &= ~uspi->s_fmask;
2967b4ee73eSEvgeniy return uspi->s_ubh.bh[index]->b_data + offset;
2977b4ee73eSEvgeniy }
2987b4ee73eSEvgeniy
2997b4ee73eSEvgeniy #define ubh_get_usb_first(uspi) \
3007b4ee73eSEvgeniy ((struct ufs_super_block_first *)get_usb_offset((uspi), 0))
3017b4ee73eSEvgeniy
3027b4ee73eSEvgeniy #define ubh_get_usb_second(uspi) \
3037b4ee73eSEvgeniy ((struct ufs_super_block_second *)get_usb_offset((uspi), UFS_SECTOR_SIZE))
3047b4ee73eSEvgeniy
3057b4ee73eSEvgeniy #define ubh_get_usb_third(uspi) \
3067b4ee73eSEvgeniy ((struct ufs_super_block_third *)get_usb_offset((uspi), 2*UFS_SECTOR_SIZE))
3077b4ee73eSEvgeniy
3081da177e4SLinus Torvalds
3091da177e4SLinus Torvalds #define ubh_get_ucg(ubh) \
3101da177e4SLinus Torvalds ((struct ufs_cylinder_group *)((ubh)->bh[0]->b_data))
3111da177e4SLinus Torvalds
3121da177e4SLinus Torvalds
3131da177e4SLinus Torvalds /*
3141da177e4SLinus Torvalds * Extract byte from ufs_buffer_head
3151da177e4SLinus Torvalds * Extract the bits for a block from a map inside ufs_buffer_head
3161da177e4SLinus Torvalds */
3171da177e4SLinus Torvalds #define ubh_get_addr8(ubh,begin) \
3181da177e4SLinus Torvalds ((u8*)(ubh)->bh[(begin) >> uspi->s_fshift]->b_data + \
3191da177e4SLinus Torvalds ((begin) & ~uspi->s_fmask))
3201da177e4SLinus Torvalds
3211da177e4SLinus Torvalds #define ubh_get_addr16(ubh,begin) \
3221da177e4SLinus Torvalds (((__fs16*)((ubh)->bh[(begin) >> (uspi->s_fshift-1)]->b_data)) + \
32371a3d1b4SMariusz Kozlowski ((begin) & ((uspi->fsize>>1) - 1)))
3241da177e4SLinus Torvalds
3251da177e4SLinus Torvalds #define ubh_get_addr32(ubh,begin) \
3261da177e4SLinus Torvalds (((__fs32*)((ubh)->bh[(begin) >> (uspi->s_fshift-2)]->b_data)) + \
3271da177e4SLinus Torvalds ((begin) & ((uspi->s_fsize>>2) - 1)))
3281da177e4SLinus Torvalds
32954fb996aSEvgeniy Dushistov #define ubh_get_addr64(ubh,begin) \
33054fb996aSEvgeniy Dushistov (((__fs64*)((ubh)->bh[(begin) >> (uspi->s_fshift-3)]->b_data)) + \
33154fb996aSEvgeniy Dushistov ((begin) & ((uspi->s_fsize>>3) - 1)))
33254fb996aSEvgeniy Dushistov
3331da177e4SLinus Torvalds #define ubh_get_addr ubh_get_addr8
3341da177e4SLinus Torvalds
ubh_get_data_ptr(struct ufs_sb_private_info * uspi,struct ufs_buffer_head * ubh,u64 blk)33554fb996aSEvgeniy Dushistov static inline void *ubh_get_data_ptr(struct ufs_sb_private_info *uspi,
33654fb996aSEvgeniy Dushistov struct ufs_buffer_head *ubh,
33754fb996aSEvgeniy Dushistov u64 blk)
33854fb996aSEvgeniy Dushistov {
33954fb996aSEvgeniy Dushistov if (uspi->fs_magic == UFS2_MAGIC)
34054fb996aSEvgeniy Dushistov return ubh_get_addr64(ubh, blk);
34154fb996aSEvgeniy Dushistov else
34254fb996aSEvgeniy Dushistov return ubh_get_addr32(ubh, blk);
34354fb996aSEvgeniy Dushistov }
34454fb996aSEvgeniy Dushistov
3451da177e4SLinus Torvalds #define ubh_blkmap(ubh,begin,bit) \
3461da177e4SLinus Torvalds ((*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) >> ((bit) & 7)) & (0xff >> (UFS_MAXFRAG - uspi->s_fpb)))
3471da177e4SLinus Torvalds
348c596961dSAl Viro static inline u64
ufs_freefrags(struct ufs_sb_private_info * uspi)349c596961dSAl Viro ufs_freefrags(struct ufs_sb_private_info *uspi)
350ee3ffd6cSEvgeniy Dushistov {
351ee3ffd6cSEvgeniy Dushistov return ufs_blkstofrags(uspi->cs_total.cs_nbfree) +
352c596961dSAl Viro uspi->cs_total.cs_nffree;
353ee3ffd6cSEvgeniy Dushistov }
3541da177e4SLinus Torvalds
3551da177e4SLinus Torvalds /*
3561da177e4SLinus Torvalds * Macros to access cylinder group array structures
3571da177e4SLinus Torvalds */
3581da177e4SLinus Torvalds #define ubh_cg_blktot(ucpi,cylno) \
3599695ef16SEvgeniy Dushistov (*((__fs32*)ubh_get_addr(UCPI_UBH(ucpi), (ucpi)->c_btotoff + ((cylno) << 2))))
3601da177e4SLinus Torvalds
3611da177e4SLinus Torvalds #define ubh_cg_blks(ucpi,cylno,rpos) \
3629695ef16SEvgeniy Dushistov (*((__fs16*)ubh_get_addr(UCPI_UBH(ucpi), \
3631da177e4SLinus Torvalds (ucpi)->c_boff + (((cylno) * uspi->s_nrpos + (rpos)) << 1 ))))
3641da177e4SLinus Torvalds
3651da177e4SLinus Torvalds /*
3661da177e4SLinus Torvalds * Bitmap operations
3671da177e4SLinus Torvalds * These functions work like classical bitmap operations.
3681da177e4SLinus Torvalds * The difference is that we don't have the whole bitmap
3691da177e4SLinus Torvalds * in one contiguous chunk of memory, but in several buffers.
3701da177e4SLinus Torvalds * The parameters of each function are super_block, ufs_buffer_head and
3711da177e4SLinus Torvalds * position of the beginning of the bitmap.
3721da177e4SLinus Torvalds */
3731da177e4SLinus Torvalds #define ubh_setbit(ubh,begin,bit) \
3741da177e4SLinus Torvalds (*ubh_get_addr(ubh, (begin) + ((bit) >> 3)) |= (1 << ((bit) & 7)))
3751da177e4SLinus Torvalds
3761da177e4SLinus Torvalds #define ubh_clrbit(ubh,begin,bit) \
3771da177e4SLinus Torvalds (*ubh_get_addr (ubh, (begin) + ((bit) >> 3)) &= ~(1 << ((bit) & 7)))
3781da177e4SLinus Torvalds
3791da177e4SLinus Torvalds #define ubh_isset(ubh,begin,bit) \
3801da177e4SLinus Torvalds (*ubh_get_addr (ubh, (begin) + ((bit) >> 3)) & (1 << ((bit) & 7)))
3811da177e4SLinus Torvalds
3821da177e4SLinus Torvalds #define ubh_isclr(ubh,begin,bit) (!ubh_isset(ubh,begin,bit))
3831da177e4SLinus Torvalds
3841da177e4SLinus Torvalds #define ubh_find_first_zero_bit(ubh,begin,size) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,0)
3851da177e4SLinus Torvalds
3861da177e4SLinus Torvalds #define ubh_find_next_zero_bit(ubh,begin,size,offset) _ubh_find_next_zero_bit_(uspi,ubh,begin,size,offset)
_ubh_find_next_zero_bit_(struct ufs_sb_private_info * uspi,struct ufs_buffer_head * ubh,unsigned begin,unsigned size,unsigned offset)3871da177e4SLinus Torvalds static inline unsigned _ubh_find_next_zero_bit_(
3881da177e4SLinus Torvalds struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh,
3891da177e4SLinus Torvalds unsigned begin, unsigned size, unsigned offset)
3901da177e4SLinus Torvalds {
3911da177e4SLinus Torvalds unsigned base, count, pos;
3921da177e4SLinus Torvalds
3931da177e4SLinus Torvalds size -= offset;
3941da177e4SLinus Torvalds begin <<= 3;
3951da177e4SLinus Torvalds offset += begin;
3961da177e4SLinus Torvalds base = offset >> uspi->s_bpfshift;
3971da177e4SLinus Torvalds offset &= uspi->s_bpfmask;
3981da177e4SLinus Torvalds for (;;) {
3991da177e4SLinus Torvalds count = min_t(unsigned int, size + offset, uspi->s_bpf);
4001da177e4SLinus Torvalds size -= count - offset;
4013cdc7125SAkinobu Mita pos = find_next_zero_bit_le(ubh->bh[base]->b_data, count, offset);
4021da177e4SLinus Torvalds if (pos < count || !size)
4031da177e4SLinus Torvalds break;
4041da177e4SLinus Torvalds base++;
4051da177e4SLinus Torvalds offset = 0;
4061da177e4SLinus Torvalds }
4071da177e4SLinus Torvalds return (base << uspi->s_bpfshift) + pos - begin;
4081da177e4SLinus Torvalds }
4091da177e4SLinus Torvalds
find_last_zero_bit(unsigned char * bitmap,unsigned size,unsigned offset)4101da177e4SLinus Torvalds static inline unsigned find_last_zero_bit (unsigned char * bitmap,
4111da177e4SLinus Torvalds unsigned size, unsigned offset)
4121da177e4SLinus Torvalds {
4131da177e4SLinus Torvalds unsigned bit, i;
4141da177e4SLinus Torvalds unsigned char * mapp;
4151da177e4SLinus Torvalds unsigned char map;
4161da177e4SLinus Torvalds
4171da177e4SLinus Torvalds mapp = bitmap + (size >> 3);
4181da177e4SLinus Torvalds map = *mapp--;
4191da177e4SLinus Torvalds bit = 1 << (size & 7);
4201da177e4SLinus Torvalds for (i = size; i > offset; i--) {
4211da177e4SLinus Torvalds if ((map & bit) == 0)
4221da177e4SLinus Torvalds break;
4231da177e4SLinus Torvalds if ((i & 7) != 0) {
4241da177e4SLinus Torvalds bit >>= 1;
4251da177e4SLinus Torvalds } else {
4261da177e4SLinus Torvalds map = *mapp--;
4271da177e4SLinus Torvalds bit = 1 << 7;
4281da177e4SLinus Torvalds }
4291da177e4SLinus Torvalds }
4301da177e4SLinus Torvalds return i;
4311da177e4SLinus Torvalds }
4321da177e4SLinus Torvalds
4331da177e4SLinus Torvalds #define ubh_find_last_zero_bit(ubh,begin,size,offset) _ubh_find_last_zero_bit_(uspi,ubh,begin,size,offset)
_ubh_find_last_zero_bit_(struct ufs_sb_private_info * uspi,struct ufs_buffer_head * ubh,unsigned begin,unsigned start,unsigned end)4341da177e4SLinus Torvalds static inline unsigned _ubh_find_last_zero_bit_(
4351da177e4SLinus Torvalds struct ufs_sb_private_info * uspi, struct ufs_buffer_head * ubh,
4361da177e4SLinus Torvalds unsigned begin, unsigned start, unsigned end)
4371da177e4SLinus Torvalds {
4381da177e4SLinus Torvalds unsigned base, count, pos, size;
4391da177e4SLinus Torvalds
4401da177e4SLinus Torvalds size = start - end;
4411da177e4SLinus Torvalds begin <<= 3;
4421da177e4SLinus Torvalds start += begin;
4431da177e4SLinus Torvalds base = start >> uspi->s_bpfshift;
4441da177e4SLinus Torvalds start &= uspi->s_bpfmask;
4451da177e4SLinus Torvalds for (;;) {
4461da177e4SLinus Torvalds count = min_t(unsigned int,
4471da177e4SLinus Torvalds size + (uspi->s_bpf - start), uspi->s_bpf)
4481da177e4SLinus Torvalds - (uspi->s_bpf - start);
4491da177e4SLinus Torvalds size -= count;
4501da177e4SLinus Torvalds pos = find_last_zero_bit (ubh->bh[base]->b_data,
4511da177e4SLinus Torvalds start, start - count);
4521da177e4SLinus Torvalds if (pos > start - count || !size)
4531da177e4SLinus Torvalds break;
4541da177e4SLinus Torvalds base--;
4551da177e4SLinus Torvalds start = uspi->s_bpf;
4561da177e4SLinus Torvalds }
4571da177e4SLinus Torvalds return (base << uspi->s_bpfshift) + pos - begin;
4581da177e4SLinus Torvalds }
4591da177e4SLinus Torvalds
4601da177e4SLinus Torvalds #define ubh_isblockclear(ubh,begin,block) (!_ubh_isblockset_(uspi,ubh,begin,block))
4611da177e4SLinus Torvalds
4621da177e4SLinus Torvalds #define ubh_isblockset(ubh,begin,block) _ubh_isblockset_(uspi,ubh,begin,block)
_ubh_isblockset_(struct ufs_sb_private_info * uspi,struct ufs_buffer_head * ubh,unsigned begin,unsigned block)4631da177e4SLinus Torvalds static inline int _ubh_isblockset_(struct ufs_sb_private_info * uspi,
4641da177e4SLinus Torvalds struct ufs_buffer_head * ubh, unsigned begin, unsigned block)
4651da177e4SLinus Torvalds {
466414cf718SAl Viro u8 mask;
4671da177e4SLinus Torvalds switch (uspi->s_fpb) {
4681da177e4SLinus Torvalds case 8:
4691da177e4SLinus Torvalds return (*ubh_get_addr (ubh, begin + block) == 0xff);
4701da177e4SLinus Torvalds case 4:
471414cf718SAl Viro mask = 0x0f << ((block & 0x01) << 2);
472414cf718SAl Viro return (*ubh_get_addr (ubh, begin + (block >> 1)) & mask) == mask;
4731da177e4SLinus Torvalds case 2:
474414cf718SAl Viro mask = 0x03 << ((block & 0x03) << 1);
475414cf718SAl Viro return (*ubh_get_addr (ubh, begin + (block >> 2)) & mask) == mask;
4761da177e4SLinus Torvalds case 1:
477414cf718SAl Viro mask = 0x01 << (block & 0x07);
478414cf718SAl Viro return (*ubh_get_addr (ubh, begin + (block >> 3)) & mask) == mask;
4791da177e4SLinus Torvalds }
4801da177e4SLinus Torvalds return 0;
4811da177e4SLinus Torvalds }
4821da177e4SLinus Torvalds
4831da177e4SLinus Torvalds #define ubh_clrblock(ubh,begin,block) _ubh_clrblock_(uspi,ubh,begin,block)
_ubh_clrblock_(struct ufs_sb_private_info * uspi,struct ufs_buffer_head * ubh,unsigned begin,unsigned block)4841da177e4SLinus Torvalds static inline void _ubh_clrblock_(struct ufs_sb_private_info * uspi,
4851da177e4SLinus Torvalds struct ufs_buffer_head * ubh, unsigned begin, unsigned block)
4861da177e4SLinus Torvalds {
4871da177e4SLinus Torvalds switch (uspi->s_fpb) {
4881da177e4SLinus Torvalds case 8:
4891da177e4SLinus Torvalds *ubh_get_addr (ubh, begin + block) = 0x00;
4901da177e4SLinus Torvalds return;
4911da177e4SLinus Torvalds case 4:
4921da177e4SLinus Torvalds *ubh_get_addr (ubh, begin + (block >> 1)) &= ~(0x0f << ((block & 0x01) << 2));
4931da177e4SLinus Torvalds return;
4941da177e4SLinus Torvalds case 2:
4951da177e4SLinus Torvalds *ubh_get_addr (ubh, begin + (block >> 2)) &= ~(0x03 << ((block & 0x03) << 1));
4961da177e4SLinus Torvalds return;
4971da177e4SLinus Torvalds case 1:
4981da177e4SLinus Torvalds *ubh_get_addr (ubh, begin + (block >> 3)) &= ~(0x01 << ((block & 0x07)));
4991da177e4SLinus Torvalds return;
5001da177e4SLinus Torvalds }
5011da177e4SLinus Torvalds }
5021da177e4SLinus Torvalds
5031da177e4SLinus Torvalds #define ubh_setblock(ubh,begin,block) _ubh_setblock_(uspi,ubh,begin,block)
_ubh_setblock_(struct ufs_sb_private_info * uspi,struct ufs_buffer_head * ubh,unsigned begin,unsigned block)5041da177e4SLinus Torvalds static inline void _ubh_setblock_(struct ufs_sb_private_info * uspi,
5051da177e4SLinus Torvalds struct ufs_buffer_head * ubh, unsigned begin, unsigned block)
5061da177e4SLinus Torvalds {
5071da177e4SLinus Torvalds switch (uspi->s_fpb) {
5081da177e4SLinus Torvalds case 8:
5091da177e4SLinus Torvalds *ubh_get_addr(ubh, begin + block) = 0xff;
5101da177e4SLinus Torvalds return;
5111da177e4SLinus Torvalds case 4:
5121da177e4SLinus Torvalds *ubh_get_addr(ubh, begin + (block >> 1)) |= (0x0f << ((block & 0x01) << 2));
5131da177e4SLinus Torvalds return;
5141da177e4SLinus Torvalds case 2:
5151da177e4SLinus Torvalds *ubh_get_addr(ubh, begin + (block >> 2)) |= (0x03 << ((block & 0x03) << 1));
5161da177e4SLinus Torvalds return;
5171da177e4SLinus Torvalds case 1:
5181da177e4SLinus Torvalds *ubh_get_addr(ubh, begin + (block >> 3)) |= (0x01 << ((block & 0x07)));
5191da177e4SLinus Torvalds return;
5201da177e4SLinus Torvalds }
5211da177e4SLinus Torvalds }
5221da177e4SLinus Torvalds
ufs_fragacct(struct super_block * sb,unsigned blockmap,__fs32 * fraglist,int cnt)5231da177e4SLinus Torvalds static inline void ufs_fragacct (struct super_block * sb, unsigned blockmap,
5241da177e4SLinus Torvalds __fs32 * fraglist, int cnt)
5251da177e4SLinus Torvalds {
5261da177e4SLinus Torvalds struct ufs_sb_private_info * uspi;
5271da177e4SLinus Torvalds unsigned fragsize, pos;
5281da177e4SLinus Torvalds
5291da177e4SLinus Torvalds uspi = UFS_SB(sb)->s_uspi;
5301da177e4SLinus Torvalds
5311da177e4SLinus Torvalds fragsize = 0;
5321da177e4SLinus Torvalds for (pos = 0; pos < uspi->s_fpb; pos++) {
5331da177e4SLinus Torvalds if (blockmap & (1 << pos)) {
5341da177e4SLinus Torvalds fragsize++;
5351da177e4SLinus Torvalds }
5361da177e4SLinus Torvalds else if (fragsize > 0) {
5371da177e4SLinus Torvalds fs32_add(sb, &fraglist[fragsize], cnt);
5381da177e4SLinus Torvalds fragsize = 0;
5391da177e4SLinus Torvalds }
5401da177e4SLinus Torvalds }
5411da177e4SLinus Torvalds if (fragsize > 0 && fragsize < uspi->s_fpb)
5421da177e4SLinus Torvalds fs32_add(sb, &fraglist[fragsize], cnt);
5431da177e4SLinus Torvalds }
54454fb996aSEvgeniy Dushistov
ufs_get_direct_data_ptr(struct ufs_sb_private_info * uspi,struct ufs_inode_info * ufsi,unsigned blk)54554fb996aSEvgeniy Dushistov static inline void *ufs_get_direct_data_ptr(struct ufs_sb_private_info *uspi,
54654fb996aSEvgeniy Dushistov struct ufs_inode_info *ufsi,
54754fb996aSEvgeniy Dushistov unsigned blk)
54854fb996aSEvgeniy Dushistov {
54954fb996aSEvgeniy Dushistov BUG_ON(blk > UFS_TIND_BLOCK);
55054fb996aSEvgeniy Dushistov return uspi->fs_magic == UFS2_MAGIC ?
55154fb996aSEvgeniy Dushistov (void *)&ufsi->i_u1.u2_i_data[blk] :
55254fb996aSEvgeniy Dushistov (void *)&ufsi->i_u1.i_data[blk];
55354fb996aSEvgeniy Dushistov }
55454fb996aSEvgeniy Dushistov
ufs_data_ptr_to_cpu(struct super_block * sb,void * p)55554fb996aSEvgeniy Dushistov static inline u64 ufs_data_ptr_to_cpu(struct super_block *sb, void *p)
55654fb996aSEvgeniy Dushistov {
55754fb996aSEvgeniy Dushistov return UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC ?
55854fb996aSEvgeniy Dushistov fs64_to_cpu(sb, *(__fs64 *)p) :
55954fb996aSEvgeniy Dushistov fs32_to_cpu(sb, *(__fs32 *)p);
56054fb996aSEvgeniy Dushistov }
56154fb996aSEvgeniy Dushistov
ufs_cpu_to_data_ptr(struct super_block * sb,void * p,u64 val)56254fb996aSEvgeniy Dushistov static inline void ufs_cpu_to_data_ptr(struct super_block *sb, void *p, u64 val)
56354fb996aSEvgeniy Dushistov {
56454fb996aSEvgeniy Dushistov if (UFS_SB(sb)->s_uspi->fs_magic == UFS2_MAGIC)
56554fb996aSEvgeniy Dushistov *(__fs64 *)p = cpu_to_fs64(sb, val);
56654fb996aSEvgeniy Dushistov else
56754fb996aSEvgeniy Dushistov *(__fs32 *)p = cpu_to_fs32(sb, val);
56854fb996aSEvgeniy Dushistov }
56954fb996aSEvgeniy Dushistov
ufs_data_ptr_clear(struct ufs_sb_private_info * uspi,void * p)57054fb996aSEvgeniy Dushistov static inline void ufs_data_ptr_clear(struct ufs_sb_private_info *uspi,
57154fb996aSEvgeniy Dushistov void *p)
57254fb996aSEvgeniy Dushistov {
57354fb996aSEvgeniy Dushistov if (uspi->fs_magic == UFS2_MAGIC)
57454fb996aSEvgeniy Dushistov *(__fs64 *)p = 0;
57554fb996aSEvgeniy Dushistov else
57654fb996aSEvgeniy Dushistov *(__fs32 *)p = 0;
57754fb996aSEvgeniy Dushistov }
57854fb996aSEvgeniy Dushistov
ufs_is_data_ptr_zero(struct ufs_sb_private_info * uspi,void * p)57954fb996aSEvgeniy Dushistov static inline int ufs_is_data_ptr_zero(struct ufs_sb_private_info *uspi,
58054fb996aSEvgeniy Dushistov void *p)
58154fb996aSEvgeniy Dushistov {
58254fb996aSEvgeniy Dushistov if (uspi->fs_magic == UFS2_MAGIC)
58354fb996aSEvgeniy Dushistov return *(__fs64 *)p == 0;
58454fb996aSEvgeniy Dushistov else
58554fb996aSEvgeniy Dushistov return *(__fs32 *)p == 0;
58654fb996aSEvgeniy Dushistov }
587a3fda0ffSArnd Bergmann
ufs_get_seconds(struct super_block * sbp)588a3fda0ffSArnd Bergmann static inline __fs32 ufs_get_seconds(struct super_block *sbp)
589a3fda0ffSArnd Bergmann {
590a3fda0ffSArnd Bergmann time64_t now = ktime_get_real_seconds();
591a3fda0ffSArnd Bergmann
592a3fda0ffSArnd Bergmann /* Signed 32-bit interpretation wraps around in 2038, which
593a3fda0ffSArnd Bergmann * happens in ufs1 inode stamps but not ufs2 using 64-bits
594a3fda0ffSArnd Bergmann * stamps. For superblock and blockgroup, let's assume
595a3fda0ffSArnd Bergmann * unsigned 32-bit stamps, which are good until y2106.
596a3fda0ffSArnd Bergmann * Wrap around rather than clamp here to make the dirty
597a3fda0ffSArnd Bergmann * file system detection work in the superblock stamp.
598a3fda0ffSArnd Bergmann */
599a3fda0ffSArnd Bergmann return cpu_to_fs32(sbp, lower_32_bits(now));
600a3fda0ffSArnd Bergmann }
601