VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
d2912cb15bdda (Thomas Gleixner    2019-06-04 10:11:33 +0200   1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   2) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   3)  *  linux/fs/adfs/inode.c
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   4)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   5)  *  Copyright (C) 1997-1999 Russell King
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   6)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   7) #include <linux/buffer_head.h>
a9185b41a4f84 (Christoph Hellwig  2010-03-05 09:21:37 +0100   8) #include <linux/writeback.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   9) #include "adfs.h"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  10) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  11) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  12)  * Lookup/Create a block at offset 'block' into 'inode'.  We currently do
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  13)  * not support creation of new blocks, so we return -EIO for this case.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  14)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  15) static int
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  16) adfs_get_block(struct inode *inode, sector_t block, struct buffer_head *bh,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  17) 	       int create)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  18) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  19) 	if (!create) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  20) 		if (block >= inode->i_blocks)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  21) 			goto abort_toobig;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  22) 
25e5d4df3b46a (Russell King       2019-12-09 11:11:38 +0000  23) 		block = __adfs_block_map(inode->i_sb, ADFS_I(inode)->indaddr,
25e5d4df3b46a (Russell King       2019-12-09 11:11:38 +0000  24) 					 block);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  25) 		if (block)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  26) 			map_bh(bh, inode->i_sb, block);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  27) 		return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  28) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  29) 	/* don't support allocation of blocks yet */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  30) 	return -EIO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  31) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  32) abort_toobig:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  33) 	return 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  34) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  35) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  36) static int adfs_writepage(struct page *page, struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  37) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  38) 	return block_write_full_page(page, adfs_get_block, wbc);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  39) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  40) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  41) static int adfs_readpage(struct file *file, struct page *page)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  42) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  43) 	return block_read_full_page(page, adfs_get_block);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  44) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  45) 
6229518384623 (Marco Stornelli    2012-12-15 11:51:11 +0100  46) static void adfs_write_failed(struct address_space *mapping, loff_t to)
6229518384623 (Marco Stornelli    2012-12-15 11:51:11 +0100  47) {
6229518384623 (Marco Stornelli    2012-12-15 11:51:11 +0100  48) 	struct inode *inode = mapping->host;
6229518384623 (Marco Stornelli    2012-12-15 11:51:11 +0100  49) 
6229518384623 (Marco Stornelli    2012-12-15 11:51:11 +0100  50) 	if (to > inode->i_size)
7caef26767c17 (Kirill A. Shutemov 2013-09-12 15:13:56 -0700  51) 		truncate_pagecache(inode, inode->i_size);
6229518384623 (Marco Stornelli    2012-12-15 11:51:11 +0100  52) }
6229518384623 (Marco Stornelli    2012-12-15 11:51:11 +0100  53) 
b4585729f0b61 (Nicholas Piggin    2007-10-16 01:25:23 -0700  54) static int adfs_write_begin(struct file *file, struct address_space *mapping,
b4585729f0b61 (Nicholas Piggin    2007-10-16 01:25:23 -0700  55) 			loff_t pos, unsigned len, unsigned flags,
b4585729f0b61 (Nicholas Piggin    2007-10-16 01:25:23 -0700  56) 			struct page **pagep, void **fsdata)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  57) {
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  58) 	int ret;
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  59) 
b4585729f0b61 (Nicholas Piggin    2007-10-16 01:25:23 -0700  60) 	*pagep = NULL;
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  61) 	ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata,
b4585729f0b61 (Nicholas Piggin    2007-10-16 01:25:23 -0700  62) 				adfs_get_block,
b4585729f0b61 (Nicholas Piggin    2007-10-16 01:25:23 -0700  63) 				&ADFS_I(mapping->host)->mmu_private);
6229518384623 (Marco Stornelli    2012-12-15 11:51:11 +0100  64) 	if (unlikely(ret))
6229518384623 (Marco Stornelli    2012-12-15 11:51:11 +0100  65) 		adfs_write_failed(mapping, pos + len);
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  66) 
282dc17884988 (Christoph Hellwig  2010-06-04 11:29:55 +0200  67) 	return ret;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  68) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  69) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  70) static sector_t _adfs_bmap(struct address_space *mapping, sector_t block)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  71) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  72) 	return generic_block_bmap(mapping, block, adfs_get_block);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  73) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  74) 
f5e54d6e53a20 (Christoph Hellwig  2006-06-28 04:26:44 -0700  75) static const struct address_space_operations adfs_aops = {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  76) 	.readpage	= adfs_readpage,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  77) 	.writepage	= adfs_writepage,
b4585729f0b61 (Nicholas Piggin    2007-10-16 01:25:23 -0700  78) 	.write_begin	= adfs_write_begin,
b4585729f0b61 (Nicholas Piggin    2007-10-16 01:25:23 -0700  79) 	.write_end	= generic_write_end,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  80) 	.bmap		= _adfs_bmap
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  81) };
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  82) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  83) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  84)  * Convert ADFS attributes and filetype to Linux permission.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  85)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  86) static umode_t
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  87) adfs_atts2mode(struct super_block *sb, struct inode *inode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  88) {
da23ef0549d42 (Stuart Swales      2011-03-22 16:35:06 -0700  89) 	unsigned int attr = ADFS_I(inode)->attr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  90) 	umode_t mode, rmask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  91) 	struct adfs_sb_info *asb = ADFS_SB(sb);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  92) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  93) 	if (attr & ADFS_NDA_DIRECTORY) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  94) 		mode = S_IRUGO & asb->s_owner_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  95) 		return S_IFDIR | S_IXUGO | mode;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  96) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  97) 
b4ed8f75c8287 (Russell King       2019-06-04 14:50:24 +0100  98) 	switch (adfs_filetype(ADFS_I(inode)->loadaddr)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  99) 	case 0xfc0:	/* LinkFS */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 100) 		return S_IFLNK|S_IRWXUGO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 101) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 102) 	case 0xfe6:	/* UnixExec */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 103) 		rmask = S_IRUGO | S_IXUGO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 104) 		break;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 105) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 106) 	default:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 107) 		rmask = S_IRUGO;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 108) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 109) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 110) 	mode = S_IFREG;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 111) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 112) 	if (attr & ADFS_NDA_OWNER_READ)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 113) 		mode |= rmask & asb->s_owner_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 114) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 115) 	if (attr & ADFS_NDA_OWNER_WRITE)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 116) 		mode |= S_IWUGO & asb->s_owner_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 117) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 118) 	if (attr & ADFS_NDA_PUBLIC_READ)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 119) 		mode |= rmask & asb->s_other_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 120) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 121) 	if (attr & ADFS_NDA_PUBLIC_WRITE)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 122) 		mode |= S_IWUGO & asb->s_other_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 123) 	return mode;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 124) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 125) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 126) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 127)  * Convert Linux permission to ADFS attribute.  We try to do the reverse
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 128)  * of atts2mode, but there is not a 1:1 translation.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 129)  */
81916245ce231 (Russell King       2019-12-09 11:08:23 +0000 130) static int adfs_mode2atts(struct super_block *sb, struct inode *inode,
81916245ce231 (Russell King       2019-12-09 11:08:23 +0000 131) 			  umode_t ia_mode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 132) {
81916245ce231 (Russell King       2019-12-09 11:08:23 +0000 133) 	struct adfs_sb_info *asb = ADFS_SB(sb);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 134) 	umode_t mode;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 135) 	int attr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 136) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 137) 	/* FIXME: should we be able to alter a link? */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 138) 	if (S_ISLNK(inode->i_mode))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 139) 		return ADFS_I(inode)->attr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 140) 
81916245ce231 (Russell King       2019-12-09 11:08:23 +0000 141) 	/* Directories do not have read/write permissions on the media */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 142) 	if (S_ISDIR(inode->i_mode))
81916245ce231 (Russell King       2019-12-09 11:08:23 +0000 143) 		return ADFS_NDA_DIRECTORY;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 144) 
81916245ce231 (Russell King       2019-12-09 11:08:23 +0000 145) 	attr = 0;
81916245ce231 (Russell King       2019-12-09 11:08:23 +0000 146) 	mode = ia_mode & asb->s_owner_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 147) 	if (mode & S_IRUGO)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 148) 		attr |= ADFS_NDA_OWNER_READ;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 149) 	if (mode & S_IWUGO)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 150) 		attr |= ADFS_NDA_OWNER_WRITE;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 151) 
81916245ce231 (Russell King       2019-12-09 11:08:23 +0000 152) 	mode = ia_mode & asb->s_other_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 153) 	mode &= ~asb->s_owner_mask;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 154) 	if (mode & S_IRUGO)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 155) 		attr |= ADFS_NDA_PUBLIC_READ;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 156) 	if (mode & S_IWUGO)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 157) 		attr |= ADFS_NDA_PUBLIC_WRITE;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 158) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 159) 	return attr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 160) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 161) 
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 162) static const s64 nsec_unix_epoch_diff_risc_os_epoch = 2208988800000000000LL;
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 163) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 164) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 165)  * Convert an ADFS time to Unix time.  ADFS has a 40-bit centi-second time
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 166)  * referenced to 1 Jan 1900 (til 2248) so we need to discard 2208988800 seconds
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 167)  * of time to convert from RISC OS epoch to Unix epoch.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 168)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 169) static void
d9edcbc42c77b (Arnd Bergmann      2018-08-21 22:01:09 -0700 170) adfs_adfs2unix_time(struct timespec64 *tv, struct inode *inode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 171) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 172) 	unsigned int high, low;
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 173) 	/* 01 Jan 1970 00:00:00 (Unix epoch) as nanoseconds since
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 174) 	 * 01 Jan 1900 00:00:00 (RISC OS epoch)
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 175) 	 */
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 176) 	s64 nsec;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 177) 
b4ed8f75c8287 (Russell King       2019-06-04 14:50:24 +0100 178) 	if (!adfs_inode_is_stamped(inode))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 179) 		goto cur_time;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 180) 
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 181) 	high = ADFS_I(inode)->loadaddr & 0xFF; /* top 8 bits of timestamp */
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 182) 	low  = ADFS_I(inode)->execaddr;    /* bottom 32 bits of timestamp */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 183) 
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 184) 	/* convert 40-bit centi-seconds to 32-bit seconds
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 185) 	 * going via nanoseconds to retain precision
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 186) 	 */
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 187) 	nsec = (((s64) high << 32) | (s64) low) * 10000000; /* cs to ns */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 188) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 189) 	/* Files dated pre  01 Jan 1970 00:00:00. */
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 190) 	if (nsec < nsec_unix_epoch_diff_risc_os_epoch)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 191) 		goto too_early;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 192) 
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 193) 	/* convert from RISC OS to Unix epoch */
7a9730af9c596 (Stuart Swales      2011-03-22 16:35:05 -0700 194) 	nsec -= nsec_unix_epoch_diff_risc_os_epoch;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 195) 
d9edcbc42c77b (Arnd Bergmann      2018-08-21 22:01:09 -0700 196) 	*tv = ns_to_timespec64(nsec);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 197) 	return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 198) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 199)  cur_time:
d9edcbc42c77b (Arnd Bergmann      2018-08-21 22:01:09 -0700 200) 	*tv = current_time(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 201) 	return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 202) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 203)  too_early:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 204) 	tv->tv_sec = tv->tv_nsec = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 205) 	return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 206) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 207) 
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 208) /* Convert an Unix time to ADFS time for an entry that is already stamped. */
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 209) static void adfs_unix2adfs_time(struct inode *inode,
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 210) 				const struct timespec64 *ts)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 211) {
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 212) 	s64 cs, nsec = timespec64_to_ns(ts);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 213) 
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 214) 	/* convert from Unix to RISC OS epoch */
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 215) 	nsec += nsec_unix_epoch_diff_risc_os_epoch;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 216) 
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 217) 	/* convert from nanoseconds to centiseconds */
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 218) 	cs = div_s64(nsec, 10000000);
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 219) 
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 220) 	cs = clamp_t(s64, cs, 0, 0xffffffffff);
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 221) 
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 222) 	ADFS_I(inode)->loadaddr &= ~0xff;
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 223) 	ADFS_I(inode)->loadaddr |= (cs >> 32) & 0xff;
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 224) 	ADFS_I(inode)->execaddr = cs;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 225) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 226) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 227) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 228)  * Fill in the inode information from the object information.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 229)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 230)  * Note that this is an inode-less filesystem, so we can't use the inode
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 231)  * number to reference the metadata on the media.  Instead, we use the
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 232)  * inode number to hold the object ID, which in turn will tell us where
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 233)  * the data is held.  We also save the parent object ID, and with these
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 234)  * two, we can locate the metadata.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 235)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 236)  * This does mean that we rely on an objects parent remaining the same at
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 237)  * all times - we cannot cope with a cross-directory rename (yet).
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 238)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 239) struct inode *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 240) adfs_iget(struct super_block *sb, struct object_info *obj)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 241) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 242) 	struct inode *inode;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 243) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 244) 	inode = new_inode(sb);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 245) 	if (!inode)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 246) 		goto out;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 247) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 248) 	inode->i_uid	 = ADFS_SB(sb)->s_uid;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 249) 	inode->i_gid	 = ADFS_SB(sb)->s_gid;
5ed70bb47767d (Russell King       2019-06-04 14:49:57 +0100 250) 	inode->i_ino	 = obj->indaddr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 251) 	inode->i_size	 = obj->size;
bfe8684869601 (Miklos Szeredi     2011-10-28 14:13:29 +0200 252) 	set_nlink(inode, 2);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 253) 	inode->i_blocks	 = (inode->i_size + sb->s_blocksize - 1) >>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 254) 			    sb->s_blocksize_bits;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 255) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 256) 	/*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 257) 	 * we need to save the parent directory ID so that
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 258) 	 * write_inode can update the directory information
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 259) 	 * for this file.  This will need special handling
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 260) 	 * for cross-directory renames.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 261) 	 */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 262) 	ADFS_I(inode)->parent_id = obj->parent_id;
25e5d4df3b46a (Russell King       2019-12-09 11:11:38 +0000 263) 	ADFS_I(inode)->indaddr   = obj->indaddr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 264) 	ADFS_I(inode)->loadaddr  = obj->loadaddr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 265) 	ADFS_I(inode)->execaddr  = obj->execaddr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 266) 	ADFS_I(inode)->attr      = obj->attr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 267) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 268) 	inode->i_mode	 = adfs_atts2mode(sb, inode);
d9edcbc42c77b (Arnd Bergmann      2018-08-21 22:01:09 -0700 269) 	adfs_adfs2unix_time(&inode->i_mtime, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 270) 	inode->i_atime = inode->i_mtime;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 271) 	inode->i_ctime = inode->i_mtime;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 272) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 273) 	if (S_ISDIR(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 274) 		inode->i_op	= &adfs_dir_inode_operations;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 275) 		inode->i_fop	= &adfs_dir_operations;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 276) 	} else if (S_ISREG(inode->i_mode)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 277) 		inode->i_op	= &adfs_file_inode_operations;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 278) 		inode->i_fop	= &adfs_file_operations;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 279) 		inode->i_mapping->a_ops = &adfs_aops;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 280) 		ADFS_I(inode)->mmu_private = inode->i_size;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 281) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 282) 
d8e78da868202 (Al Viro            2018-06-30 03:15:49 -0400 283) 	inode_fake_hash(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 284) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 285) out:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 286) 	return inode;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 287) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 288) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 289) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 290)  * Validate and convert a changed access mode/time to their ADFS equivalents.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 291)  * adfs_write_inode will actually write the information back to the directory
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 292)  * later.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 293)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 294) int
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 295) adfs_notify_change(struct user_namespace *mnt_userns, struct dentry *dentry,
549c7297717c3 (Christian Brauner  2021-01-21 14:19:43 +0100 296) 		   struct iattr *attr)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 297) {
2b0143b5c986b (David Howells      2015-03-17 22:25:59 +0000 298) 	struct inode *inode = d_inode(dentry);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 299) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 300) 	unsigned int ia_valid = attr->ia_valid;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 301) 	int error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 302) 	
2f221d6f7b881 (Christian Brauner  2021-01-21 14:19:26 +0100 303) 	error = setattr_prepare(&init_user_ns, dentry, attr);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 304) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 305) 	/*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 306) 	 * we can't change the UID or GID of any file -
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 307) 	 * we have a global UID/GID in the superblock
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 308) 	 */
c010d1ff4f69c (Eric W. Biederman  2012-02-07 15:58:38 -0800 309) 	if ((ia_valid & ATTR_UID && !uid_eq(attr->ia_uid, ADFS_SB(sb)->s_uid)) ||
c010d1ff4f69c (Eric W. Biederman  2012-02-07 15:58:38 -0800 310) 	    (ia_valid & ATTR_GID && !gid_eq(attr->ia_gid, ADFS_SB(sb)->s_gid)))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 311) 		error = -EPERM;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 312) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 313) 	if (error)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 314) 		goto out;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 315) 
15c6fd9786dfa (Nicholas Piggin    2010-05-27 01:05:34 +1000 316) 	/* XXX: this is missing some actual on-disk truncation.. */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 317) 	if (ia_valid & ATTR_SIZE)
2c27c65ed0696 (Christoph Hellwig  2010-06-04 11:30:04 +0200 318) 		truncate_setsize(inode, attr->ia_size);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 319) 
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 320) 	if (ia_valid & ATTR_MTIME && adfs_inode_is_stamped(inode)) {
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 321) 		adfs_unix2adfs_time(inode, &attr->ia_mtime);
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 322) 		adfs_adfs2unix_time(&inode->i_mtime, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 323) 	}
eeeb9dd98ec35 (Russell King       2019-12-09 11:08:18 +0000 324) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 325) 	/*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 326) 	 * FIXME: should we make these == to i_mtime since we don't
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 327) 	 * have the ability to represent them in our filesystem?
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 328) 	 */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 329) 	if (ia_valid & ATTR_ATIME)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 330) 		inode->i_atime = attr->ia_atime;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 331) 	if (ia_valid & ATTR_CTIME)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 332) 		inode->i_ctime = attr->ia_ctime;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 333) 	if (ia_valid & ATTR_MODE) {
81916245ce231 (Russell King       2019-12-09 11:08:23 +0000 334) 		ADFS_I(inode)->attr = adfs_mode2atts(sb, inode, attr->ia_mode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 335) 		inode->i_mode = adfs_atts2mode(sb, inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 336) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 337) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 338) 	/*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 339) 	 * FIXME: should we be marking this inode dirty even if
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 340) 	 * we don't have any metadata to write back?
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 341) 	 */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 342) 	if (ia_valid & (ATTR_SIZE | ATTR_MTIME | ATTR_MODE))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 343) 		mark_inode_dirty(inode);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 344) out:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 345) 	return error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 346) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 347) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 348) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 349)  * write an existing inode back to the directory, and therefore the disk.
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 350)  * The adfs-specific inode data has already been updated by
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 351)  * adfs_notify_change()
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 352)  */
a9185b41a4f84 (Christoph Hellwig  2010-03-05 09:21:37 +0100 353) int adfs_write_inode(struct inode *inode, struct writeback_control *wbc)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 354) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 355) 	struct super_block *sb = inode->i_sb;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 356) 	struct object_info obj;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 357) 	int ret;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 358) 
25e5d4df3b46a (Russell King       2019-12-09 11:11:38 +0000 359) 	obj.indaddr	= ADFS_I(inode)->indaddr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 360) 	obj.name_len	= 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 361) 	obj.parent_id	= ADFS_I(inode)->parent_id;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 362) 	obj.loadaddr	= ADFS_I(inode)->loadaddr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 363) 	obj.execaddr	= ADFS_I(inode)->execaddr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 364) 	obj.attr	= ADFS_I(inode)->attr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 365) 	obj.size	= inode->i_size;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 366) 
a9185b41a4f84 (Christoph Hellwig  2010-03-05 09:21:37 +0100 367) 	ret = adfs_dir_update(sb, &obj, wbc->sync_mode == WB_SYNC_ALL);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 368) 	return ret;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 369) }