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 ...@@ -1037,15 +1037,12 @@ config SYSV_FS
If you haven't heard about all of this before, it's safe to say N. If you haven't heard about all of this before, it's safe to say N.
config UDF_FS config UDF_FS
tristate "UDF file system support (read only)" tristate "UDF file system support"
---help--- ---help---
This is the new file system used on some CD-ROMs and DVDs. Say Y if 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 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 if written to by other UDF utilities, such as DirectCD.
file system support is read-only. If you want to write to UDF Please read <file:Documentation/filesystems/udf.txt>.
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>.
This file system support is also available as a module ( = code This file system support is also available as a module ( = code
which can be inserted in and removed from the running kernel which can be inserted in and removed from the running kernel
...@@ -1055,14 +1052,6 @@ config UDF_FS ...@@ -1055,14 +1052,6 @@ config UDF_FS
If unsure, say N. 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 config UFS_FS
tristate "UFS file system support (read only)" tristate "UFS file system support (read only)"
---help--- ---help---
......
...@@ -461,8 +461,7 @@ static void udf_table_free_blocks(struct super_block * sb, ...@@ -461,8 +461,7 @@ static void udf_table_free_blocks(struct super_block * sb,
elen = 0; elen = 0;
obloc = nbloc = UDF_I_LOCATION(table); obloc = nbloc = UDF_I_LOCATION(table);
obh = nbh = udf_tread(sb, udf_get_lb_pblock(sb, nbloc, 0)); obh = nbh = NULL;
atomic_inc(&nbh->b_count);
while (count && (etype = while (count && (etype =
udf_next_aext(table, &nbloc, &nextoffset, &eloc, &elen, &nbh, 1)) != -1) 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, ...@@ -506,7 +505,7 @@ static void udf_table_free_blocks(struct super_block * sb,
udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1); udf_write_aext(table, obloc, &oextoffset, eloc, elen, obh, 1);
} }
if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) if (nbh != obh)
{ {
i = -1; i = -1;
obloc = nbloc; obloc = nbloc;
...@@ -580,7 +579,10 @@ static void udf_table_free_blocks(struct super_block * sb, ...@@ -580,7 +579,10 @@ static void udf_table_free_blocks(struct super_block * sb,
{ {
loffset = nextoffset; loffset = nextoffset;
aed->lengthAllocDescs = cpu_to_le32(adsize); 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); dptr = nbh->b_data + sizeof(struct allocExtDesc);
memcpy(dptr, sptr, adsize); memcpy(dptr, sptr, adsize);
nextoffset = sizeof(struct allocExtDesc) + adsize; nextoffset = sizeof(struct allocExtDesc) + adsize;
...@@ -591,8 +593,8 @@ static void udf_table_free_blocks(struct super_block * sb, ...@@ -591,8 +593,8 @@ static void udf_table_free_blocks(struct super_block * sb,
aed->lengthAllocDescs = cpu_to_le32(0); aed->lengthAllocDescs = cpu_to_le32(0);
sptr = (obh)->b_data + nextoffset; sptr = (obh)->b_data + nextoffset;
nextoffset = sizeof(struct allocExtDesc); nextoffset = sizeof(struct allocExtDesc);
if (memcmp(&UDF_I_LOCATION(table), &obloc, sizeof(lb_addr))) if (obh)
{ {
aed = (struct allocExtDesc *)(obh)->b_data; aed = (struct allocExtDesc *)(obh)->b_data;
aed->lengthAllocDescs = aed->lengthAllocDescs =
...@@ -631,15 +633,20 @@ static void udf_table_free_blocks(struct super_block * sb, ...@@ -631,15 +633,20 @@ static void udf_table_free_blocks(struct super_block * sb,
break; break;
} }
} }
udf_update_tag(obh->b_data, loffset); if (obh)
mark_buffer_dirty(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 */ if (elen) /* It's possible that stealing the block emptied the extent */
{ {
udf_write_aext(table, nbloc, &nextoffset, eloc, elen, nbh, 1); 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; UDF_I_LENALLOC(table) += adsize;
mark_inode_dirty(table); mark_inode_dirty(table);
...@@ -690,7 +697,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb, ...@@ -690,7 +697,7 @@ static int udf_table_prealloc_blocks(struct super_block * sb,
extoffset = sizeof(struct unallocSpaceEntry); extoffset = sizeof(struct unallocSpaceEntry);
bloc = UDF_I_LOCATION(table); bloc = UDF_I_LOCATION(table);
bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0)); bh = NULL;
eloc.logicalBlockNum = 0xFFFFFFFF; eloc.logicalBlockNum = 0xFFFFFFFF;
while (first_block != eloc.logicalBlockNum && (etype = while (first_block != eloc.logicalBlockNum && (etype =
...@@ -768,8 +775,7 @@ static int udf_table_new_block(struct super_block * sb, ...@@ -768,8 +775,7 @@ static int udf_table_new_block(struct super_block * sb,
extoffset = sizeof(struct unallocSpaceEntry); extoffset = sizeof(struct unallocSpaceEntry);
bloc = UDF_I_LOCATION(table); bloc = UDF_I_LOCATION(table);
goal_bh = bh = udf_tread(sb, udf_get_lb_pblock(sb, bloc, 0)); goal_bh = bh = NULL;
atomic_inc(&goal_bh->b_count);
while (spread && (etype = while (spread && (etype =
udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1) udf_next_aext(table, &bloc, &extoffset, &eloc, &elen, &bh, 1)) != -1)
......
...@@ -89,13 +89,14 @@ int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) ...@@ -89,13 +89,14 @@ int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
if ( filp->f_pos == 0 ) 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(); unlock_kernel();
return 0; return 0;
} }
filp->f_pos ++; filp->f_pos ++;
} }
result = do_udf_readdir(dir, filp, filldir, dirent); result = do_udf_readdir(dir, filp, filldir, dirent);
UPDATE_ATIME(dir); UPDATE_ATIME(dir);
unlock_kernel(); unlock_kernel();
...@@ -129,7 +130,9 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d ...@@ -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); nf_pos = (udf_ext0_offset(dir) >> 2);
fibh.soffset = fibh.eoffset = (nf_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 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)) &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
{ {
offset >>= dir->i_sb->s_blocksize_bits; offset >>= dir->i_sb->s_blocksize_bits;
...@@ -143,40 +146,40 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d ...@@ -143,40 +146,40 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
} }
else else
offset = 0; offset = 0;
}
else
{
udf_release_data(bh);
return -ENOENT;
}
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
return -EIO;
}
if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1))) if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
{
i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
for (num=0; i>0; i--)
{ {
block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i); udf_release_data(bh);
tmp = udf_tgetblk(dir->i_sb, block); return -EIO;
if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
bha[num++] = tmp;
else
brelse(tmp);
} }
if (num)
if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9))-1)))
{ {
ll_rw_block(READA, num, bha); i = 16 >> (dir->i_sb->s_blocksize_bits - 9);
for (i=0; i<num; i++) if (i+offset > (elen >> dir->i_sb->s_blocksize_bits))
brelse(bha[i]); i = (elen >> dir->i_sb->s_blocksize_bits)-offset;
for (num=0; i>0; i--)
{
block = udf_get_lb_pblock(dir->i_sb, eloc, offset+i);
tmp = udf_tgetblk(dir->i_sb, block);
if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp))
bha[num++] = tmp;
else
brelse(tmp);
}
if (num)
{
ll_rw_block(READA, num, bha);
for (i=0; i<num; i++)
brelse(bha[i]);
}
} }
} }
else
{
udf_release_data(bh);
return -ENOENT;
}
while ( nf_pos < size ) while ( nf_pos < size )
{ {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
*/ */
#include "udfdecl.h" #include "udfdecl.h"
#include "udf_i.h"
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/string.h> #include <linux/string.h>
...@@ -85,6 +86,24 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos, ...@@ -85,6 +86,24 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
fibh->soffset = fibh->eoffset; 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) if (fibh->eoffset == dir->i_sb->s_blocksize)
{ {
int lextoffset = *extoffset; int lextoffset = *extoffset;
...@@ -276,53 +295,43 @@ udf_get_fileextent(void * buffer, int bufsize, int * offset) ...@@ -276,53 +295,43 @@ udf_get_fileextent(void * buffer, int bufsize, int * offset)
} }
short_ad * 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; short_ad *sa;
uint8_t * ptr;
if ( (!buffer) || (!offset) ) if ( (!ptr) || (!offset) )
{ {
printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n"); printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n");
return NULL; return NULL;
} }
ptr = (uint8_t *)buffer; if ( (*offset < 0) || ((*offset + sizeof(short_ad)) > maxoffset) )
if ( (*offset > 0) && (*offset < maxoffset) )
ptr += *offset;
else
return NULL; return NULL;
else if ((sa = (short_ad *)ptr)->extLength == 0)
if ((sa = (short_ad *)ptr)->extLength == 0)
return NULL; return NULL;
else if (inc)
(*offset) += sizeof(short_ad); if (inc)
*offset += sizeof(short_ad);
return sa; return sa;
} }
long_ad * 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; long_ad *la;
uint8_t * ptr;
if ( (!buffer) || !(offset) ) if ( (!ptr) || (!offset) )
{ {
printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n"); printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n");
return NULL; return NULL;
} }
ptr = (uint8_t *)buffer; if ( (*offset < 0) || ((*offset + sizeof(long_ad)) > maxoffset) )
if ( (*offset > 0) && (*offset < maxoffset) )
ptr += *offset;
else
return NULL; return NULL;
else if ((la = (long_ad *)ptr)->extLength == 0)
if ((la = (long_ad *)ptr)->extLength == 0)
return NULL; return NULL;
else if (inc)
(*offset) += sizeof(long_ad); if (inc)
*offset += sizeof(long_ad);
return la; return la;
} }
...@@ -47,64 +47,36 @@ ...@@ -47,64 +47,36 @@
static int udf_adinicb_readpage(struct file *file, struct page * page) static int udf_adinicb_readpage(struct file *file, struct page * page)
{ {
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
struct buffer_head *bh;
int block;
char *kaddr; char *kaddr;
int err = 0;
if (!PageLocked(page)) if (!PageLocked(page))
PAGE_BUG(page); PAGE_BUG(page);
kaddr = kmap(page); kaddr = kmap(page);
memset(kaddr, 0, PAGE_CACHE_SIZE); memset(kaddr, 0, PAGE_CACHE_SIZE);
block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); memcpy(kaddr, UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), inode->i_size);
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);
flush_dcache_page(page); flush_dcache_page(page);
SetPageUptodate(page); SetPageUptodate(page);
out:
kunmap(page); kunmap(page);
unlock_page(page); unlock_page(page);
return err; return 0;
} }
static int udf_adinicb_writepage(struct page *page) static int udf_adinicb_writepage(struct page *page)
{ {
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
struct buffer_head *bh;
int block;
char *kaddr; char *kaddr;
int err = 0;
if (!PageLocked(page)) if (!PageLocked(page))
PAGE_BUG(page); PAGE_BUG(page);
kaddr = kmap(page); kaddr = kmap(page);
block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), kaddr, inode->i_size);
bh = sb_bread(inode->i_sb, block); mark_inode_dirty(inode);
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);
SetPageUptodate(page); SetPageUptodate(page);
out:
kunmap(page); kunmap(page);
unlock_page(page); unlock_page(page);
return err; return 0;
} }
static int udf_adinicb_prepare_write(struct file *file, struct page *page, unsigned offset, unsigned to) 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 ...@@ -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) static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{ {
struct inode *inode = page->mapping->host; struct inode *inode = page->mapping->host;
struct buffer_head *bh;
int block;
char *kaddr = page_address(page); char *kaddr = page_address(page);
int err = 0;
block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0); memcpy(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset,
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,
kaddr + offset, to - offset); kaddr + offset, to - offset);
mark_buffer_dirty(bh); mark_inode_dirty(inode);
brelse(bh);
SetPageUptodate(page); SetPageUptodate(page);
out:
kunmap(page); kunmap(page);
/* only one page here */ /* only one page here */
if (to > inode->i_size) if (to > inode->i_size)
inode->i_size = to; inode->i_size = to;
return err; return 0;
} }
struct address_space_operations udf_adinicb_aops = { struct address_space_operations udf_adinicb_aops = {
...@@ -232,9 +190,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -232,9 +190,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
int result = -EINVAL; int result = -EINVAL;
struct buffer_head *bh = NULL;
long_ad eaicb;
uint8_t *ea = NULL;
if ( permission(inode, MAY_READ) != 0 ) if ( permission(inode, MAY_READ) != 0 )
{ {
...@@ -249,7 +204,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -249,7 +204,6 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return -EINVAL; return -EINVAL;
} }
/* first, do ioctls that don't need to udf_read */
switch (cmd) switch (cmd)
{ {
case UDF_GETVOLIDENT: case UDF_GETVOLIDENT:
...@@ -267,50 +221,16 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, ...@@ -267,50 +221,16 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd,
return result; 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: case UDF_GETEASIZE:
result = put_user(UDF_I_LENEATTR(inode), (int *)arg); result = put_user(UDF_I_LENEATTR(inode), (int *)arg);
break; break;
case UDF_GETEABLOCK: 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; UDF_I_LENEATTR(inode)) ? -EFAULT : 0;
break; break;
} }
udf_release_data(bh);
return result; return result;
} }
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/quotaops.h> #include <linux/quotaops.h>
#include <linux/udf_fs.h> #include <linux/udf_fs.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/slab.h>
#include "udf_i.h" #include "udf_i.h"
#include "udf_sb.h" #include "udf_sb.h"
...@@ -135,13 +136,20 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err) ...@@ -135,13 +136,20 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
inode->i_blocks = 0; inode->i_blocks = 0;
UDF_I_LENEATTR(inode) = 0; UDF_I_LENEATTR(inode) = 0;
UDF_I_LENALLOC(inode) = 0; UDF_I_LENALLOC(inode) = 0;
UDF_I_USE(inode) = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE)) 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_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 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)) if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_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)) 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) ...@@ -152,7 +160,6 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err)
UDF_I_CRTIME(inode) = CURRENT_TIME; UDF_I_CRTIME(inode) = CURRENT_TIME;
UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = UDF_I_UCTIME(inode) =
UDF_I_UCRTIME(inode) = CURRENT_UTIME; UDF_I_UCRTIME(inode) = CURRENT_UTIME;
UDF_I_NEW_INODE(inode) = 1;
insert_inode_hash(inode); insert_inode_hash(inode);
mark_inode_dirty(inode); mark_inode_dirty(inode);
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/pagemap.h> #include <linux/pagemap.h>
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include <linux/slab.h>
#include "udf_i.h" #include "udf_i.h"
#include "udf_sb.h" #include "udf_sb.h"
...@@ -122,6 +123,11 @@ void udf_delete_inode(struct inode * inode) ...@@ -122,6 +123,11 @@ void udf_delete_inode(struct inode * inode)
clear_inode(inode); clear_inode(inode);
} }
void udf_clear_inode(struct inode *inode)
{
kfree(UDF_I_DATA(inode));
}
void udf_discard_prealloc(struct inode * inode) void udf_discard_prealloc(struct inode * inode)
{ {
if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) && if (inode->i_size && inode->i_size != UDF_I_LENEXTENTS(inode) &&
...@@ -162,10 +168,8 @@ struct address_space_operations udf_aops = { ...@@ -162,10 +168,8 @@ struct address_space_operations udf_aops = {
void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
{ {
struct buffer_head *bh = NULL;
struct page *page; struct page *page;
char *kaddr; char *kaddr;
int block;
/* from now on we have normal address_space methods */ /* from now on we have normal address_space methods */
inode->i_data.a_ops = &udf_aops; inode->i_data.a_ops = &udf_aops;
...@@ -180,10 +184,6 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) ...@@ -180,10 +184,6 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
return; 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); page = grab_cache_page(inode->i_mapping, 0);
if (!PageLocked(page)) if (!PageLocked(page))
PAGE_BUG(page); PAGE_BUG(page);
...@@ -192,21 +192,19 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err) ...@@ -192,21 +192,19 @@ void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
kaddr = kmap(page); kaddr = kmap(page);
memset(kaddr + UDF_I_LENALLOC(inode), 0x00, memset(kaddr + UDF_I_LENALLOC(inode), 0x00,
PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode)); 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)); UDF_I_LENALLOC(inode));
flush_dcache_page(page); flush_dcache_page(page);
SetPageUptodate(page); SetPageUptodate(page);
kunmap(page); kunmap(page);
} }
memset(bh->b_data + udf_file_entry_alloc_offset(inode), memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0x00,
0, UDF_I_LENALLOC(inode)); UDF_I_LENALLOC(inode));
UDF_I_LENALLOC(inode) = 0; UDF_I_LENALLOC(inode) = 0;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT; UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
else else
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG; 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) if (inode->i_data.a_ops->writepage(page) == -EAGAIN)
__set_page_dirty_nobuffers(page); __set_page_dirty_nobuffers(page);
...@@ -221,18 +219,21 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int ...@@ -221,18 +219,21 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
struct buffer_head *sbh = NULL, *dbh = NULL; struct buffer_head *sbh = NULL, *dbh = NULL;
lb_addr bloc, eloc; lb_addr bloc, eloc;
uint32_t elen, extoffset; uint32_t elen, extoffset;
uint8_t alloctype;
struct udf_fileident_bh sfibh, dfibh; struct udf_fileident_bh sfibh, dfibh;
loff_t f_pos = udf_ext0_offset(inode) >> 2; loff_t f_pos = udf_ext0_offset(inode) >> 2;
int size = (udf_ext0_offset(inode) + inode->i_size) >> 2; int size = (udf_ext0_offset(inode) + inode->i_size) >> 2;
struct fileIdentDesc cfi, *sfi, *dfi; struct fileIdentDesc cfi, *sfi, *dfi;
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
alloctype = ICBTAG_FLAG_AD_SHORT;
else
alloctype = ICBTAG_FLAG_AD_LONG;
if (!inode->i_size) if (!inode->i_size)
{ {
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) UDF_I_ALLOCTYPE(inode) = alloctype;
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_SHORT;
else
UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_LONG;
mark_inode_dirty(inode); mark_inode_dirty(inode);
return NULL; return NULL;
} }
...@@ -248,9 +249,6 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int ...@@ -248,9 +249,6 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
UDF_I_LOCATION(inode).partitionReferenceNum, 0); UDF_I_LOCATION(inode).partitionReferenceNum, 0);
if (!newblock) if (!newblock)
return NULL; return NULL;
sbh = udf_tread(inode->i_sb, inode->i_ino);
if (!sbh)
return NULL;
dbh = udf_tgetblk(inode->i_sb, newblock); dbh = udf_tgetblk(inode->i_sb, newblock);
if (!dbh) if (!dbh)
return NULL; return NULL;
...@@ -261,18 +259,19 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int ...@@ -261,18 +259,19 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
mark_buffer_dirty_inode(dbh, inode); mark_buffer_dirty_inode(dbh, inode);
sfibh.soffset = sfibh.eoffset = (f_pos & ((inode->i_sb->s_blocksize - 1) >> 2)) << 2; 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.soffset = dfibh.eoffset = 0;
dfibh.sbh = dfibh.ebh = dbh; dfibh.sbh = dfibh.ebh = dbh;
while ( (f_pos < size) ) 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); sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
if (!sfi) if (!sfi)
{ {
udf_release_data(sbh);
udf_release_data(dbh); udf_release_data(dbh);
return NULL; return NULL;
} }
UDF_I_ALLOCTYPE(inode) = alloctype;
sfi->descTag.tagLocation = *block; sfi->descTag.tagLocation = *block;
dfibh.soffset = dfibh.eoffset; dfibh.soffset = dfibh.eoffset;
dfibh.eoffset += (sfibh.eoffset - sfibh.soffset); dfibh.eoffset += (sfibh.eoffset - sfibh.soffset);
...@@ -280,21 +279,15 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int ...@@ -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, if (udf_write_fi(inode, sfi, dfi, &dfibh, sfi->impUse,
sfi->fileIdent + sfi->lengthOfImpUse)) sfi->fileIdent + sfi->lengthOfImpUse))
{ {
udf_release_data(sbh); UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB;
udf_release_data(dbh); udf_release_data(dbh);
return NULL; return NULL;
} }
} }
mark_buffer_dirty_inode(dbh, inode); mark_buffer_dirty_inode(dbh, inode);
memset(sbh->b_data + udf_file_entry_alloc_offset(inode), memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode), 0, UDF_I_LENALLOC(inode));
0, UDF_I_LENALLOC(inode));
UDF_I_LENALLOC(inode) = 0; 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); bloc = UDF_I_LOCATION(inode);
eloc.logicalBlockNum = *block; eloc.logicalBlockNum = *block;
eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum; eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
...@@ -304,7 +297,6 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int ...@@ -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); udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
/* UniqueID stuff */ /* UniqueID stuff */
mark_buffer_dirty(sbh);
udf_release_data(sbh); udf_release_data(sbh);
mark_inode_dirty(inode); mark_inode_dirty(inode);
return dbh; return dbh;
...@@ -725,7 +717,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, ...@@ -725,7 +717,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
if (elen > numalloc) if (elen > numalloc)
{ {
laarr[c].extLength -= laarr[i].extLength -=
(numalloc << inode->i_sb->s_blocksize_bits); (numalloc << inode->i_sb->s_blocksize_bits);
numalloc = 0; numalloc = 0;
} }
...@@ -847,7 +839,6 @@ struct buffer_head * udf_bread(struct inode * inode, int block, ...@@ -847,7 +839,6 @@ struct buffer_head * udf_bread(struct inode * inode, int block,
void udf_truncate(struct inode * inode) void udf_truncate(struct inode * inode)
{ {
int offset; int offset;
struct buffer_head *bh;
int err; int err;
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
...@@ -874,16 +865,8 @@ void udf_truncate(struct inode * inode) ...@@ -874,16 +865,8 @@ void udf_truncate(struct inode * inode)
} }
else else
{ {
offset = (inode->i_size & (inode->i_sb->s_blocksize - 1)) + offset = inode->i_size & (inode->i_sb->s_blocksize - 1);
udf_file_entry_alloc_offset(inode); memset(UDF_I_DATA(inode) + UDF_I_LENEATTR(inode) + offset, 0x00, inode->i_sb->s_blocksize - offset - 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);
}
UDF_I_LENALLOC(inode) = inode->i_size; UDF_I_LENALLOC(inode) = inode->i_size;
} }
} }
...@@ -1031,8 +1014,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -1031,8 +1014,6 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
long convtime_usec; long convtime_usec;
int offset, alen; int offset, alen;
UDF_I_NEW_INODE(inode) = 0;
fe = (struct fileEntry *)bh->b_data; fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)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) ...@@ -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_BLOCK(inode) = 0;
UDF_I_NEXT_ALLOC_GOAL(inode) = 0; UDF_I_NEXT_ALLOC_GOAL(inode) = 0;
if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_EFE) 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) 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) 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) = UDF_I_LENALLOC(inode) =
le32_to_cpu( le32_to_cpu(
((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs); ((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; return;
} }
...@@ -1080,7 +1075,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) ...@@ -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_convert_permissions(fe);
inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask; 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_blocks = le64_to_cpu(fe->logicalBlocksRecorded) <<
(inode->i_sb->s_blocksize_bits - 9); (inode->i_sb->s_blocksize_bits - 9);
...@@ -1326,19 +1321,11 @@ udf_update_inode(struct inode *inode, int do_sync) ...@@ -1326,19 +1321,11 @@ udf_update_inode(struct inode *inode, int do_sync)
udf_debug("bread failure\n"); udf_debug("bread failure\n");
return -EIO; return -EIO;
} }
memset(bh->b_data, 0x00, inode->i_sb->s_blocksize);
fe = (struct fileEntry *)bh->b_data; fe = (struct fileEntry *)bh->b_data;
efe = (struct extendedFileEntry *)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) if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE)
{ {
...@@ -1346,6 +1333,7 @@ udf_update_inode(struct inode *inode, int do_sync) ...@@ -1346,6 +1333,7 @@ udf_update_inode(struct inode *inode, int do_sync)
(struct unallocSpaceEntry *)bh->b_data; (struct unallocSpaceEntry *)bh->b_data;
use->lengthAllocDescs = cpu_to_le32(UDF_I_LENALLOC(inode)); 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) - crclen = sizeof(struct unallocSpaceEntry) + UDF_I_LENALLOC(inode) -
sizeof(tag); sizeof(tag);
use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum); use->descTag.tagLocation = cpu_to_le32(UDF_I_LOCATION(inode).logicalBlockNum);
...@@ -1416,8 +1404,9 @@ udf_update_inode(struct inode *inode, int do_sync) ...@@ -1416,8 +1404,9 @@ udf_update_inode(struct inode *inode, int do_sync)
udf_release_data(tbh); 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( fe->logicalBlocksRecorded = cpu_to_le64(
(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >> (inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >>
(inode->i_sb->s_blocksize_bits - 9)); (inode->i_sb->s_blocksize_bits - 9));
...@@ -1440,6 +1429,7 @@ udf_update_inode(struct inode *inode, int do_sync) ...@@ -1440,6 +1429,7 @@ udf_update_inode(struct inode *inode, int do_sync)
} }
else 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->objectSize = cpu_to_le64(inode->i_size);
efe->logicalBlocksRecorded = cpu_to_le64( efe->logicalBlocksRecorded = cpu_to_le64(
(inode->i_blocks + (1 << (inode->i_sb->s_blocksize_bits - 9)) - 1) >> (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, ...@@ -1620,17 +1610,12 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
long_ad *lad = NULL; long_ad *lad = NULL;
struct allocExtDesc *aed; struct allocExtDesc *aed;
int8_t etype; int8_t etype;
uint8_t *ptr;
if (!(*bh)) if (!*bh)
{ ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
if (!(*bh = udf_tread(inode->i_sb, else
udf_get_lb_pblock(inode->i_sb, *bloc, 0)))) ptr = (*bh)->b_data + *extoffset;
{
udf_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, *bloc, 0));
return -1;
}
}
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(short_ad); adsize = sizeof(short_ad);
...@@ -1669,7 +1654,7 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset, ...@@ -1669,7 +1654,7 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
{ {
loffset = *extoffset; loffset = *extoffset;
aed->lengthAllocDescs = cpu_to_le32(adsize); aed->lengthAllocDescs = cpu_to_le32(adsize);
sptr = (*bh)->b_data + *extoffset - adsize; sptr = ptr - adsize;
dptr = nbh->b_data + sizeof(struct allocExtDesc); dptr = nbh->b_data + sizeof(struct allocExtDesc);
memcpy(dptr, sptr, adsize); memcpy(dptr, sptr, adsize);
*extoffset = sizeof(struct allocExtDesc) + adsize; *extoffset = sizeof(struct allocExtDesc) + adsize;
...@@ -1678,10 +1663,10 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset, ...@@ -1678,10 +1663,10 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
{ {
loffset = *extoffset + adsize; loffset = *extoffset + adsize;
aed->lengthAllocDescs = cpu_to_le32(0); aed->lengthAllocDescs = cpu_to_le32(0);
sptr = (*bh)->b_data + *extoffset; sptr = ptr;
*extoffset = sizeof(struct allocExtDesc); *extoffset = sizeof(struct allocExtDesc);
if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr))) if (*bh)
{ {
aed = (struct allocExtDesc *)(*bh)->b_data; aed = (struct allocExtDesc *)(*bh)->b_data;
aed->lengthAllocDescs = aed->lengthAllocDescs =
...@@ -1721,18 +1706,23 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset, ...@@ -1721,18 +1706,23 @@ int8_t udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
break; break;
} }
} }
if (!UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT) || UDF_SB_UDFREV(inode->i_sb) >= 0x0201) if (*bh)
udf_update_tag((*bh)->b_data, loffset); {
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 else
udf_update_tag((*bh)->b_data, sizeof(struct allocExtDesc)); mark_inode_dirty(inode);
mark_buffer_dirty_inode(*bh, inode);
udf_release_data(*bh);
*bh = nbh; *bh = nbh;
} }
etype = udf_write_aext(inode, *bloc, extoffset, eloc, elen, *bh, inc); 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; UDF_I_LENALLOC(inode) += adsize;
mark_inode_dirty(inode); mark_inode_dirty(inode);
...@@ -1756,49 +1746,40 @@ int8_t udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset, ...@@ -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) lb_addr eloc, uint32_t elen, struct buffer_head *bh, int inc)
{ {
int adsize; int adsize;
short_ad *sad = NULL; uint8_t *ptr;
long_ad *lad = NULL;
if (!(bh)) if (!bh)
{ ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
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 else
{
ptr = bh->b_data + *extoffset;
atomic_inc(&bh->b_count); 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)) switch (UDF_I_ALLOCTYPE(inode))
{ {
case ICBTAG_FLAG_AD_SHORT: 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->extLength = cpu_to_le32(elen);
sad->extPosition = cpu_to_le32(eloc.logicalBlockNum); sad->extPosition = cpu_to_le32(eloc.logicalBlockNum);
adsize = sizeof(short_ad);
break; break;
} }
case ICBTAG_FLAG_AD_LONG: 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->extLength = cpu_to_le32(elen);
lad->extLocation = cpu_to_lelb(eloc); lad->extLocation = cpu_to_lelb(eloc);
memset(lad->impUse, 0x00, sizeof(lad->impUse)); memset(lad->impUse, 0x00, sizeof(lad->impUse));
adsize = sizeof(long_ad);
break; 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) 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, ...@@ -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)); le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct allocExtDesc));
} }
mark_buffer_dirty_inode(bh, inode); mark_buffer_dirty_inode(bh, inode);
udf_release_data(bh);
} }
else else
{
mark_inode_dirty(inode); mark_inode_dirty(inode);
mark_buffer_dirty(bh);
}
if (inc) if (inc)
*extoffset += adsize; *extoffset += adsize;
udf_release_data(bh);
return (elen >> 30); return (elen >> 30);
} }
int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset, 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) lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
{ {
uint16_t tagIdent;
int pos, alen;
int8_t etype; 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, *bloc = *eloc;
udf_get_lb_pblock(inode->i_sb, *bloc, 0)))) *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_debug("reading block %d failed!\n",
udf_get_lb_pblock(inode->i_sb, *bloc, 0)); udf_get_lb_pblock(inode->i_sb, *bloc, 0));
...@@ -1838,154 +1817,38 @@ int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset, ...@@ -1838,154 +1817,38 @@ int8_t udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
} }
} }
tagIdent = le16_to_cpu(((tag *)(*bh)->b_data)->tagIdent); return etype;
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, 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) lb_addr *eloc, uint32_t *elen, struct buffer_head **bh, int inc)
{ {
int pos, alen; int alen;
int8_t etype; int8_t etype;
uint8_t *ptr;
if (!(*bh)) 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 (!(UDF_I_EXTENDED_FE(inode))) if (!(*extoffset))
pos = sizeof(struct fileEntry) + UDF_I_LENEATTR(inode); *extoffset = udf_file_entry_alloc_offset(inode);
else ptr = UDF_I_DATA(inode) + *extoffset - udf_file_entry_alloc_offset(inode) + UDF_I_LENEATTR(inode);
pos = sizeof(struct extendedFileEntry) + UDF_I_LENEATTR(inode); alen = udf_file_entry_alloc_offset(inode) + UDF_I_LENALLOC(inode);
alen = UDF_I_LENALLOC(inode) + pos;
} }
else else
{ {
struct allocExtDesc *aed = (struct allocExtDesc *)(*bh)->b_data; if (!(*extoffset))
*extoffset = sizeof(struct allocExtDesc);
pos = sizeof(struct allocExtDesc); ptr = (*bh)->b_data + *extoffset;
alen = le32_to_cpu(aed->lengthAllocDescs) + pos; alen = le32_to_cpu(((struct allocExtDesc *)(*bh)->b_data)->lengthAllocDescs);
} }
if (!(*extoffset))
*extoffset = pos;
switch (UDF_I_ALLOCTYPE(inode)) switch (UDF_I_ALLOCTYPE(inode))
{ {
case ICBTAG_FLAG_AD_SHORT: case ICBTAG_FLAG_AD_SHORT:
{ {
short_ad *sad; 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; return -1;
etype = le32_to_cpu(sad->extLength) >> 30; etype = le32_to_cpu(sad->extLength) >> 30;
...@@ -1998,7 +1861,7 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset, ...@@ -1998,7 +1861,7 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
{ {
long_ad *lad; 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; return -1;
etype = le32_to_cpu(lad->extLength) >> 30; etype = le32_to_cpu(lad->extLength) >> 30;
...@@ -2012,15 +1875,8 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset, ...@@ -2012,15 +1875,8 @@ int8_t udf_current_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
return -1; return -1;
} }
} }
if (*elen)
return etype;
udf_debug("Empty Extent!\n"); return etype;
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_insert_aext(struct inode *inode, lb_addr bloc, int extoffset, 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, ...@@ -2030,17 +1886,7 @@ int8_t udf_insert_aext(struct inode *inode, lb_addr bloc, int extoffset,
uint32_t oelen; uint32_t oelen;
int8_t etype; int8_t etype;
if (!bh) 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
atomic_inc(&bh->b_count); atomic_inc(&bh->b_count);
while ((etype = udf_next_aext(inode, &bloc, &extoffset, &oeloc, &oelen, &bh, 0)) != -1) 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, ...@@ -2064,19 +1910,11 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
int8_t etype; int8_t etype;
struct allocExtDesc *aed; struct allocExtDesc *aed;
if (!(nbh)) if (nbh)
{ {
if (!(nbh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, nbloc, 0))))
{
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);
atomic_inc(&nbh->b_count); atomic_inc(&nbh->b_count);
}
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT) if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_SHORT)
adsize = sizeof(short_ad); adsize = sizeof(short_ad);
...@@ -2095,7 +1933,7 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset, ...@@ -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) 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); udf_write_aext(inode, obloc, &oextoffset, eloc, (etype << 30) | elen, obh, 1);
if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) if (obh != nbh)
{ {
obloc = nbloc; obloc = nbloc;
udf_release_data(obh); udf_release_data(obh);
...@@ -2107,12 +1945,12 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset, ...@@ -2107,12 +1945,12 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
memset(&eloc, 0x00, sizeof(lb_addr)); memset(&eloc, 0x00, sizeof(lb_addr));
elen = 0; elen = 0;
if (memcmp(&nbloc, &obloc, sizeof(lb_addr))) if (nbh != obh)
{ {
udf_free_blocks(inode->i_sb, inode, nbloc, 0, 1); 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);
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); UDF_I_LENALLOC(inode) -= (adsize * 2);
mark_inode_dirty(inode); mark_inode_dirty(inode);
...@@ -2132,7 +1970,7 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset, ...@@ -2132,7 +1970,7 @@ int8_t udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
else else
{ {
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; UDF_I_LENALLOC(inode) -= adsize;
mark_inode_dirty(inode); mark_inode_dirty(inode);
...@@ -2207,9 +2045,7 @@ long udf_block_map(struct inode *inode, long block) ...@@ -2207,9 +2045,7 @@ long udf_block_map(struct inode *inode, long block)
ret = 0; ret = 0;
unlock_kernel(); unlock_kernel();
udf_release_data(bh);
if (bh)
udf_release_data(bh);
if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV)) if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
return udf_fixed_to_variable(ret); return udf_fixed_to_variable(ret);
......
...@@ -71,15 +71,10 @@ unsigned long ...@@ -71,15 +71,10 @@ unsigned long
udf_get_last_block(struct super_block *sb) udf_get_last_block(struct super_block *sb)
{ {
struct block_device *bdev = sb->s_bdev; struct block_device *bdev = sb->s_bdev;
int ret;
unsigned long lblock = 0; unsigned long lblock = 0;
ret = ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock); if (ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock))
if (ret) /* Hard Disk */
{
lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits; lblock = bdev->bd_inode->i_size >> sb->s_blocksize_bits;
}
if (lblock) if (lblock)
return lblock - 1; return lblock - 1;
......
...@@ -74,7 +74,7 @@ udf_add_extendedattr(struct inode * inode, uint32_t size, uint32_t type, ...@@ -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); *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; struct fileEntry *fe;
...@@ -190,7 +190,7 @@ udf_get_extendedattr(struct inode * inode, uint32_t type, uint8_t subtype, ...@@ -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); *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; struct fileEntry *fe;
...@@ -269,10 +269,10 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1 ...@@ -269,10 +269,10 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1
if (block == 0xFFFFFFFF) if (block == 0xFFFFFFFF)
return NULL; return NULL;
bh = udf_tread(sb, block); bh = udf_tread(sb, block + UDF_SB_SESSION(sb));
if (!bh) 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; return NULL;
} }
...@@ -283,7 +283,7 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1 ...@@ -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) ) if ( location != le32_to_cpu(tag_p->tagLocation) )
{ {
udf_debug("location mismatch block %u, tag %u != %u\n", 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; goto error_out;
} }
...@@ -315,7 +315,7 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1 ...@@ -315,7 +315,7 @@ udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint1
return bh; return bh;
} }
udf_debug("Crc failure block %d: crc = %d, crclen = %d\n", 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: error_out:
brelse(bh); brelse(bh);
......
...@@ -56,12 +56,16 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, ...@@ -56,12 +56,16 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
uint8_t lfi = cfi->lengthFileIdent; uint8_t lfi = cfi->lengthFileIdent;
int padlen = fibh->eoffset - fibh->soffset - liu - lfi - int padlen = fibh->eoffset - fibh->soffset - liu - lfi -
sizeof(struct fileIdentDesc); sizeof(struct fileIdentDesc);
int adinicb = 0;
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
adinicb = 1;
offset = fibh->soffset + sizeof(struct fileIdentDesc); offset = fibh->soffset + sizeof(struct fileIdentDesc);
if (impuse) if (impuse)
{ {
if (offset + liu < 0) if (adinicb || (offset + liu < 0))
memcpy((uint8_t *)sfi->impUse, impuse, liu); memcpy((uint8_t *)sfi->impUse, impuse, liu);
else if (offset >= 0) else if (offset >= 0)
memcpy(fibh->ebh->b_data + offset, impuse, liu); memcpy(fibh->ebh->b_data + offset, impuse, liu);
...@@ -76,7 +80,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, ...@@ -76,7 +80,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
if (fileident) if (fileident)
{ {
if (offset + lfi < 0) if (adinicb || (offset + lfi < 0))
memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi); memcpy((uint8_t *)sfi->fileIdent + liu, fileident, lfi);
else if (offset >= 0) else if (offset >= 0)
memcpy(fibh->ebh->b_data + offset, fileident, lfi); memcpy(fibh->ebh->b_data + offset, fileident, lfi);
...@@ -89,7 +93,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, ...@@ -89,7 +93,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
offset += lfi; offset += lfi;
if (offset + padlen < 0) if (adinicb || (offset + padlen < 0))
memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen); memset((uint8_t *)sfi->padding + liu + lfi, 0x00, padlen);
else if (offset >= 0) else if (offset >= 0)
memset(fibh->ebh->b_data + offset, 0x00, padlen); memset(fibh->ebh->b_data + offset, 0x00, padlen);
...@@ -123,7 +127,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, ...@@ -123,7 +127,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
checksum += ((uint8_t *)&cfi->descTag)[i]; checksum += ((uint8_t *)&cfi->descTag)[i];
cfi->descTag.tagChecksum = checksum; 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)); memcpy((uint8_t *)sfi, (uint8_t *)cfi, sizeof(struct fileIdentDesc));
else else
{ {
...@@ -132,9 +136,14 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, ...@@ -132,9 +136,14 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi,
sizeof(struct fileIdentDesc) + fibh->soffset); sizeof(struct fileIdentDesc) + fibh->soffset);
} }
if (fibh->sbh != fibh->ebh) if (adinicb)
mark_buffer_dirty_inode(fibh->ebh, inode); mark_inode_dirty(inode);
mark_buffer_dirty_inode(fibh->sbh, inode); else
{
if (fibh->sbh != fibh->ebh)
mark_buffer_dirty_inode(fibh->ebh, inode);
mark_buffer_dirty_inode(fibh->sbh, inode);
}
return 0; return 0;
} }
...@@ -161,7 +170,9 @@ udf_find_entry(struct inode *dir, struct dentry *dentry, ...@@ -161,7 +170,9 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
f_pos = (udf_ext0_offset(dir) >> 2); f_pos = (udf_ext0_offset(dir) >> 2);
fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 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)) &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
{ {
offset >>= dir->i_sb->s_blocksize_bits; offset >>= dir->i_sb->s_blocksize_bits;
...@@ -175,6 +186,12 @@ udf_find_entry(struct inode *dir, struct dentry *dentry, ...@@ -175,6 +186,12 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
} }
else else
offset = 0; offset = 0;
if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
return NULL;
}
} }
else else
{ {
...@@ -182,12 +199,6 @@ udf_find_entry(struct inode *dir, struct dentry *dentry, ...@@ -182,12 +199,6 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
return NULL; return NULL;
} }
if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
return NULL;
}
while ( (f_pos < size) ) while ( (f_pos < size) )
{ {
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh); fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
...@@ -304,7 +315,8 @@ udf_lookup(struct inode *dir, struct dentry *dentry) ...@@ -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) }; lb_addr lb = { 0, simple_strtoul(dentry->d_name.name+3, NULL, 0) };
inode = udf_iget(dir->i_sb, lb); inode = udf_iget(dir->i_sb, lb);
if (!inode) { if (!inode)
{
unlock_kernel(); unlock_kernel();
return ERR_PTR(-EACCES); return ERR_PTR(-EACCES);
} }
...@@ -319,7 +331,8 @@ udf_lookup(struct inode *dir, struct dentry *dentry) ...@@ -319,7 +331,8 @@ udf_lookup(struct inode *dir, struct dentry *dentry)
udf_release_data(fibh.sbh); udf_release_data(fibh.sbh);
inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation)); inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation));
if ( !inode ) { if ( !inode )
{
unlock_kernel(); unlock_kernel();
return ERR_PTR(-EACCES); return ERR_PTR(-EACCES);
} }
...@@ -336,7 +349,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry, ...@@ -336,7 +349,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
{ {
struct super_block *sb; struct super_block *sb;
struct fileIdentDesc *fi=NULL; struct fileIdentDesc *fi=NULL;
struct ustr unifilename;
char name[UDF_NAME_LEN], fname[UDF_NAME_LEN]; char name[UDF_NAME_LEN], fname[UDF_NAME_LEN];
int namelen; int namelen;
loff_t f_pos; loff_t f_pos;
...@@ -361,30 +373,11 @@ udf_add_entry(struct inode *dir, struct dentry *dentry, ...@@ -361,30 +373,11 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
return NULL; return NULL;
} }
if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) ) if ( !(namelen = udf_put_filename(sb, dentry->d_name.name, name, dentry->d_name.len)))
{ {
*err = -ENAMETOOLONG; *err = -ENAMETOOLONG;
return NULL; 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)) )
{
*err = -ENAMETOOLONG;
return NULL;
}
}
else
return NULL;
} }
else else
namelen = 0; namelen = 0;
...@@ -394,7 +387,9 @@ udf_add_entry(struct inode *dir, struct dentry *dentry, ...@@ -394,7 +387,9 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
f_pos = (udf_ext0_offset(dir) >> 2); f_pos = (udf_ext0_offset(dir) >> 2);
fibh->soffset = fibh->eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 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)) &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
{ {
offset >>= dir->i_sb->s_blocksize_bits; offset >>= dir->i_sb->s_blocksize_bits;
...@@ -415,94 +410,89 @@ udf_add_entry(struct inode *dir, struct dentry *dentry, ...@@ -415,94 +410,89 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
*err = -EIO; *err = -EIO;
return NULL; return NULL;
} }
block = UDF_I_LOCATION(dir).logicalBlockNum; block = UDF_I_LOCATION(dir).logicalBlockNum;
while ( (f_pos < size) ) }
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);
if (!fi)
{ {
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh); if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
if (!fi) udf_release_data(fibh->sbh);
{ udf_release_data(bh);
if (fibh->sbh != fibh->ebh) *err = -EIO;
udf_release_data(fibh->ebh); return NULL;
udf_release_data(fibh->sbh); }
udf_release_data(bh);
*err = -EIO; liu = le16_to_cpu(cfi->lengthOfImpUse);
return NULL; lfi = cfi->lengthFileIdent;
}
if (fibh->sbh == fibh->ebh)
liu = le16_to_cpu(cfi->lengthOfImpUse); nameptr = fi->fileIdent + liu;
lfi = cfi->lengthFileIdent; else
{
if (fibh->sbh == fibh->ebh) int poffset; /* Unpaded ending offset */
nameptr = fi->fileIdent + liu;
poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi;
if (poffset >= lfi)
nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
else else
{ {
int poffset; /* Unpaded ending offset */ nameptr = fname;
memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
poffset = fibh->soffset + sizeof(struct fileIdentDesc) + liu + lfi; memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
if (poffset >= lfi)
nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
else
{
nameptr = fname;
memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
}
} }
}
if ( (cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
if ( (cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0 )
{
if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
{ {
if (((sizeof(struct fileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen) udf_release_data(bh);
cfi->descTag.tagSerialNum = cpu_to_le16(1);
cfi->fileVersionNum = cpu_to_le16(1);
cfi->fileCharacteristics = 0;
cfi->lengthFileIdent = namelen;
cfi->lengthOfImpUse = cpu_to_le16(0);
if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
return fi;
else
{ {
udf_release_data(bh); *err = -EIO;
cfi->descTag.tagSerialNum = cpu_to_le16(1); return NULL;
cfi->fileVersionNum = cpu_to_le16(1);
cfi->fileCharacteristics = 0;
cfi->lengthFileIdent = namelen;
cfi->lengthOfImpUse = cpu_to_le16(0);
if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name))
return fi;
else
{
*err = -EIO;
return NULL;
}
} }
} }
}
if (!lfi || !dentry) if (!lfi || !dentry)
continue; continue;
if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) && if ((flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi)) &&
udf_match(flen, fname, &(dentry->d_name))) udf_match(flen, fname, &(dentry->d_name)))
{
if (fibh->sbh != fibh->ebh)
udf_release_data(fibh->ebh);
udf_release_data(fibh->sbh);
udf_release_data(bh);
*err = -EEXIST;
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); if (fibh->sbh != fibh->ebh)
fibh->soffset = fibh->eoffset = udf_file_entry_alloc_offset(dir); udf_release_data(fibh->ebh);
} udf_release_data(fibh->sbh);
else udf_release_data(bh);
{ *err = -EEXIST;
fibh->sbh = fibh->ebh = NULL; return NULL;
fibh->soffset = fibh->eoffset = sb->s_blocksize;
} }
} }
add:
f_pos += nfidlen; f_pos += nfidlen;
if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB && if (UDF_I_ALLOCTYPE(dir) == ICBTAG_FLAG_AD_IN_ICB &&
...@@ -539,13 +529,17 @@ udf_add_entry(struct inode *dir, struct dentry *dentry, ...@@ -539,13 +529,17 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
fibh->sbh = fibh->ebh; 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) >> block = eloc.logicalBlockNum + ((elen - 1) >>
dir->i_sb->s_blocksize_bits); dir->i_sb->s_blocksize_bits);
else fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
block = UDF_I_LOCATION(dir).logicalBlockNum; }
fi = (struct fileIdentDesc *)(fibh->sbh->b_data + fibh->soffset);
} }
else else
{ {
...@@ -635,7 +629,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode) ...@@ -635,7 +629,8 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode)
lock_kernel(); lock_kernel();
inode = udf_new_inode(dir, mode, &err); inode = udf_new_inode(dir, mode, &err);
if (!inode) { if (!inode)
{
unlock_kernel(); unlock_kernel();
return err; return err;
} }
...@@ -796,7 +791,10 @@ static int empty_dir(struct inode *dir) ...@@ -796,7 +791,10 @@ static int empty_dir(struct inode *dir)
f_pos = (udf_ext0_offset(dir) >> 2); f_pos = (udf_ext0_offset(dir) >> 2);
fibh.soffset = fibh.eoffset = (f_pos & ((dir->i_sb->s_blocksize - 1) >> 2)) << 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)) &bloc, &extoffset, &eloc, &elen, &offset, &bh) == (EXT_RECORDED_ALLOCATED >> 30))
{ {
offset >>= dir->i_sb->s_blocksize_bits; offset >>= dir->i_sb->s_blocksize_bits;
...@@ -810,6 +808,12 @@ static int empty_dir(struct inode *dir) ...@@ -810,6 +808,12 @@ static int empty_dir(struct inode *dir)
} }
else else
offset = 0; offset = 0;
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
{
udf_release_data(bh);
return 0;
}
} }
else else
{ {
...@@ -817,8 +821,6 @@ static int empty_dir(struct inode *dir) ...@@ -817,8 +821,6 @@ static int empty_dir(struct inode *dir)
return 0; return 0;
} }
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block)))
return 0;
while ( (f_pos < size) ) while ( (f_pos < size) )
{ {
...@@ -835,6 +837,9 @@ static int empty_dir(struct inode *dir) ...@@ -835,6 +837,9 @@ static int empty_dir(struct inode *dir)
if (cfi.lengthFileIdent && (cfi.fileCharacteristics & FID_FILE_CHAR_DELETED) == 0) 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); udf_release_data(bh);
return 0; return 0;
} }
...@@ -950,6 +955,8 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char * ...@@ -950,6 +955,8 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
char *ea; char *ea;
int err; int err;
int block; int block;
char name[UDF_NAME_LEN];
int namelen;
lock_kernel(); lock_kernel();
if (!(inode = udf_new_inode(dir, S_IFLNK, &err))) 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 * ...@@ -987,13 +994,10 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
unlock_buffer(bh); unlock_buffer(bh);
mark_buffer_dirty_inode(bh, inode); mark_buffer_dirty_inode(bh, inode);
ea = bh->b_data + udf_ext0_offset(inode);
} }
else else
{ ea = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
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);
eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode); eoffset = inode->i_sb->s_blocksize - udf_ext0_offset(inode);
pc = (struct pathComponent *)ea; pc = (struct pathComponent *)ea;
...@@ -1031,22 +1035,25 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char * ...@@ -1031,22 +1035,25 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
pc->componentType = 5; pc->componentType = 5;
pc->lengthComponentIdent = 0; pc->lengthComponentIdent = 0;
pc->componentFileVersionNum = 0; pc->componentFileVersionNum = 0;
if (pc->componentIdent[0] == '.') if (compstart[0] == '.')
{ {
if (pc->lengthComponentIdent == 1) if ((symname-compstart) == 1)
pc->componentType = 4; pc->componentType = 4;
else if (pc->lengthComponentIdent == 2 && pc->componentIdent[1] == '.') else if ((symname-compstart) == 2 && compstart[1] == '.')
pc->componentType = 3; pc->componentType = 3;
} }
if (pc->componentType == 5) 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; goto out_no_entry;
else 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; elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
...@@ -1114,12 +1121,14 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir, ...@@ -1114,12 +1121,14 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
struct fileIdentDesc cfi, *fi; struct fileIdentDesc cfi, *fi;
lock_kernel(); lock_kernel();
if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1) { if (inode->i_nlink >= (256<<sizeof(inode->i_nlink))-1)
{
unlock_kernel(); unlock_kernel();
return -EMLINK; return -EMLINK;
} }
if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err))) { if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
{
unlock_kernel(); unlock_kernel();
return err; return err;
} }
...@@ -1204,10 +1213,21 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry, ...@@ -1204,10 +1213,21 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
goto end_rename; goto end_rename;
} }
retval = -EIO; retval = -EIO;
dir_bh = udf_bread(old_inode, 0, 0, &retval); if (UDF_I_ALLOCTYPE(old_inode) == ICBTAG_FLAG_AD_IN_ICB)
if (!dir_bh) {
goto end_rename; dir_fi = udf_get_fileident(UDF_I_DATA(old_inode) -
dir_fi = udf_get_fileident(dir_bh->b_data, old_inode->i_sb->s_blocksize, &offset); (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) if (!dir_fi)
goto end_rename; goto end_rename;
if (udf_get_lb_pblock(old_inode->i_sb, cpu_to_lelb(dir_fi->icb.extLocation), 0) != 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, ...@@ -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; UDF_I_UCTIME(old_dir) = UDF_I_UMTIME(old_dir) = CURRENT_UTIME;
mark_inode_dirty(old_dir); mark_inode_dirty(old_dir);
if (dir_bh) if (dir_fi)
{ {
dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir)); dir_fi->icb.extLocation = lelb_to_cpu(UDF_I_LOCATION(new_dir));
udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) + udf_update_tag((char *)dir_fi, (sizeof(struct fileIdentDesc) +
......
...@@ -83,7 +83,7 @@ struct appIdentSuffix ...@@ -83,7 +83,7 @@ struct appIdentSuffix
{ {
uint8_t impUse[8]; uint8_t impUse[8];
} __attribute__ ((packed)); } __attribute__ ((packed));
/* Logical Volume Integrity Descriptor (UDF 2.01 2.2.6) */ /* Logical Volume Integrity Descriptor (UDF 2.01 2.2.6) */
/* Implementation Use (UDF 2.01 2.2.6.4) */ /* Implementation Use (UDF 2.01 2.2.6.4) */
struct logicalVolIntegrityDescImpUse struct logicalVolIntegrityDescImpUse
......
...@@ -135,7 +135,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) ...@@ -135,7 +135,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags)
SLAB_CTOR_CONSTRUCTOR) SLAB_CTOR_CONSTRUCTOR)
inode_init_once(&ei->vfs_inode); inode_init_once(&ei->vfs_inode);
} }
static int init_inodecache(void) static int init_inodecache(void)
{ {
udf_inode_cachep = kmem_cache_create("udf_inode_cache", udf_inode_cachep = kmem_cache_create("udf_inode_cache",
...@@ -161,6 +161,7 @@ static struct super_operations udf_sb_ops = { ...@@ -161,6 +161,7 @@ static struct super_operations udf_sb_ops = {
.write_inode = udf_write_inode, .write_inode = udf_write_inode,
.put_inode = udf_put_inode, .put_inode = udf_put_inode,
.delete_inode = udf_delete_inode, .delete_inode = udf_delete_inode,
.clear_inode = udf_clear_inode,
.put_super = udf_put_super, .put_super = udf_put_super,
.write_super = udf_write_super, .write_super = udf_write_super,
.statfs = udf_statfs, .statfs = udf_statfs,
...@@ -285,7 +286,8 @@ udf_parse_options(char *options, struct udf_options *uopt) ...@@ -285,7 +286,8 @@ udf_parse_options(char *options, struct udf_options *uopt)
if (!options) if (!options)
return 1; return 1;
while ((opt = strsep(&options, ",")) != NULL) { while ((opt = strsep(&options, ",")) != NULL)
{
if (!*opt) if (!*opt)
continue; continue;
/* Make "opt=val" into two strings */ /* Make "opt=val" into two strings */
...@@ -383,10 +385,6 @@ udf_remount_fs(struct super_block *sb, int *flags, char *options) ...@@ -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_gid = uopt.gid;
UDF_SB(sb)->s_umask = uopt.umask; UDF_SB(sb)->s_umask = uopt.umask;
#if UDFFS_RW != 1
*flags |= MS_RDONLY;
#endif
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0; return 0;
if (*flags & MS_RDONLY) if (*flags & MS_RDONLY)
...@@ -591,14 +589,14 @@ udf_find_anchor(struct super_block *sb) ...@@ -591,14 +589,14 @@ udf_find_anchor(struct super_block *sb)
{ {
if (location == last[i] - UDF_SB_SESSION(sb)) if (location == last[i] - UDF_SB_SESSION(sb))
{ {
lastblock = UDF_SB_ANCHOR(sb)[0] = last[i]; lastblock = UDF_SB_ANCHOR(sb)[0] = last[i] - UDF_SB_SESSION(sb);
UDF_SB_ANCHOR(sb)[1] = last[i] - 256; 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)) else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
{ {
UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]); 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_ANCHOR(sb)[1] = lastblock - 256 - UDF_SB_SESSION(sb);
} }
else else
udf_debug("Anchor found at block %d, location mismatch %d.\n", udf_debug("Anchor found at block %d, location mismatch %d.\n",
...@@ -607,7 +605,7 @@ udf_find_anchor(struct super_block *sb) ...@@ -607,7 +605,7 @@ udf_find_anchor(struct super_block *sb)
else if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE) else if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE)
{ {
lastblock = last[i]; lastblock = last[i];
UDF_SB_ANCHOR(sb)[3] = 512 + UDF_SB_SESSION(sb); UDF_SB_ANCHOR(sb)[3] = 512;
} }
else else
{ {
...@@ -852,7 +850,7 @@ udf_load_partdesc(struct super_block *sb, struct buffer_head *bh) ...@@ -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)) 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_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) if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_READ_ONLY)
UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_READ_ONLY; UDF_SB_PARTFLAGS(sb,i) |= UDF_PART_FLAG_READ_ONLY;
if (le32_to_cpu(p->accessType) == PD_ACCESS_TYPE_WRITE_ONCE) 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) ...@@ -1428,10 +1426,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
sb->s_fs_info = sbi; sb->s_fs_info = sbi;
memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info)); 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)) if (!udf_parse_options((char *)options, &uopt))
goto error_out; goto error_out;
...@@ -1478,7 +1472,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) ...@@ -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_LASTBLOCK(sb) = uopt.lastblock;
UDF_SB_ANCHOR(sb)[0] = UDF_SB_ANCHOR(sb)[1] = 0; UDF_SB_ANCHOR(sb)[0] = UDF_SB_ANCHOR(sb)[1] = 0;
UDF_SB_ANCHOR(sb)[2] = uopt.anchor; 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 */ 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) ...@@ -1543,8 +1537,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
{ {
timestamp ts; timestamp ts;
udf_time_to_stamp(&ts, UDF_SB_RECORDTIME(sb), 0); 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", udf_info("UDF %s (%s) Mounting volume '%s', timestamp %04u/%02u/%02u %02u:%02u (%x)\n",
UDFFS_VERSION, UDFFS_RW ? "rw" : "ro", UDFFS_DATE, UDFFS_VERSION, UDFFS_DATE,
UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute, UDF_SB_VOLIDENT(sb), ts.year, ts.month, ts.day, ts.hour, ts.minute,
ts.typeAndTimezone); ts.typeAndTimezone);
} }
...@@ -1726,8 +1720,6 @@ udf_put_super(struct super_block *sb) ...@@ -1726,8 +1720,6 @@ udf_put_super(struct super_block *sb)
static int static int
udf_statfs(struct super_block *sb, struct statfs *buf) udf_statfs(struct super_block *sb, struct statfs *buf)
{ {
lock_kernel();
buf->f_type = UDF_SUPER_MAGIC; buf->f_type = UDF_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize; buf->f_bsize = sb->s_blocksize;
buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)); buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb));
...@@ -1740,8 +1732,6 @@ udf_statfs(struct super_block *sb, struct statfs *buf) ...@@ -1740,8 +1732,6 @@ udf_statfs(struct super_block *sb, struct statfs *buf)
/* __kernel_fsid_t f_fsid */ /* __kernel_fsid_t f_fsid */
buf->f_namelen = UDF_NAME_LEN; buf->f_namelen = UDF_NAME_LEN;
unlock_kernel();
return 0; return 0;
} }
...@@ -1763,6 +1753,8 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap) ...@@ -1763,6 +1753,8 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
uint16_t ident; uint16_t ident;
struct spaceBitmapDesc *bm; struct spaceBitmapDesc *bm;
lock_kernel();
loc.logicalBlockNum = bitmap->s_extPosition; loc.logicalBlockNum = bitmap->s_extPosition;
loc.partitionReferenceNum = UDF_SB_PARTITION(sb); loc.partitionReferenceNum = UDF_SB_PARTITION(sb);
bh = udf_read_ptagged(sb, loc, 0, &ident); bh = udf_read_ptagged(sb, loc, 0, &ident);
...@@ -1770,13 +1762,13 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap) ...@@ -1770,13 +1762,13 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
if (!bh) if (!bh)
{ {
printk(KERN_ERR "udf: udf_count_free failed\n"); printk(KERN_ERR "udf: udf_count_free failed\n");
return 0; goto out;
} }
else if (ident != TAG_IDENT_SBD) else if (ident != TAG_IDENT_SBD)
{ {
udf_release_data(bh); udf_release_data(bh);
printk(KERN_ERR "udf: udf_count_free failed\n"); printk(KERN_ERR "udf: udf_count_free failed\n");
return 0; goto out;
} }
bm = (struct spaceBitmapDesc *)bh->b_data; bm = (struct spaceBitmapDesc *)bh->b_data;
...@@ -1802,13 +1794,17 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap) ...@@ -1802,13 +1794,17 @@ udf_count_free_bitmap(struct super_block *sb, struct udf_bitmap *bitmap)
if (!bh) if (!bh)
{ {
udf_debug("read failed\n"); udf_debug("read failed\n");
return accum; goto out;
} }
index = 0; index = 0;
ptr = (uint8_t *)bh->b_data; ptr = (uint8_t *)bh->b_data;
} }
} }
udf_release_data(bh); udf_release_data(bh);
out:
unlock_kernel();
return accum; return accum;
} }
...@@ -1821,6 +1817,8 @@ udf_count_free_table(struct super_block *sb, struct inode * table) ...@@ -1821,6 +1817,8 @@ udf_count_free_table(struct super_block *sb, struct inode * table)
int8_t etype; int8_t etype;
struct buffer_head *bh = NULL; struct buffer_head *bh = NULL;
lock_kernel();
bloc = UDF_I_LOCATION(table); bloc = UDF_I_LOCATION(table);
extoffset = sizeof(struct unallocSpaceEntry); extoffset = sizeof(struct unallocSpaceEntry);
...@@ -1829,6 +1827,9 @@ udf_count_free_table(struct super_block *sb, struct inode * table) ...@@ -1829,6 +1827,9 @@ udf_count_free_table(struct super_block *sb, struct inode * table)
accum += (elen >> table->i_sb->s_blocksize_bits); accum += (elen >> table->i_sb->s_blocksize_bits);
} }
udf_release_data(bh); udf_release_data(bh);
unlock_kernel();
return accum; return accum;
} }
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include <linux/buffer_head.h> #include <linux/buffer_head.h>
#include "udf_i.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; struct pathComponent *pc;
int elen = 0; int elen = 0;
...@@ -66,9 +66,9 @@ static void udf_pc_to_char(char *from, int fromlen, char *to) ...@@ -66,9 +66,9 @@ static void udf_pc_to_char(char *from, int fromlen, char *to)
/* that would be . - just ignore */ /* that would be . - just ignore */
break; break;
case 5: case 5:
memcpy(p, pc->componentIdent, pc->lengthComponentIdent); p += udf_get_filename(sb, pc->componentIdent, p, pc->lengthComponentIdent);
p += pc->lengthComponentIdent;
*p++ = '/'; *p++ = '/';
break;
} }
elen += sizeof(struct pathComponent) + pc->lengthComponentIdent; elen += sizeof(struct pathComponent) + pc->lengthComponentIdent;
} }
...@@ -85,17 +85,10 @@ static int udf_symlink_filler(struct file *file, struct page *page) ...@@ -85,17 +85,10 @@ static int udf_symlink_filler(struct file *file, struct page *page)
char *symlink; char *symlink;
int err = -EIO; int err = -EIO;
char *p = kmap(page); char *p = kmap(page);
lock_kernel(); lock_kernel();
if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB) if (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB)
{ symlink = UDF_I_DATA(inode) + UDF_I_LENEATTR(inode);
bh = udf_tread(inode->i_sb, inode->i_ino);
if (!bh)
goto out;
symlink = bh->b_data + udf_file_entry_alloc_offset(inode);
}
else else
{ {
bh = sb_bread(inode->i_sb, udf_block_map(inode, 0)); 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) ...@@ -106,7 +99,7 @@ static int udf_symlink_filler(struct file *file, struct page *page)
symlink = bh->b_data; 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); udf_release_data(bh);
unlock_kernel(); unlock_kernel();
......
...@@ -95,7 +95,7 @@ void udf_truncate_extents(struct inode * inode) ...@@ -95,7 +95,7 @@ void udf_truncate_extents(struct inode * inode)
else else
lenalloc = extoffset - adsize; lenalloc = extoffset - adsize;
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr))) if (!bh)
lenalloc -= udf_file_entry_alloc_offset(inode); lenalloc -= udf_file_entry_alloc_offset(inode);
else else
lenalloc -= sizeof(struct allocExtDesc); lenalloc -= sizeof(struct allocExtDesc);
...@@ -108,15 +108,15 @@ void udf_truncate_extents(struct inode * inode) ...@@ -108,15 +108,15 @@ void udf_truncate_extents(struct inode * inode)
extoffset = 0; extoffset = 0;
if (lelen) if (lelen)
{ {
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr))) if (!bh)
memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode)); BUG();
else else
memset(bh->b_data, 0x00, sizeof(struct allocExtDesc)); memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen); udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
} }
else else
{ {
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr))) if (!bh)
{ {
UDF_I_LENALLOC(inode) = lenalloc; UDF_I_LENALLOC(inode) = lenalloc;
mark_inode_dirty(inode); mark_inode_dirty(inode);
...@@ -135,9 +135,9 @@ void udf_truncate_extents(struct inode * inode) ...@@ -135,9 +135,9 @@ void udf_truncate_extents(struct inode * inode)
} }
udf_release_data(bh); udf_release_data(bh);
bh = NULL; extoffset = sizeof(struct allocExtDesc);
bloc = eloc; bloc = eloc;
bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, bloc, 0));
if (elen) if (elen)
lelen = (elen + inode->i_sb->s_blocksize - 1) >> lelen = (elen + inode->i_sb->s_blocksize - 1) >>
inode->i_sb->s_blocksize_bits; inode->i_sb->s_blocksize_bits;
...@@ -153,15 +153,15 @@ void udf_truncate_extents(struct inode * inode) ...@@ -153,15 +153,15 @@ void udf_truncate_extents(struct inode * inode)
if (lelen) if (lelen)
{ {
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr))) if (!bh)
memset(bh->b_data, 0x00, udf_file_entry_alloc_offset(inode)); BUG();
else else
memset(bh->b_data, 0x00, sizeof(struct allocExtDesc)); memset(bh->b_data, 0x00, sizeof(struct allocExtDesc));
udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen); udf_free_blocks(inode->i_sb, inode, bloc, 0, lelen);
} }
else else
{ {
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr))) if (!bh)
{ {
UDF_I_LENALLOC(inode) = lenalloc; UDF_I_LENALLOC(inode) = lenalloc;
mark_inode_dirty(inode); mark_inode_dirty(inode);
......
...@@ -13,14 +13,17 @@ static inline struct udf_inode_info *UDF_I(struct inode *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_LENEXTENTS(X) ( UDF_I(X)->i_lenExtents )
#define UDF_I_UNIQUE(X) ( UDF_I(X)->i_unique ) #define UDF_I_UNIQUE(X) ( UDF_I(X)->i_unique )
#define UDF_I_ALLOCTYPE(X) ( UDF_I(X)->i_alloc_type ) #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_EFE(X) ( UDF_I(X)->i_efe )
#define UDF_I_STRAT4096(X) ( UDF_I(X)->i_strat_4096 ) #define UDF_I_USE(X) ( UDF_I(X)->i_use )
#define UDF_I_NEW_INODE(X) ( UDF_I(X)->i_new_inode ) #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_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_NEXT_ALLOC_GOAL(X) ( UDF_I(X)->i_next_alloc_goal )
#define UDF_I_UMTIME(X) ( UDF_I(X)->i_umtime ) #define UDF_I_UMTIME(X) ( UDF_I(X)->i_umtime )
#define UDF_I_UCTIME(X) ( UDF_I(X)->i_uctime ) #define UDF_I_UCTIME(X) ( UDF_I(X)->i_uctime )
#define UDF_I_CRTIME(X) ( UDF_I(X)->i_crtime ) #define UDF_I_CRTIME(X) ( UDF_I(X)->i_crtime )
#define UDF_I_UCRTIME(X) ( UDF_I(X)->i_ucrtime ) #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) */ #endif /* !defined(_LINUX_UDF_I_H) */
...@@ -16,10 +16,6 @@ ...@@ -16,10 +16,6 @@
#include <linux/version.h> #include <linux/version.h>
#endif #endif
#if !defined(CONFIG_UDF_FS) && !defined(CONFIG_UDF_FS_MODULE)
#define CONFIG_UDF_FS_MODULE
#endif
#include "udfend.h" #include "udfend.h"
#define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) ) #define udf_fixed_to_variable(x) ( ( ( (x) >> 5 ) * 39 ) + ( (x) & 0x0000001F ) )
...@@ -35,9 +31,11 @@ ...@@ -35,9 +31,11 @@
#define CURRENT_UTIME (xtime.tv_nsec / 1000) #define CURRENT_UTIME (xtime.tv_nsec / 1000)
#define udf_file_entry_alloc_offset(inode)\ #define udf_file_entry_alloc_offset(inode)\
((UDF_I_EXTENDED_FE(inode) ?\ (UDF_I_USE(inode) ?\
sizeof(struct extendedFileEntry) :\ sizeof(struct unallocSpaceEntry) :\
sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode)) ((UDF_I_EFE(inode) ?\
sizeof(struct extendedFileEntry) :\
sizeof(struct fileEntry)) + UDF_I_LENEATTR(inode)))
#define udf_ext0_offset(inode)\ #define udf_ext0_offset(inode)\
(UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ?\ (UDF_I_ALLOCTYPE(inode) == ICBTAG_FLAG_AD_IN_ICB ?\
...@@ -114,6 +112,7 @@ extern void udf_truncate(struct inode *); ...@@ -114,6 +112,7 @@ extern void udf_truncate(struct inode *);
extern void udf_read_inode(struct inode *); extern void udf_read_inode(struct inode *);
extern void udf_put_inode(struct inode *); extern void udf_put_inode(struct inode *);
extern void udf_delete_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 void udf_write_inode(struct inode *, int);
extern long udf_block_map(struct inode *, long); 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 **); 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 ...@@ -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_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 struct buffer_head *udf_read_ptagged(struct super_block *, lb_addr, uint32_t, uint16_t *);
extern void udf_release_data(struct buffer_head *); 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 */ /* lowlevel.c */
extern unsigned int udf_get_last_session(struct super_block *); extern unsigned int udf_get_last_session(struct super_block *);
...@@ -148,6 +151,9 @@ extern int udf_relocate_blocks(struct super_block *, long, long *); ...@@ -148,6 +151,9 @@ extern int udf_relocate_blocks(struct super_block *, long, long *);
/* unicode.c */ /* unicode.c */
extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); 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 */ /* ialloc.c */
extern void udf_free_inode(struct inode *); extern void udf_free_inode(struct inode *);
...@@ -168,40 +174,17 @@ extern int udf_fsync_inode(struct inode *, int); ...@@ -168,40 +174,17 @@ extern int udf_fsync_inode(struct inode *, int);
/* directory.c */ /* directory.c */
extern uint8_t * udf_filead_read(struct inode *, uint8_t *, uint8_t, lb_addr, int *, int *, struct buffer_head **, int *); 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 **); 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 **);
extern struct fileIdentDesc * udf_get_fileident(void * buffer, int bufsize, int * offset);
/* unicode.c */ extern extent_ad * udf_get_fileextent(void * buffer, int bufsize, int * offset);
extern int udf_ustr_to_dchars(uint8_t *, const struct ustr *, int); extern long_ad * udf_get_filelongad(uint8_t *, int, int *, int);
extern int udf_ustr_to_char(uint8_t *, const struct ustr *, int); extern short_ad * udf_get_fileshortad(uint8_t *, int, int *, int);
extern int udf_ustr_to_dstring(dstring *, const struct ustr *, int); extern uint8_t * udf_get_filead(struct fileEntry *, uint8_t *, int, int, int, 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);
/* crc.c */ /* crc.c */
extern uint16_t udf_crc(uint8_t *, uint32_t, uint16_t); 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 */ /* udftime.c */
extern time_t *udf_stamp_to_time(time_t *, long *, timestamp); extern time_t *udf_stamp_to_time(time_t *, long *, timestamp);
extern timestamp *udf_time_to_stamp(timestamp *, time_t, long); 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 */ #endif /* __UDF_DECL_H */
...@@ -32,46 +32,9 @@ ...@@ -32,46 +32,9 @@
#include "udf_sb.h" #include "udf_sb.h"
int udf_ustr_to_dchars(uint8_t *dest, const struct ustr *src, int strlen) static int udf_translate_to_linux(uint8_t *, uint8_t *, int, uint8_t *, int);
{
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;
}
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) ) if ( (!dest) || (!src) || (!strlen) || (strlen >= UDF_NAME_LEN) )
return 0; return 0;
...@@ -82,15 +45,6 @@ int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen) ...@@ -82,15 +45,6 @@ int udf_char_to_ustr(struct ustr *dest, const uint8_t *src, int strlen)
return 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 * udf_build_ustr
*/ */
...@@ -112,7 +66,7 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size) ...@@ -112,7 +66,7 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
/* /*
* udf_build_ustr_exact * 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) ) if ( (!dest) || (!ptr) || (!exactsize) )
return -1; return -1;
...@@ -224,7 +178,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i) ...@@ -224,7 +178,7 @@ int udf_CS0toUTF8(struct ustr *utf_o, struct ustr *ocu_i)
* November 12, 1997 - Andrew E. Mileski * November 12, 1997 - Andrew E. Mileski
* Written, tested, and released. * 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; unsigned c, i, max_val, utf_char;
int utf_cnt; int utf_cnt;
...@@ -318,7 +272,7 @@ int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length) ...@@ -318,7 +272,7 @@ int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
return u_len + 1; 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; uint8_t *ocu;
uint32_t c; uint32_t c;
...@@ -360,7 +314,7 @@ int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i) ...@@ -360,7 +314,7 @@ int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, struct ustr *ocu_i)
return utf_o->u_len; 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; unsigned len, i, max_val;
uint16_t uni_char; uint16_t uni_char;
...@@ -434,12 +388,42 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, int ...@@ -434,12 +388,42 @@ int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, int
return 0; 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 ILLEGAL_CHAR_MARK '_'
#define EXT_MARK '.' #define EXT_MARK '.'
#define CRC_MARK '#' #define CRC_MARK '#'
#define EXT_SIZE 5 #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 index, newIndex = 0, needsCRC = 0;
int extIndex = 0, newExtIndex = 0, hasExt = 0; int extIndex = 0, newExtIndex = 0, hasExt = 0;
......
...@@ -34,23 +34,11 @@ ...@@ -34,23 +34,11 @@
#ifndef _UDF_FS_H #ifndef _UDF_FS_H
#define _UDF_FS_H 1 #define _UDF_FS_H 1
#include <linux/config.h>
#define UDF_PREALLOCATE #define UDF_PREALLOCATE
#define UDF_DEFAULT_PREALLOC_BLOCKS 8 #define UDF_DEFAULT_PREALLOC_BLOCKS 8
#define UDFFS_DATE "2002/03/11" #define UDFFS_DATE "2002/11/15"
#define UDFFS_VERSION "0.9.6" #define UDFFS_VERSION "0.9.7"
#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_DEBUG #define UDFFS_DEBUG
......
...@@ -23,30 +23,49 @@ ...@@ -23,30 +23,49 @@
#ifndef _ECMA_167_H #ifndef _ECMA_167_H
typedef struct typedef struct
{ {
__u32 logicalBlockNum; __u32 logicalBlockNum;
__u16 partitionReferenceNum; __u16 partitionReferenceNum;
} __attribute__ ((packed)) lb_addr; } __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 #endif
struct udf_inode_info struct udf_inode_info
{ {
long i_umtime; long i_umtime;
long i_uctime; long i_uctime;
long i_crtime; long i_crtime;
long i_ucrtime; long i_ucrtime;
/* Physical address of inode */ /* Physical address of inode */
lb_addr i_location; lb_addr i_location;
__u64 i_unique; __u64 i_unique;
__u32 i_lenEAttr; __u32 i_lenEAttr;
__u32 i_lenAlloc; __u32 i_lenAlloc;
__u64 i_lenExtents; __u64 i_lenExtents;
__u32 i_next_alloc_block; __u32 i_next_alloc_block;
__u32 i_next_alloc_goal; __u32 i_next_alloc_goal;
unsigned i_alloc_type : 3; unsigned i_alloc_type : 3;
unsigned i_extended_fe : 1; unsigned i_efe : 1;
unsigned i_strat_4096 : 1; unsigned i_use : 1;
unsigned i_new_inode : 1; unsigned i_strat4096 : 1;
unsigned reserved : 26; unsigned reserved : 26;
union
{
short_ad *i_sad;
long_ad *i_lad;
__u8 *i_data;
} i_ext;
struct inode vfs_inode; 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