summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-07 15:45:24 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-07 15:45:24 +0000
commit9f9f3e6e8548a596697778337110a423c384b6f3 (patch)
tree5dd4b290ef532cf5ecb058e1a92cd3435afeac8c /fs
parentd5c9a365ee7d2fded249aa5abfc5e89587583029 (diff)
Merge with Linux 2.3.49.
Diffstat (limited to 'fs')
-rw-r--r--fs/affs/inode.c1
-rw-r--r--fs/affs/namei.c6
-rw-r--r--fs/attr.c3
-rw-r--r--fs/binfmt_elf.c13
-rw-r--r--fs/binfmt_script.c5
-rw-r--r--fs/block_dev.c2
-rw-r--r--fs/exec.c25
-rw-r--r--fs/nfsd/export.c2
-rw-r--r--fs/nfsd/nfs3xdr.c6
-rw-r--r--fs/nfsd/vfs.c118
-rw-r--r--fs/ntfs/fs.c2
-rw-r--r--fs/openpromfs/inode.c2
-rw-r--r--fs/udf/balloc.c36
-rw-r--r--fs/udf/dir.c17
-rw-r--r--fs/udf/directory.c15
-rw-r--r--fs/udf/file.c136
-rw-r--r--fs/udf/ialloc.c38
-rw-r--r--fs/udf/inode.c200
-rw-r--r--fs/udf/lowlevel.c49
-rw-r--r--fs/udf/misc.c2
-rw-r--r--fs/udf/namei.c421
-rw-r--r--fs/udf/partition.c2
-rw-r--r--fs/udf/super.c188
-rw-r--r--fs/udf/symlink.c2
-rw-r--r--fs/udf/truncate.c101
-rw-r--r--fs/udf/udf_i.h1
-rw-r--r--fs/udf/udf_sb.h87
-rw-r--r--fs/udf/udfdecl.h17
-rw-r--r--fs/udf/udftime.c24
-rw-r--r--fs/udf/unicode.c20
30 files changed, 869 insertions, 672 deletions
diff --git a/fs/affs/inode.c b/fs/affs/inode.c
index 1e5647c39..780b99ad3 100644
--- a/fs/affs/inode.c
+++ b/fs/affs/inode.c
@@ -31,6 +31,7 @@
extern int *blk_size[];
extern struct timezone sys_tz;
+extern struct inode_operations affs_symlink_inode_operations;
#define MIN(a,b) (((a)<(b))?(a):(b))
diff --git a/fs/affs/namei.c b/fs/affs/namei.c
index 8ebf8319b..43085a64b 100644
--- a/fs/affs/namei.c
+++ b/fs/affs/namei.c
@@ -21,6 +21,8 @@
#include <linux/errno.h>
+extern struct inode_operations affs_symlink_inode_operations;
+
/* Simple toupper() for DOS\1 */
static unsigned int
@@ -273,10 +275,10 @@ affs_create(struct inode *dir, struct dentry *dentry, int mode)
goto out;
pr_debug("AFFS: ino=%lu\n",inode->i_ino);
- if (dir->i_sb->u.affs_sb.s_flags & SF_OFS)
+ if (dir->i_sb->u.affs_sb.s_flags & SF_OFS) {
inode->i_op = &affs_file_inode_operations;
inode->i_fop = &affs_file_operations_ofs;
- else {
+ } else {
inode->i_op = &affs_file_inode_operations;
inode->i_fop = &affs_file_operations;
inode->i_mapping->a_ops = &affs_aops;
diff --git a/fs/attr.c b/fs/attr.c
index 304ebd3db..b3ad3dfb2 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -91,8 +91,7 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
if (!(ia_valid & ATTR_MTIME_SET))
attr->ia_mtime = now;
- if (inode->i_sb && inode->i_sb->s_op &&
- inode->i_op->setattr)
+ if (inode && inode->i_op && inode->i_op->setattr)
error = inode->i_op->setattr(dentry, attr);
else {
error = inode_change_ok(inode, attr);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 7ce625d6d..52e9fe7b8 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -30,6 +30,7 @@
#include <linux/elfcore.h>
#include <linux/init.h>
#include <linux/highuid.h>
+#include <linux/smp_lock.h>
#include <asm/uaccess.h>
#include <asm/pgalloc.h>
@@ -504,13 +505,19 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
unsigned long old_pers = current->personality;
current->personality = PER_SVR4;
+ lock_kernel();
interpreter_dentry = open_namei(elf_interpreter,
0, 0);
+ unlock_kernel();
current->personality = old_pers;
} else
-#endif
+#endif
+ {
+ lock_kernel();
interpreter_dentry = open_namei(elf_interpreter,
0, 0);
+ unlock_kernel();
+ }
set_fs(old_fs);
retval = PTR_ERR(interpreter_dentry);
if (IS_ERR(interpreter_dentry))
@@ -678,7 +685,9 @@ do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
interpreter_dentry,
&interp_load_addr);
+ lock_kernel();
dput(interpreter_dentry);
+ unlock_kernel();
kfree(elf_interpreter);
if (elf_entry == ~0UL) {
@@ -775,7 +784,9 @@ out:
/* error cleanup */
out_free_dentry:
+ lock_kernel();
dput(interpreter_dentry);
+ unlock_kernel();
out_free_interp:
if (elf_interpreter)
kfree(elf_interpreter);
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c
index be8695e2b..8c71ec4a9 100644
--- a/fs/binfmt_script.c
+++ b/fs/binfmt_script.c
@@ -11,6 +11,7 @@
#include <linux/malloc.h>
#include <linux/binfmts.h>
#include <linux/init.h>
+#include <linux/smp_lock.h>
static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
{
@@ -27,7 +28,9 @@ static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
*/
bprm->sh_bang++;
+ lock_kernel();
dput(bprm->dentry);
+ unlock_kernel();
bprm->dentry = NULL;
bprm->buf[127] = '\0';
@@ -78,7 +81,9 @@ static int do_load_script(struct linux_binprm *bprm,struct pt_regs *regs)
/*
* OK, now restart the process with the interpreter's dentry.
*/
+ lock_kernel();
dentry = open_namei(interp, 0, 0);
+ unlock_kernel();
if (IS_ERR(dentry))
return PTR_ERR(dentry);
diff --git a/fs/block_dev.c b/fs/block_dev.c
index c455a735d..5a202c7e1 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -630,7 +630,7 @@ int blkdev_put(struct block_device *bdev, int kind)
/* syncing will go here */
if (kind == BDEV_FILE || kind == BDEV_FS)
fsync_dev(rdev);
- if (atomic_dec_and_test(&bdev->bd_openers)) {
+ if (atomic_dec_and_test(&bdev->bd_openers) && MAJOR(rdev) != RAMDISK_MAJOR) {
/* invalidating buffers will go here */
invalidate_buffers(rdev);
}
diff --git a/fs/exec.c b/fs/exec.c
index 886e9ab8c..694bba675 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -277,13 +277,13 @@ void put_dirty_page(struct task_struct * tsk, struct page *page, unsigned long a
pmd = pmd_alloc(pgd, address);
if (!pmd) {
__free_page(page);
- oom(tsk);
+ force_sig(SIGKILL, tsk);
return;
}
pte = pte_alloc(pmd, address);
if (!pte) {
__free_page(page);
- oom(tsk);
+ force_sig(SIGKILL, tsk);
return;
}
if (!pte_none(*pte)) {
@@ -738,14 +738,18 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
char * dynloader[] = { "/sbin/loader" };
struct dentry * dentry;
+ lock_kernel();
dput(bprm->dentry);
+ unlock_kernel();
bprm->dentry = NULL;
bprm_loader.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
for (i = 0 ; i < MAX_ARG_PAGES ; i++) /* clear page-table */
bprm_loader.page[i] = NULL;
+ lock_kernel();
dentry = open_namei(dynloader[0], 0, 0);
+ unlock_kernel();
retval = PTR_ERR(dentry);
if (IS_ERR(dentry))
return retval;
@@ -766,8 +770,11 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
continue;
retval = fn(bprm, regs);
if (retval >= 0) {
- if (bprm->dentry)
+ if (bprm->dentry) {
+ lock_kernel();
dput(bprm->dentry);
+ unlock_kernel();
+ }
bprm->dentry = NULL;
current->did_exec = 1;
return retval;
@@ -810,7 +817,10 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
+ lock_kernel();
dentry = open_namei(filename, 0, 0);
+ unlock_kernel();
+
retval = PTR_ERR(dentry);
if (IS_ERR(dentry))
return retval;
@@ -821,12 +831,16 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
bprm.loader = 0;
bprm.exec = 0;
if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) {
+ lock_kernel();
dput(dentry);
+ unlock_kernel();
return bprm.argc;
}
if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) {
+ lock_kernel();
dput(dentry);
+ unlock_kernel();
return bprm.envc;
}
@@ -854,8 +868,11 @@ int do_execve(char * filename, char ** argv, char ** envp, struct pt_regs * regs
out:
/* Something went wrong, return the inode and free the argument pages*/
- if (bprm.dentry)
+ if (bprm.dentry) {
+ lock_kernel();
dput(bprm.dentry);
+ unlock_kernel();
+ }
/* Assumes that free_page() can take a NULL argument. */
/* I hope this is ok for all architectures */
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index bfa5729ea..24a8208bb 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -611,7 +611,7 @@ struct flags {
{ NFSEXP_SUNSECURE, { "sunsecure", ""}},
{ NFSEXP_CROSSMNT, {"nohide", ""}},
{ NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}},
- { NFSEXP_NOAUTHNLM, {"no_auth_nlm", ""}},
+ { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}},
{ 0, {"", ""}}
};
diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c
index 8c3f8b525..84ef13ded 100644
--- a/fs/nfsd/nfs3xdr.c
+++ b/fs/nfsd/nfs3xdr.c
@@ -181,7 +181,11 @@ encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct dentry *dentry)
} else {
p = xdr_encode_hyper(p, (u64) inode->i_size);
}
- p = xdr_encode_hyper(p, ((u64)inode->i_blocks) << 9);
+ if (inode->i_blksize == 0 && inode->i_blocks == 0)
+ /* Minix file system(?) i_size is (hopefully) close enough */
+ p = xdr_encode_hyper(p, (u64)(inode->i_size +511)& ~511);
+ else
+ p = xdr_encode_hyper(p, ((u64)inode->i_blocks) << 9);
*p++ = htonl((u32) MAJOR(inode->i_rdev));
*p++ = htonl((u32) MINOR(inode->i_rdev));
p = xdr_encode_hyper(p, (u64) inode->i_dev);
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index c0f7da6cc..55c351852 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -216,8 +216,10 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
if (iap->ia_valid & (ATTR_ATIME | ATTR_MTIME | ATTR_SIZE))
accmode |= MAY_WRITE;
- if (iap->ia_valid & ATTR_SIZE)
+ if (iap->ia_valid & ATTR_SIZE) {
+ accmode |= MAY_OWNER_OVERRIDE;
ftype = S_IFREG;
+ }
/* Get inode */
err = fh_verify(rqstp, fhp, ftype, accmode);
@@ -247,7 +249,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
if (delta<0) delta = -delta;
if (delta < MAX_TOUCH_TIME_ERROR) {
/* turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME
- * this will cause notify_change to setthese times to "now"
+ * this will cause notify_change to set these times to "now"
*/
iap->ia_valid &= ~BOTH_TIME_SET;
err = inode_change_ok(inode, iap);
@@ -262,7 +264,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap)
if (!S_ISREG(inode->i_mode))
printk("nfsd_setattr: size change??\n");
if (iap->ia_size < inode->i_size) {
- err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC);
+ err = nfsd_permission(fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE);
if (err)
goto out;
}
@@ -369,7 +371,7 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access)
struct svc_export *export;
struct dentry *dentry;
u32 query, result = 0;
- int error;
+ unsigned int error;
error = fh_verify(rqstp, fhp, 0, MAY_NOP);
if (error)
@@ -378,28 +380,39 @@ nfsd_access(struct svc_rqst *rqstp, struct svc_fh *fhp, u32 *access)
export = fhp->fh_export;
dentry = fhp->fh_dentry;
- if (S_ISREG(dentry->d_inode->i_mode)) {
+ if (S_ISREG(dentry->d_inode->i_mode))
map = nfs3_regaccess;
- } else if (S_ISDIR(dentry->d_inode->i_mode)) {
+ else if (S_ISDIR(dentry->d_inode->i_mode))
map = nfs3_diraccess;
- } else {
+ else
map = nfs3_anyaccess;
- }
+
query = *access;
- while (map->access) {
+ for (; map->access; map++) {
if (map->access & query) {
- error = nfsd_permission(export, dentry, map->how);
- if (error == 0)
+ unsigned int err2;
+ err2 = nfsd_permission(export, dentry, map->how);
+ /* cannot use a "switch" as nfserr_* are variables, even though they are constant :-( */
+ if (err2 == 0)
result |= map->access;
- else if (error != -EPERM)
+ /* the following error codes just mean the access was not allowed,
+ * rather than an error occurred */
+ else if (err2 == nfserr_rofs ||
+ err2 == nfserr_acces ||
+ err2 == nfserr_perm
+ )
+ /* simply don't "or" in the access bit. */
+ ;
+ else {
+ error = err2;
goto out;
+ }
}
- map++;
}
*access = result;
-out:
+ out:
return error;
}
#endif
@@ -419,7 +432,10 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, int type,
struct inode *inode;
int err;
- err = fh_verify(rqstp, fhp, type, access);
+ /* If we get here, then the client has already done an "open", and (hopefully)
+ * checked permission - so allow OWNER_OVERRIDE in case a chmod has now revoked
+ * permission */
+ err = fh_verify(rqstp, fhp, type, access | MAY_OWNER_OVERRIDE);
if (err)
goto out;
@@ -1029,60 +1045,6 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp,
#endif /* CONFIG_NFSD_V3 */
/*
- * Truncate a file.
- * The calling routines must make sure to update the ctime
- * field and call notify_change.
- *
- * XXX Nobody calls this thing? -DaveM
- * N.B. After this call fhp needs an fh_put
- */
-int
-nfsd_truncate(struct svc_rqst *rqstp, struct svc_fh *fhp, unsigned long size)
-{
- struct dentry *dentry;
- struct inode *inode;
- struct iattr newattrs;
- int err;
- kernel_cap_t saved_cap = 0;
-
- err = fh_verify(rqstp, fhp, S_IFREG, MAY_WRITE | MAY_TRUNC);
- if (err)
- goto out;
-
- dentry = fhp->fh_dentry;
- inode = dentry->d_inode;
-
- err = get_write_access(inode);
- if (err)
- goto out_nfserr;
- err = locks_verify_truncate(inode, NULL, size);
- if (err)
- goto out_nfserr;
-
- /* Things look sane, lock and do it. */
- fh_lock(fhp);
- DQUOT_INIT(inode);
- newattrs.ia_size = size;
- newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
- if (current->fsuid != 0) {
- saved_cap = current->cap_effective;
- cap_clear(current->cap_effective);
- }
- err = notify_change(dentry, &newattrs);
- if (current->fsuid != 0)
- current->cap_effective = saved_cap;
- put_write_access(inode);
- if (EX_ISSYNC(fhp->fh_export))
- nfsd_sync_dir(dentry);
- fh_unlock(fhp);
-out_nfserr:
- if (err)
- err = nfserrno(-err);
-out:
- return err;
-}
-
-/*
* Read a symlink. On entry, *lenp must contain the maximum path length that
* fits into the buffer. On return, it contains the true length.
* N.B. After this call fhp needs an fh_put
@@ -1627,7 +1589,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
if (acc == MAY_NOP)
return 0;
#if 0
- dprintk("nfsd: permission 0x%x%s%s%s%s%s%s mode 0%o%s%s%s\n",
+ dprintk("nfsd: permission 0x%x%s%s%s%s%s%s%s mode 0%o%s%s%s\n",
acc,
(acc & MAY_READ)? " read" : "",
(acc & MAY_WRITE)? " write" : "",
@@ -1635,6 +1597,7 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
(acc & MAY_SATTR)? " sattr" : "",
(acc & MAY_TRUNC)? " trunc" : "",
(acc & MAY_LOCK)? " lock" : "",
+ (acc & MAY_OWNER_OVERRIDE)? " owneroverride" : "",
inode->i_mode,
IS_IMMUTABLE(inode)? " immut" : "",
IS_APPEND(inode)? " append" : "",
@@ -1654,23 +1617,30 @@ nfsd_permission(struct svc_export *exp, struct dentry *dentry, int acc)
if (acc & MAY_LOCK) {
/* If we cannot rely on authentication in NLM requests,
- * just allow locks, others require read permission
+ * just allow locks, otherwise require read permission, or
+ * ownership
*/
if (exp->ex_flags & NFSEXP_NOAUTHNLM)
return 0;
else
- acc = MAY_READ;
+ acc = MAY_READ | MAY_OWNER_OVERRIDE;
}
/*
- * The file owner always gets access permission. This is to make
+ * The file owner always gets access permission for accesses that
+ * would normally be checked at open time. This is to make
* file access work even when the client has done a fchmod(fd, 0).
*
* However, `cp foo bar' should fail nevertheless when bar is
* readonly. A sensible way to do this might be to reject all
* attempts to truncate a read-only file, because a creat() call
* always implies file truncation.
+ * ... but this isn't really fair. A process may reasonably call
+ * ftruncate on an open file descriptor on a file with perm 000.
+ * We must trust the client to do permission checking - using "ACCESS"
+ * with NFSv3.
*/
- if (inode->i_uid == current->fsuid /* && !(acc & MAY_TRUNC) */)
+ if ((acc & MAY_OWNER_OVERRIDE) &&
+ inode->i_uid == current->fsuid)
return 0;
if (current->fsuid != 0) {
diff --git a/fs/ntfs/fs.c b/fs/ntfs/fs.c
index 139ff0d0b..6db74a14e 100644
--- a/fs/ntfs/fs.c
+++ b/fs/ntfs/fs.c
@@ -692,7 +692,7 @@ static void ntfs_read_inode(struct inode* inode)
inode->u.ntfs_i.mmu_private = inode->i_size;
} else {
inode->i_op=&ntfs_inode_operations_nobmap;
- inode->i_fop=&ntfs_file_operations_nommap,
+ inode->i_fop=&ntfs_file_operations_nommap;
}
inode->i_mode=S_IFREG|S_IRUGO;
}
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c
index b03172491..1f9139a51 100644
--- a/fs/openpromfs/inode.c
+++ b/fs/openpromfs/inode.c
@@ -1,4 +1,4 @@
-/* $Id: inode.c,v 1.5 2000/02/10 21:16:06 davem Exp $
+/* $Id: inode.c,v 1.6 2000/02/27 08:19:47 davem Exp $
* openpromfs.c: /proc/openprom handling routines
*
* Copyright (C) 1996-1999 Jakub Jelinek (jakub@redhat.com)
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c
index 41274039d..1aa3aa1c4 100644
--- a/fs/udf/balloc.c
+++ b/fs/udf/balloc.c
@@ -15,7 +15,7 @@
* ftp://prep.ai.mit.edu/pub/gnu/GPL
* Each contributing author retains all rights to their own work.
*
- * (C) 1999 Ben Fennema
+ * (C) 1999-2000 Ben Fennema
* (C) 1999 Stelias Computing Inc
*
* HISTORY
@@ -27,6 +27,7 @@
#include "udfdecl.h"
#include <linux/fs.h>
#include <linux/locks.h>
+#include <linux/quotaops.h>
#include <linux/udf_fs.h>
#include <asm/bitops.h>
@@ -171,8 +172,8 @@ static inline int load_block_bitmap(struct super_block *sb,
unsigned int block_group)
{
int slot;
- int nr_groups = (UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)) +
- (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8);
+ int nr_groups = (UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)) +
+ (sizeof(struct SpaceBitmapDesc) << 3) + (sb->s_blocksize * 8) - 1) / (sb->s_blocksize * 8);
if (UDF_SB_LOADED_BLOCK_BITMAPS(sb) > 0 &&
UDF_SB_BLOCK_BITMAP_NUMBER(sb, 0) == block_group &&
@@ -259,10 +260,14 @@ do_more:
udf_debug("bit %ld already set\n", bit + i);
udf_debug("byte=%2x\n", ((char *)bh->b_data)[(bit + i) >> 3]);
}
- else if (UDF_SB_LVIDBH(sb))
+ else
{
- UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] =
- cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)])+1);
+ DQUOT_FREE_BLOCK(sb, inode, 1);
+ if (UDF_SB_LVIDBH(sb))
+ {
+ UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)] =
+ cpu_to_le32(le32_to_cpu(UDF_SB_LVID(sb)->freeSpaceTable[UDF_SB_PARTITION(sb)])+1);
+ }
}
}
mark_buffer_dirty(bh, 1);
@@ -280,7 +285,7 @@ error_return:
return;
}
-int udf_alloc_blocks(const struct inode * inode, Uint16 partition,
+int udf_prealloc_blocks(const struct inode * inode, Uint16 partition,
Uint32 first_block, Uint32 block_count)
{
int alloc_count = 0;
@@ -318,16 +323,18 @@ repeat:
{
if (!udf_test_bit(bit, bh->b_data))
goto out;
- if (!udf_clear_bit(bit, bh->b_data))
+ else if (DQUOT_PREALLOC_BLOCK(sb, inode, 1))
+ goto out;
+ else if (!udf_clear_bit(bit, bh->b_data))
{
udf_debug("bit already cleared for block %d\n", bit);
+ DQUOT_FREE_BLOCK(sb, inode, 1);
goto out;
}
block_count --;
alloc_count ++;
bit ++;
block ++;
-
}
mark_buffer_dirty(bh, 1);
if (block_count > 0)
@@ -451,6 +458,17 @@ search_back:
for (i=0; i<7 && bit > (group_start << 3) && udf_test_bit(bit - 1, bh->b_data); i++, bit--);
got_block:
+
+ /*
+ * Check quota for allocation of this block.
+ */
+ if (DQUOT_ALLOC_BLOCK(sb, inode, 1))
+ {
+ unlock_super(sb);
+ *err = -EDQUOT;
+ return 0;
+ }
+
newblock = bit + (block_group << (sb->s_blocksize_bits + 3)) -
(sizeof(struct SpaceBitmapDesc) << 3);
diff --git a/fs/udf/dir.c b/fs/udf/dir.c
index c31ff527a..09121f0ef 100644
--- a/fs/udf/dir.c
+++ b/fs/udf/dir.c
@@ -15,7 +15,7 @@
* ftp://prep.ai.mit.edu/pub/gnu/GPL
* Each contributing author retains all rights to their own work.
*
- * (C) 1998-1999 Ben Fennema
+ * (C) 1998-2000 Ben Fennema
*
* HISTORY
*
@@ -32,7 +32,6 @@
#include "udfdecl.h"
#if defined(__linux__) && defined(__KERNEL__)
-#include <linux/config.h>
#include <linux/version.h>
#include "udf_i.h"
#include "udf_sb.h"
@@ -50,10 +49,10 @@ static int do_udf_readdir(struct inode *, struct file *, filldir_t, void *);
/* readdir and lookup functions */
struct file_operations udf_dir_operations = {
- read: generic_read_dir,
- readdir: udf_readdir,
- ioctl: udf_ioctl,
- fsync: udf_sync_file,
+ read: generic_read_dir,
+ readdir: udf_readdir,
+ ioctl: udf_ioctl,
+ fsync: udf_sync_file,
};
/*
@@ -159,7 +158,7 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
{
filp->f_pos = nf_pos;
- fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &offset, &bh);
+ fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
if (!fi)
{
@@ -193,13 +192,13 @@ do_udf_readdir(struct inode * dir, struct file *filp, filldir_t filldir, void *d
if ( (cfi.fileCharacteristics & FILE_DELETED) != 0 )
{
- if ( !IS_UNDELETE(dir->i_sb) )
+ if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE) )
continue;
}
if ( (cfi.fileCharacteristics & FILE_HIDDEN) != 0 )
{
- if ( !IS_UNHIDE(dir->i_sb) )
+ if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE) )
continue;
}
diff --git a/fs/udf/directory.c b/fs/udf/directory.c
index 84c97ee9d..1200e74f7 100644
--- a/fs/udf/directory.c
+++ b/fs/udf/directory.c
@@ -88,11 +88,10 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
struct udf_fileident_bh *fibh,
struct FileIdentDesc *cfi,
lb_addr *bloc, Uint32 *extoffset,
+ lb_addr *eloc, Uint32 *elen,
Uint32 *offset, struct buffer_head **bh)
{
struct FileIdentDesc *fi;
- lb_addr eloc;
- Uint32 elen;
int block;
fibh->soffset = fibh->eoffset;
@@ -101,17 +100,17 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
{
int lextoffset = *extoffset;
- if (udf_next_aext(dir, bloc, extoffset, &eloc, &elen, bh, 1) !=
+ if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
EXTENT_RECORDED_ALLOCATED)
{
return NULL;
}
- block = udf_get_lb_pblock(dir->i_sb, eloc, *offset);
+ block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
(*offset) ++;
- if ((*offset << dir->i_sb->s_blocksize_bits) >= elen)
+ if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
*offset = 0;
else
*extoffset = lextoffset;
@@ -143,17 +142,17 @@ udf_fileident_read(struct inode *dir, loff_t *nf_pos,
{
int lextoffset = *extoffset;
- if (udf_next_aext(dir, bloc, extoffset, &eloc, &elen, bh, 1) !=
+ if (udf_next_aext(dir, bloc, extoffset, eloc, elen, bh, 1) !=
EXTENT_RECORDED_ALLOCATED)
{
return NULL;
}
- block = udf_get_lb_pblock(dir->i_sb, eloc, *offset);
+ block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset);
(*offset) ++;
- if ((*offset << dir->i_sb->s_blocksize_bits) >= elen)
+ if ((*offset << dir->i_sb->s_blocksize_bits) >= *elen)
*offset = 0;
else
*extoffset = lextoffset;
diff --git a/fs/udf/file.c b/fs/udf/file.c
index cea86257b..73d47ac10 100644
--- a/fs/udf/file.c
+++ b/fs/udf/file.c
@@ -16,8 +16,8 @@
* Each contributing author retains all rights to their own work.
*
* (C) 1998-1999 Dave Boynton
- * (C) 1998-1999 Ben Fennema
- * (C) 1999 Stelias Computing Inc
+ * (C) 1998-2000 Ben Fennema
+ * (C) 1999-2000 Stelias Computing Inc
*
* HISTORY
*
@@ -31,7 +31,6 @@
*/
#include "udfdecl.h"
-#include <linux/config.h>
#include <linux/fs.h>
#include <linux/udf_fs.h>
#include <asm/uaccess.h>
@@ -43,52 +42,22 @@
#include "udf_i.h"
#include "udf_sb.h"
-/*
- * Make sure the offset never goes beyond the 32-bit mark..
- */
-static loff_t udf_file_llseek(struct file * file, loff_t offset, int origin)
-{
- struct inode * inode = file->f_dentry->d_inode;
-
- switch (origin)
- {
- case 2:
- {
- offset += inode->i_size;
- break;
- }
- case 1:
- {
- offset += file->f_pos;
- break;
- }
- }
- if (offset != file->f_pos)
- {
- file->f_pos = offset;
- file->f_reada = 0;
- file->f_version = ++event;
- }
- return offset;
-}
-
static int udf_adinicb_readpage(struct dentry *dentry, struct page * page)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = (struct inode *)page->mapping->host;
struct buffer_head *bh;
- unsigned long kaddr = 0;
+ int block;
+ char *kaddr;
if (!PageLocked(page))
PAGE_BUG(page);
- kaddr = kmap(page);
- memset((char *)kaddr, 0, PAGE_CACHE_SIZE);
- bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
- ll_rw_block (READ, 1, &bh);
- wait_on_buffer(bh);
- memcpy((char *)kaddr, bh->b_data + udf_ext0_offset(inode),
- inode->i_size);
+ kaddr = (char *)kmap(page);
+ memset(kaddr, 0, PAGE_CACHE_SIZE);
+ block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
+ bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize);
+ memcpy(kaddr, bh->b_data + udf_ext0_offset(inode), inode->i_size);
brelse(bh);
SetPageUptodate(page);
kunmap(page);
@@ -98,25 +67,20 @@ static int udf_adinicb_readpage(struct dentry *dentry, struct page * page)
static int udf_adinicb_writepage(struct dentry *dentry, struct page *page)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = (struct inode *)page->mapping->host;
struct buffer_head *bh;
- unsigned long kaddr = 0;
+ int block;
+ char *kaddr;
if (!PageLocked(page))
- BUG();
+ PAGE_BUG(page);
- kaddr = kmap(page);
- bh = getblk (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
- if (!buffer_uptodate(bh))
- {
- ll_rw_block (READ, 1, &bh);
- wait_on_buffer(bh);
- }
- memcpy(bh->b_data + udf_ext0_offset(inode), (char *)kaddr,
- inode->i_size);
- ll_rw_block (WRITE, 1, &bh);
- wait_on_buffer(bh);
+ kaddr = (char *)kmap(page);
+ block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
+ bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize);
+ memcpy(bh->b_data + udf_ext0_offset(inode), kaddr, inode->i_size);
+ mark_buffer_dirty(bh, 0);
brelse(bh);
SetPageUptodate(page);
kunmap(page);
@@ -131,20 +95,20 @@ static int udf_adinicb_prepare_write(struct page *page, unsigned offset, unsigne
static int udf_adinicb_commit_write(struct file *file, struct page *page, unsigned offset, unsigned to)
{
- struct inode *inode = file->f_dentry->d_inode;
+ struct inode *inode = (struct inode *)page->mapping->host;
+
struct buffer_head *bh;
+ int block;
char *kaddr = (char*)page_address(page);
- bh = bread (inode->i_dev, inode->i_ino, inode->i_sb->s_blocksize);
- if (!buffer_uptodate(bh)) {
- ll_rw_block (READ, 1, &bh);
- wait_on_buffer(bh);
- }
+
+ block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
+ bh = bread (inode->i_dev, block, inode->i_sb->s_blocksize);
memcpy(bh->b_data + udf_file_entry_alloc_offset(inode) + offset,
kaddr + offset, to-offset);
mark_buffer_dirty(bh, 0);
brelse(bh);
- kunmap(page);
SetPageUptodate(page);
+ kunmap(page);
/* only one page here */
if (to > inode->i_size)
inode->i_size = to;
@@ -152,10 +116,10 @@ static int udf_adinicb_commit_write(struct file *file, struct page *page, unsign
}
struct address_space_operations udf_adinicb_aops = {
- readpage: udf_adinicb_readpage,
- writepage: udf_adinicb_writepage,
- prepare_write: udf_adinicb_prepare_write,
- commit_write: udf_adinicb_commit_write
+ readpage: udf_adinicb_readpage,
+ writepage: udf_adinicb_writepage,
+ prepare_write: udf_adinicb_prepare_write,
+ commit_write: udf_adinicb_commit_write,
};
static ssize_t udf_file_write(struct file * file, const char * buf,
@@ -165,20 +129,25 @@ static ssize_t udf_file_write(struct file * file, const char * buf,
struct inode *inode = file->f_dentry->d_inode;
int err, pos;
- if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+ {
if (file->f_flags & O_APPEND)
pos = inode->i_size;
else
pos = *ppos;
- if (inode->i_sb->s_blocksize <
- (udf_file_entry_alloc_offset(inode) + pos + count)) {
- udf_expand_file_adinicb(file, pos + count, &err);
- if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB) {
+ if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
+ pos + count))
+ {
+ udf_expand_file_adinicb(inode, pos + count, &err);
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+ {
udf_debug("udf_expand_adinicb: err=%d\n", err);
return err;
}
- } else {
+ }
+ else
+ {
if (pos + count > inode->i_size)
UDF_I_LENALLOC(inode) = pos + count;
else
@@ -187,7 +156,9 @@ static ssize_t udf_file_write(struct file * file, const char * buf,
}
retval = generic_file_write(file, buf, count, ppos);
- if (retval > 0) {
+
+ if (retval > 0)
+ {
UDF_I_UCTIME(inode) = UDF_I_UMTIME(inode) = CURRENT_UTIME;
mark_inode_dirty(inode);
}
@@ -350,18 +321,15 @@ static int udf_open_file(struct inode * inode, struct file * filp)
}
struct file_operations udf_file_operations = {
- llseek: udf_file_llseek,
- read: generic_file_read,
- write: udf_file_write,
- ioctl: udf_ioctl,
- mmap: generic_file_mmap,
- open: udf_open_file,
- release: udf_release_file,
- fsync: udf_sync_file,
+ read: generic_file_read,
+ ioctl: udf_ioctl,
+ open: udf_open_file,
+ mmap: generic_file_mmap,
+ write: udf_file_write,
+ release: udf_release_file,
+ fsync: udf_sync_file,
};
struct inode_operations udf_file_inode_operations = {
-#if CONFIG_UDF_RW == 1
- truncate: udf_truncate,
-#endif
+ truncate: udf_truncate,
};
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c
index 1f3300b7f..914527765 100644
--- a/fs/udf/ialloc.c
+++ b/fs/udf/ialloc.c
@@ -26,6 +26,7 @@
#include "udfdecl.h"
#include <linux/fs.h>
#include <linux/locks.h>
+#include <linux/quotaops.h>
#include <linux/udf_fs.h>
#include "udf_i.h"
@@ -60,6 +61,13 @@ void udf_free_inode(struct inode * inode)
ino = inode->i_ino;
+ /*
+ * Note: we must free any quota before locking the superblock,
+ * as writing the quota to disk may need the lock as well.
+ */
+ DQUOT_FREE_INODE(sb, inode);
+ DQUOT_DROP(inode);
+
lock_super(sb);
is_directory = S_ISDIR(inode->i_mode);
@@ -132,7 +140,9 @@ struct inode * udf_new_inode (const struct inode *dir, int mode, int * err)
inode->i_nlink = 1;
inode->i_dev = sb->s_dev;
inode->i_uid = current->fsuid;
- if (dir->i_mode & S_ISGID)
+ if (test_opt (sb, GRPID))
+ inode->i_gid = dir->i_gid;
+ else if (dir->i_mode & S_ISGID)
{
inode->i_gid = dir->i_gid;
if (S_ISDIR(mode))
@@ -140,6 +150,7 @@ struct inode * udf_new_inode (const struct inode *dir, int mode, int * err)
}
else
inode->i_gid = current->fsgid;
+
UDF_I_LOCATION(inode).logicalBlockNum = block;
UDF_I_LOCATION(inode).partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
inode->i_ino = udf_get_lb_pblock(sb, UDF_I_LOCATION(inode), 0);
@@ -148,12 +159,35 @@ struct inode * udf_new_inode (const struct inode *dir, int mode, int * err)
inode->i_size = 0;
UDF_I_LENEATTR(inode) = 0;
UDF_I_LENALLOC(inode) = 0;
- UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_IN_ICB;
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_EXTENDED_FE))
+ {
+ UDF_I_EXTENDED_FE(inode) = 1;
+ UDF_UPDATE_UDFREV(inode->i_sb, UDF_VERS_USE_EXTENDED_FE);
+ }
+ else
+ UDF_I_EXTENDED_FE(inode) = 0;
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB))
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_IN_ICB;
+ else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
+ else
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
UDF_I_UMTIME(inode) = UDF_I_UATIME(inode) = UDF_I_UCTIME(inode) = CURRENT_UTIME;
+ UDF_I_NEW_INODE(inode) = 1;
insert_inode_hash(inode);
mark_inode_dirty(inode);
+
unlock_super(sb);
+ if (DQUOT_ALLOC_INODE(sb, inode))
+ {
+ sb->dq_op->drop(inode);
+ inode->i_nlink = 0;
+ iput(inode);
+ *err = -EDQUOT;
+ return NULL;
+ }
+
*err = 0;
return inode;
}
diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index 335f54c75..264086135 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -74,7 +74,10 @@ static int udf_get_block(struct inode *, long, struct buffer_head *, int);
*/
void udf_put_inode(struct inode * inode)
{
+ lock_kernel();
udf_discard_prealloc(inode);
+ write_inode_now(inode);
+ unlock_kernel();
}
/*
@@ -95,10 +98,20 @@ void udf_put_inode(struct inode * inode)
*/
void udf_delete_inode(struct inode * inode)
{
+ lock_kernel();
+
+ if (is_bad_inode(inode))
+ {
+ clear_inode(inode);
+ goto out;
+ }
+
inode->i_size = 0;
- if (inode->i_blocks)
- udf_truncate(inode);
+ udf_truncate(inode);
+ write_inode_now(inode);
udf_free_inode(inode);
+out:
+ unlock_kernel();
}
void udf_discard_prealloc(struct inode * inode)
@@ -107,64 +120,61 @@ void udf_discard_prealloc(struct inode * inode)
udf_trunc(inode);
}
-static int udf_alloc_block(struct inode *inode, Uint16 partition,
- Uint32 goal, int *err)
-{
- int result = 0;
- wait_on_super(inode->i_sb);
-
- result = udf_new_block(inode, partition, goal, err);
-
- return result;
-}
-
static int udf_writepage(struct dentry *dentry, struct page *page)
{
- return block_write_full_page(page,udf_get_block);
+ return block_write_full_page(page, udf_get_block);
}
+
static int udf_readpage(struct dentry *dentry, struct page *page)
{
- return block_read_full_page(page,udf_get_block);
+ return block_read_full_page(page, udf_get_block);
}
+
static int udf_prepare_write(struct page *page, unsigned from, unsigned to)
{
- return block_prepare_write(page,from,to,udf_get_block);
+ return block_prepare_write(page, from, to, udf_get_block);
}
+
static int udf_bmap(struct address_space *mapping, long block)
{
return generic_block_bmap(mapping,block,udf_get_block);
}
-static struct address_space_operations udf_aops = {
- readpage: udf_readpage,
- writepage: udf_writepage,
- prepare_write: udf_prepare_write,
- commit_write: generic_commit_write,
- bmap: udf_bmap
+
+struct address_space_operations udf_aops = {
+ readpage: udf_readpage,
+ writepage: udf_writepage,
+ prepare_write: udf_prepare_write,
+ commit_write: generic_commit_write,
+ bmap: udf_bmap,
};
-void udf_expand_file_adinicb(struct file * filp, int newsize, int * err)
+void udf_expand_file_adinicb(struct inode * inode, int newsize, int * err)
{
- struct inode * inode = filp->f_dentry->d_inode;
struct buffer_head *bh = NULL;
struct page *page;
unsigned long kaddr = 0;
+ int block;
/* from now on we have normal address_space methods */
inode->i_data.a_ops = &udf_aops;
if (!UDF_I_LENALLOC(inode))
{
- UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
+ else
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
mark_inode_dirty(inode);
return;
}
- bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
+ block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
+ bh = udf_tread(inode->i_sb, block, inode->i_sb->s_blocksize);
if (!bh)
return;
- page = grab_cache_page(&inode->i_data, 0);
+ page = grab_cache_page(inode->i_mapping, 0);
if (!PageLocked(page))
- BUG();
+ PAGE_BUG(page);
if (!Page_Uptodate(page))
{
kaddr = kmap(page);
@@ -172,17 +182,21 @@ void udf_expand_file_adinicb(struct file * filp, int newsize, int * err)
PAGE_CACHE_SIZE - UDF_I_LENALLOC(inode));
memcpy((char *)kaddr, bh->b_data + udf_file_entry_alloc_offset(inode),
UDF_I_LENALLOC(inode));
+ SetPageUptodate(page);
kunmap(page);
}
memset(bh->b_data + udf_file_entry_alloc_offset(inode),
0, UDF_I_LENALLOC(inode));
UDF_I_LENALLOC(inode) = 0;
- UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
+ else
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
inode->i_blocks = inode->i_sb->s_blocksize / 512;
mark_buffer_dirty(bh, 1);
udf_release_data(bh);
- inode->i_data.a_ops->writepage(filp->f_dentry, page);
+ inode->i_data.a_ops->writepage(NULL, page);
UnlockPage(page);
page_cache_release(page);
@@ -192,9 +206,10 @@ void udf_expand_file_adinicb(struct file * filp, int newsize, int * err)
struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int *err)
{
- long_ad newad;
int newblock;
struct buffer_head *sbh = NULL, *dbh = NULL;
+ lb_addr bloc, eloc;
+ Uint32 elen, extoffset;
struct udf_fileident_bh sfibh, dfibh;
loff_t f_pos = udf_ext0_offset(inode) >> 2;
@@ -203,13 +218,16 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
if (!inode->i_size)
{
- UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
+ else
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
mark_inode_dirty(inode);
return NULL;
}
/* alloc block, and copy data to it */
- *block = udf_alloc_block(inode,
+ *block = udf_new_block(inode,
UDF_I_LOCATION(inode).partitionReferenceNum,
UDF_I_LOCATION(inode).logicalBlockNum, err);
@@ -232,7 +250,7 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
dfibh.sbh = dfibh.ebh = dbh;
while ( (f_pos < size) )
{
- sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL);
+ sfi = udf_fileident_read(inode, &f_pos, &sfibh, &cfi, NULL, NULL, NULL, NULL, NULL, NULL);
if (!sfi)
{
udf_release_data(sbh);
@@ -256,17 +274,19 @@ struct buffer_head * udf_expand_dir_adinicb(struct inode *inode, int *block, int
memset(sbh->b_data + udf_file_entry_alloc_offset(inode),
0, UDF_I_LENALLOC(inode));
- memset(&newad, 0x00, sizeof(long_ad));
- newad.extLength = inode->i_size;
- newad.extLocation.logicalBlockNum = *block;
- newad.extLocation.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
+ UDF_I_LENALLOC(inode) = 0;
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD))
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_SHORT;
+ else
+ UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
+ bloc = UDF_I_LOCATION(inode);
+ eloc.logicalBlockNum = *block;
+ eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
+ elen = inode->i_size;
+ extoffset = udf_file_entry_alloc_offset(inode);
+ udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &sbh, 0);
/* UniqueID stuff */
- memcpy(sbh->b_data + udf_file_entry_alloc_offset(inode),
- &newad, sizeof(newad));
-
- UDF_I_LENALLOC(inode) = sizeof(newad);
- UDF_I_ALLOCTYPE(inode) = ICB_FLAG_AD_LONG;
inode->i_blocks = inode->i_sb->s_blocksize / 512;
mark_buffer_dirty(sbh, 1);
udf_release_data(sbh);
@@ -438,6 +458,14 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
if (etype == -1)
{
endnum = startnum = ((count > 1) ? 1 : count);
+ if (laarr[c].extLength & (inode->i_sb->s_blocksize - 1))
+ {
+ laarr[c].extLength =
+ (laarr[c].extLength & UDF_EXTENT_FLAG_MASK) |
+ (((laarr[c].extLength & UDF_EXTENT_LENGTH_MASK) +
+ inode->i_sb->s_blocksize - 1) &
+ ~(inode->i_sb->s_blocksize - 1));
+ }
c = !c;
laarr[c].extLength = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) |
((offset + 1) << inode->i_sb->s_blocksize_bits);
@@ -506,7 +534,7 @@ static struct buffer_head * inode_getblk(struct inode * inode, long block,
goal = UDF_I_LOCATION(inode).logicalBlockNum + 1;
}
- if (!(newblocknum = udf_alloc_block(inode,
+ if (!(newblocknum = udf_new_block(inode,
UDF_I_LOCATION(inode).partitionReferenceNum, goal, err)))
{
udf_release_data(pbh);
@@ -613,7 +641,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
{
int start, length = 0, currlength = 0, i;
- if (*endnum == (c+1) && !lastblock)
+ if (*endnum >= (c+1) && !lastblock)
return;
if ((laarr[c+1].extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED)
@@ -644,7 +672,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock,
int next = laarr[start].extLocation.logicalBlockNum +
(((laarr[start].extLength & UDF_EXTENT_LENGTH_MASK) +
inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits);
- int numalloc = udf_alloc_blocks(inode,
+ int numalloc = udf_prealloc_blocks(inode,
laarr[start].extLocation.partitionReferenceNum,
next, (UDF_DEFAULT_PREALLOC_BLOCKS > length ? length :
UDF_DEFAULT_PREALLOC_BLOCKS) - currlength);
@@ -864,7 +892,6 @@ __udf_read_inode(struct inode *inode)
*/
inode->i_blksize = PAGE_SIZE;
- inode->i_version = 1;
bh = udf_read_ptagged(inode->i_sb, UDF_I_LOCATION(inode), 0, &ident);
@@ -948,6 +975,9 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh)
long convtime_usec;
int offset, alen;
+ inode->i_version = ++event;
+ UDF_I_NEW_INODE(inode) = 0;
+
fe = (struct FileEntry *)bh->b_data;
efe = (struct ExtendedFileEntry *)bh->b_data;
@@ -1183,7 +1213,9 @@ udf_convert_permissions(struct FileEntry *fe)
void udf_write_inode(struct inode * inode)
{
+ lock_kernel();
udf_update_inode(inode, 0);
+ unlock_kernel();
}
int udf_sync_inode(struct inode * inode)
@@ -1214,6 +1246,17 @@ udf_update_inode(struct inode *inode, int do_sync)
}
fe = (struct FileEntry *)bh->b_data;
efe = (struct ExtendedFileEntry *)bh->b_data;
+ if (UDF_I_NEW_INODE(inode) == 1)
+ {
+ if (UDF_I_EXTENDED_FE(inode) == 0)
+ memset(bh->b_data, 0x0, 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 (inode->i_uid != UDF_SB(inode->i_sb)->s_uid)
fe->uid = cpu_to_le32(inode->i_uid);
@@ -1236,7 +1279,6 @@ udf_update_inode(struct inode *inode, int do_sync)
else
fe->fileLinkCount = cpu_to_le16(inode->i_nlink);
-
fe->informationLength = cpu_to_le64(inode->i_size);
if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode))
@@ -1312,8 +1354,17 @@ udf_update_inode(struct inode *inode, int do_sync)
efe->descTag.tagIdent = le16_to_cpu(TID_EXTENDED_FILE_ENTRY);
crclen = sizeof(struct ExtendedFileEntry);
}
- fe->icbTag.strategyType = UDF_I_STRAT4096(inode) ? cpu_to_le16(4096) :
- cpu_to_le16(4);
+ if (UDF_I_STRAT4096(inode))
+ {
+ fe->icbTag.strategyType = cpu_to_le16(4096);
+ fe->icbTag.strategyParameter = cpu_to_le16(1);
+ fe->icbTag.numEntries = cpu_to_le16(2);
+ }
+ else
+ {
+ fe->icbTag.strategyType = cpu_to_le16(4);
+ fe->icbTag.numEntries = cpu_to_le16(1);
+ }
if (S_ISDIR(inode->i_mode))
fe->icbTag.fileType = FILE_TYPE_DIRECTORY;
@@ -1454,11 +1505,10 @@ int udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
char *sptr, *dptr;
struct buffer_head *nbh;
int err, loffset;
- Uint32 lblock = bloc->logicalBlockNum;
- Uint16 lpart = bloc->partitionReferenceNum;
+ lb_addr obloc = *bloc;
if (!(bloc->logicalBlockNum = udf_new_block(inode,
- lpart, lblock, &err)))
+ obloc.partitionReferenceNum, obloc.logicalBlockNum, &err)))
{
return -1;
}
@@ -1468,7 +1518,7 @@ int udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
return -1;
}
aed = (struct AllocExtDesc *)(nbh->b_data);
- aed->previousAllocExtLocation = cpu_to_le32(lblock);
+ aed->previousAllocExtLocation = cpu_to_le32(obloc.logicalBlockNum);
if (*extoffset + adsize > inode->i_sb->s_blocksize)
{
loffset = *extoffset;
@@ -1485,14 +1535,17 @@ int udf_add_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
sptr = (*bh)->b_data + *extoffset;
*extoffset = sizeof(struct AllocExtDesc);
- if (UDF_I_LOCATION(inode).logicalBlockNum == lblock)
- UDF_I_LENALLOC(inode) += adsize;
- else
+ if (memcmp(&UDF_I_LOCATION(inode), &obloc, sizeof(lb_addr)))
{
aed = (struct AllocExtDesc *)(*bh)->b_data;
aed->lengthAllocDescs =
cpu_to_le32(le32_to_cpu(aed->lengthAllocDescs) + adsize);
}
+ else
+ {
+ UDF_I_LENALLOC(inode) += adsize;
+ mark_inode_dirty(inode);
+ }
}
udf_new_tag(nbh->b_data, TID_ALLOC_EXTENT_DESC, 2, 1,
bloc->logicalBlockNum, sizeof(tag));
@@ -1547,7 +1600,7 @@ int udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
short_ad *sad = NULL;
long_ad *lad = NULL;
- if (!(*bh))
+ if (!(*bh))
{
if (!(*bh = udf_tread(inode->i_sb,
udf_get_lb_pblock(inode->i_sb, bloc, 0),
@@ -1590,6 +1643,8 @@ int udf_write_aext(struct inode *inode, lb_addr bloc, int *extoffset,
udf_update_tag((*bh)->b_data,
le32_to_cpu(aed->lengthAllocDescs) + sizeof(struct AllocExtDesc));
}
+ else
+ mark_inode_dirty(inode);
mark_buffer_dirty(*bh, 1);
@@ -1681,10 +1736,11 @@ int udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
}
case ICB_FLAG_AD_IN_ICB:
{
- *bloc = *eloc = UDF_I_LOCATION(inode);
- *elen = UDF_I_LENALLOC(inode);
- *extoffset = udf_file_entry_alloc_offset(inode);
+ if (UDF_I_LENALLOC(inode) == 0)
+ return -1;
etype = EXTENT_RECORDED_ALLOCATED;
+ *eloc = UDF_I_LOCATION(inode);
+ *elen = UDF_I_LENALLOC(inode);
break;
}
default:
@@ -1696,8 +1752,8 @@ int udf_next_aext(struct inode *inode, lb_addr *bloc, int *extoffset,
if (*elen)
return etype;
- udf_debug("Empty Extent, inode=%ld, alloctype=%d, elen=%d, etype=%d, extoffset=%d\n",
- inode->i_ino, UDF_I_ALLOCTYPE(inode), *elen, etype, *extoffset);
+ 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) == ICB_FLAG_AD_SHORT)
*extoffset -= sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_LONG)
@@ -1917,7 +1973,7 @@ int udf_delete_aext(struct inode *inode, lb_addr nbloc, int nextoffset,
int inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset,
lb_addr *eloc, Uint32 *elen, Uint32 *offset, struct buffer_head **bh)
{
- int etype, lbcount = 0, b_off;
+ int etype, lbcount = 0;
if (block < 0)
{
@@ -1930,23 +1986,23 @@ int inode_bmap(struct inode *inode, int block, lb_addr *bloc, Uint32 *extoffset,
return -1;
}
- *extoffset = udf_file_entry_alloc_offset(inode);
+ *extoffset = 0;
*elen = 0;
- b_off = block << inode->i_sb->s_blocksize_bits;
*bloc = UDF_I_LOCATION(inode);
do
{
- lbcount += *elen;
-
if ((etype = udf_next_aext(inode, bloc, extoffset, eloc, elen, bh, 1)) == -1)
{
- *offset = (b_off - lbcount) >> inode->i_sb->s_blocksize_bits;
+ *offset = block - lbcount;
return -1;
}
- } while (lbcount + *elen <= b_off);
+ lbcount += ((*elen + inode->i_sb->s_blocksize - 1) >>
+ inode->i_sb->s_blocksize_bits);
+ } while (lbcount <= block);
- *offset = (b_off - lbcount) >> inode->i_sb->s_blocksize_bits;
+ *offset = block + ((*elen + inode->i_sb->s_blocksize - 1) >>
+ inode->i_sb->s_blocksize_bits) - lbcount;
return etype;
}
@@ -1966,7 +2022,7 @@ long udf_locked_block_map(struct inode *inode, long block)
if (bh)
udf_release_data(bh);
- if (UDF_SB(inode->i_sb)->s_flags & UDF_FLAG_VARCONV)
+ if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_VARCONV))
return udf_fixed_to_variable(ret);
else
return ret;
diff --git a/fs/udf/lowlevel.c b/fs/udf/lowlevel.c
index d8993254e..653997033 100644
--- a/fs/udf/lowlevel.c
+++ b/fs/udf/lowlevel.c
@@ -68,39 +68,40 @@ udf_get_last_session(struct super_block *sb)
}
unsigned int
-udf_get_last_block(struct super_block *sb, int *flags)
+udf_get_last_block(struct super_block *sb)
{
extern int *blksize_size[];
kdev_t dev = sb->s_dev;
struct block_device *bdev = sb->s_bdev;
int ret;
- unsigned long lblock;
- unsigned int hbsize = get_hardblocksize(dev);
- unsigned int secsize = 512;
- unsigned int mult = 0;
- unsigned int div = 0;
+ unsigned long lblock = 0;
- if (!hbsize)
- hbsize = blksize_size[MAJOR(dev)][MINOR(dev)];
+ ret = ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock);
- if (secsize > hbsize)
- mult = secsize / hbsize;
- else if (hbsize > secsize)
- div = hbsize / secsize;
+ if (ret) /* Hard Disk */
+ {
+ unsigned int hbsize = get_hardblocksize(dev);
+ unsigned int blocksize = sb->s_blocksize;
+ unsigned int mult = 0;
+ unsigned int div = 0;
- lblock = 0;
- ret = ioctl_by_bdev(bdev, BLKGETSIZE, (unsigned long) &lblock);
+ if (!hbsize)
+ hbsize = blksize_size[MAJOR(dev)][MINOR(dev)];
- if (!ret && lblock != 0x7FFFFFFF) /* Hard Disk */
- {
- if (mult)
- lblock *= mult;
- else if (div)
- lblock /= div;
- }
- else /* CDROM */
- {
- ret = ioctl_by_bdev(bdev, CDROM_LAST_WRITTEN, (unsigned long) &lblock);
+ if (hbsize > blocksize)
+ mult = hbsize / blocksize;
+ else if (blocksize > hbsize)
+ div = blocksize / hbsize;
+
+ ret = ioctl_by_bdev(bdev, BLKGETSIZE, (unsigned long) &lblock);
+
+ if (!ret && lblock != 0x7FFFFFFF)
+ {
+ if (mult)
+ lblock *= mult;
+ else if (div)
+ lblock /= div;
+ }
}
if (!ret && lblock)
diff --git a/fs/udf/misc.c b/fs/udf/misc.c
index 834727ae8..bed1e3984 100644
--- a/fs/udf/misc.c
+++ b/fs/udf/misc.c
@@ -69,7 +69,7 @@ udf64_high32(Uint64 indat)
extern struct buffer_head *
udf_tread(struct super_block *sb, int block, int size)
{
- if (UDF_SB(sb)->s_flags & UDF_FLAG_VARCONV)
+ if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV))
return bread(sb->s_dev, udf_fixed_to_variable(block), size);
else
return bread(sb->s_dev, block, size);
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index f31bff3fc..db140e66e 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -26,16 +26,14 @@
#include "udfdecl.h"
-#if defined(__linux__) && defined(__KERNEL__)
-#include <linux/version.h>
#include "udf_i.h"
#include "udf_sb.h"
#include <linux/string.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/malloc.h>
+#include <linux/quotaops.h>
#include <linux/udf_fs.h>
-#endif
static inline int udf_match(int len, const char * const name, struct qstr *qs)
{
@@ -185,14 +183,13 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
{
- udf_debug("udf_tread failed: block=%d\n", block);
udf_release_data(bh);
return NULL;
}
while ( (f_pos < size) )
{
- fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &offset, &bh);
+ fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
if (!fi)
{
@@ -228,13 +225,13 @@ udf_find_entry(struct inode *dir, struct dentry *dentry,
if ( (cfi->fileCharacteristics & FILE_DELETED) != 0 )
{
- if ( !IS_UNDELETE(dir->i_sb) )
+ if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNDELETE) )
continue;
}
if ( (cfi->fileCharacteristics & FILE_HIDDEN) != 0 )
{
- if ( !IS_UNHIDE(dir->i_sb) )
+ if ( !UDF_QUERY_FLAG(dir->i_sb, UDF_FLAG_UNHIDE) )
continue;
}
@@ -352,23 +349,27 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
return NULL;
sb = dir->i_sb;
- if (!dentry->d_name.len)
- return NULL;
-
- if (dir->i_size == 0)
+ if (dentry->d_name.len)
{
- *err = -ENOENT;
- return NULL;
- }
+ if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
+ {
+ *err = -ENAMETOOLONG;
+ return NULL;
+ }
- if ( !(udf_char_to_ustr(&unifilename, dentry->d_name.name, dentry->d_name.len)) )
+ if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) )
+ {
+ *err = -ENAMETOOLONG;
+ return NULL;
+ }
+ }
+ else if (dir->i_size != 0)
{
- *err = -ENAMETOOLONG;
+ *err = -ENOENT;
return NULL;
}
-
- if ( !(namelen = udf_UTF8toCS0(name, &unifilename, UDF_NAME_LEN)) )
- return 0;
+ else /* .. */
+ namelen = 0;
nfidlen = (sizeof(struct FileIdentDesc) + 0 + namelen + 3) & ~3;
@@ -388,83 +389,95 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
}
else
offset = 0;
- }
- else
- {
- udf_release_data(bh);
- return NULL;
- }
- if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
- return NULL;
-
- block = UDF_I_LOCATION(dir).logicalBlockNum;
-
- while ( (f_pos < size) )
- {
- fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &offset, &bh);
-
- if (!fi)
+ if (!(fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize)))
{
- if (fibh->sbh != fibh->ebh)
- udf_release_data(fibh->ebh);
- udf_release_data(fibh->sbh);
udf_release_data(bh);
return NULL;
}
-
- liu = le16_to_cpu(cfi->lengthOfImpUse);
- lfi = cfi->lengthFileIdent;
-
- if (fibh->sbh == fibh->ebh)
- nameptr = fi->fileIdent + liu;
- else
+
+ block = UDF_I_LOCATION(dir).logicalBlockNum;
+
+ while ( (f_pos < size) )
{
- int poffset; /* Unpaded ending offset */
-
- poffset = fibh->soffset + sizeof(struct FileIdentDesc) + liu + lfi;
-
- if (poffset >= lfi)
- nameptr = (char *)(fibh->ebh->b_data + poffset - lfi);
- else
+ fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+
+ if (!fi)
{
- nameptr = fname;
- memcpy(nameptr, fi->fileIdent + liu, lfi - poffset);
- memcpy(nameptr + lfi - poffset, fibh->ebh->b_data, poffset);
+ if (fibh->sbh != fibh->ebh)
+ udf_release_data(fibh->ebh);
+ udf_release_data(fibh->sbh);
+ udf_release_data(bh);
+ return NULL;
}
- }
-
- if ( (cfi->fileCharacteristics & FILE_DELETED) != 0 )
- {
- if (((sizeof(struct FileIdentDesc) + liu + lfi + 3) & ~3) == nfidlen)
+
+ liu = le16_to_cpu(cfi->lengthOfImpUse);
+ lfi = cfi->lengthFileIdent;
+
+ if (fibh->sbh == fibh->ebh)
+ nameptr = fi->fileIdent + liu;
+ else
{
- 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(cfi, fi, fibh, NULL, name))
- return fi;
+ int poffset; /* Unpaded ending offset */
+
+ poffset = fibh->soffset + sizeof(struct FileIdentDesc) + liu + lfi;
+
+ 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 & FILE_DELETED) != 0 )
+ {
+ 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(cfi, fi, fibh, NULL, name))
+ return fi;
+ else
+ return NULL;
+ }
+ }
+
+ if (!lfi)
+ continue;
+
+ if ((flen = udf_get_filename(nameptr, fname, lfi)))
+ {
+ if (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;
+ }
}
}
-
- if (!lfi)
- continue;
-
- if ((flen = udf_get_filename(nameptr, fname, lfi)))
+ }
+ else
+ {
+ block = udf_get_lb_pblock(dir->i_sb, UDF_I_LOCATION(dir), 0);
+ if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
{
- if (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;
- }
+ fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block, dir->i_sb->s_blocksize);
+ fibh->soffset = fibh->eoffset = udf_file_entry_alloc_offset(dir);
+ }
+ else
+ {
+ fibh->sbh = fibh->ebh = NULL;
+ fibh->soffset = fibh->eoffset = sb->s_blocksize;
}
}
@@ -484,14 +497,14 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
if (!(fibh->sbh = fibh->ebh = udf_expand_dir_adinicb(dir, &block, err)))
return NULL;
bloc = UDF_I_LOCATION(dir);
+ eloc.logicalBlockNum = block;
+ eloc.partitionReferenceNum = UDF_I_LOCATION(dir).partitionReferenceNum;
+ elen = dir->i_sb->s_blocksize;
extoffset = udf_file_entry_alloc_offset(dir);
- }
- else
- {
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_SHORT)
- extoffset -= sizeof(short_ad);
+ extoffset += sizeof(short_ad);
else if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_LONG)
- extoffset -= sizeof(long_ad);
+ extoffset += sizeof(long_ad);
}
if (sb->s_blocksize - fibh->eoffset >= nfidlen)
@@ -505,25 +518,8 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
}
if (UDF_I_ALLOCTYPE(dir) != ICB_FLAG_AD_IN_ICB)
- {
- Uint32 lextoffset = extoffset;
- if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) !=
- EXTENT_RECORDED_ALLOCATED)
- {
- udf_release_data(bh);
- udf_release_data(fibh->sbh);
- return NULL;
- }
- else
- {
- if (elen & (sb->s_blocksize - 1))
- elen += nfidlen;
- block = eloc.logicalBlockNum + ((elen - 1) >>
- dir->i_sb->s_blocksize_bits);
- elen = (EXTENT_RECORDED_ALLOCATED << 30) | elen;
- udf_write_aext(dir, bloc, &lextoffset, eloc, elen, &bh, 1);
- }
- }
+ block = eloc.logicalBlockNum + ((elen - 1) >>
+ dir->i_sb->s_blocksize_bits);
else
block = UDF_I_LOCATION(dir).logicalBlockNum;
@@ -531,8 +527,6 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
}
else
{
- Uint32 lextoffset = extoffset;
-
fibh->soffset = fibh->eoffset - sb->s_blocksize;
fibh->eoffset += nfidlen - sb->s_blocksize;
if (fibh->sbh != fibh->ebh)
@@ -541,21 +535,8 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
fibh->sbh = fibh->ebh;
}
- if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) !=
- EXTENT_RECORDED_ALLOCATED)
- {
- udf_release_data(bh);
- udf_release_data(fibh->sbh);
- return NULL;
- }
- else
- {
- elen = ((elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1));
- block = eloc.logicalBlockNum +
- ((elen - 1) >> dir->i_sb->s_blocksize_bits);
- elen = (EXTENT_RECORDED_ALLOCATED << 30) | elen;
- udf_write_aext(dir, bloc, &lextoffset, eloc, elen, &bh, 0);
- }
+ block = eloc.logicalBlockNum + ((elen - 1) >>
+ dir->i_sb->s_blocksize_bits);
*err = -ENOSPC;
if (!(fibh->ebh = udf_bread(dir, f_pos >> (dir->i_sb->s_blocksize_bits - 2), 1, err)))
@@ -564,38 +545,27 @@ udf_add_entry(struct inode *dir, struct dentry *dentry,
udf_release_data(fibh->sbh);
return NULL;
}
+
if (!(fibh->soffset))
{
- if (udf_next_aext(dir, &bloc, &lextoffset, &eloc, &elen, &bh, 1) ==
+ if (udf_next_aext(dir, &bloc, &extoffset, &eloc, &elen, &bh, 1) ==
EXTENT_RECORDED_ALLOCATED)
{
- if (block == (eloc.logicalBlockNum +
- ((elen - 1) >> dir->i_sb->s_blocksize_bits)))
- {
- if (udf_next_aext(dir, &bloc, &lextoffset, &eloc, &elen, &bh, 1) !=
- EXTENT_RECORDED_ALLOCATED)
- {
- udf_release_data(bh);
- udf_release_data(fibh->sbh);
- udf_release_data(fibh->ebh);
- udf_debug("next extent not recorded and allocated\n");
- return NULL;
- }
- }
+ block = eloc.logicalBlockNum + ((elen - 1) >>
+ dir->i_sb->s_blocksize_bits);
}
else
- {
- udf_release_data(bh);
- udf_release_data(fibh->sbh);
- udf_release_data(fibh->ebh);
- udf_debug("next extent not recorded and allocated\n");
- return NULL;
- }
- block = eloc.logicalBlockNum + ((elen - 1) >>
- dir->i_sb->s_blocksize_bits);
- }
+ block ++;
- fi = (struct FileIdentDesc *)(fibh->sbh->b_data + sb->s_blocksize + fibh->soffset);
+ udf_release_data(fibh->sbh);
+ fibh->sbh = fibh->ebh;
+ fi = (struct FileIdentDesc *)(fibh->sbh->b_data);
+ }
+ else
+ {
+ fi = (struct FileIdentDesc *)
+ (fibh->sbh->b_data + sb->s_blocksize + fibh->soffset);
+ }
}
memset(cfi, 0, sizeof(struct FileIdentDesc));
@@ -642,7 +612,10 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode)
if (!inode)
return err;
- inode->i_data.a_ops = &udf_adinicb_aops;
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+ inode->i_data.a_ops = &udf_adinicb_aops;
+ else
+ inode->i_data.a_ops = &udf_aops;
inode->i_op = &udf_file_inode_operations;
inode->i_fop = &udf_file_operations;
inode->i_mode = mode;
@@ -650,7 +623,6 @@ static int udf_create(struct inode *dir, struct dentry *dentry, int mode)
if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
{
- udf_debug("udf_add_entry failure!\n");
inode->i_nlink --;
mark_inode_dirty(inode);
iput(inode);
@@ -689,7 +661,6 @@ static int udf_mknod(struct inode * dir, struct dentry * dentry, int mode, int r
init_special_inode(inode, mode, rdev);
if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
{
- udf_debug("udf_add_entry failure!\n");
inode->i_nlink --;
mark_inode_dirty(inode);
iput(inode);
@@ -721,9 +692,8 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
struct inode * inode;
struct udf_fileident_bh fibh;
int err;
- struct FileEntry *fe;
struct FileIdentDesc cfi, *fi;
- Uint32 loc;
+ struct dentry parent;
err = -EMLINK;
if (dir->i_nlink >= (256<<sizeof(dir->i_nlink))-1)
@@ -736,12 +706,10 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
inode->i_op = &udf_dir_inode_operations;
inode->i_fop = &udf_dir_operations;
- inode->i_size = (sizeof(struct FileIdentDesc) + 3) & ~3;
- UDF_I_LENALLOC(inode) = inode->i_size;
- loc = UDF_I_LOCATION(inode).logicalBlockNum;
- fibh.sbh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
-
- if (!fibh.sbh)
+ parent.d_name.len = 0;
+ parent.d_name.name = NULL;
+ inode->i_size = 0;
+ if (!(fi = udf_add_entry(inode, &parent, &fibh, &cfi, &err)))
{
inode->i_nlink--;
mark_inode_dirty(inode);
@@ -749,21 +717,11 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
goto out;
}
inode->i_nlink = 2;
- fe = (struct FileEntry *)fibh.sbh->b_data;
- fi = (struct FileIdentDesc *)&(fe->extendedAttr[UDF_I_LENEATTR(inode)]);
- udf_new_tag((char *)&cfi, TID_FILE_IDENT_DESC, 2, 1, loc,
- sizeof(struct FileIdentDesc));
- cfi.fileVersionNum = cpu_to_le16(1);
- cfi.fileCharacteristics = FILE_DIRECTORY | FILE_PARENT;
- cfi.lengthFileIdent = 0;
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(dir));
*(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse =
cpu_to_le32(UDF_I_UNIQUE(dir) & 0x00000000FFFFFFFFUL);
- cfi.lengthOfImpUse = cpu_to_le16(0);
- fibh.ebh = fibh.sbh;
- fibh.soffset = sizeof(struct FileEntry);
- fibh.eoffset = sizeof(struct FileEntry) + inode->i_size;
+ cfi.fileCharacteristics = FILE_DIRECTORY | FILE_PARENT;
udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
udf_release_data(fibh.sbh);
inode->i_mode = S_IFDIR | (mode & (S_IRWXUGO|S_ISVTX) & ~current->fs->umask);
@@ -773,7 +731,6 @@ static int udf_mkdir(struct inode * dir, struct dentry * dentry, int mode)
if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
{
- udf_debug("udf_add_entry failure!\n");
inode->i_nlink = 0;
mark_inode_dirty(inode);
iput(inode);
@@ -836,7 +793,7 @@ static int empty_dir(struct inode *dir)
while ( (f_pos < size) )
{
- fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &bloc, &extoffset, &offset, &bh);
+ fi = udf_fileident_read(dir, &f_pos, &fibh, &cfi, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
if (!fi)
{
@@ -873,6 +830,7 @@ static int udf_rmdir(struct inode * dir, struct dentry * dentry)
goto out;
inode = dentry->d_inode;
+ DQUOT_INIT(inode);
retval = -EIO;
if (udf_get_lb_pblock(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation), 0) != inode->i_ino)
@@ -920,6 +878,7 @@ static int udf_unlink(struct inode * dir, struct dentry * dentry)
goto out;
inode = dentry->d_inode;
+ DQUOT_INIT(inode);
retval = -EIO;
@@ -959,6 +918,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
{
struct inode * inode;
struct PathComponent *pc;
+ char *compstart;
struct udf_fileident_bh fibh;
struct buffer_head *bh = NULL;
int eoffset, elen = 0;
@@ -966,6 +926,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
struct FileIdentDesc cfi;
char *ea;
int err;
+ int block;
if (!(inode = udf_new_inode(dir, S_IFLNK, &err)))
goto out;
@@ -974,8 +935,34 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
inode->i_data.a_ops = &udf_symlink_aops;
inode->i_op = &page_symlink_inode_operations;
- bh = udf_tread(inode->i_sb, inode->i_ino, inode->i_sb->s_blocksize);
- ea = bh->b_data + udf_file_entry_alloc_offset(inode);
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+ {
+ struct buffer_head *bh = NULL;
+ lb_addr bloc, eloc;
+ Uint32 elen, extoffset;
+
+ block = udf_new_block(inode,
+ UDF_I_LOCATION(inode).partitionReferenceNum,
+ UDF_I_LOCATION(inode).logicalBlockNum, &err);
+ if (!block)
+ goto out_no_entry;
+ bloc = UDF_I_LOCATION(inode);
+ eloc.logicalBlockNum = block;
+ eloc.partitionReferenceNum = UDF_I_LOCATION(inode).partitionReferenceNum;
+ elen = inode->i_sb->s_blocksize;
+ extoffset = udf_file_entry_alloc_offset(inode);
+ udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 0);
+ udf_release_data(bh);
+
+ inode->i_blocks = inode->i_sb->s_blocksize / 512;
+ block = udf_get_pblock(inode->i_sb, block,
+ UDF_I_LOCATION(inode).partitionReferenceNum, 0);
+ }
+ else
+ block = udf_get_lb_pblock(inode->i_sb, UDF_I_LOCATION(inode), 0);
+
+ bh = udf_tread(inode->i_sb, block, inode->i_sb->s_blocksize);
+ ea = bh->b_data + udf_ext0_offset(inode);
eoffset = inode->i_sb->s_blocksize - (ea - bh->b_data);
pc = (struct PathComponent *)ea;
@@ -994,9 +981,13 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
elen += sizeof(struct PathComponent);
}
- while (*symname && eoffset > elen + sizeof(struct PathComponent))
+ err = -ENAMETOOLONG;
+
+ while (*symname)
{
- char *compstart;
+ if (elen + sizeof(struct PathComponent) > eoffset)
+ goto out_no_entry;
+
pc = (struct PathComponent *)(ea + elen);
compstart = (char *)symname;
@@ -1020,7 +1011,7 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
if (pc->componentType == 5)
{
if (elen + sizeof(struct PathComponent) + symname - compstart > eoffset)
- pc->lengthComponentIdent = eoffset - elen - sizeof(struct PathComponent);
+ goto out_no_entry;
else
pc->lengthComponentIdent = symname - compstart;
@@ -1039,25 +1030,27 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
}
udf_release_data(bh);
- UDF_I_LENALLOC(inode) = inode->i_size = elen;
+ inode->i_size = elen;
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+ UDF_I_LENALLOC(inode) = inode->i_size;
mark_inode_dirty(inode);
if (!(fi = udf_add_entry(dir, dentry, &fibh, &cfi, &err)))
- goto out;
+ goto out_no_entry;
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
- if (UDF_SB_LVIDBH(inode->i_sb))
- {
- struct LogicalVolHeaderDesc *lvhd;
- Uint64 uniqueID;
- lvhd = (struct LogicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
- uniqueID = le64_to_cpu(lvhd->uniqueID);
+ if (UDF_SB_LVIDBH(inode->i_sb))
+ {
+ struct LogicalVolHeaderDesc *lvhd;
+ Uint64 uniqueID;
+ lvhd = (struct LogicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
+ uniqueID = le64_to_cpu(lvhd->uniqueID);
*(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse =
- le32_to_cpu(uniqueID & 0x00000000FFFFFFFFUL);
- if (!(++uniqueID & 0x00000000FFFFFFFFUL))
- uniqueID += 16;
- lvhd->uniqueID = cpu_to_le64(uniqueID);
- mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);
+ cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
+ if (!(++uniqueID & 0x00000000FFFFFFFFUL))
+ uniqueID += 16;
+ lvhd->uniqueID = cpu_to_le64(uniqueID);
+ mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);
}
udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
@@ -1073,6 +1066,12 @@ static int udf_symlink(struct inode * dir, struct dentry * dentry, const char *
out:
return err;
+
+out_no_entry:
+ inode->i_nlink--;
+ mark_inode_dirty(inode);
+ iput(inode);
+ goto out;
}
static int udf_link(struct dentry * old_dentry, struct inode * dir,
@@ -1093,18 +1092,18 @@ static int udf_link(struct dentry * old_dentry, struct inode * dir,
return err;
cfi.icb.extLength = cpu_to_le32(inode->i_sb->s_blocksize);
cfi.icb.extLocation = cpu_to_lelb(UDF_I_LOCATION(inode));
- if (UDF_SB_LVIDBH(inode->i_sb))
- {
- struct LogicalVolHeaderDesc *lvhd;
- Uint64 uniqueID;
- lvhd = (struct LogicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
- uniqueID = le64_to_cpu(lvhd->uniqueID);
+ if (UDF_SB_LVIDBH(inode->i_sb))
+ {
+ struct LogicalVolHeaderDesc *lvhd;
+ Uint64 uniqueID;
+ lvhd = (struct LogicalVolHeaderDesc *)(UDF_SB_LVID(inode->i_sb)->logicalVolContentsUse);
+ uniqueID = le64_to_cpu(lvhd->uniqueID);
*(Uint32 *)((struct ADImpUse *)cfi.icb.impUse)->impUse =
cpu_to_le32(uniqueID & 0x00000000FFFFFFFFUL);
- if (!(++uniqueID & 0x00000000FFFFFFFFUL))
- uniqueID += 16;
- lvhd->uniqueID = cpu_to_le64(uniqueID);
- mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);
+ if (!(++uniqueID & 0x00000000FFFFFFFFUL))
+ uniqueID += 16;
+ lvhd->uniqueID = cpu_to_le64(uniqueID);
+ mark_buffer_dirty(UDF_SB_LVIDBH(inode->i_sb), 1);
}
udf_write_fi(&cfi, fi, &fibh, NULL, NULL);
if (UDF_I_ALLOCTYPE(dir) == ICB_FLAG_AD_IN_ICB)
@@ -1157,9 +1156,7 @@ static int udf_rename (struct inode * old_dir, struct dentry * old_dentry,
}
else
{
-/*
DQUOT_INIT(new_inode);
-*/
}
}
if (S_ISDIR(old_inode->i_mode))
@@ -1272,15 +1269,13 @@ end_rename:
}
struct inode_operations udf_dir_inode_operations = {
- lookup: udf_lookup,
-#if CONFIG_UDF_RW == 1
- create: udf_create,
- link: udf_link,
- unlink: udf_unlink,
- symlink: udf_symlink,
- mkdir: udf_mkdir,
- rmdir: udf_rmdir,
- mknod: udf_mknod,
- rename: udf_rename,
-#endif
+ lookup: udf_lookup,
+ create: udf_create,
+ link: udf_link,
+ unlink: udf_unlink,
+ symlink: udf_symlink,
+ mkdir: udf_mkdir,
+ rmdir: udf_rmdir,
+ mknod: udf_mknod,
+ rename: udf_rename,
};
diff --git a/fs/udf/partition.c b/fs/udf/partition.c
index 658d2220e..dcdf7666c 100644
--- a/fs/udf/partition.c
+++ b/fs/udf/partition.c
@@ -15,7 +15,7 @@
* ftp://prep.ai.mit.edu/pub/gnu/GPL
* Each contributing author retains all rights to their own work.
*
- * (C) 1998-1999 Ben Fennema
+ * (C) 1998-2000 Ben Fennema
*
* HISTORY
*
diff --git a/fs/udf/super.c b/fs/udf/super.c
index ed98bf802..6b3e32f03 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -78,6 +78,7 @@ static char error_buf[1024];
/* These are the "meat" - everything else is stuffing */
static struct super_block *udf_read_super(struct super_block *, void *, int);
static void udf_put_super(struct super_block *);
+static void udf_write_super(struct super_block *);
static int udf_remount_fs(struct super_block *, int *, char *);
static int udf_check_valid(struct super_block *, int, int);
static int udf_vrs(struct super_block *sb, int silent);
@@ -96,24 +97,21 @@ static int udf_statfs(struct super_block *, struct statfs *, int);
/* UDF filesystem type */
static struct file_system_type udf_fstype = {
- "udf", /* name */
- FS_REQUIRES_DEV, /* fs_flags */
- udf_read_super, /* read_super */
- NULL /* next */
+ name: "udf",
+ fs_flags: FS_REQUIRES_DEV,
+ read_super: udf_read_super,
};
/* Superblock operations */
-static struct super_operations udf_sb_ops =
-{
- read_inode: udf_read_inode,
- put_inode: udf_put_inode,
- put_super: udf_put_super,
- statfs: udf_statfs,
- remount_fs: udf_remount_fs,
-#if CONFIG_UDF_RW == 1
- write_inode: udf_write_inode,
- delete_inode: udf_delete_inode,
-#endif
+static struct super_operations udf_sb_ops = {
+ read_inode: udf_read_inode,
+ write_inode: udf_write_inode,
+ put_inode: udf_put_inode,
+ delete_inode: udf_delete_inode,
+ put_super: udf_put_super,
+ write_super: udf_write_super,
+ statfs: udf_statfs,
+ remount_fs: udf_remount_fs,
};
struct udf_options
@@ -201,14 +199,18 @@ int __init init_udf_fs(void)
* gid= Set the default group.
* umask= Set the default umask.
* uid= Set the default user.
+ * bs= Set the block size.
* unhide Show otherwise hidden files.
* undelete Show deleted files in lists.
+ * adinicb Embed data in the inode (default)
+ * noadinicb Don't embed data in the inode
+ * shortad Use short ad's
+ * longad Use long ad's (default)
* strict Set strict conformance (unused)
*
* The remaining are for debugging and disaster recovery:
*
- * bs= Set the block size. (may not work unless 2048)
- * novrs Skip volume sequence recognition
+ * novrs Skip volume sequence recognition
*
* The following expect a offset from 0.
*
@@ -244,7 +246,7 @@ udf_parse_options(char *options, struct udf_options *uopt)
char *opt, *val;
uopt->novrs = 0;
- uopt->blocksize = 2048;
+ uopt->blocksize = 512;
uopt->partition = 0xFFFF;
uopt->session = 0xFFFFFFFF;
uopt->lastblock = 0xFFFFFFFF;
@@ -256,7 +258,7 @@ udf_parse_options(char *options, struct udf_options *uopt)
if (!options)
return 1;
- for (opt = strtok(options, ","); opt; opt = strtok(NULL, ","))
+ for (opt = strtok(options, ","); opt; opt = strtok(NULL, ","))
{
/* Make "opt=val" into two strings */
val = strchr(opt, '=');
@@ -267,15 +269,23 @@ udf_parse_options(char *options, struct udf_options *uopt)
else if (!strcmp(opt, "bs") && val)
uopt->blocksize = simple_strtoul(val, NULL, 0);
else if (!strcmp(opt, "unhide") && !val)
- uopt->flags |= UDF_FLAG_UNHIDE;
+ uopt->flags |= (1 << UDF_FLAG_UNHIDE);
else if (!strcmp(opt, "undelete") && !val)
- uopt->flags |= UDF_FLAG_UNDELETE;
+ uopt->flags |= (1 << UDF_FLAG_UNDELETE);
+ else if (!strcmp(opt, "noadinicb") && !val)
+ uopt->flags &= ~(1 << UDF_FLAG_USE_AD_IN_ICB);
+ else if (!strcmp(opt, "adinicb") && !val)
+ uopt->flags |= (1 << UDF_FLAG_USE_AD_IN_ICB);
+ else if (!strcmp(opt, "shortad") && !val)
+ uopt->flags |= (1 << UDF_FLAG_USE_SHORT_AD);
+ else if (!strcmp(opt, "longad") && !val)
+ uopt->flags &= ~(1 << UDF_FLAG_USE_SHORT_AD);
else if (!strcmp(opt, "gid") && val)
uopt->gid = simple_strtoul(val, NULL, 0);
else if (!strcmp(opt, "umask") && val)
uopt->umask = simple_strtoul(val, NULL, 0);
else if (!strcmp(opt, "strict") && !val)
- uopt->flags |= UDF_FLAG_STRICT;
+ uopt->flags |= (1 << UDF_FLAG_STRICT);
else if (!strcmp(opt, "uid") && val)
uopt->uid = simple_strtoul(val, NULL, 0);
else if (!strcmp(opt, "session") && val)
@@ -308,23 +318,35 @@ udf_parse_options(char *options, struct udf_options *uopt)
return 1;
}
+void
+udf_write_super(struct super_block *sb)
+{
+ if (!(sb->s_flags & MS_RDONLY))
+ udf_open_lvid(sb);
+ sb->s_dirt = 0;
+}
+
static int
udf_remount_fs(struct super_block *sb, int *flags, char *options)
{
struct udf_options uopt;
- uopt.flags = UDF_SB(sb)->s_flags ;
- uopt.uid = UDF_SB(sb)->s_uid ;
- uopt.gid = UDF_SB(sb)->s_gid ;
- uopt.umask = UDF_SB(sb)->s_umask ;
+ uopt.flags = UDF_SB(sb)->s_flags ;
+ uopt.uid = UDF_SB(sb)->s_uid ;
+ uopt.gid = UDF_SB(sb)->s_gid ;
+ uopt.umask = UDF_SB(sb)->s_umask ;
if ( !udf_parse_options(options, &uopt) )
return -EINVAL;
- UDF_SB(sb)->s_flags = uopt.flags;
- UDF_SB(sb)->s_uid = uopt.uid;
- UDF_SB(sb)->s_gid = uopt.gid;
- UDF_SB(sb)->s_umask = uopt.umask;
+ UDF_SB(sb)->s_flags = uopt.flags;
+ UDF_SB(sb)->s_uid = uopt.uid;
+ UDF_SB(sb)->s_gid = uopt.gid;
+ UDF_SB(sb)->s_umask = uopt.umask;
+
+#if CONFIG_UDF_RW != 1
+ *flags |= MS_RDONLY;
+#endif
if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
return 0;
@@ -367,8 +389,8 @@ static int
udf_set_blocksize(struct super_block *sb, int bsize)
{
/* Use specified block size if specified */
- sb->s_blocksize = get_hardblocksize(sb->s_dev);
- sb->s_blocksize = sb->s_blocksize ? sb->s_blocksize : 2048;
+ if (!(sb->s_blocksize = get_hardblocksize(sb->s_dev)))
+ sb->s_blocksize = 2048;
if (bsize > sb->s_blocksize)
sb->s_blocksize = bsize;
@@ -414,7 +436,7 @@ udf_vrs(struct super_block *sb, int silent)
for (;!nsr02 && !nsr03; sector += 2048)
{
/* Read a block */
- bh = udf_tread(sb, sector >> sb->s_blocksize_bits, 2048);
+ bh = udf_tread(sb, sector >> sb->s_blocksize_bits, sb->s_blocksize);
if (!bh)
break;
@@ -548,7 +570,7 @@ udf_find_anchor(struct super_block *sb, int useranchor, int lastblock)
}
else if (location == udf_variable_to_fixed(last[i]) - UDF_SB_SESSION(sb))
{
- UDF_SB(sb)->s_flags |= UDF_FLAG_VARCONV;
+ UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
lastblock = UDF_SB_ANCHOR(sb)[0] = udf_variable_to_fixed(last[i]);
UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
}
@@ -597,7 +619,7 @@ udf_find_anchor(struct super_block *sb, int useranchor, int lastblock)
if (ident == TID_ANCHOR_VOL_DESC_PTR &&
location == udf_variable_to_fixed(last[i]) - 256)
{
- UDF_SB(sb)->s_flags |= UDF_FLAG_VARCONV;
+ UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
lastblock = udf_variable_to_fixed(last[i]);
UDF_SB_ANCHOR(sb)[1] = lastblock - 256;
}
@@ -615,7 +637,7 @@ udf_find_anchor(struct super_block *sb, int useranchor, int lastblock)
udf_release_data(bh);
if (ident == TID_ANCHOR_VOL_DESC_PTR && location == 256)
- UDF_SB(sb)->s_flags |= UDF_FLAG_VARCONV;
+ UDF_SET_FLAG(sb, UDF_FLAG_VARCONV);
}
}
@@ -755,17 +777,17 @@ udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
if ( udf_stamp_to_time(&recording, &recording_usec,
lets_to_cpu(pvoldesc->recordingDateAndTime)) )
{
- timestamp ts;
- ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
+ timestamp ts;
+ ts = lets_to_cpu(pvoldesc->recordingDateAndTime);
udf_debug("recording time %ld/%ld, %04u/%02u/%02u %02u:%02u (%x)\n",
recording, recording_usec,
ts.year, ts.month, ts.day, ts.hour, ts.minute, ts.typeAndTimezone);
- UDF_SB_RECORDTIME(sb) = recording;
+ UDF_SB_RECORDTIME(sb) = recording;
}
if ( !udf_build_ustr(&instr, pvoldesc->volIdent, 32) )
{
- if (!udf_CS0toUTF8(&outstr, &instr))
+ if (udf_CS0toUTF8(&outstr, &instr))
{
udf_debug("volIdent[] = '%s'\n", outstr.u_name);
strncpy( UDF_SB_VOLIDENT(sb), outstr.u_name, outstr.u_len);
@@ -774,7 +796,7 @@ udf_load_pvoldesc(struct super_block *sb, struct buffer_head *bh)
if ( !udf_build_ustr(&instr, pvoldesc->volSetIdent, 128) )
{
- if (!udf_CS0toUTF8(&outstr, &instr))
+ if (udf_CS0toUTF8(&outstr, &instr))
udf_debug("volSetIdent[] = '%s'\n", outstr.u_name);
}
}
@@ -1107,10 +1129,10 @@ udf_load_partition(struct super_block *sb, lb_addr *fileset)
Uint16 ident;
struct buffer_head *bh;
long main_s, main_e, reserve_s, reserve_e;
- int i;
+ int i, j;
if (!sb)
- return 1;
+ return 1;
for (i=0; i<sizeof(UDF_SB_ANCHOR(sb))/sizeof(int); i++)
{
@@ -1166,12 +1188,21 @@ udf_load_partition(struct super_block *sb, lb_addr *fileset)
return 1;
}
- if (i == 0)
- ino.partitionReferenceNum = i+1;
- else
- ino.partitionReferenceNum = i-1;
+ for (j=0; j<UDF_SB_NUMPARTS(sb); j++)
+ {
+ if (j != i &&
+ UDF_SB_PARTVSN(sb,i) == UDF_SB_PARTVSN(sb,j) &&
+ UDF_SB_PARTNUM(sb,i) == UDF_SB_PARTNUM(sb,j))
+ {
+ ino.partitionReferenceNum = j;
+ ino.logicalBlockNum = UDF_SB_LASTBLOCK(sb) -
+ UDF_SB_PARTROOT(sb,j);
+ break;
+ }
+ }
- ino.logicalBlockNum = UDF_SB_LASTBLOCK(sb) - UDF_SB_PARTROOT(sb,ino.partitionReferenceNum);
+ if (j == UDF_SB_NUMPARTS(sb))
+ return 1;
if (!(UDF_SB_VAT(sb) = udf_iget(sb, ino)))
return 1;
@@ -1206,7 +1237,6 @@ udf_load_partition(struct super_block *sb, lb_addr *fileset)
static void udf_open_lvid(struct super_block *sb)
{
-#if CONFIG_UDF_RW == 1
if (UDF_SB_LVIDBH(sb))
{
int i;
@@ -1229,13 +1259,12 @@ static void udf_open_lvid(struct super_block *sb)
((Uint8 *)&(UDF_SB_LVID(sb)->descTag))[i];
mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
+ sb->s_dirt = 0;
}
-#endif
}
static void udf_close_lvid(struct super_block *sb)
{
-#if CONFIG_UDF_RW == 1
if (UDF_SB_LVIDBH(sb) &&
UDF_SB_LVID(sb)->integrityType == INTEGRITY_TYPE_OPEN)
{
@@ -1246,7 +1275,12 @@ static void udf_close_lvid(struct super_block *sb)
UDF_SB_LVIDIU(sb)->impIdent.identSuffix[1] = UDF_OS_ID_LINUX;
if (udf_time_to_stamp(&cpu_time, CURRENT_TIME, CURRENT_UTIME))
UDF_SB_LVID(sb)->recordingDateAndTime = cpu_to_lets(cpu_time);
-
+ if (UDF_MAX_WRITE_VERSION > le16_to_cpu(UDF_SB_LVIDIU(sb)->maxUDFWriteRev))
+ UDF_SB_LVIDIU(sb)->maxUDFWriteRev = cpu_to_le16(UDF_MAX_WRITE_VERSION);
+ if (UDF_SB_UDFREV(sb) > le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFReadRev))
+ UDF_SB_LVIDIU(sb)->minUDFReadRev = cpu_to_le16(UDF_SB_UDFREV(sb));
+ if (UDF_SB_UDFREV(sb) > le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFWriteRev))
+ UDF_SB_LVIDIU(sb)->minUDFWriteRev = cpu_to_le16(UDF_SB_UDFREV(sb));
UDF_SB_LVID(sb)->integrityType = INTEGRITY_TYPE_CLOSE;
UDF_SB_LVID(sb)->descTag.descCRC =
@@ -1261,7 +1295,6 @@ static void udf_close_lvid(struct super_block *sb)
mark_buffer_dirty(UDF_SB_LVIDBH(sb), 1);
}
-#endif
}
/*
@@ -1288,7 +1321,7 @@ udf_read_super(struct super_block *sb, void *options, int silent)
lb_addr rootdir, fileset;
int i;
- uopt.flags = 0;
+ uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB);
uopt.uid = -1;
uopt.gid = -1;
uopt.umask = 0;
@@ -1297,19 +1330,17 @@ udf_read_super(struct super_block *sb, void *options, int silent)
MOD_INC_USE_COUNT;
lock_super(sb);
+ memset(UDF_SB(sb), 0x00, sizeof(struct udf_sb_info));
- UDF_SB_PARTMAPS(sb) = NULL;
- UDF_SB_LVIDBH(sb) = NULL;
- UDF_SB_VAT(sb) = NULL;
+#if CONFIG_UDF_RW != 1
+ sb->s_flags |= MS_RDONLY;
+#endif
if (!udf_parse_options((char *)options, &uopt))
goto error_out;
- memset(UDF_SB_ANCHOR(sb), 0x00, sizeof(UDF_SB_ANCHOR(sb)));
fileset.logicalBlockNum = 0xFFFFFFFF;
fileset.partitionReferenceNum = 0xFFFF;
- UDF_SB_RECORDTIME(sb)=0;
- UDF_SB_VOLIDENT(sb)[0]=0;
UDF_SB(sb)->s_flags = uopt.flags;
UDF_SB(sb)->s_uid = uopt.uid;
@@ -1328,7 +1359,7 @@ udf_read_super(struct super_block *sb, void *options, int silent)
udf_debug("Multi-session=%d\n", UDF_SB_SESSION(sb));
if ( uopt.lastblock == 0xFFFFFFFF )
- UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb, &(UDF_SB(sb)->s_flags));
+ UDF_SB_LASTBLOCK(sb) = udf_get_last_block(sb);
else
UDF_SB_LASTBLOCK(sb) = uopt.lastblock;
@@ -1338,7 +1369,7 @@ udf_read_super(struct super_block *sb, void *options, int silent)
if (udf_check_valid(sb, uopt.novrs, silent)) /* read volume recognition sequences */
{
- udf_debug("No VRS found\n");
+ printk("UDF-fs: No VRS found\n");
goto error_out;
}
@@ -1357,19 +1388,42 @@ udf_read_super(struct super_block *sb, void *options, int silent)
if (udf_load_partition(sb, &fileset))
{
- udf_debug("No partition found (1)\n");
+ printk("UDF-fs: No partition found (1)\n");
goto error_out;
}
+ if ( UDF_SB_LVIDBH(sb) )
+ {
+ Uint16 minUDFReadRev = le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFReadRev);
+ Uint16 minUDFWriteRev = le16_to_cpu(UDF_SB_LVIDIU(sb)->minUDFWriteRev);
+ /* Uint16 maxUDFWriteRev = le16_to_cpu(UDF_SB_LVIDIU(sb)->maxUDFWriteRev); */
+
+ if (minUDFReadRev > UDF_MAX_READ_VERSION)
+ {
+ printk("UDF-fs: minUDFReadRev=%x (max is %x)\n",
+ UDF_SB_LVIDIU(sb)->minUDFReadRev, UDF_MAX_READ_VERSION);
+ goto error_out;
+ }
+ else if (minUDFWriteRev > UDF_MAX_WRITE_VERSION)
+ {
+ sb->s_flags |= MS_RDONLY;
+ }
+
+ if (minUDFReadRev >= UDF_VERS_USE_EXTENDED_FE)
+ UDF_SET_FLAG(sb, UDF_FLAG_USE_EXTENDED_FE);
+ if (minUDFReadRev >= UDF_VERS_USE_STREAMS)
+ UDF_SET_FLAG(sb, UDF_FLAG_USE_STREAMS);
+ }
+
if ( !UDF_SB_NUMPARTS(sb) )
{
- udf_debug("No partition found (2)\n");
+ printk("UDF-fs: No partition found (2)\n");
goto error_out;
}
if ( udf_find_fileset(sb, &fileset, &rootdir) )
{
- udf_debug("No fileset found\n");
+ printk("UDF-fs: No fileset found\n");
goto error_out;
}
@@ -1392,7 +1446,7 @@ udf_read_super(struct super_block *sb, void *options, int silent)
inode = udf_iget(sb, rootdir);
if (!inode)
{
- udf_debug("Error in udf_iget, block=%d, partition=%d\n",
+ printk("UDF-fs: Error in udf_iget, block=%d, partition=%d\n",
rootdir.logicalBlockNum, rootdir.partitionReferenceNum);
goto error_out;
}
@@ -1401,8 +1455,8 @@ udf_read_super(struct super_block *sb, void *options, int silent)
sb->s_root = d_alloc_root(inode);
if (!sb->s_root)
{
+ printk("UDF-fs: Couldn't allocate root dentry\n");
iput(inode);
- udf_debug("Couldn't allocate root dentry\n");
goto error_out;
}
diff --git a/fs/udf/symlink.c b/fs/udf/symlink.c
index 5a286ce84..86c83695d 100644
--- a/fs/udf/symlink.c
+++ b/fs/udf/symlink.c
@@ -122,5 +122,5 @@ out:
* symlinks can't do much...
*/
struct address_space_operations udf_symlink_aops = {
- readpage: udf_symlink_filler,
+ readpage: udf_symlink_filler,
};
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c
index f5602dc0e..262a411d6 100644
--- a/fs/udf/truncate.c
+++ b/fs/udf/truncate.c
@@ -32,27 +32,34 @@
#include "udf_i.h"
#include "udf_sb.h"
-static void extent_trunc(struct inode * inode, lb_addr bloc, int *extoffset,
- lb_addr eloc, Uint8 etype, Uint32 elen, struct buffer_head **bh, Uint32 offset)
+static void extent_trunc(struct inode * inode, lb_addr bloc, int extoffset,
+ lb_addr eloc, Uint8 etype, Uint32 elen, struct buffer_head **bh, Uint32 nelen)
{
lb_addr neloc = { 0, 0 };
- int nelen = 0;
int blocks = inode->i_sb->s_blocksize / 512;
int last_block = (elen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
+ int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
- if (offset)
+ if (nelen)
{
- nelen = (etype << 30) |
- (((offset - 1) << inode->i_sb->s_blocksize_bits) +
- (inode->i_size & (inode->i_sb->s_blocksize - 1)));
neloc = eloc;
+ nelen = (etype << 30) | nelen;
+ }
+
+ if (elen != nelen)
+ {
+ udf_write_aext(inode, bloc, &extoffset, neloc, nelen, bh, 0);
+ if (last_block - first_block > 0)
+ {
+ if (etype == EXTENT_RECORDED_ALLOCATED)
+ {
+ inode->i_blocks -= (blocks * (last_block - first_block));
+ mark_inode_dirty(inode);
+ }
+ if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED)
+ udf_free_blocks(inode, eloc, first_block, last_block - first_block);
+ }
}
- if (etype == EXTENT_RECORDED_ALLOCATED)
- inode->i_blocks -= (blocks * (last_block - offset));
- udf_write_aext(inode, bloc, extoffset, neloc, nelen, bh, 1);
- mark_inode_dirty(inode);
- if (etype != EXTENT_NOT_RECORDED_NOT_ALLOCATED)
- udf_free_blocks(inode, eloc, offset, last_block - offset);
}
void udf_trunc(struct inode * inode)
@@ -60,7 +67,7 @@ void udf_trunc(struct inode * inode)
lb_addr bloc, eloc, neloc = { 0, 0 };
Uint32 extoffset, elen, offset, nelen = 0, lelen = 0, lenalloc;
int etype;
- int first_block = (inode->i_size + inode->i_sb->s_blocksize - 1) >> inode->i_sb->s_blocksize_bits;
+ int first_block = inode->i_size >> inode->i_sb->s_blocksize_bits;
struct buffer_head *bh = NULL;
int adsize;
@@ -71,10 +78,14 @@ void udf_trunc(struct inode * inode)
else
adsize = 0;
- if ((etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh)) != -1)
+ etype = inode_bmap(inode, first_block, &bloc, &extoffset, &eloc, &elen, &offset, &bh);
+ offset = (offset << inode->i_sb->s_blocksize_bits) |
+ (inode->i_size & (inode->i_sb->s_blocksize - 1));
+ if (etype != -1)
{
extoffset -= adsize;
- extent_trunc(inode, bloc, &extoffset, eloc, etype, elen, &bh, offset);
+ extent_trunc(inode, bloc, extoffset, eloc, etype, elen, &bh, offset);
+ extoffset += adsize;
if (offset)
lenalloc = extoffset;
@@ -103,11 +114,17 @@ void udf_trunc(struct inode * inode)
else
{
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+ {
UDF_I_LENALLOC(inode) = lenalloc;
+ mark_inode_dirty(inode);
+ }
else
{
struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh->b_data);
aed->lengthAllocDescs = cpu_to_le32(lenalloc);
+ udf_update_tag(bh->b_data, lenalloc +
+ sizeof(struct AllocExtDesc));
+ mark_buffer_dirty(bh, 1);
}
}
@@ -122,7 +139,10 @@ void udf_trunc(struct inode * inode)
lelen = 1;
}
else
- extent_trunc(inode, bloc, &extoffset, eloc, etype, elen, &bh, 0);
+ {
+ extent_trunc(inode, bloc, extoffset, eloc, etype, elen, &bh, 0);
+ extoffset += adsize;
+ }
}
if (lelen)
@@ -136,29 +156,42 @@ void udf_trunc(struct inode * inode)
else
{
if (!memcmp(&UDF_I_LOCATION(inode), &bloc, sizeof(lb_addr)))
+ {
UDF_I_LENALLOC(inode) = lenalloc;
+ mark_inode_dirty(inode);
+ }
else
{
struct AllocExtDesc *aed = (struct AllocExtDesc *)(bh->b_data);
aed->lengthAllocDescs = cpu_to_le32(lenalloc);
+ udf_update_tag(bh->b_data, lenalloc +
+ sizeof(struct AllocExtDesc));
+ mark_buffer_dirty(bh, 1);
}
}
}
else if (inode->i_size)
{
- char tetype;
-
if (offset)
{
extoffset -= adsize;
- tetype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
- if (tetype == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
+ etype = udf_next_aext(inode, &bloc, &extoffset, &eloc, &elen, &bh, 1);
+ if (etype == EXTENT_NOT_RECORDED_NOT_ALLOCATED)
{
extoffset -= adsize;
- elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) |
- (elen + (offset << inode->i_sb->s_blocksize_bits));
+ elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | (elen + offset);
udf_write_aext(inode, bloc, &extoffset, eloc, elen, &bh, 0);
}
+ else if (etype == EXTENT_NOT_RECORDED_ALLOCATED)
+ {
+ lb_addr neloc = { 0, 0 };
+ extoffset -= adsize;
+ nelen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) |
+ ((elen + offset + inode->i_sb->s_blocksize - 1) &
+ ~(inode->i_sb->s_blocksize - 1));
+ udf_write_aext(inode, bloc, &extoffset, neloc, nelen, &bh, 1);
+ udf_add_aext(inode, &bloc, &extoffset, eloc, (etype << 30) | elen, &bh, 1);
+ }
else
{
if (elen & (inode->i_sb->s_blocksize - 1))
@@ -170,8 +203,7 @@ void udf_trunc(struct inode * inode)
udf_write_aext(inode, bloc, &extoffset, eloc, elen, &bh, 1);
}
memset(&eloc, 0x00, sizeof(lb_addr));
- elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) |
- (offset << inode->i_sb->s_blocksize_bits);
+ elen = (EXTENT_NOT_RECORDED_NOT_ALLOCATED << 30) | offset;
udf_add_aext(inode, &bloc, &extoffset, eloc, elen, &bh, 1);
}
}
@@ -182,6 +214,8 @@ void udf_trunc(struct inode * inode)
void udf_truncate(struct inode * inode)
{
+ int err;
+
if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) ||
S_ISLNK(inode->i_mode)))
return;
@@ -189,7 +223,22 @@ void udf_truncate(struct inode * inode)
return;
if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
- UDF_I_LENALLOC(inode) = inode->i_size;
+ {
+ if (inode->i_sb->s_blocksize < (udf_file_entry_alloc_offset(inode) +
+ inode->i_size))
+ {
+ udf_expand_file_adinicb(inode, inode->i_size, &err);
+ if (UDF_I_ALLOCTYPE(inode) == ICB_FLAG_AD_IN_ICB)
+ {
+ inode->i_size = UDF_I_LENALLOC(inode);
+ return;
+ }
+ else
+ udf_trunc(inode);
+ }
+ else
+ UDF_I_LENALLOC(inode) = inode->i_size;
+ }
else
udf_trunc(inode);
diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h
index 4d1f64c85..57afcb21f 100644
--- a/fs/udf/udf_i.h
+++ b/fs/udf/udf_i.h
@@ -10,6 +10,7 @@
#define UDF_I_ALLOCTYPE(X) ( UDF_I(X)->i_alloc_type )
#define UDF_I_EXTENDED_FE(X)( UDF_I(X)->i_extended_fe )
#define UDF_I_STRAT4096(X) ( UDF_I(X)->i_strat_4096 )
+#define UDF_I_NEW_INODE(X) ( UDF_I(X)->i_new_inode )
#define UDF_I_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_UATIME(X) ( UDF_I(X)->i_uatime )
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h
index 5fab514bc..6084c5613 100644
--- a/fs/udf/udf_sb.h
+++ b/fs/udf/udf_sb.h
@@ -2,13 +2,23 @@
#define __LINUX_UDF_SB_H
/* Since UDF 1.50 is ISO 13346 based... */
-#define UDF_SUPER_MAGIC 0x15013346
+#define UDF_SUPER_MAGIC 0x15013346
-#define UDF_FLAG_STRICT 0x00000001U
-#define UDF_FLAG_UNDELETE 0x00000002U
-#define UDF_FLAG_UNHIDE 0x00000004U
-#define UDF_FLAG_VARCONV 0x00000008U
+#define UDF_MAX_READ_VERSION 0x0200
+#define UDF_MAX_WRITE_VERSION 0x0200
+#define UDF_FLAG_USE_EXTENDED_FE 0
+#define UDF_VERS_USE_EXTENDED_FE 0x0200
+#define UDF_FLAG_USE_STREAMS 1
+#define UDF_VERS_USE_STREAMS 0x0200
+#define UDF_FLAG_USE_SHORT_AD 2
+#define UDF_FLAG_USE_AD_IN_ICB 3
+#define UDF_FLAG_USE_FILE_CTIME_EA 4
+#define UDF_FLAG_STRICT 5
+#define UDF_FLAG_UNDELETE 6
+#define UDF_FLAG_UNHIDE 7
+#define UDF_FLAG_VARCONV 8
+
#define UDF_SB_FREE(X)\
{\
if (UDF_SB(X))\
@@ -27,37 +37,42 @@
memset(UDF_SB_PARTMAPS(X), 0x00, sizeof(struct udf_part_map) * Y);\
}
-#define IS_STRICT(X) ( UDF_SB(X)->s_flags & UDF_FLAG_STRICT )
-#define IS_UNDELETE(X) ( UDF_SB(X)->s_flags & UDF_FLAG_UNDELETE )
-#define IS_UNHIDE(X) ( UDF_SB(X)->s_flags & UDF_FLAG_UNHIDE )
-
-#define UDF_SB_SESSION(X) ( UDF_SB(X)->s_session )
-#define UDF_SB_ANCHOR(X) ( UDF_SB(X)->s_anchor )
-#define UDF_SB_NUMPARTS(X) ( UDF_SB(X)->s_partitions )
-#define UDF_SB_VOLUME(X) ( UDF_SB(X)->s_thisvolume )
-#define UDF_SB_LASTBLOCK(X) ( UDF_SB(X)->s_lastblock )
-#define UDF_SB_VOLDESC(X) ( UDF_SB(X)->s_voldesc )
-#define UDF_SB_LVIDBH(X) ( UDF_SB(X)->s_lvidbh )
-#define UDF_SB_LVID(X) ( (struct LogicalVolIntegrityDesc *)UDF_SB_LVIDBH(X)->b_data )
-#define UDF_SB_LVIDIU(X) ( (struct LogicalVolIntegrityDescImpUse *)&(UDF_SB_LVID(sb)->impUse[UDF_SB_LVID(sb)->numOfPartitions * 2 * sizeof(Uint32)/sizeof(Uint8)]) )
-#define UDF_SB_PARTITION(X) ( UDF_SB(X)->s_partition )
-#define UDF_SB_RECORDTIME(X) ( UDF_SB(X)->s_recordtime )
-#define UDF_SB_VOLIDENT(X) ( UDF_SB(X)->s_volident )
-#define UDF_SB_PARTMAPS(X) ( UDF_SB(X)->s_partmaps )
-#define UDF_SB_SERIALNUM(X) ( UDF_SB(X)->s_serialnum )
-#define UDF_SB_VAT(X) ( UDF_SB(X)->s_vat )
-
-#define UDF_SB_BLOCK_BITMAP_NUMBER(X,Y) ( UDF_SB(X)->s_block_bitmap_number[Y] )
-#define UDF_SB_BLOCK_BITMAP(X,Y) ( UDF_SB(X)->s_block_bitmap[Y] )
-#define UDF_SB_LOADED_BLOCK_BITMAPS(X) ( UDF_SB(X)->s_loaded_block_bitmaps )
+#define UDF_QUERY_FLAG(X,Y) ( UDF_SB(X)->s_flags & ( 1 << (Y) ) )
+#define UDF_SET_FLAG(X,Y) ( UDF_SB(X)->s_flags |= ( 1 << (Y) ) )
+#define UDF_CLEAR_FLAG(X,Y) ( UDF_SB(X)->s_flags &= ~( 1 << (Y) ) )
+
+#define UDF_UPDATE_UDFREV(X,Y) ( ((Y) > UDF_SB_UDFREV(X)) ? UDF_SB_UDFREV(X) = (Y) : UDF_SB_UDFREV(X) )
+
+#define UDF_SB_PARTMAPS(X) ( UDF_SB(X)->s_partmaps )
+#define UDF_SB_PARTTYPE(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_type )
+#define UDF_SB_PARTROOT(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_root )
+#define UDF_SB_PARTLEN(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_len )
+#define UDF_SB_PARTVSN(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_volumeseqnum )
+#define UDF_SB_PARTNUM(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_num )
+#define UDF_SB_TYPESPAR(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_type_specific.s_sparing )
+#define UDF_SB_TYPEVIRT(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_type_specific.s_virtual )
+#define UDF_SB_PARTFUNC(X,Y) ( UDF_SB_PARTMAPS(X)[(Y)].s_partition_func )
-#define UDF_SB_PARTTYPE(X,Y) ( UDF_SB_PARTMAPS(X)[Y].s_partition_type )
-#define UDF_SB_PARTROOT(X,Y) ( UDF_SB_PARTMAPS(X)[Y].s_partition_root )
-#define UDF_SB_PARTLEN(X,Y) ( UDF_SB_PARTMAPS(X)[Y].s_partition_len )
-#define UDF_SB_PARTVSN(X,Y) ( UDF_SB_PARTMAPS(X)[Y].s_volumeseqnum )
-#define UDF_SB_PARTNUM(X,Y) ( UDF_SB_PARTMAPS(X)[Y].s_partition_num )
-#define UDF_SB_TYPESPAR(X,Y) ( UDF_SB_PARTMAPS(X)[Y].s_type_specific.s_sparing )
-#define UDF_SB_TYPEVIRT(X,Y) ( UDF_SB_PARTMAPS(X)[Y].s_type_specific.s_virtual )
-#define UDF_SB_PARTFUNC(X,Y) ( UDF_SB_PARTMAPS(X)[Y].s_partition_func )
+#define UDF_SB_VOLIDENT(X) ( UDF_SB(X)->s_volident )
+#define UDF_SB_NUMPARTS(X) ( UDF_SB(X)->s_partitions )
+#define UDF_SB_PARTITION(X) ( UDF_SB(X)->s_partition )
+#define UDF_SB_SESSION(X) ( UDF_SB(X)->s_session )
+#define UDF_SB_ANCHOR(X) ( UDF_SB(X)->s_anchor )
+#define UDF_SB_LASTBLOCK(X) ( UDF_SB(X)->s_lastblock )
+#define UDF_SB_LVIDBH(X) ( UDF_SB(X)->s_lvidbh )
+#define UDF_SB_LVID(X) ( (struct LogicalVolIntegrityDesc *)UDF_SB_LVIDBH(X)->b_data )
+#define UDF_SB_LVIDIU(X) ( (struct LogicalVolIntegrityDescImpUse *)&(UDF_SB_LVID(X)->impUse[UDF_SB_LVID(X)->numOfPartitions * 2 * sizeof(Uint32)/sizeof(Uint8)]) )
+
+#define UDF_SB_LOADED_BLOCK_BITMAPS(X) ( UDF_SB(X)->s_loaded_block_bitmaps )
+#define UDF_SB_BLOCK_BITMAP_NUMBER(X,Y) ( UDF_SB(X)->s_block_bitmap_number[(Y)] )
+#define UDF_SB_BLOCK_BITMAP(X,Y) ( UDF_SB(X)->s_block_bitmap[(Y)] )
+#define UDF_SB_UMASK(X) ( UDF_SB(X)->s_umask )
+#define UDF_SB_GID(X) ( UDF_SB(X)->s_gid )
+#define UDF_SB_UID(X) ( UDF_SB(X)->s_uid )
+#define UDF_SB_RECORDTIME(X) ( UDF_SB(X)->s_recordtime )
+#define UDF_SB_SERIALNUM(X) ( UDF_SB(X)->s_serialnum )
+#define UDF_SB_UDFREV(X) ( UDF_SB(X)->s_udfrev )
+#define UDF_SB_FLAGS(X) ( UDF_SB(X)->s_flags )
+#define UDF_SB_VAT(X) ( UDF_SB(X)->s_vat )
#endif /* __LINUX_UDF_SB_H */
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 74a84f36c..b2d7f1ab4 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -1,17 +1,15 @@
#ifndef __UDF_DECL_H
#define __UDF_DECL_H
-#define UDF_VERSION_NOTICE "v0.9.0"
-
#include <linux/udf_167.h>
#include <linux/udf_udf.h>
#include "udfend.h"
+#include <linux/udf_fs.h>
+
#ifdef __KERNEL__
#include <linux/types.h>
-#include <linux/udf_fs.h>
-#include <linux/config.h>
#ifndef LINUX_VERSION_CODE
#include <linux/version.h>
@@ -62,9 +60,10 @@ struct buffer_head;
struct super_block;
extern struct inode_operations udf_dir_inode_operations;
-extern struct inode_operations udf_file_inode_operations;
extern struct file_operations udf_dir_operations;
+extern struct inode_operations udf_file_inode_operations;
extern struct file_operations udf_file_operations;
+extern struct address_space_operations udf_aops;
extern struct address_space_operations udf_adinicb_aops;
extern struct address_space_operations udf_symlink_aops;
@@ -127,7 +126,7 @@ extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long)
/* inode.c */
extern struct inode *udf_iget(struct super_block *, lb_addr);
extern int udf_sync_inode(struct inode *);
-extern void udf_expand_file_adinicb(struct file *, int, int *);
+extern void udf_expand_file_adinicb(struct inode *, int, int *);
extern struct buffer_head * udf_expand_dir_adinicb(struct inode *, int *, int *);
extern struct buffer_head * udf_getblk(struct inode *, long, int, int *);
extern struct buffer_head * udf_bread(struct inode *, int, int, int *);
@@ -158,7 +157,7 @@ extern void udf_release_data(struct buffer_head *);
/* lowlevel.c */
extern unsigned int udf_get_last_session(struct super_block *);
-extern unsigned int udf_get_last_block(struct super_block *, int *);
+extern unsigned int udf_get_last_block(struct super_block *);
/* partition.c */
extern Uint32 udf_get_pblock(struct super_block *, Uint32, Uint16, Uint32);
@@ -180,13 +179,13 @@ extern void udf_truncate(struct inode *);
/* balloc.c */
extern void udf_free_blocks(const struct inode *, lb_addr, Uint32, Uint32);
-extern int udf_alloc_blocks(const struct inode *, Uint16, Uint32, Uint32);
+extern int udf_prealloc_blocks(const struct inode *, Uint16, Uint32, Uint32);
extern int udf_new_block(const struct inode *, Uint16, Uint32, int *);
extern int udf_sync_file(struct file *, struct dentry *);
/* directory.c */
extern Uint8 * udf_filead_read(struct inode *, Uint8 *, Uint8, 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 *, Uint32 *, struct buffer_head **);
+extern struct FileIdentDesc * udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct FileIdentDesc *, lb_addr *, Uint32 *, lb_addr *, Uint32 *, Uint32 *, struct buffer_head **);
#endif /* __KERNEL__ */
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c
index b2a9e3462..8f46e508f 100644
--- a/fs/udf/udftime.c
+++ b/fs/udf/udftime.c
@@ -54,12 +54,12 @@
/* How many days come before each month (0-12). */
const unsigned short int __mon_yday[2][13] =
- {
- /* Normal years. */
- { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
- /* Leap years. */
- { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
- };
+{
+ /* Normal years. */
+ { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+ /* Leap years. */
+ { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+};
#define MAX_YEAR_SECONDS 69
#define SPD 0x15180 /*3600*24*/
@@ -90,8 +90,8 @@ time_t year_seconds[MAX_YEAR_SECONDS]= {
extern struct timezone sys_tz;
#endif
-#define SECS_PER_HOUR (60 * 60)
-#define SECS_PER_DAY (SECS_PER_HOUR * 24)
+#define SECS_PER_HOUR (60 * 60)
+#define SECS_PER_DAY (SECS_PER_HOUR * 24)
time_t *
udf_stamp_to_time(time_t *dest, long *dest_usec, timestamp src)
@@ -139,10 +139,10 @@ udf_time_to_stamp(timestamp *dest, time_t tv_sec, long tv_usec)
gettimeofday(&tv, &sys_tz);
#endif
- offset = (-sys_tz.tz_minuteswest);
+ offset = -sys_tz.tz_minuteswest;
- if (!dest)
- return NULL;
+ if (!dest)
+ return NULL;
dest->typeAndTimezone = 0x1000 | (offset & 0x0FFF);
@@ -180,7 +180,7 @@ udf_time_to_stamp(timestamp *dest, time_t tv_sec, long tv_usec)
dest->hundredsOfMicroseconds = (tv_usec - dest->centiseconds * 10000) / 100;
dest->microseconds = (tv_usec - dest->centiseconds * 10000 -
dest->hundredsOfMicroseconds * 100);
- return dest;
+ return dest;
}
/* EOF */
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
index 29801728d..134b3c755 100644
--- a/fs/udf/unicode.c
+++ b/fs/udf/unicode.c
@@ -26,7 +26,7 @@
#ifdef __KERNEL__
#include <linux/kernel.h>
-#include <linux/string.h> /* for memset */
+#include <linux/string.h> /* for memset */
#include <linux/udf_fs.h>
#else
#include <string.h>
@@ -98,7 +98,7 @@ int udf_dstring_to_ustr(struct ustr *dest, const dstring *src, int dlength)
*/
int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
{
- int usesize;
+ int usesize;
if ( (!dest) || (!ptr) || (!size) )
return -1;
@@ -116,14 +116,14 @@ int udf_build_ustr(struct ustr *dest, dstring *ptr, int size)
*/
int udf_build_ustr_exact(struct ustr *dest, dstring *ptr, int exactsize)
{
- if ( (!dest) || (!ptr) || (!exactsize) )
- return -1;
-
- memset(dest, 0, sizeof(struct ustr));
- dest->u_cmpID=ptr[0];
- dest->u_len=exactsize-1;
- memcpy(dest->u_name, ptr+1, exactsize-1);
- return 0;
+ if ( (!dest) || (!ptr) || (!exactsize) )
+ return -1;
+
+ memset(dest, 0, sizeof(struct ustr));
+ dest->u_cmpID=ptr[0];
+ dest->u_len=exactsize-1;
+ memcpy(dest->u_name, ptr+1, exactsize-1);
+ return 0;
}
/*