diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/affs/inode.c | 1 | ||||
-rw-r--r-- | fs/affs/namei.c | 6 | ||||
-rw-r--r-- | fs/attr.c | 3 | ||||
-rw-r--r-- | fs/binfmt_elf.c | 13 | ||||
-rw-r--r-- | fs/binfmt_script.c | 5 | ||||
-rw-r--r-- | fs/block_dev.c | 2 | ||||
-rw-r--r-- | fs/exec.c | 25 | ||||
-rw-r--r-- | fs/nfsd/export.c | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs3xdr.c | 6 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 118 | ||||
-rw-r--r-- | fs/ntfs/fs.c | 2 | ||||
-rw-r--r-- | fs/openpromfs/inode.c | 2 | ||||
-rw-r--r-- | fs/udf/balloc.c | 36 | ||||
-rw-r--r-- | fs/udf/dir.c | 17 | ||||
-rw-r--r-- | fs/udf/directory.c | 15 | ||||
-rw-r--r-- | fs/udf/file.c | 136 | ||||
-rw-r--r-- | fs/udf/ialloc.c | 38 | ||||
-rw-r--r-- | fs/udf/inode.c | 200 | ||||
-rw-r--r-- | fs/udf/lowlevel.c | 49 | ||||
-rw-r--r-- | fs/udf/misc.c | 2 | ||||
-rw-r--r-- | fs/udf/namei.c | 421 | ||||
-rw-r--r-- | fs/udf/partition.c | 2 | ||||
-rw-r--r-- | fs/udf/super.c | 188 | ||||
-rw-r--r-- | fs/udf/symlink.c | 2 | ||||
-rw-r--r-- | fs/udf/truncate.c | 101 | ||||
-rw-r--r-- | fs/udf/udf_i.h | 1 | ||||
-rw-r--r-- | fs/udf/udf_sb.h | 87 | ||||
-rw-r--r-- | fs/udf/udfdecl.h | 17 | ||||
-rw-r--r-- | fs/udf/udftime.c | 24 | ||||
-rw-r--r-- | fs/udf/unicode.c | 20 |
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; @@ -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); } @@ -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; } /* |