Commit 0fc9e32a authored by Ben Fennema's avatar Ben Fennema Committed by Linus Torvalds

[PATCH] UDF sync with CVS

This patch updates udf to the CVS version:
  - removes UDF_RW
  - fixes a extraneous read after write which killed CDRW performance
  - fixes setting the session
  - fix a array index bug in udf_prealloc_extents
  - fix symlinks to correspond to the UDF spec
parent f2b38c55
......@@ -1037,15 +1037,12 @@ config SYSV_FS
If you haven't heard about all of this before, it's safe to say N.
config UDF_FS
tristate "UDF file system support (read only)"
tristate "UDF file system support"
---help---
This is the new file system used on some CD-ROMs and DVDs. Say Y if
you intend to mount DVD discs or CDRW's written in packet mode, or
if written to by other UDF utilities, such as DirectCD. This UDF
file system support is read-only. If you want to write to UDF
file systems on some media, you need to say Y to "UDF read-write
support" below in addition. Please read
<file:Documentation/filesystems/udf.txt>.
if written to by other UDF utilities, such as DirectCD.
Please read <file:Documentation/filesystems/udf.txt>.
This file system support is also available as a module ( = code
which can be inserted in and removed from the running kernel
......@@ -1055,14 +1052,6 @@ config UDF_FS
If unsure, say N.
config UDF_RW
bool "UDF write support (DANGEROUS)"
depends on UDF_FS && EXPERIMENTAL
help
Say Y if you want to test write support for UDF file systems.
Due to lack of support for writing to CDR/CDRW's, this option
is only supported for hard discs, DVD-RAM, and loopback files.
config UFS_FS
tristate "UFS file system support (read only)"
---help---
......
......@@ -461,8 +461,7 @@ static void udf_table_free_blocks(struct super_block * sb,
elen = 0;
obloc = nbloc = UDF_I_LOCATION(table);
obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0));
atomic_inc(&nbh->b_count);
obh = nbh = NULL;
while (count && (etype =
udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
......@@ -506,7 +505,7 @@ static void udf_table_free_blocks(struct super_block * sb,
udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
}
if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
if (nbh != obh)
{
i = -1;
obloc = nbloc;
......@@ -580,7 +579,10 @@ static void udf_table_free_blocks(struct super_block * sb,
{
loffset = nextoffset;
aed->lengthAllocDescs = cpu_to_le32(adsize);
sptr = (obh)->b_data + nextoffset - adsize;
if (obh)
sptr = UDF_I_DATA(inode) + nextoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode) - adsize;
else
sptr = obh->b_data + nextoffset - adsize;
dptr = nbh->b_data + sizeof(struct allocExtDesc);
memcpy(dptr, sptr, adsize);
nextoffset = sizeof(struct allocExtDesc) + adsize;
......@@ -592,7 +594,7 @@ static void udf_table_free_blocks(struct super_block * sb,
sptr = (obh)->b_data + nextoffset;
nextoffset = sizeof(struct allocExtDesc);
if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr)))
if (obh)
{
aed = (struct allocExtDesc *)(obh)->b_data;
aed->lengthAllocDescs =
......@@ -631,15 +633,20 @@ static void udf_table_free_blocks(struct super_block * sb,
break;
}
}
if (obh)
{
udf_update_tag(obh->b_data, loffset);
mark_buffer_dirty(obh);
}
else
mark_inode_dirty(table);
}
if (elen) /* It's possible that stealing the block emptied the extent */
{
udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1);
if (!memcmp(&UDF_I_LOCATION(table), &nbloc, sizeof(lb_addr)))
if (!nbh)
{
UDF_I_LENALLOC(table) += adsize;
mark_inode_dirty(table);
......@@ -690,7 +697,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
extoffset = sizeof(struct unallocSpaceEntry);
bloc = UDF_I_LOCATION(table);
bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
bh = NULL;
eloc.logicalBlockNum = 0xFFFFFFFF;
while (first_block != eloc.logicalBlockNum && (etype =
......@@ -768,8 +775,7 @@ static int udf_table_new_block(struct super_block * sb,
extoffset = sizeof(struct unallocSpaceEntry);
bloc = UDF_I_LOCATION(table);
goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0));
atomic_inc(&goal_bh->b_count);
goal_bh = bh = NULL;
while (spread && (etype =
udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
......
......@@ -89,7 +89,8 @@ int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
if ( filp->f_pos == 0 )
{
if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0) {
if (filldir(dirent, ".", 1, filp->f_pos, dir->i_ino, DT_DIR) < 0)
{
unlock_kernel();
return 0;
}
......@@ -129,7 +130,9 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
nf_pos = (udf_ext0_offset(dir) >> 2);
fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
fibh.sbh = fibh.ebh = NULL;
else if (inode_bmap(dir, nf_pos >> (dir->i_sb->s_blocksize_bits - 2),
&bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
{
offset >>= dir->i_sb->s_blocksize_bits;
......@@ -143,12 +146,6 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
}
else
offset = 0;
}
else
{
udf_release_data(bh);
return -ENOENT;
}
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
{
......@@ -177,6 +174,12 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
brelse(bha[i]);
}
}
}
else
{
udf_release_data(bh);
return -ENOENT;
}
while ( nf_pos < size )
{
......
......@@ -17,6 +17,7 @@
*/
#include "udfdecl.h"
#include "udf_i.h"
#include <linux/fs.h>
#include <linux/string.h>
......@@ -85,6 +86,24 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
fibh->soffset = fibh->eoffset;
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
{
fi = udf_get_fileident(UDF_I_DATA(dir) -
(UDF_I_EFE(dir) ?
sizeof(struct extendedFileEntry) :
sizeof(struct fileEntry)),
dir->i_sb->s_blocksize, &(fibh->eoffset));
if (!fi)
return NULL;
*nf_pos += ((fibh->eoffset - fibh->soffset) >> 2);
memcpy((uint8_t *)cfi, (uint8_t *)fi, sizeof(struct fileIdentDesc));
return fi;
}
if (fibh->eoffset == dir->i_sb->s_blocksize)
{
int lextoffset = *extoffset;
......@@ -276,53 +295,43 @@ udf_get_fileextent(void * buffer, int bufsize, int * offset)
}
short_ad *
udf_get_fileshortad(void * buffer, int maxoffset, int *offset, int inc)
udf_get_fileshortad(uint8_t *ptr, int maxoffset, int *offset, int inc)
{
short_ad * sa;
uint8_t * ptr;
short_ad *sa;
if ( (!buffer) || (!offset) )
if ( (!ptr) || (!offset) )
{
printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
return NULL;
}
ptr = (uint8_t *)buffer;
if ( (*offset > 0) && (*offset < maxoffset) )
ptr += *offset;
else
if ( (*offset < 0) || ((*offset + sizeof(short_ad)) > maxoffset) )
return NULL;
if ((sa = (short_ad *)ptr)->extLength == 0)
else if ((sa = (short_ad *)ptr)->extLength == 0)
return NULL;
else if (inc)
(*offset) += sizeof(short_ad);
if (inc)
*offset += sizeof(short_ad);
return sa;
}
long_ad *
udf_get_filelongad(void * buffer, int maxoffset, int * offset, int inc)
udf_get_filelongad(uint8_t *ptr, int maxoffset, int * offset, int inc)
{
long_ad * la;
uint8_t * ptr;
long_ad *la;
if ( (!buffer) || !(offset) )
if ( (!ptr) || (!offset) )
{
printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
return NULL;
}
ptr = (uint8_t *)buffer;
if ( (*offset > 0) && (*offset < maxoffset) )
ptr += *offset;
else
if ( (*offset < 0) || ((*offset + sizeof(long_ad)) > maxoffset) )
return NULL;
if ((la = (long_ad *)ptr)->extLength == 0)
else if ((la = (long_ad *)ptr)->extLength == 0)
return NULL;
else if (inc)
(*offset) += sizeof(long_ad);
if (inc)
*offset += sizeof(long_ad);
return la;
}
......@@ -47,64 +47,36 @@
static int udf_adinicb_readpage(struct file *file, struct page * page)
{
struct inode *inode = page->mapping->host;
struct buffer_head *bh;
int block;
char *kaddr;
int err = 0;
if (!PageLocked(page))
PAGE_BUG(page);
kaddr = kmap(page);
memset(kaddr, 0, PAGE_CACHE_SIZE);
block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
bh = sb_bread(inode->i_sb, block);
if (!bh)
{
SetPageError(page);
err = -EIO;
goto out;
}
memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size);
brelse(bh);
memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), inode->i_size);
flush_dcache_page(page);
SetPageUptodate(page);
out:
kunmap(page);
unlock_page(page);
return err;
return 0;
}
static int udf_adinicb_writepage(struct page *page)
{
struct inode *inode = page->mapping->host;
struct buffer_head *bh;
int block;
char *kaddr;
int err = 0;
if (!PageLocked(page))
PAGE_BUG(page);
kaddr = kmap(page);
block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
bh = sb_bread(inode->i_sb, block);
if (!bh)
{
SetPageError(page);
err = -EIO;
goto out;
}
memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size);
mark_buffer_dirty(bh);
brelse(bh);
memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size);
mark_inode_dirty(inode);
SetPageUptodate(page);
out:
kunmap(page);
unlock_page(page);
return err;
return 0;
}
static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to)
......@@ -116,31 +88,17 @@ static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsig
static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
struct inode *inode = page->mapping->host;
struct buffer_head *bh;
int block;
char *kaddr = page_address(page);
int err = 0;
block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
bh = sb_bread(inode->i_sb, block);
if (!bh)
{
SetPageError(page);
err = -EIO;
goto out;
}
memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset,
kaddr + offset, to - offset);
mark_buffer_dirty(bh);
brelse(bh);
mark_inode_dirty(inode);
SetPageUptodate(page);
out:
kunmap(page);
/* only one page here */
if (to > inode->i_size)
inode->i_size = to;
return err;
return 0;
}
struct address_space_operations udf_adinicb_aops = {
......@@ -232,9 +190,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg)
{
int result = -EINVAL;
struct buffer_head *bh = NULL;
long_ad eaicb;
uint8_t *ea = NULL;
if ( permission(inode, MAY_READ) != 0 )
{
......@@ -249,7 +204,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return -EINVAL;
}
/* first, do ioctls that don't need to udf_read */
switch (cmd)
{
case UDF_GETVOLIDENT:
......@@ -267,50 +221,16 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return result;
}
}
/* ok, we need to read the inode */
bh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0));
if (!bh)
{
udf_debug("bread failed (inode=%ld)\n", inode->i_ino);
return -EIO;
}
if (UDF_I_EXTENDED_FE(inode) == 0)
{
struct fileEntry *fe;
fe = (struct fileEntry *)bh->b_data;
eaicb = lela_to_cpu(fe->extendedAttrICB);
if (UDF_I_LENEATTR(inode))
ea = fe->extendedAttr;
}
else
{
struct extendedFileEntry *efe;
efe = (struct extendedFileEntry *)bh->b_data;
eaicb = lela_to_cpu(efe->extendedAttrICB);
if (UDF_I_LENEATTR(inode))
ea = efe->extendedAttr;
}
switch (cmd)
{
case UDF_GETEASIZE:
result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
break;
case UDF_GETEABLOCK:
result = copy_to_user((char *)arg, ea,
result = copy_to_user((char *)arg, UDF_I_DATA(inode),
UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
break;
}
udf_release_data(bh);
return result;
}
......
......@@ -28,6 +28,7 @@
#include <linux/quotaops.h>
#include <linux/udf_fs.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include "udf_i.h"
#include "udf_sb.h"
......@@ -135,13 +136,20 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
inode->i_blocks = 0;
UDF_I_LENEATTR(inode) = 0;
UDF_I_LENALLOC(inode) = 0;
UDF_I_USE(inode) = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE))
{
UDF_I_EXTENDED_FE(inode) = 1;
UDF_I_EFE(inode) = 1;
UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
}
else
UDF_I_EXTENDED_FE(inode) = 0;
{
UDF_I_EFE(inode) = 0;
UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
memset(UDF_I_DATA(inode), 0x00, inode->i_sb->s_blocksize - sizeof(struct fileEntry));
}
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
......@@ -152,7 +160,6 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
UDF_I_CRTIME(inode) = CURRENT_TIME;
UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) =
UDF_I_UCRTIME(inode) = CURRENT_UTIME;
UDF_I_NEW_INODE(inode) = 1;
insert_inode_hash(inode);
mark_inode_dirty(inode);
......
This diff is collapsed.
......@@ -71,15 +71,10 @@ unsigned long
udf_get_last_block(struct super_block *sb)
{
struct block_device *bdev = sb->s_bdev;
int ret;
unsigned long lblock = 0;
ret = ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock);
if (ret) /* Hard Disk */
{
if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock))
lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits;
}
if (lblock)
return lblock - 1;
......
......@@ -74,7 +74,7 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type,
*bh = udf_tread(inode->i_sb, inode->i_ino);
if (UDF_I_EXTENDED_FE(inode) == 0)
if (UDF_I_EFE(inode) == 0)
{
struct fileEntry *fe;
......@@ -190,7 +190,7 @@ udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype,
*bh = udf_tread(inode->i_sb, inode->i_ino);
if (UDF_I_EXTENDED_FE(inode) == 0)
if (UDF_I_EFE(inode) == 0)
{
struct fileEntry *fe;
......@@ -269,10 +269,10 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1
if (block == 0xFFFFFFFF)
return NULL;
bh = udf_tread(sb, block);
bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
if (!bh)
{
udf_debug("block=%d, location=%d: read failed\n", block, location);
udf_debug("block=%d, location=%d: read failed\n", block + UDF_SB_SESSION(sb), location);
return NULL;
}
......@@ -283,7 +283,7 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1
if ( location != le32_to_cpu(tag_p->tagLocation) )
{
udf_debug("location mismatch block %u, tag %u != %u\n",
block, le32_to_cpu(tag_p->tagLocation), location);
block + UDF_SB_SESSION(sb), le32_to_cpu(tag_p->tagLocation), location);
goto error_out;
}
......@@ -315,7 +315,7 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1
return bh;
}
udf_debug("Crc failure block %d: crc = %d, crclen = %d\n",
block, le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
block + UDF_SB_SESSION(sb), le16_to_cpu(tag_p->descCRC), le16_to_cpu(tag_p->descCRCLength));
error_out:
brelse(bh);
......
This diff is collapsed.
......@@ -161,6 +161,7 @@ static struct super_operations udf_sb_ops = {
.write_inode = udf_write_inode,
.put_inode = udf_put_inode,
.delete_inode = udf_delete_inode,
.clear_inode = udf_clear_inode,
.put_super = udf_put_super,
.write_super = udf_write_super,
.statfs = udf_statfs,
......@@ -285,7 +286,8 @@ udf_parse_options(char *options, struct udf_options *uopt)
if (!options)
return 1;
while ((opt = strsep(&options, ",")) != NULL) {
while ((opt = strsep(&options, ",")) != NULL)
{
if (!*opt)
continue;
/* Make "opt=val" into two strings */
......@@ -383,10 +385,6 @@ udf_remount_fs(struct super_block *sb, int *flags, char *options)
UDF_SB(sb)->s_gid = uopt.gid;
UDF_SB(sb)->s_umask = uopt.umask;
#if UDFFS_RW != 1
*flags |= MS_RDONLY;
#endif
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
if (*flags & MS_RDONLY)
......@@ -591,14 +589,14 @@ udf_find_anchor(struct super_block *sb)
{
if (location == last[i] - UDF_SB_SESSION(sb))
{
lastblock = UDF_SB_ANCHOR(sb)[0] = last[i];
UDF_SB_ANCHOR(sb)[1] = last[i] - 256;
lastblock = UDF_SB_ANCHOR(sb)[0] = last[i] - UDF_SB_SESSION(sb);
UDF_SB_ANCHOR(sb)[1] = last[i] - 256 - UDF_SB_SESSION(sb);
}
else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
{
UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb);
UDF_SB_ANCHOR(sb)[1] = lastblock - 256 - UDF_SB_SESSION(sb);
}
else
udf_debug("Anchor found at block %d, location mismatch %d.\n",
......@@ -607,7 +605,7 @@ udf_find_anchor(struct super_block *sb)
else if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE)
{
lastblock = last[i];
UDF_SB_ANCHOR(sb)[3] = 512 + UDF_SB_SESSION(sb);
UDF_SB_ANCHOR(sb)[3] = 512;
}
else
{
......@@ -852,7 +850,7 @@ udf_load_partdesc(struct super_block *sb, struct buffer_head *bh)
if (UDF_SB_PARTMAPS(sb)[i].s_partition_num == le16_to_cpu(p->partitionNumber))
{
UDF_SB_PARTLEN(sb,i) = le32_to_cpu(p->partitionLength); /* blocks */
UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation) + UDF_SB_SESSION(sb);
UDF_SB_PARTROOT(sb,i) = le32_to_cpu(p->partitionStartingLocation);
if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_READ_ONLY)
UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_READ_ONLY;
if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_WRITE_ONCE)
......@@ -1428,10 +1426,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
sb->s_fs_info = sbi;
memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
#if UDFFS_RW != 1
sb->s_flags |= MS_RDONLY;
#endif
if (!udf_parse_options((char *)options, &uopt))
goto error_out;
......@@ -1478,7 +1472,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
UDF_SB_ANCHOR(sb)[0] = UDF_SB_ANCHOR(sb)[1] = 0;
UDF_SB_ANCHOR(sb)[2] = uopt.anchor;
UDF_SB_ANCHOR(sb)[3] = UDF_SB_SESSION(sb) + 256;
UDF_SB_ANCHOR(sb)[3] = 256;
if (udf_check_valid(sb, uopt.novrs, silent)) /* read volume recognition sequences */
{
......@@ -1543,8 +1537,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
{
timestamp ts;
udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0);
udf_info("UDF %s-%s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
UDFFS_VERSION, UDFFS_RW ? "rw" : "ro", UDFFS_DATE,
udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
UDFFS_VERSION, UDFFS_DATE,
UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
ts.typeAndTimezone);
}
......@@ -1726,8 +1720,6 @@ udf_put_super(struct super_block *sb)
static int
udf_statfs(struct super_block *sb, struct statfs *buf)
{
lock_kernel();
buf->f_type = UDF_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
......@@ -1740,8 +1732,6 @@ udf_statfs(struct super_block *sb, struct statfs *buf)
/* __kernel_fsid_t f_fsid */
buf->f_namelen = UDF_NAME_LEN;
unlock_kernel();
return 0;
}
......@@ -1763,6 +1753,8 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
uint16_t ident;
struct spaceBitmapDesc *bm;
lock_kernel();
loc.logicalBlockNum = bitmap->s_extPosition;
loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
bh = udf_read_ptagged(sb, loc, 0, &ident);
......@@ -1770,13 +1762,13 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
if (!bh)
{
printk(KERN_ERR "udf: udf_count_free failed\n");
return 0;
goto out;
}
else if (ident != TAG_IDENT_SBD)
{
udf_release_data(bh);
printk(KERN_ERR "udf: udf_count_free failed\n");
return 0;
goto out;
}
bm = (struct spaceBitmapDesc *)bh->b_data;
......@@ -1802,13 +1794,17 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
if (!bh)
{
udf_debug("read failed\n");
return accum;
goto out;
}
index = 0;
ptr = (uint8_t *)bh->b_data;
}
}
udf_release_data(bh);
out:
unlock_kernel();
return accum;
}
......@@ -1821,6 +1817,8 @@ udf_count_free_table(struct super_block *sb, struct inode * table)
int8_t etype;
struct buffer_head *bh = NULL;
lock_kernel();
bloc = UDF_I_LOCATION(table);
extoffset = sizeof(struct unallocSpaceEntry);
......@@ -1829,6 +1827,9 @@ udf_count_free_table(struct super_block *sb, struct inode * table)
accum += (elen >> table->i_sb->s_blocksize_bits);
}
udf_release_data(bh);
unlock_kernel();
return accum;
}
......
......@@ -38,7 +38,7 @@
#include <linux/buffer_head.h>
#include "udf_i.h"
static void udf_pc_to_char(char *from, int fromlen, char *to)
static void udf_pc_to_char(struct super_block *sb, char *from, int fromlen, char *to)
{
struct pathComponent *pc;
int elen = 0;
......@@ -66,9 +66,9 @@ static void udf_pc_to_char(char *from, int fromlen, char *to)
/* that would be . - just ignore */
break;
case 5:
memcpy(p, pc->componentIdent, pc->lengthComponentIdent);
p += pc->lengthComponentIdent;
p += udf_get_filename(sb, pc->componentIdent, p, pc->lengthComponentIdent);
*p++ = '/';
break;
}
elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
}
......@@ -88,14 +88,7 @@ static int udf_symlink_filler(struct file *file, struct page *page)
lock_kernel();
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
{
bh = udf_tread(inode->i_sb, inode->i_ino);
if (!bh)
goto out;
symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
}
symlink = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
else
{
bh = sb_bread(inode->i_sb, udf_block_map(inode, 0));
......@@ -106,7 +99,7 @@ static int udf_symlink_filler(struct file *file, struct page *page)
symlink = bh->b_data;
}
udf_pc_to_char(symlink, inode->i_size, p);
udf_pc_to_char(inode->i_sb, symlink, inode->i_size, p);
udf_release_data(bh);
unlock_kernel();
......
......@@ -95,7 +95,7 @@ void udf_truncate_extents(struct inode * inode)
else
lenalloc = extoffset - adsize;
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
if (!bh)
lenalloc -= udf_file_entry_alloc_offset(inode);
else
lenalloc -= sizeof(struct allocExtDesc);
......@@ -108,15 +108,15 @@ void udf_truncate_extents(struct inode * inode)
extoffset = 0;
if (lelen)
{
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
if (!bh)
BUG();
else
memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
}
else
{
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
if (!bh)
{
UDF_I_LENALLOC(inode) = lenalloc;
mark_inode_dirty(inode);
......@@ -135,9 +135,9 @@ void udf_truncate_extents(struct inode * inode)
}
udf_release_data(bh);
bh = NULL;
extoffset = sizeof(struct allocExtDesc);
bloc = eloc;
bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0));
if (elen)
lelen = (elen + inode->i_sb->s_blocksize - 1) >>
inode->i_sb->s_blocksize_bits;
......@@ -153,15 +153,15 @@ void udf_truncate_extents(struct inode * inode)
if (lelen)
{
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode));
if (!bh)
BUG();
else
memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
}
else
{
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
if (!bh)
{
UDF_I_LENALLOC(inode) = lenalloc;
mark_inode_dirty(inode);
......
......@@ -13,14 +13,17 @@ static inline struct udf_inode_info *UDF_I(struct inode *inode)
#define UDF_I_LENEXTENTS(X) ( UDF_I(X)->i_lenExtents )
#define UDF_I_UNIQUE(X) ( UDF_I(X)->i_unique )
#define UDF_I_ALLOCTYPE(X) ( UDF_I(X)->i_alloc_type )
#define UDF_I_EXTENDED_FE(X) ( UDF_I(X)->i_extended_fe )
#define UDF_I_STRAT4096(X) ( UDF_I(X)->i_strat_4096 )
#define UDF_I_NEW_INODE(X) ( UDF_I(X)->i_new_inode )
#define UDF_I_EFE(X) ( UDF_I(X)->i_efe )
#define UDF_I_USE(X) ( UDF_I(X)->i_use )
#define UDF_I_STRAT4096(X) ( UDF_I(X)->i_strat4096 )
#define UDF_I_NEXT_ALLOC_BLOCK(X) ( UDF_I(X)->i_next_alloc_block )
#define UDF_I_NEXT_ALLOC_GOAL(X) ( UDF_I(X)->i_next_alloc_goal )
#define UDF_I_UMTIME(X) ( UDF_I(X)->i_umtime )
#define UDF_I_UCTIME(X) ( UDF_I(X)->i_uctime )
#define UDF_I_CRTIME(X) ( UDF_I(X)->i_crtime )
#define UDF_I_UCRTIME(X) ( UDF_I(X)->i_ucrtime )
#define UDF_I_SAD(X) ( UDF_I(X)->i_ext.i_sad )
#define UDF_I_LAD(X) ( UDF_I(X)->i_ext.i_lad )
#define UDF_I_DATA(X) ( UDF_I(X)->i_ext.i_data )
#endif /* !defined(_LINUX_UDF_I_H) */
......@@ -16,10 +16,6 @@
#include <linux/version.h>
#endif
#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
#define CONFIG_UDF_FS_MODULE
#endif
#include "udfend.h"
#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
......@@ -35,9 +31,11 @@
#define CURRENT_UTIME (xtime.tv_nsec / 1000)
#define udf_file_entry_alloc_offset(inode)\
((UDF_I_EXTENDED_FE(inode) ?\
(UDF_I_USE(inode) ?\
sizeof(struct unallocSpaceEntry) :\
((UDF_I_EFE(inode) ?\
sizeof(struct extendedFileEntry) :\
sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode))
sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode)))
#define udf_ext0_offset(inode)\
(UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ?\
......@@ -114,6 +112,7 @@ extern void udf_truncate(struct inode *);
extern void udf_read_inode(struct inode *);
extern void udf_put_inode(struct inode *);
extern void udf_delete_inode(struct inode *);
extern void udf_clear_inode(struct inode *);
extern void udf_write_inode(struct inode *, int);
extern long udf_block_map(struct inode *, long);
extern int8_t inode_bmap(struct inode *, int, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
......@@ -134,6 +133,10 @@ extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, uint
extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *);
extern struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
extern void udf_release_data(struct buffer_head *);
extern uint32_t udf64_low32(uint64_t);
extern uint32_t udf64_high32(uint64_t);
extern void udf_update_tag(char *, int);
extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
/* lowlevel.c */
extern unsigned int udf_get_last_session(struct super_block *);
......@@ -148,6 +151,9 @@ extern int udf_relocate_blocks(struct super_block *, long, long *);
/* unicode.c */
extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int);
extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, int);
extern int udf_build_ustr(struct ustr *, dstring *, int);
extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
/* ialloc.c */
extern void udf_free_inode(struct inode *);
......@@ -168,40 +174,17 @@ extern int udf_fsync_inode(struct inode *, int);
/* directory.c */
extern uint8_t * udf_filead_read(struct inode *, uint8_t *, uint8_t, lb_addr, int *, int *, struct buffer_head **, int *);
extern struct fileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, lb_addr *, uint32_t *, lb_addr *, uint32_t *, uint32_t *, struct buffer_head **);
/* unicode.c */
extern int udf_ustr_to_dchars(uint8_t *, const struct ustr *, int);
extern int udf_ustr_to_char(uint8_t *, const struct ustr *, int);
extern int udf_ustr_to_dstring(dstring *, const struct ustr *, int);
extern int udf_dchars_to_ustr(struct ustr *, const uint8_t *, int);
extern int udf_char_to_ustr(struct ustr *, const uint8_t *, int);
extern int udf_dstring_to_ustr(struct ustr *, const dstring *, int);
extern int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
extern int udf_build_ustr(struct ustr *, dstring *, int);
extern int udf_build_ustr_exact(struct ustr *, dstring *, int);
extern int udf_CS0toUTF8(struct ustr *, struct ustr *);
extern int udf_UTF8toCS0(dstring *, struct ustr *, int);
extern int udf_CS0toNLS(struct nls_table *, struct ustr *, struct ustr *);
extern int udf_NLStoCS0(struct nls_table *, dstring *, struct ustr *, int);
extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
/* crc.c */
extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t);
/* misc.c */
extern uint32_t udf64_low32(uint64_t);
extern uint32_t udf64_high32(uint64_t);
extern void udf_update_tag(char *, int);
extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int);
/* udftime.c */
extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
extern timestamp *udf_time_to_stamp(timestamp *, time_t, long);
/* directory.c */
extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
extern long_ad * udf_get_filelongad(void * buffer, int bufsize, int * offset, int);
extern short_ad * udf_get_fileshortad(void * buffer, int bufsize, int * offset, int);
extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, int *);
#endif /* __UDF_DECL_H */
......@@ -32,46 +32,9 @@
#include "udf_sb.h"
int udf_ustr_to_dchars(uint8_t *dest, const struct ustr *src, int strlen)
{
if ( (!dest) || (!src) || (!strlen) || (src->u_len > strlen) )
return 0;
memcpy(dest+1, src->u_name, src->u_len);
dest[0] = src->u_cmpID;
return src->u_len + 1;
}
int udf_ustr_to_char(uint8_t *dest, const struct ustr *src, int strlen)
{
if ( (!dest) || (!src) || (!strlen) || (src->u_len >= strlen) )
return 0;
memcpy(dest, src->u_name, src->u_len);
return src->u_len;
}
int udf_ustr_to_dstring(dstring *dest, const struct ustr *src, int dlength)
{
if ( udf_ustr_to_dchars(dest, src, dlength-1) )
{
dest[dlength-1] = src->u_len + 1;
return dlength;
}
else
return 0;
}
int udf_dchars_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
{
if ( (!dest) || (!src) || (!strlen) || (strlen > UDF_NAME_LEN) )
return 0;
memset(dest, 0, sizeof(struct ustr));
memcpy(dest->u_name, src+1, strlen-1);
dest->u_cmpID = src[0];
dest->u_len = strlen-1;
return strlen-1;
}
static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
static int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
{
if ( (!dest) || (!src) || (!strlen) || (strlen >= UDF_NAME_LEN) )
return 0;
......@@ -82,15 +45,6 @@ int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
return strlen;
}
int udf_dstring_to_ustr(struct ustr *dest, const dstring *src, int dlength)
{
if ( dlength && udf_dchars_to_ustr(dest, src, src[dlength-1]) )
return dlength;
else
return 0;
}
/*
* udf_build_ustr
*/
......@@ -112,7 +66,7 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
/*
* udf_build_ustr_exact
*/
int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
static int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
{
if ( (!dest) || (!ptr) || (!exactsize) )
return -1;
......@@ -224,7 +178,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
* November 12, 1997 - Andrew E. Mileski
* Written, tested, and released.
*/
int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
{
unsigned c, i, max_val, utf_char;
int utf_cnt;
......@@ -318,7 +272,7 @@ int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
return u_len + 1;
}
int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
{
uint8_t *ocu;
uint32_t c;
......@@ -360,7 +314,7 @@ int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
return utf_o->u_len;
}
int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length)
{
unsigned len, i, max_val;
uint16_t uni_char;
......@@ -434,12 +388,42 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, int
return 0;
}
int udf_put_filename(struct super_block *sb, const uint8_t *sname, uint8_t *dname, int flen)
{
struct ustr unifilename;
int namelen;
if ( !(udf_char_to_ustr(&unifilename, sname, flen)) )
{
return 0;
}
if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
{
if ( !(namelen = udf_UTF8toCS0(dname, &unifilename, UDF_NAME_LEN)) )
{
return 0;
}
}
else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
{
if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, dname, &unifilename, UDF_NAME_LEN)) )
{
return 0;
}
}
else
return 0;
return namelen;
}
#define ILLEGAL_CHAR_MARK '_'
#define EXT_MARK '.'
#define CRC_MARK '#'
#define EXT_SIZE 5
int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
static int udf_translate_to_linux(uint8_t *newName, uint8_t *udfName, int udfLen, uint8_t *fidName, int fidNameLen)
{
int index, newIndex = 0, needsCRC = 0;
int extIndex = 0, newExtIndex = 0, hasExt = 0;
......
......@@ -34,23 +34,11 @@
#ifndef _UDF_FS_H
#define _UDF_FS_H 1
#include <linux/config.h>
#define UDF_PREALLOCATE
#define UDF_DEFAULT_PREALLOC_BLOCKS 8
#define UDFFS_DATE "2002/03/11"
#define UDFFS_VERSION "0.9.6"
#if !defined(UDFFS_RW)
#if defined(CONFIG_UDF_RW)
#define UDFFS_RW 1
#else /* !defined(CONFIG_UDF_RW) */
#define UDFFS_RW 0
#endif /* defined(CONFIG_UDF_RW) */
#endif /* !defined(UDFFS_RW) */
#define UDFFS_DATE "2002/11/15"
#define UDFFS_VERSION "0.9.7"
#define UDFFS_DEBUG
......
......@@ -26,6 +26,19 @@ typedef struct
__u32 logicalBlockNum;
__u16 partitionReferenceNum;
} __attribute__ ((packed)) lb_addr;
typedef struct
{
__u32 extLength;
__u32 extPosition;
} __attribute__ ((packed)) short_ad;
typedef struct
{
__u32 extLength;
lb_addr extLocation;
__u8 impUse[6];
} __attribute__ ((packed)) long_ad;
#endif
struct udf_inode_info
......@@ -43,10 +56,16 @@ struct udf_inode_info
__u32 i_next_alloc_block;
__u32 i_next_alloc_goal;
unsigned i_alloc_type : 3;
unsigned i_extended_fe : 1;
unsigned i_strat_4096 : 1;
unsigned i_new_inode : 1;
unsigned i_efe : 1;
unsigned i_use : 1;
unsigned i_strat4096 : 1;
unsigned reserved : 26;
union
{
short_ad *i_sad;
long_ad *i_lad;
__u8 *i_data;
} i_ext;
struct inode vfs_inode;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment