| .. | .. | 
|---|
| 45 | 45 |  | 
|---|
| 46 | 46 | #define EXTENT_MERGE_SIZE 5 | 
|---|
| 47 | 47 |  | 
|---|
|  | 48 | +#define FE_MAPPED_PERMS	(FE_PERM_U_READ | FE_PERM_U_WRITE | FE_PERM_U_EXEC | \ | 
|---|
|  | 49 | +			 FE_PERM_G_READ | FE_PERM_G_WRITE | FE_PERM_G_EXEC | \ | 
|---|
|  | 50 | +			 FE_PERM_O_READ | FE_PERM_O_WRITE | FE_PERM_O_EXEC) | 
|---|
|  | 51 | + | 
|---|
|  | 52 | +#define FE_DELETE_PERMS	(FE_PERM_U_DELETE | FE_PERM_G_DELETE | \ | 
|---|
|  | 53 | +			 FE_PERM_O_DELETE) | 
|---|
|  | 54 | + | 
|---|
| 48 | 55 | static umode_t udf_convert_permissions(struct fileEntry *); | 
|---|
| 49 | 56 | static int udf_update_inode(struct inode *, int); | 
|---|
| 50 | 57 | static int udf_sync_inode(struct inode *inode); | 
|---|
| .. | .. | 
|---|
| 150 | 157 | truncate_inode_pages_final(&inode->i_data); | 
|---|
| 151 | 158 | invalidate_inode_buffers(inode); | 
|---|
| 152 | 159 | clear_inode(inode); | 
|---|
| 153 |  | -	kfree(iinfo->i_ext.i_data); | 
|---|
| 154 |  | -	iinfo->i_ext.i_data = NULL; | 
|---|
|  | 160 | +	kfree(iinfo->i_data); | 
|---|
|  | 161 | +	iinfo->i_data = NULL; | 
|---|
| 155 | 162 | udf_clear_extent_cache(inode); | 
|---|
| 156 | 163 | if (want_delete) { | 
|---|
| 157 | 164 | udf_free_inode(inode); | 
|---|
| .. | .. | 
|---|
| 191 | 198 | return mpage_readpage(page, udf_get_block); | 
|---|
| 192 | 199 | } | 
|---|
| 193 | 200 |  | 
|---|
| 194 |  | -static int udf_readpages(struct file *file, struct address_space *mapping, | 
|---|
| 195 |  | -			struct list_head *pages, unsigned nr_pages) | 
|---|
|  | 201 | +static void udf_readahead(struct readahead_control *rac) | 
|---|
| 196 | 202 | { | 
|---|
| 197 |  | -	return mpage_readpages(mapping, pages, nr_pages, udf_get_block); | 
|---|
|  | 203 | +	mpage_readahead(rac, udf_get_block); | 
|---|
| 198 | 204 | } | 
|---|
| 199 | 205 |  | 
|---|
| 200 | 206 | static int udf_write_begin(struct file *file, struct address_space *mapping, | 
|---|
| .. | .. | 
|---|
| 230 | 236 |  | 
|---|
| 231 | 237 | const struct address_space_operations udf_aops = { | 
|---|
| 232 | 238 | .readpage	= udf_readpage, | 
|---|
| 233 |  | -	.readpages	= udf_readpages, | 
|---|
|  | 239 | +	.readahead	= udf_readahead, | 
|---|
| 234 | 240 | .writepage	= udf_writepage, | 
|---|
| 235 | 241 | .writepages	= udf_writepages, | 
|---|
| 236 | 242 | .write_begin	= udf_write_begin, | 
|---|
| .. | .. | 
|---|
| 278 | 284 | kaddr = kmap_atomic(page); | 
|---|
| 279 | 285 | memset(kaddr + iinfo->i_lenAlloc, 0x00, | 
|---|
| 280 | 286 | PAGE_SIZE - iinfo->i_lenAlloc); | 
|---|
| 281 |  | -		memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, | 
|---|
|  | 287 | +		memcpy(kaddr, iinfo->i_data + iinfo->i_lenEAttr, | 
|---|
| 282 | 288 | iinfo->i_lenAlloc); | 
|---|
| 283 | 289 | flush_dcache_page(page); | 
|---|
| 284 | 290 | SetPageUptodate(page); | 
|---|
| 285 | 291 | kunmap_atomic(kaddr); | 
|---|
| 286 | 292 | } | 
|---|
| 287 | 293 | down_write(&iinfo->i_data_sem); | 
|---|
| 288 |  | -	memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0x00, | 
|---|
|  | 294 | +	memset(iinfo->i_data + iinfo->i_lenEAttr, 0x00, | 
|---|
| 289 | 295 | iinfo->i_lenAlloc); | 
|---|
| 290 | 296 | iinfo->i_lenAlloc = 0; | 
|---|
| 291 | 297 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) | 
|---|
| .. | .. | 
|---|
| 303 | 309 | lock_page(page); | 
|---|
| 304 | 310 | down_write(&iinfo->i_data_sem); | 
|---|
| 305 | 311 | kaddr = kmap_atomic(page); | 
|---|
| 306 |  | -		memcpy(iinfo->i_ext.i_data + iinfo->i_lenEAttr, kaddr, | 
|---|
| 307 |  | -		       inode->i_size); | 
|---|
|  | 312 | +		memcpy(iinfo->i_data + iinfo->i_lenEAttr, kaddr, inode->i_size); | 
|---|
| 308 | 313 | kunmap_atomic(kaddr); | 
|---|
| 309 | 314 | unlock_page(page); | 
|---|
| 310 | 315 | iinfo->i_alloc_type = ICBTAG_FLAG_AD_IN_ICB; | 
|---|
| .. | .. | 
|---|
| 392 | 397 | } | 
|---|
| 393 | 398 | mark_buffer_dirty_inode(dbh, inode); | 
|---|
| 394 | 399 |  | 
|---|
| 395 |  | -	memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr, 0, | 
|---|
| 396 |  | -		iinfo->i_lenAlloc); | 
|---|
|  | 400 | +	memset(iinfo->i_data + iinfo->i_lenEAttr, 0, iinfo->i_lenAlloc); | 
|---|
| 397 | 401 | iinfo->i_lenAlloc = 0; | 
|---|
| 398 | 402 | eloc.logicalBlockNum = *block; | 
|---|
| 399 | 403 | eloc.partitionReferenceNum = | 
|---|
| .. | .. | 
|---|
| 1259 | 1263 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { | 
|---|
| 1260 | 1264 | down_write(&iinfo->i_data_sem); | 
|---|
| 1261 | 1265 | udf_clear_extent_cache(inode); | 
|---|
| 1262 |  | -			memset(iinfo->i_ext.i_data + iinfo->i_lenEAttr + newsize, | 
|---|
|  | 1266 | +			memset(iinfo->i_data + iinfo->i_lenEAttr + newsize, | 
|---|
| 1263 | 1267 | 0x00, bsize - newsize - | 
|---|
| 1264 | 1268 | udf_file_entry_alloc_offset(inode)); | 
|---|
| 1265 | 1269 | iinfo->i_lenAlloc = newsize; | 
|---|
| .. | .. | 
|---|
| 1274 | 1278 | truncate_setsize(inode, newsize); | 
|---|
| 1275 | 1279 | down_write(&iinfo->i_data_sem); | 
|---|
| 1276 | 1280 | udf_clear_extent_cache(inode); | 
|---|
| 1277 |  | -		udf_truncate_extents(inode); | 
|---|
|  | 1281 | +		err = udf_truncate_extents(inode); | 
|---|
| 1278 | 1282 | up_write(&iinfo->i_data_sem); | 
|---|
|  | 1283 | +		if (err) | 
|---|
|  | 1284 | +			return err; | 
|---|
| 1279 | 1285 | } | 
|---|
| 1280 | 1286 | update_time: | 
|---|
| 1281 | 1287 | inode->i_mtime = inode->i_ctime = current_time(inode); | 
|---|
| .. | .. | 
|---|
| 1408 | 1414 | sizeof(struct extendedFileEntry)); | 
|---|
| 1409 | 1415 | if (ret) | 
|---|
| 1410 | 1416 | goto out; | 
|---|
| 1411 |  | -		memcpy(iinfo->i_ext.i_data, | 
|---|
|  | 1417 | +		memcpy(iinfo->i_data, | 
|---|
| 1412 | 1418 | bh->b_data + sizeof(struct extendedFileEntry), | 
|---|
| 1413 | 1419 | bs - sizeof(struct extendedFileEntry)); | 
|---|
| 1414 | 1420 | } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_FE)) { | 
|---|
| .. | .. | 
|---|
| 1417 | 1423 | ret = udf_alloc_i_data(inode, bs - sizeof(struct fileEntry)); | 
|---|
| 1418 | 1424 | if (ret) | 
|---|
| 1419 | 1425 | goto out; | 
|---|
| 1420 |  | -		memcpy(iinfo->i_ext.i_data, | 
|---|
|  | 1426 | +		memcpy(iinfo->i_data, | 
|---|
| 1421 | 1427 | bh->b_data + sizeof(struct fileEntry), | 
|---|
| 1422 | 1428 | bs - sizeof(struct fileEntry)); | 
|---|
| 1423 | 1429 | } else if (fe->descTag.tagIdent == cpu_to_le16(TAG_IDENT_USE)) { | 
|---|
| .. | .. | 
|---|
| 1430 | 1436 | sizeof(struct unallocSpaceEntry)); | 
|---|
| 1431 | 1437 | if (ret) | 
|---|
| 1432 | 1438 | goto out; | 
|---|
| 1433 |  | -		memcpy(iinfo->i_ext.i_data, | 
|---|
|  | 1439 | +		memcpy(iinfo->i_data, | 
|---|
| 1434 | 1440 | bh->b_data + sizeof(struct unallocSpaceEntry), | 
|---|
| 1435 | 1441 | bs - sizeof(struct unallocSpaceEntry)); | 
|---|
| 1436 | 1442 | return 0; | 
|---|
| .. | .. | 
|---|
| 1461 | 1467 | else | 
|---|
| 1462 | 1468 | inode->i_mode = udf_convert_permissions(fe); | 
|---|
| 1463 | 1469 | inode->i_mode &= ~sbi->s_umask; | 
|---|
|  | 1470 | +	iinfo->i_extraPerms = le32_to_cpu(fe->permissions) & ~FE_MAPPED_PERMS; | 
|---|
|  | 1471 | + | 
|---|
| 1464 | 1472 | read_unlock(&sbi->s_cred_lock); | 
|---|
| 1465 | 1473 |  | 
|---|
| 1466 | 1474 | link_count = le16_to_cpu(fe->fileLinkCount); | 
|---|
| .. | .. | 
|---|
| 1488 | 1496 | iinfo->i_lenEAttr = le32_to_cpu(fe->lengthExtendedAttr); | 
|---|
| 1489 | 1497 | iinfo->i_lenAlloc = le32_to_cpu(fe->lengthAllocDescs); | 
|---|
| 1490 | 1498 | iinfo->i_checkpoint = le32_to_cpu(fe->checkpoint); | 
|---|
|  | 1499 | +		iinfo->i_streamdir = 0; | 
|---|
|  | 1500 | +		iinfo->i_lenStreams = 0; | 
|---|
| 1491 | 1501 | } else { | 
|---|
| 1492 | 1502 | inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << | 
|---|
| 1493 | 1503 | (inode->i_sb->s_blocksize_bits - 9); | 
|---|
| .. | .. | 
|---|
| 1501 | 1511 | iinfo->i_lenEAttr = le32_to_cpu(efe->lengthExtendedAttr); | 
|---|
| 1502 | 1512 | iinfo->i_lenAlloc = le32_to_cpu(efe->lengthAllocDescs); | 
|---|
| 1503 | 1513 | iinfo->i_checkpoint = le32_to_cpu(efe->checkpoint); | 
|---|
|  | 1514 | + | 
|---|
|  | 1515 | +		/* Named streams */ | 
|---|
|  | 1516 | +		iinfo->i_streamdir = (efe->streamDirectoryICB.extLength != 0); | 
|---|
|  | 1517 | +		iinfo->i_locStreamdir = | 
|---|
|  | 1518 | +			lelb_to_cpu(efe->streamDirectoryICB.extLocation); | 
|---|
|  | 1519 | +		iinfo->i_lenStreams = le64_to_cpu(efe->objectSize); | 
|---|
|  | 1520 | +		if (iinfo->i_lenStreams >= inode->i_size) | 
|---|
|  | 1521 | +			iinfo->i_lenStreams -= inode->i_size; | 
|---|
|  | 1522 | +		else | 
|---|
|  | 1523 | +			iinfo->i_lenStreams = 0; | 
|---|
| 1504 | 1524 | } | 
|---|
| 1505 | 1525 | inode->i_generation = iinfo->i_unique; | 
|---|
| 1506 | 1526 |  | 
|---|
| .. | .. | 
|---|
| 1597 | 1617 | static int udf_alloc_i_data(struct inode *inode, size_t size) | 
|---|
| 1598 | 1618 | { | 
|---|
| 1599 | 1619 | struct udf_inode_info *iinfo = UDF_I(inode); | 
|---|
| 1600 |  | -	iinfo->i_ext.i_data = kmalloc(size, GFP_KERNEL); | 
|---|
| 1601 |  | -	if (!iinfo->i_ext.i_data) | 
|---|
|  | 1620 | +	iinfo->i_data = kmalloc(size, GFP_KERNEL); | 
|---|
|  | 1621 | +	if (!iinfo->i_data) | 
|---|
| 1602 | 1622 | return -ENOMEM; | 
|---|
| 1603 | 1623 | return 0; | 
|---|
| 1604 | 1624 | } | 
|---|
| .. | .. | 
|---|
| 1620 | 1640 | ((flags & ICBTAG_FLAG_STICKY) ? S_ISVTX : 0); | 
|---|
| 1621 | 1641 |  | 
|---|
| 1622 | 1642 | return mode; | 
|---|
|  | 1643 | +} | 
|---|
|  | 1644 | + | 
|---|
|  | 1645 | +void udf_update_extra_perms(struct inode *inode, umode_t mode) | 
|---|
|  | 1646 | +{ | 
|---|
|  | 1647 | +	struct udf_inode_info *iinfo = UDF_I(inode); | 
|---|
|  | 1648 | + | 
|---|
|  | 1649 | +	/* | 
|---|
|  | 1650 | +	 * UDF 2.01 sec. 3.3.3.3 Note 2: | 
|---|
|  | 1651 | +	 * In Unix, delete permission tracks write | 
|---|
|  | 1652 | +	 */ | 
|---|
|  | 1653 | +	iinfo->i_extraPerms &= ~FE_DELETE_PERMS; | 
|---|
|  | 1654 | +	if (mode & 0200) | 
|---|
|  | 1655 | +		iinfo->i_extraPerms |= FE_PERM_U_DELETE; | 
|---|
|  | 1656 | +	if (mode & 0020) | 
|---|
|  | 1657 | +		iinfo->i_extraPerms |= FE_PERM_G_DELETE; | 
|---|
|  | 1658 | +	if (mode & 0002) | 
|---|
|  | 1659 | +		iinfo->i_extraPerms |= FE_PERM_O_DELETE; | 
|---|
| 1623 | 1660 | } | 
|---|
| 1624 | 1661 |  | 
|---|
| 1625 | 1662 | int udf_write_inode(struct inode *inode, struct writeback_control *wbc) | 
|---|
| .. | .. | 
|---|
| 1672 | 1709 |  | 
|---|
| 1673 | 1710 | use->lengthAllocDescs = cpu_to_le32(iinfo->i_lenAlloc); | 
|---|
| 1674 | 1711 | memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), | 
|---|
| 1675 |  | -		       iinfo->i_ext.i_data, inode->i_sb->s_blocksize - | 
|---|
|  | 1712 | +		       iinfo->i_data, inode->i_sb->s_blocksize - | 
|---|
| 1676 | 1713 | sizeof(struct unallocSpaceEntry)); | 
|---|
| 1677 | 1714 | use->descTag.tagIdent = cpu_to_le16(TAG_IDENT_USE); | 
|---|
| 1678 | 1715 | crclen = sizeof(struct unallocSpaceEntry); | 
|---|
| .. | .. | 
|---|
| 1694 | 1731 | ((inode->i_mode & 0070) << 2) | | 
|---|
| 1695 | 1732 | ((inode->i_mode & 0700) << 4); | 
|---|
| 1696 | 1733 |  | 
|---|
| 1697 |  | -	udfperms |= (le32_to_cpu(fe->permissions) & | 
|---|
| 1698 |  | -		    (FE_PERM_O_DELETE | FE_PERM_O_CHATTR | | 
|---|
| 1699 |  | -		     FE_PERM_G_DELETE | FE_PERM_G_CHATTR | | 
|---|
| 1700 |  | -		     FE_PERM_U_DELETE | FE_PERM_U_CHATTR)); | 
|---|
|  | 1734 | +	udfperms |= iinfo->i_extraPerms; | 
|---|
| 1701 | 1735 | fe->permissions = cpu_to_le32(udfperms); | 
|---|
| 1702 | 1736 |  | 
|---|
| 1703 | 1737 | if (S_ISDIR(inode->i_mode) && inode->i_nlink > 0) | 
|---|
| .. | .. | 
|---|
| 1741 | 1775 |  | 
|---|
| 1742 | 1776 | if (iinfo->i_efe == 0) { | 
|---|
| 1743 | 1777 | memcpy(bh->b_data + sizeof(struct fileEntry), | 
|---|
| 1744 |  | -		       iinfo->i_ext.i_data, | 
|---|
|  | 1778 | +		       iinfo->i_data, | 
|---|
| 1745 | 1779 | inode->i_sb->s_blocksize - sizeof(struct fileEntry)); | 
|---|
| 1746 | 1780 | fe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); | 
|---|
| 1747 | 1781 |  | 
|---|
| .. | .. | 
|---|
| 1760 | 1794 | crclen = sizeof(struct fileEntry); | 
|---|
| 1761 | 1795 | } else { | 
|---|
| 1762 | 1796 | memcpy(bh->b_data + sizeof(struct extendedFileEntry), | 
|---|
| 1763 |  | -		       iinfo->i_ext.i_data, | 
|---|
|  | 1797 | +		       iinfo->i_data, | 
|---|
| 1764 | 1798 | inode->i_sb->s_blocksize - | 
|---|
| 1765 | 1799 | sizeof(struct extendedFileEntry)); | 
|---|
| 1766 |  | -		efe->objectSize = cpu_to_le64(inode->i_size); | 
|---|
|  | 1800 | +		efe->objectSize = | 
|---|
|  | 1801 | +			cpu_to_le64(inode->i_size + iinfo->i_lenStreams); | 
|---|
| 1767 | 1802 | efe->logicalBlocksRecorded = cpu_to_le64(lb_recorded); | 
|---|
|  | 1803 | + | 
|---|
|  | 1804 | +		if (iinfo->i_streamdir) { | 
|---|
|  | 1805 | +			struct long_ad *icb_lad = &efe->streamDirectoryICB; | 
|---|
|  | 1806 | + | 
|---|
|  | 1807 | +			icb_lad->extLocation = | 
|---|
|  | 1808 | +				cpu_to_lelb(iinfo->i_locStreamdir); | 
|---|
|  | 1809 | +			icb_lad->extLength = | 
|---|
|  | 1810 | +				cpu_to_le32(inode->i_sb->s_blocksize); | 
|---|
|  | 1811 | +		} | 
|---|
| 1768 | 1812 |  | 
|---|
| 1769 | 1813 | udf_adjust_time(iinfo, inode->i_atime); | 
|---|
| 1770 | 1814 | udf_adjust_time(iinfo, inode->i_mtime); | 
|---|
| .. | .. | 
|---|
| 1939 | 1983 |  | 
|---|
| 1940 | 1984 | __udf_add_aext(inode, &nepos, &cp_loc, cp_len, 1); | 
|---|
| 1941 | 1985 | udf_write_aext(inode, epos, &nepos.block, | 
|---|
| 1942 |  | -			       sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDECS, 0); | 
|---|
|  | 1986 | +			       sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDESCS, 0); | 
|---|
| 1943 | 1987 | } else { | 
|---|
| 1944 | 1988 | __udf_add_aext(inode, epos, &nepos.block, | 
|---|
| 1945 |  | -			       sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDECS, 0); | 
|---|
|  | 1989 | +			       sb->s_blocksize | EXT_NEXT_EXTENT_ALLOCDESCS, 0); | 
|---|
| 1946 | 1990 | } | 
|---|
| 1947 | 1991 |  | 
|---|
| 1948 | 1992 | brelse(epos->bh); | 
|---|
| .. | .. | 
|---|
| 2046 | 2090 | struct udf_inode_info *iinfo = UDF_I(inode); | 
|---|
| 2047 | 2091 |  | 
|---|
| 2048 | 2092 | if (!epos->bh) | 
|---|
| 2049 |  | -		ptr = iinfo->i_ext.i_data + epos->offset - | 
|---|
|  | 2093 | +		ptr = iinfo->i_data + epos->offset - | 
|---|
| 2050 | 2094 | udf_file_entry_alloc_offset(inode) + | 
|---|
| 2051 | 2095 | iinfo->i_lenEAttr; | 
|---|
| 2052 | 2096 | else | 
|---|
| .. | .. | 
|---|
| 2101 | 2145 | unsigned int indirections = 0; | 
|---|
| 2102 | 2146 |  | 
|---|
| 2103 | 2147 | while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) == | 
|---|
| 2104 |  | -	       (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { | 
|---|
|  | 2148 | +	       (EXT_NEXT_EXTENT_ALLOCDESCS >> 30)) { | 
|---|
| 2105 | 2149 | udf_pblk_t block; | 
|---|
| 2106 | 2150 |  | 
|---|
| 2107 | 2151 | if (++indirections > UDF_MAX_INDIR_EXTS) { | 
|---|
| .. | .. | 
|---|
| 2138 | 2182 | if (!epos->bh) { | 
|---|
| 2139 | 2183 | if (!epos->offset) | 
|---|
| 2140 | 2184 | epos->offset = udf_file_entry_alloc_offset(inode); | 
|---|
| 2141 |  | -		ptr = iinfo->i_ext.i_data + epos->offset - | 
|---|
|  | 2185 | +		ptr = iinfo->i_data + epos->offset - | 
|---|
| 2142 | 2186 | udf_file_entry_alloc_offset(inode) + | 
|---|
| 2143 | 2187 | iinfo->i_lenEAttr; | 
|---|
| 2144 | 2188 | alen = udf_file_entry_alloc_offset(inode) + | 
|---|