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);
......
......@@ -39,6 +39,7 @@
#include <linux/module.h>
#include <linux/pagemap.h>
#include <linux/buffer_head.h>
#include <linux/slab.h>
#include "udf_i.h"
#include "udf_sb.h"
......@@ -122,6 +123,11 @@ void udf_delete_inode(struct inode * inode)
clear_inode(inode);
}
void udf_clear_inode(struct inode *inode)
{
kfree(UDF_I_DATA(inode));
}
void udf_discard_prealloc(struct inode * inode)
{
if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) &&
......@@ -162,10 +168,8 @@ struct address_space_operations udf_aops = {
void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
{
struct buffer_head *bh = NULL;
struct page *page;
char *kaddr;
int block;
/* from now on we have normal address_space methods */
inode->i_data.a_ops = &udf_aops;
......@@ -180,10 +184,6 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
return;
}
block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
bh = udf_tread(inode->i_sb, block);
if (!bh)
return;
page = grab_cache_page(inode->i_mapping, 0);
if (!PageLocked(page))
PAGE_BUG(page);
......@@ -192,21 +192,19 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
kaddr = kmap(page);
memset(kaddr + UDF_I_LENALLOC(inode), 0x00,
PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
memcpy(kaddr, bh->b_data + udf_file_entry_alloc_offset(inode),
memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode),
UDF_I_LENALLOC(inode));
flush_dcache_page(page);
SetPageUptodate(page);
kunmap(page);
}
memset(bh->b_data + udf_file_entry_alloc_offset(inode),
0, UDF_I_LENALLOC(inode));
memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0x00,
UDF_I_LENALLOC(inode));
UDF_I_LENALLOC(inode) = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
else
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
mark_buffer_dirty_inode(bh, inode);
udf_release_data(bh);
if (inode->i_data.a_ops->writepage(page) == -EAGAIN)
__set_page_dirty_nobuffers(page);
......@@ -221,18 +219,21 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
struct buffer_head *sbh = NULL, *dbh = NULL;
lb_addr bloc, eloc;
uint32_t elen, extoffset;
uint8_t alloctype;
struct udf_fileident_bh sfibh, dfibh;
loff_t f_pos = udf_ext0_offset(inode) >> 2;
int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
struct fileIdentDesc cfi, *sfi, *dfi;
if (!inode->i_size)
{
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
alloctype = ICBTAG_FLAG_AD_SHORT;
else
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
alloctype = ICBTAG_FLAG_AD_LONG;
if (!inode->i_size)
{
UDF_I_ALLOCTYPE(inode) = alloctype;
mark_inode_dirty(inode);
return NULL;
}
......@@ -248,9 +249,6 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
UDF_I_LOCATION(inode).partitionReferenceNum, 0);
if (!newblock)
return NULL;
sbh = udf_tread(inode->i_sb, inode->i_ino);
if (!sbh)
return NULL;
dbh = udf_tgetblk(inode->i_sb, newblock);
if (!dbh)
return NULL;
......@@ -261,18 +259,19 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
mark_buffer_dirty_inode(dbh, inode);
sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2;
sfibh.sbh = sfibh.ebh = sbh;
sbh = sfibh.sbh = sfibh.ebh = NULL;
dfibh.soffset = dfibh.eoffset = 0;
dfibh.sbh = dfibh.ebh = dbh;
while ( (f_pos < size) )
{
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
if (!sfi)
{
udf_release_data(sbh);
udf_release_data(dbh);
return NULL;
}
UDF_I_ALLOCTYPE(inode) = alloctype;
sfi->descTag.tagLocation = *block;
dfibh.soffset = dfibh.eoffset;
dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
......@@ -280,21 +279,15 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
sfi->fileIdent + sfi->lengthOfImpUse))
{
udf_release_data(sbh);
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
udf_release_data(dbh);
return NULL;
}
}
mark_buffer_dirty_inode(dbh, inode);
memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
0, UDF_I_LENALLOC(inode));
memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
UDF_I_LENALLOC(inode) = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
else
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
bloc = UDF_I_LOCATION(inode);
eloc.logicalBlockNum = *block;
eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
......@@ -304,7 +297,6 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
/* UniqueID stuff */
mark_buffer_dirty(sbh);
udf_release_data(sbh);
mark_inode_dirty(inode);
return dbh;
......@@ -725,7 +717,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
if (elen > numalloc)
{
laarr[c].extLength -=
laarr[i].extLength -=
(numalloc << inode->i_sb->s_blocksize_bits);
numalloc = 0;
}
......@@ -847,7 +839,6 @@ struct buffer_head * udf_bread(struct inode * inode, int block,
void udf_truncate(struct inode * inode)
{
int offset;
struct buffer_head *bh;
int err;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
......@@ -874,16 +865,8 @@ void udf_truncate(struct inode * inode)
}
else
{
offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) +
udf_file_entry_alloc_offset(inode);
if ((bh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0))))
{
memset(bh->b_data + offset, 0x00, inode->i_sb->s_blocksize - offset);
mark_buffer_dirty(bh);
udf_release_data(bh);
}
offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset, 0x00, inode->i_sb->s_blocksize - offset - udf_file_entry_alloc_offset(inode));
UDF_I_LENALLOC(inode) = inode->i_size;
}
}
......@@ -1031,8 +1014,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
long convtime_usec;
int offset, alen;
UDF_I_NEW_INODE(inode) = 0;
fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)bh->b_data;
......@@ -1053,14 +1034,28 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
UDF_I_NEXT_ALLOC_BLOCK(inode) = 0;
UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE)
UDF_I_EXTENDED_FE(inode) = 1;
{
UDF_I_EFE(inode) = 1;
UDF_I_USE(inode) = 0;
UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL);
memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
}
else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE)
UDF_I_EXTENDED_FE(inode) = 0;
{
UDF_I_EFE(inode) = 0;
UDF_I_USE(inode) = 0;
UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL);
memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
}
else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
{
UDF_I_EFE(inode) = 0;
UDF_I_USE(inode) = 1;
UDF_I_LENALLOC(inode) =
le32_to_cpu(
((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs);
UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL);
memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
return;
}
......@@ -1080,7 +1075,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
inode->i_mode = udf_convert_permissions(fe);
inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask;
if (UDF_I_EXTENDED_FE(inode) == 0)
if (UDF_I_EFE(inode) == 0)
{
inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9);
......@@ -1326,19 +1321,11 @@ udf_update_inode(struct inode *inode, int do_sync)
udf_debug("bread failure\n");
return -EIO;
}
memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)bh->b_data;
if (UDF_I_NEW_INODE(inode) == 1)
{
if (UDF_I_EXTENDED_FE(inode) == 0)
memset(bh->b_data, 0x00, sizeof(struct fileEntry));
else
memset(bh->b_data, 0x00, sizeof(struct extendedFileEntry));
memset(bh->b_data + udf_file_entry_alloc_offset(inode) +
UDF_I_LENALLOC(inode), 0x0, inode->i_sb->s_blocksize -
udf_file_entry_alloc_offset(inode) - UDF_I_LENALLOC(inode));
UDF_I_NEW_INODE(inode) = 0;
}
if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
{
......@@ -1346,6 +1333,7 @@ udf_update_inode(struct inode *inode, int do_sync)
(struct unallocSpaceEntry *)bh->b_data;
use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode));
memcpy(bh->b_data + sizeof(struct unallocSpaceEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry));
crclen = sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) -
sizeof(tag);
use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
......@@ -1416,8 +1404,9 @@ udf_update_inode(struct inode *inode, int do_sync)
udf_release_data(tbh);
}
if (UDF_I_EXTENDED_FE(inode) == 0)
if (UDF_I_EFE(inode) == 0)
{
memcpy(bh->b_data + sizeof(struct fileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct fileEntry));
fe->logicalBlocksRecorded = cpu_to_le64(
(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
(inode->i_sb->s_blocksize_bits - 9));
......@@ -1440,6 +1429,7 @@ udf_update_inode(struct inode *inode, int do_sync)
}
else
{
memcpy(bh->b_data + sizeof(struct extendedFileEntry), UDF_I_DATA(inode), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry));
efe->objectSize = cpu_to_le64(inode->i_size);
efe->logicalBlocksRecorded = cpu_to_le64(
(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
......@@ -1620,17 +1610,12 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
long_ad *lad = NULL;
struct allocExtDesc *aed;
int8_t etype;
uint8_t *ptr;
if (!(*bh))
{
if (!(*bh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
{
udf_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, *bloc, 0));
return -1;
}
}
if (!*bh)
ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
else
ptr = (*bh)->b_data + *extoffset;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
......@@ -1669,7 +1654,7 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
{
loffset = *extoffset;
aed->lengthAllocDescs = cpu_to_le32(adsize);
sptr = (*bh)->b_data + *extoffset - adsize;
sptr = ptr - adsize;
dptr = nbh->b_data + sizeof(struct allocExtDesc);
memcpy(dptr, sptr, adsize);
*extoffset = sizeof(struct allocExtDesc) + adsize;
......@@ -1678,10 +1663,10 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
{
loffset = *extoffset + adsize;
aed->lengthAllocDescs = cpu_to_le32(0);
sptr = (*bh)->b_data + *extoffset;
sptr = ptr;
*extoffset = sizeof(struct allocExtDesc);
if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
if (*bh)
{
aed = (struct allocExtDesc *)(*bh)->b_data;
aed->lengthAllocDescs =
......@@ -1721,18 +1706,23 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
break;
}
}
if (*bh)
{
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
udf_update_tag((*bh)->b_data, loffset);
else
udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc));
mark_buffer_dirty_inode(*bh, inode);
udf_release_data(*bh);
}
else
mark_inode_dirty(inode);
*bh = nbh;
}
etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc);
if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
if (!*bh)
{
UDF_I_LENALLOC(inode) += adsize;
mark_inode_dirty(inode);
......@@ -1756,49 +1746,40 @@ int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
{
int adsize;
short_ad *sad = NULL;
long_ad *lad = NULL;
uint8_t *ptr;
if (!(bh))
{
if (!(bh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, bloc, 0))))
{
udf_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, bloc, 0));
return -1;
}
}
if (!bh)
ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
else
{
ptr = bh->b_data + *extoffset;
atomic_inc(&bh->b_count);
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
adsize = sizeof(long_ad);
else
return -1;
}
switch (UDF_I_ALLOCTYPE(inode))
{
case ICBTAG_FLAG_AD_SHORT:
{
sad = (short_ad *)((bh)->b_data + *extoffset);
short_ad *sad = (short_ad *)ptr;
sad->extLength = cpu_to_le32(elen);
sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
adsize = sizeof(short_ad);
break;
}
case ICBTAG_FLAG_AD_LONG:
{
lad = (long_ad *)((bh)->b_data + *extoffset);
long_ad *lad = (long_ad *)ptr;
lad->extLength = cpu_to_le32(elen);
lad->extLocation = cpu_to_lelb(eloc);
memset(lad->impUse, 0x00, sizeof(lad->impUse));
adsize = sizeof(long_ad);
break;
}
default:
return -1;
}
if (memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
if (bh)
{
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201)
{
......@@ -1807,30 +1788,28 @@ int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
}
mark_buffer_dirty_inode(bh, inode);
udf_release_data(bh);
}
else
{
mark_inode_dirty(inode);
mark_buffer_dirty(bh);
}
if (inc)
*extoffset += adsize;
udf_release_data(bh);
return (elen >> 30);
}
int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
{
uint16_t tagIdent;
int pos, alen;
int8_t etype;
if (!(*bh))
while ((etype = udf_current_aext(inode, bloc, extoffset, eloc, elen, bh, inc)) ==
(EXT_NEXT_EXTENT_ALLOCDECS >> 30))
{
if (!(*bh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
*bloc = *eloc;
*extoffset = sizeof(struct allocExtDesc);
udf_release_data(*bh);
if (!(*bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
{
udf_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, *bloc, 0));
......@@ -1838,146 +1817,30 @@ int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
}
}
tagIdent = le16_to_cpu(((tag *)(*bh)->b_data)->tagIdent);
if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
{
if (tagIdent == TAG_IDENT_FE || tagIdent == TAG_IDENT_EFE ||
UDF_I_NEW_INODE(inode))
{
pos = udf_file_entry_alloc_offset(inode);
alen = UDF_I_LENALLOC(inode) + pos;
}
else if (tagIdent == TAG_IDENT_USE)
{
pos = sizeof(struct unallocSpaceEntry);
alen = UDF_I_LENALLOC(inode) + pos;
}
else
return -1;
}
else if (tagIdent == TAG_IDENT_AED)
{
struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
pos = sizeof(struct allocExtDesc);
alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
}
else
return -1;
if (!(*extoffset))
*extoffset = pos;
switch (UDF_I_ALLOCTYPE(inode))
{
case ICBTAG_FLAG_AD_SHORT:
{
short_ad *sad;
if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
return -1;
if ((etype = le32_to_cpu(sad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
{
bloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
*extoffset = 0;
udf_release_data(*bh);
*bh = NULL;
return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
}
else
{
eloc->logicalBlockNum = le32_to_cpu(sad->extPosition);
eloc->partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
*elen = le32_to_cpu(sad->extLength) & UDF_EXTENT_LENGTH_MASK;
}
break;
}
case ICBTAG_FLAG_AD_LONG:
{
long_ad *lad;
if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
return -1;
if ((etype = le32_to_cpu(lad->extLength) >> 30) == (EXT_NEXT_EXTENT_ALLOCDECS >> 30))
{
*bloc = lelb_to_cpu(lad->extLocation);
*extoffset = 0;
udf_release_data(*bh);
*bh = NULL;
return udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, inc);
}
else
{
*eloc = lelb_to_cpu(lad->extLocation);
*elen = le32_to_cpu(lad->extLength) & UDF_EXTENT_LENGTH_MASK;
}
break;
}
case ICBTAG_FLAG_AD_IN_ICB:
{
if (UDF_I_LENALLOC(inode) == 0)
return -1;
etype = (EXT_RECORDED_ALLOCATED >> 30);
*eloc = UDF_I_LOCATION(inode);
*elen = UDF_I_LENALLOC(inode);
break;
}
default:
{
udf_debug("alloc_type = %d unsupported\n", UDF_I_ALLOCTYPE(inode));
return -1;
}
}
if (*elen)
return etype;
udf_debug("Empty Extent, inode=%ld, alloctype=%d, eloc=%d, elen=%d, etype=%d, extoffset=%d\n",
inode->i_ino, UDF_I_ALLOCTYPE(inode), eloc->logicalBlockNum, *elen, etype, *extoffset);
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
*extoffset -= sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
*extoffset -= sizeof(long_ad);
return -1;
}
int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
{
int pos, alen;
int alen;
int8_t etype;
uint8_t *ptr;
if (!(*bh))
{
if (!(*bh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, *bloc, 0))))
{
udf_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, *bloc, 0));
return -1;
}
}
if (!memcmp(&UDF_I_LOCATION(inode), bloc, sizeof(lb_addr)))
if (!*bh)
{
if (!(UDF_I_EXTENDED_FE(inode)))
pos = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode);
else
pos = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode);
alen = UDF_I_LENALLOC(inode) + pos;
if (!(*extoffset))
*extoffset = udf_file_entry_alloc_offset(inode);
ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
}
else
{
struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data;
pos = sizeof(struct allocExtDesc);
alen = le32_to_cpu(aed->lengthAllocDescs) + pos;
}
if (!(*extoffset))
*extoffset = pos;
*extoffset = sizeof(struct allocExtDesc);
ptr = (*bh)->b_data + *extoffset;
alen = le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
}
switch (UDF_I_ALLOCTYPE(inode))
{
......@@ -1985,7 +1848,7 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
{
short_ad *sad;
if (!(sad = udf_get_fileshortad((*bh)->b_data, alen, extoffset, inc)))
if (!(sad = udf_get_fileshortad(ptr, alen, extoffset, inc)))
return -1;
etype = le32_to_cpu(sad->extLength) >> 30;
......@@ -1998,7 +1861,7 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
{
long_ad *lad;
if (!(lad = udf_get_filelongad((*bh)->b_data, alen, extoffset, inc)))
if (!(lad = udf_get_filelongad(ptr, alen, extoffset, inc)))
return -1;
etype = le32_to_cpu(lad->extLength) >> 30;
......@@ -2012,15 +1875,8 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
return -1;
}
}
if (*elen)
return etype;
udf_debug("Empty Extent!\n");
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
*extoffset -= sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_LONG)
*extoffset -= sizeof(long_ad);
return -1;
return etype;
}
int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
......@@ -2030,17 +1886,7 @@ int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
uint32_t oelen;
int8_t etype;
if (!bh)
{
if (!(bh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, bloc, 0))))
{
udf_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, bloc, 0));
return -1;
}
}
else
if (bh)
atomic_inc(&bh->b_count);
while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1)
......@@ -2064,19 +1910,11 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
int8_t etype;
struct allocExtDesc *aed;
if (!(nbh))
{
if (!(nbh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, nbloc, 0))))
if (nbh)
{
udf_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, nbloc, 0));
return -1;
}
}
else
atomic_inc(&nbh->b_count);
atomic_inc(&nbh->b_count);
}
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(short_ad);
......@@ -2095,7 +1933,7 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
while ((etype = udf_next_aext(inode, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1)
{
udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
if (obh != nbh)
{
obloc = nbloc;
udf_release_data(obh);
......@@ -2107,12 +1945,12 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
memset(&eloc, 0x00, sizeof(lb_addr));
elen = 0;
if (memcmp(&nbloc, &obloc, sizeof(lb_addr)))
if (nbh != obh)
{
udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1);
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
if (!obh)
{
UDF_I_LENALLOC(inode) -= (adsize * 2);
mark_inode_dirty(inode);
......@@ -2132,7 +1970,7 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
else
{
udf_write_aext(inode, obloc, &oextoffset, eloc, elen, obh, 1);
if (!memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
if (!obh)
{
UDF_I_LENALLOC(inode) -= adsize;
mark_inode_dirty(inode);
......@@ -2207,8 +2045,6 @@ long udf_block_map(struct inode *inode, long block)
ret = 0;
unlock_kernel();
if (bh)
udf_release_data(bh);
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
......
......@@ -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);
......
......@@ -56,12 +56,16 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
uint8_t lfi = cfi->lengthFileIdent;
int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
sizeof(struct fileIdentDesc);
int adinicb = 0;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
adinicb = 1;
offset = fibh->soffset + sizeof(struct fileIdentDesc);
if (impuse)
{
if (offset + liu < 0)
if (adinicb || (offset + liu < 0))
memcpy((uint8_t *)sfi->impUse, impuse, liu);
else if (offset >= 0)
memcpy(fibh->ebh->b_data + offset, impuse, liu);
......@@ -76,7 +80,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
if (fileident)
{
if (offset + lfi < 0)
if (adinicb || (offset + lfi < 0))
memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
else if (offset >= 0)
memcpy(fibh->ebh->b_data + offset, fileident, lfi);
......@@ -89,7 +93,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
offset += lfi;
if (offset + padlen < 0)
if (adinicb || (offset + padlen < 0))
memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
else if (offset >= 0)
memset(fibh->ebh->b_data + offset, 0x00, padlen);
......@@ -123,7 +127,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
checksum += ((uint8_t *)&cfi->descTag)[i];
cfi->descTag.tagChecksum = checksum;
if (sizeof(struct fileIdentDesc) <= -fibh->soffset)
if (adinicb || (sizeof(struct fileIdentDesc) <= -fibh->soffset))
memcpy((uint8_t *)sfi, (uint8_t *)cfi, sizeof(struct fileIdentDesc));
else
{
......@@ -132,9 +136,14 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
sizeof(struct fileIdentDesc) + fibh->soffset);
}
if (adinicb)
mark_inode_dirty(inode);
else
{
if (fibh->sbh != fibh->ebh)
mark_buffer_dirty_inode(fibh->ebh, inode);
mark_buffer_dirty_inode(fibh->sbh, inode);
}
return 0;
}
......@@ -161,7 +170,9 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
f_pos = (udf_ext0_offset(dir) >> 2);
fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
if (inode_bmap(dir, f_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, f_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;
......@@ -175,14 +186,14 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
}
else
offset = 0;
}
else
if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
return NULL;
}
if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
}
else
{
udf_release_data(bh);
return NULL;
......@@ -304,7 +315,8 @@ udf_lookup(struct inode *dir, struct dentry *dentry)
{
lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
inode = udf_iget(dir->i_sb, lb);
if (!inode) {
if (!inode)
{
unlock_kernel();
return ERR_PTR(-EACCES);
}
......@@ -319,7 +331,8 @@ udf_lookup(struct inode *dir, struct dentry *dentry)
udf_release_data(fibh.sbh);
inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
if ( !inode ) {
if ( !inode )
{
unlock_kernel();
return ERR_PTR(-EACCES);
}
......@@ -336,7 +349,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
{
struct super_block *sb;
struct fileIdentDesc *fi=NULL;
struct ustr unifilename;
char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
int namelen;
loff_t f_pos;
......@@ -361,31 +373,12 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
return NULL;
}
if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
{
*err = -ENAMETOOLONG;
return NULL;
}
if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8))
{
if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) )
{
*err = -ENAMETOOLONG;
return NULL;
}
}
else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP))
{
if ( !(namelen = udf_NLStoCS0(UDF_SB(sb)->s_nls_map, name, &unifilename, UDF_NAME_LEN)) )
if ( !(namelen = udf_put_filename(sb, dentry->d_name.name, name, dentry->d_name.len)))
{
*err = -ENAMETOOLONG;
return NULL;
}
}
else
return NULL;
}
else
namelen = 0;
......@@ -394,7 +387,9 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
f_pos = (udf_ext0_offset(dir) >> 2);
fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
if (inode_bmap(dir, f_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, f_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;
......@@ -418,6 +413,15 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
block = UDF_I_LOCATION(dir).logicalBlockNum;
}
else
{
block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
fibh->sbh = fibh->ebh = NULL;
fibh->soffset = fibh->eoffset = sb->s_blocksize;
goto add;
}
while ( (f_pos < size) )
{
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
......@@ -487,22 +491,8 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
return NULL;
}
}
}
else
{
block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
{
fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
fibh->soffset = fibh->eoffset = udf_file_entry_alloc_offset(dir);
}
else
{
fibh->sbh = fibh->ebh = NULL;
fibh->soffset = fibh->eoffset = sb->s_blocksize;
}
}
add:
f_pos += nfidlen;
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
......@@ -539,14 +529,18 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
fibh->sbh = fibh->ebh;
}
if (UDF_I_ALLOCTYPE(dir) != ICBTAG_FLAG_AD_IN_ICB)
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB)
{
block = UDF_I_LOCATION(dir).logicalBlockNum;
fi = (struct fileIdentDesc *)(UDF_I_DATA(dir) + fibh->soffset - udf_ext0_offset(dir) + UDF_I_LENEATTR(dir));
}
else
{
block = eloc.logicalBlockNum + ((elen - 1) >>
dir->i_sb->s_blocksize_bits);
else
block = UDF_I_LOCATION(dir).logicalBlockNum;
fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
}
}
else
{
fibh->soffset = fibh->eoffset - sb->s_blocksize;
......@@ -635,7 +629,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode)
lock_kernel();
inode = udf_new_inode(dir, mode, &err);
if (!inode) {
if (!inode)
{
unlock_kernel();
return err;
}
......@@ -796,7 +791,10 @@ static int empty_dir(struct inode *dir)
f_pos = (udf_ext0_offset(dir) >> 2);
fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 2;
if (inode_bmap(dir, f_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, f_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;
......@@ -810,6 +808,12 @@ static int empty_dir(struct inode *dir)
}
else
offset = 0;
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
return 0;
}
}
else
{
......@@ -817,8 +821,6 @@ static int empty_dir(struct inode *dir)
return 0;
}
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
return 0;
while ( (f_pos < size) )
{
......@@ -835,6 +837,9 @@ static int empty_dir(struct inode *dir)
if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0)
{
if (fibh.sbh != fibh.ebh)
udf_release_data(fibh.ebh);
udf_release_data(fibh.sbh);
udf_release_data(bh);
return 0;
}
......@@ -950,6 +955,8 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
char *ea;
int err;
int block;
char name[UDF_NAME_LEN];
int namelen;
lock_kernel();
if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
......@@ -987,13 +994,10 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
set_buffer_uptodate(bh);
unlock_buffer(bh);
mark_buffer_dirty_inode(bh, inode);
ea = bh->b_data + udf_ext0_offset(inode);
}
else
{
block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
bh = udf_tread(inode->i_sb, block);
}
ea = bh->b_data + udf_ext0_offset(inode);
ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
pc = (struct pathComponent *)ea;
......@@ -1031,22 +1035,25 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
pc->componentType = 5;
pc->lengthComponentIdent = 0;
pc->componentFileVersionNum = 0;
if (pc->componentIdent[0] == '.')
if (compstart[0] == '.')
{
if (pc->lengthComponentIdent == 1)
if ((symname-compstart) == 1)
pc->componentType = 4;
else if (pc->lengthComponentIdent == 2 && pc->componentIdent[1] == '.')
else if ((symname-compstart) == 2 && compstart[1] == '.')
pc->componentType = 3;
}
if (pc->componentType == 5)
{
if (elen + sizeof(struct pathComponent) + symname - compstart > eoffset)
if ( !(namelen = udf_put_filename(inode->i_sb, compstart, name, symname-compstart)))
goto out_no_entry;
if (elen + sizeof(struct pathComponent) + namelen > eoffset)
goto out_no_entry;
else
pc->lengthComponentIdent = symname - compstart;
pc->lengthComponentIdent = namelen;
memcpy(pc->componentIdent, compstart, pc->lengthComponentIdent);
memcpy(pc->componentIdent, name, namelen);
}
elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
......@@ -1114,12 +1121,14 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
struct fileIdentDesc cfi, *fi;
lock_kernel();
if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1) {
if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
{
unlock_kernel();
return -EMLINK;
}
if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) {
if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
{
unlock_kernel();
return err;
}
......@@ -1204,10 +1213,21 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
goto end_rename;
}
retval = -EIO;
if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)
{
dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) -
(UDF_I_EFE(old_inode) ?
sizeof(struct extendedFileEntry) :
sizeof(struct fileEntry)),
old_inode->i_sb->s_blocksize, &offset);
}
else
{
dir_bh = udf_bread(old_inode, 0, 0, &retval);
if (!dir_bh)
goto end_rename;
dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset);
}
if (!dir_fi)
goto end_rename;
if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) !=
......@@ -1257,7 +1277,7 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;
mark_inode_dirty(old_dir);
if (dir_bh)
if (dir_fi)
{
dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
......
......@@ -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