diff options
Diffstat (limited to 'fs')
85 files changed, 1630 insertions, 1206 deletions
diff --git a/fs/Makefile b/fs/Makefile index 6e82a30..b5cd8e1 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -11,7 +11,7 @@ obj-y := open.o read_write.o file_table.o super.o \ attr.o bad_inode.o file.o filesystems.o namespace.o \ seq_file.o xattr.o libfs.o fs-writeback.o \ pnode.o drop_caches.o splice.o sync.o utimes.o \ - stack.o + stack.o fs_struct.o ifeq ($(CONFIG_BLOCK),y) obj-y += buffer.o bio.o block_dev.o direct-io.o mpage.o ioprio.o diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 7f83a46..dd9becc 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c @@ -219,16 +219,20 @@ static int adfs_remount(struct super_block *sb, int *flags, char *data) static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct adfs_sb_info *asb = ADFS_SB(dentry->d_sb); + struct super_block *sb = dentry->d_sb; + struct adfs_sb_info *sbi = ADFS_SB(sb); + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = ADFS_SUPER_MAGIC; - buf->f_namelen = asb->s_namelen; - buf->f_bsize = dentry->d_sb->s_blocksize; - buf->f_blocks = asb->s_size; - buf->f_files = asb->s_ids_per_zone * asb->s_map_size; + buf->f_namelen = sbi->s_namelen; + buf->f_bsize = sb->s_blocksize; + buf->f_blocks = sbi->s_size; + buf->f_files = sbi->s_ids_per_zone * sbi->s_map_size; buf->f_bavail = - buf->f_bfree = adfs_map_free(dentry->d_sb); + buf->f_bfree = adfs_map_free(sb); buf->f_ffree = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); return 0; } diff --git a/fs/affs/super.c b/fs/affs/super.c index a19d64b..5ce695e 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c @@ -533,6 +533,7 @@ affs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; int free; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size, AFFS_SB(sb)->s_reserved); @@ -543,6 +544,9 @@ affs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_blocks = AFFS_SB(sb)->s_partition_size - AFFS_SB(sb)->s_reserved; buf->f_bfree = free; buf->f_bavail = free; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + buf->f_namelen = 30; return 0; } diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index d06cb02..76afd0d 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c @@ -900,6 +900,7 @@ static int befs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); befs_debug(sb, "---> befs_statfs()"); @@ -910,6 +911,8 @@ befs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bavail = buf->f_bfree; buf->f_files = 0; /* UNKNOWN */ buf->f_ffree = 0; /* UNKNOWN */ + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_namelen = BEFS_NAME_LEN; befs_debug(sb, "<--- befs_statfs()"); diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 33b7235..40381df 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -12,8 +12,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> -#include <linux/stat.h> -#include <linux/time.h> #include <linux/mm.h> #include <linux/mman.h> #include <linux/errno.h> @@ -21,20 +19,15 @@ #include <linux/binfmts.h> #include <linux/string.h> #include <linux/file.h> -#include <linux/fcntl.h> -#include <linux/ptrace.h> #include <linux/slab.h> -#include <linux/shm.h> #include <linux/personality.h> #include <linux/elfcore.h> #include <linux/init.h> #include <linux/highuid.h> -#include <linux/smp.h> #include <linux/compiler.h> #include <linux/highmem.h> #include <linux/pagemap.h> #include <linux/security.h> -#include <linux/syscalls.h> #include <linux/random.h> #include <linux/elf.h> #include <linux/utsname.h> @@ -576,7 +569,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) unsigned long error; struct elf_phdr *elf_ppnt, *elf_phdata; unsigned long elf_bss, elf_brk; - int elf_exec_fileno; int retval, i; unsigned int size; unsigned long elf_entry; @@ -631,12 +623,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) goto out_free_ph; } - retval = get_unused_fd(); - if (retval < 0) - goto out_free_ph; - get_file(bprm->file); - fd_install(elf_exec_fileno = retval, bprm->file); - elf_ppnt = elf_phdata; elf_bss = 0; elf_brk = 0; @@ -655,13 +641,13 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) retval = -ENOEXEC; if (elf_ppnt->p_filesz > PATH_MAX || elf_ppnt->p_filesz < 2) - goto out_free_file; + goto out_free_ph; retval = -ENOMEM; elf_interpreter = kmalloc(elf_ppnt->p_filesz, GFP_KERNEL); if (!elf_interpreter) - goto out_free_file; + goto out_free_ph; retval = kernel_read(bprm->file, elf_ppnt->p_offset, elf_interpreter, @@ -956,8 +942,6 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) kfree(elf_phdata); - sys_close(elf_exec_fileno); - set_binfmt(&elf_format); #ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES @@ -1028,8 +1012,6 @@ out_free_dentry: fput(interpreter); out_free_interp: kfree(elf_interpreter); -out_free_file: - sys_close(elf_exec_fileno); out_free_ph: kfree(elf_phdata); goto out; diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index f3e72c5..70cfc4b 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c @@ -972,9 +972,12 @@ static int elf_fdpic_map_file_constdisp_on_uclinux( params->elfhdr_addr = seg->addr; /* clear any space allocated but not loaded */ - if (phdr->p_filesz < phdr->p_memsz) - clear_user((void *) (seg->addr + phdr->p_filesz), - phdr->p_memsz - phdr->p_filesz); + if (phdr->p_filesz < phdr->p_memsz) { + ret = clear_user((void *) (seg->addr + phdr->p_filesz), + phdr->p_memsz - phdr->p_filesz); + if (ret) + return ret; + } if (mm) { if (phdr->p_flags & PF_X) { @@ -1014,7 +1017,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, struct elf32_fdpic_loadseg *seg; struct elf32_phdr *phdr; unsigned long load_addr, delta_vaddr; - int loop, dvset; + int loop, dvset, ret; load_addr = params->load_addr; delta_vaddr = 0; @@ -1114,7 +1117,9 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, * PT_LOAD */ if (prot & PROT_WRITE && disp > 0) { kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp); - clear_user((void __user *) maddr, disp); + ret = clear_user((void __user *) maddr, disp); + if (ret) + return ret; maddr += disp; } @@ -1149,15 +1154,19 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, if (prot & PROT_WRITE && excess1 > 0) { kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr + phdr->p_filesz, excess1); - clear_user((void __user *) maddr + phdr->p_filesz, - excess1); + ret = clear_user((void __user *) maddr + phdr->p_filesz, + excess1); + if (ret) + return ret; } #else if (excess > 0) { kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr + phdr->p_filesz, excess); - clear_user((void *) maddr + phdr->p_filesz, excess); + ret = clear_user((void *) maddr + phdr->p_filesz, excess); + if (ret) + return ret; } #endif diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c index 08644a6..eff74b9 100644 --- a/fs/binfmt_som.c +++ b/fs/binfmt_som.c @@ -188,7 +188,6 @@ out: static int load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) { - int som_exec_fileno; int retval; unsigned int size; unsigned long som_entry; @@ -220,12 +219,6 @@ load_som_binary(struct linux_binprm * bprm, struct pt_regs * regs) goto out_free; } - retval = get_unused_fd(); - if (retval < 0) - goto out_free; - get_file(bprm->file); - fd_install(som_exec_fileno = retval, bprm->file); - /* Flush all traces of the currently running executable */ retval = flush_old_exec(bprm); if (retval) diff --git a/fs/block_dev.c b/fs/block_dev.c index 8c3c689..f45dbc1 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -204,6 +204,7 @@ int fsync_bdev(struct block_device *bdev) } return sync_blockdev(bdev); } +EXPORT_SYMBOL(fsync_bdev); /** * freeze_bdev -- lock a filesystem and force it into a consistent state diff --git a/fs/btrfs/acl.c b/fs/btrfs/acl.c index 1d53b62..7fdd184 100644 --- a/fs/btrfs/acl.c +++ b/fs/btrfs/acl.c @@ -256,7 +256,7 @@ int btrfs_init_acl(struct inode *inode, struct inode *dir) } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if (IS_POSIXACL(dir) && acl) { diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index bca729f..7594bec 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -267,7 +267,7 @@ static noinline int btrfs_mksubvol(struct path *parent, char *name, goto out_dput; if (!IS_POSIXACL(parent->dentry->d_inode)) - mode &= ~current->fs->umask; + mode &= ~current_umask(); error = mnt_want_write(parent->mnt); if (error) diff --git a/fs/buffer.c b/fs/buffer.c index f5f8b15..c2fa1be 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -199,13 +199,13 @@ __find_get_block_slow(struct block_device *bdev, sector_t block) head = page_buffers(page); bh = head; do { - if (bh->b_blocknr == block) { + if (!buffer_mapped(bh)) + all_mapped = 0; + else if (bh->b_blocknr == block) { ret = bh; get_bh(bh); goto out_unlock; } - if (!buffer_mapped(bh)) - all_mapped = 0; bh = bh->b_this_page; } while (bh != head); @@ -3315,7 +3315,6 @@ EXPORT_SYMBOL(cont_write_begin); EXPORT_SYMBOL(end_buffer_read_sync); EXPORT_SYMBOL(end_buffer_write_sync); EXPORT_SYMBOL(file_fsync); -EXPORT_SYMBOL(fsync_bdev); EXPORT_SYMBOL(generic_block_bmap); EXPORT_SYMBOL(generic_cont_expand_simple); EXPORT_SYMBOL(init_buffer); diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 2f35cccf..54dce78 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -254,7 +254,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, return -ENOMEM; } - mode &= ~current->fs->umask; + mode &= ~current_umask(); if (oplockEnabled) oplock = REQ_OPLOCK; @@ -479,7 +479,7 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, rc = -ENOMEM; else if (pTcon->unix_ext) { struct cifs_unix_set_info_args args = { - .mode = mode & ~current->fs->umask, + .mode = mode & ~current_umask(), .ctime = NO_CHANGE_64, .atime = NO_CHANGE_64, .mtime = NO_CHANGE_64, diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index a8797cc..f121a80 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -1125,7 +1125,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) goto mkdir_out; } - mode &= ~current->fs->umask; + mode &= ~current_umask(); rc = CIFSPOSIXCreate(xid, pTcon, SMB_O_DIRECTORY | SMB_O_CREAT, mode, NULL /* netfid */, pInfo, &oplock, full_path, cifs_sb->local_nls, @@ -1204,7 +1204,7 @@ mkdir_get_info: if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) direntry->d_inode->i_nlink = 2; - mode &= ~current->fs->umask; + mode &= ~current_umask(); /* must turn on setgid bit if parent dir has it */ if (inode->i_mode & S_ISGID) mode |= S_ISGID; diff --git a/fs/compat.c b/fs/compat.c index 55efdfe..1c859da 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -51,6 +51,7 @@ #include <linux/poll.h> #include <linux/mm.h> #include <linux/eventpoll.h> +#include <linux/fs_struct.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -1195,16 +1196,12 @@ out: return ret; } -asmlinkage ssize_t -compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) +static size_t compat_readv(struct file *file, + const struct compat_iovec __user *vec, + unsigned long vlen, loff_t *pos) { - struct file *file; ssize_t ret = -EBADF; - file = fget(fd); - if (!file) - return -EBADF; - if (!(file->f_mode & FMODE_READ)) goto out; @@ -1212,25 +1209,56 @@ compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, unsign if (!file->f_op || (!file->f_op->aio_read && !file->f_op->read)) goto out; - ret = compat_do_readv_writev(READ, file, vec, vlen, &file->f_pos); + ret = compat_do_readv_writev(READ, file, vec, vlen, pos); out: if (ret > 0) add_rchar(current, ret); inc_syscr(current); - fput(file); return ret; } asmlinkage ssize_t -compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsigned long vlen) +compat_sys_readv(unsigned long fd, const struct compat_iovec __user *vec, + unsigned long vlen) { struct file *file; - ssize_t ret = -EBADF; + int fput_needed; + ssize_t ret; - file = fget(fd); + file = fget_light(fd, &fput_needed); if (!file) return -EBADF; + ret = compat_readv(file, vec, vlen, &file->f_pos); + fput_light(file, fput_needed); + return ret; +} + +asmlinkage ssize_t +compat_sys_preadv(unsigned long fd, const struct compat_iovec __user *vec, + unsigned long vlen, u32 pos_high, u32 pos_low) +{ + loff_t pos = ((loff_t)pos_high << 32) | pos_low; + struct file *file; + int fput_needed; + ssize_t ret; + + if (pos < 0) + return -EINVAL; + file = fget_light(fd, &fput_needed); + if (!file) + return -EBADF; + ret = compat_readv(file, vec, vlen, &pos); + fput_light(file, fput_needed); + return ret; +} + +static size_t compat_writev(struct file *file, + const struct compat_iovec __user *vec, + unsigned long vlen, loff_t *pos) +{ + ssize_t ret = -EBADF; + if (!(file->f_mode & FMODE_WRITE)) goto out; @@ -1238,13 +1266,47 @@ compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, unsig if (!file->f_op || (!file->f_op->aio_write && !file->f_op->write)) goto out; - ret = compat_do_readv_writev(WRITE, file, vec, vlen, &file->f_pos); + ret = compat_do_readv_writev(WRITE, file, vec, vlen, pos); out: if (ret > 0) add_wchar(current, ret); inc_syscw(current); - fput(file); + return ret; +} + +asmlinkage ssize_t +compat_sys_writev(unsigned long fd, const struct compat_iovec __user *vec, + unsigned long vlen) +{ + struct file *file; + int fput_needed; + ssize_t ret; + + file = fget_light(fd, &fput_needed); + if (!file) + return -EBADF; + ret = compat_writev(file, vec, vlen, &file->f_pos); + fput_light(file, fput_needed); + return ret; +} + +asmlinkage ssize_t +compat_sys_pwritev(unsigned long fd, const struct compat_iovec __user *vec, + unsigned long vlen, u32 pos_high, u32 pos_low) +{ + loff_t pos = ((loff_t)pos_high << 32) | pos_low; + struct file *file; + int fput_needed; + ssize_t ret; + + if (pos < 0) + return -EINVAL; + file = fget_light(fd, &fput_needed); + if (!file) + return -EBADF; + ret = compat_writev(file, vec, vlen, &pos); + fput_light(file, fput_needed); return ret; } @@ -1441,12 +1503,15 @@ int compat_do_execve(char * filename, bprm->cred = prepare_exec_creds(); if (!bprm->cred) goto out_unlock; - check_unsafe_exec(bprm); + + retval = check_unsafe_exec(bprm); + if (retval) + goto out_unlock; file = open_exec(filename); retval = PTR_ERR(file); if (IS_ERR(file)) - goto out_unlock; + goto out_unmark; sched_exec(); @@ -1488,6 +1553,9 @@ int compat_do_execve(char * filename, goto out; /* execve succeeded */ + write_lock(¤t->fs->lock); + current->fs->in_exec = 0; + write_unlock(¤t->fs->lock); current->in_execve = 0; mutex_unlock(¤t->cred_exec_mutex); acct_update_integrals(current); @@ -1506,6 +1574,11 @@ out_file: fput(bprm->file); } +out_unmark: + write_lock(¤t->fs->lock); + current->fs->in_exec = 0; + write_unlock(¤t->fs->lock); + out_unlock: current->in_execve = 0; mutex_unlock(¤t->cred_exec_mutex); diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index ff78668..3e87ce4 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -23,7 +23,7 @@ #include <linux/if.h> #include <linux/if_bridge.h> #include <linux/slab.h> -#include <linux/raid/md.h> +#include <linux/raid/md_u.h> #include <linux/kd.h> #include <linux/route.h> #include <linux/in6.h> diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index a07338d..dd3634e 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c @@ -318,6 +318,7 @@ out: static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = CRAMFS_MAGIC; buf->f_bsize = PAGE_CACHE_SIZE; @@ -326,6 +327,8 @@ static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bavail = 0; buf->f_files = CRAMFS_SB(sb)->files; buf->f_ffree = 0; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_namelen = CRAMFS_MAXPATHLEN; return 0; } @@ -459,11 +462,14 @@ static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, s static int cramfs_readpage(struct file *file, struct page * page) { struct inode *inode = page->mapping->host; - u32 maxblock, bytes_filled; + u32 maxblock; + int bytes_filled; void *pgdata; maxblock = (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; bytes_filled = 0; + pgdata = kmap(page); + if (page->index < maxblock) { struct super_block *sb = inode->i_sb; u32 blkptr_offset = OFFSET(inode) + page->index*4; @@ -472,30 +478,43 @@ static int cramfs_readpage(struct file *file, struct page * page) start_offset = OFFSET(inode) + maxblock*4; mutex_lock(&read_mutex); if (page->index) - start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, 4); - compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - start_offset); + start_offset = *(u32 *) cramfs_read(sb, blkptr_offset-4, + 4); + compr_len = (*(u32 *) cramfs_read(sb, blkptr_offset, 4) - + start_offset); mutex_unlock(&read_mutex); - pgdata = kmap(page); + if (compr_len == 0) ; /* hole */ - else if (compr_len > (PAGE_CACHE_SIZE << 1)) - printk(KERN_ERR "cramfs: bad compressed blocksize %u\n", compr_len); - else { + else if (unlikely(compr_len > (PAGE_CACHE_SIZE << 1))) { + pr_err("cramfs: bad compressed blocksize %u\n", + compr_len); + goto err; + } else { mutex_lock(&read_mutex); bytes_filled = cramfs_uncompress_block(pgdata, PAGE_CACHE_SIZE, cramfs_read(sb, start_offset, compr_len), compr_len); mutex_unlock(&read_mutex); + if (unlikely(bytes_filled < 0)) + goto err; } - } else - pgdata = kmap(page); + } + memset(pgdata + bytes_filled, 0, PAGE_CACHE_SIZE - bytes_filled); - kunmap(page); flush_dcache_page(page); + kunmap(page); SetPageUptodate(page); unlock_page(page); return 0; + +err: + kunmap(page); + ClearPageUptodate(page); + SetPageError(page); + unlock_page(page); + return 0; } static const struct address_space_operations cramfs_aops = { diff --git a/fs/cramfs/uncompress.c b/fs/cramfs/uncompress.c index fc3ccb7..0233298 100644 --- a/fs/cramfs/uncompress.c +++ b/fs/cramfs/uncompress.c @@ -50,7 +50,7 @@ int cramfs_uncompress_block(void *dst, int dstlen, void *src, int srclen) err: printk("Error %d while decompressing!\n", err); printk("%p(%d)->%p(%d)\n", src, srclen, dst, dstlen); - return 0; + return -EIO; } int cramfs_uncompress_init(void) diff --git a/fs/dcache.c b/fs/dcache.c index 90bbd7e..761d30b 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -17,7 +17,6 @@ #include <linux/syscalls.h> #include <linux/string.h> #include <linux/mm.h> -#include <linux/fdtable.h> #include <linux/fs.h> #include <linux/fsnotify.h> #include <linux/slab.h> @@ -32,6 +31,7 @@ #include <linux/seqlock.h> #include <linux/swap.h> #include <linux/bootmem.h> +#include <linux/fs_struct.h> #include "internal.h" int sysctl_vfs_cache_pressure __read_mostly = 100; diff --git a/fs/drop_caches.c b/fs/drop_caches.c index 44d725f..b6a719a 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -18,7 +18,7 @@ static void drop_pagecache_sb(struct super_block *sb) spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { - if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) + if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) continue; if (inode->i_mapping->nrpages == 0) continue; diff --git a/fs/efs/super.c b/fs/efs/super.c index 73b19cf..f049428 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c @@ -329,18 +329,22 @@ out_no_fs: } static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct efs_sb_info *sb = SUPER_INFO(dentry->d_sb); + struct super_block *sb = dentry->d_sb; + struct efs_sb_info *sbi = SUPER_INFO(sb); + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */ buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */ - buf->f_blocks = sb->total_groups * /* total data blocks */ - (sb->group_size - sb->inode_blocks); - buf->f_bfree = sb->data_free; /* free data blocks */ - buf->f_bavail = sb->data_free; /* free blocks for non-root */ - buf->f_files = sb->total_groups * /* total inodes */ - sb->inode_blocks * + buf->f_blocks = sbi->total_groups * /* total data blocks */ + (sbi->group_size - sbi->inode_blocks); + buf->f_bfree = sbi->data_free; /* free data blocks */ + buf->f_bavail = sbi->data_free; /* free blocks for non-root */ + buf->f_files = sbi->total_groups * /* total inodes */ + sbi->inode_blocks * (EFS_BLOCKSIZE / sizeof(struct efs_dinode)); - buf->f_ffree = sb->inode_free; /* free inodes */ + buf->f_ffree = sbi->inode_free; /* free inodes */ + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_namelen = EFS_MAXNAMELEN; /* max filename length */ return 0; @@ -53,6 +53,7 @@ #include <linux/tracehook.h> #include <linux/kmod.h> #include <linux/fsnotify.h> +#include <linux/fs_struct.h> #include <asm/uaccess.h> #include <asm/mmu_context.h> @@ -1056,28 +1057,35 @@ EXPORT_SYMBOL(install_exec_creds); * - the caller must hold current->cred_exec_mutex to protect against * PTRACE_ATTACH */ -void check_unsafe_exec(struct linux_binprm *bprm) +int check_unsafe_exec(struct linux_binprm *bprm) { struct task_struct *p = current, *t; unsigned long flags; - unsigned n_fs, n_sighand; + unsigned n_fs; + int res = 0; bprm->unsafe = tracehook_unsafe_exec(p); n_fs = 1; - n_sighand = 1; + write_lock(&p->fs->lock); lock_task_sighand(p, &flags); for (t = next_thread(p); t != p; t = next_thread(t)) { if (t->fs == p->fs) n_fs++; - n_sighand++; } - if (atomic_read(&p->fs->count) > n_fs || - atomic_read(&p->sighand->count) > n_sighand) + if (p->fs->users > n_fs) { bprm->unsafe |= LSM_UNSAFE_SHARE; + } else { + if (p->fs->in_exec) + res = -EAGAIN; + p->fs->in_exec = 1; + } unlock_task_sighand(p, &flags); + write_unlock(&p->fs->lock); + + return res; } /* @@ -1296,12 +1304,15 @@ int do_execve(char * filename, bprm->cred = prepare_exec_creds(); if (!bprm->cred) goto out_unlock; - check_unsafe_exec(bprm); + + retval = check_unsafe_exec(bprm); + if (retval) + goto out_unlock; file = open_exec(filename); retval = PTR_ERR(file); if (IS_ERR(file)) - goto out_unlock; + goto out_unmark; sched_exec(); @@ -1344,6 +1355,9 @@ int do_execve(char * filename, goto out; /* execve succeeded */ + write_lock(¤t->fs->lock); + current->fs->in_exec = 0; + write_unlock(¤t->fs->lock); current->in_execve = 0; mutex_unlock(¤t->cred_exec_mutex); acct_update_integrals(current); @@ -1362,6 +1376,11 @@ out_file: fput(bprm->file); } +out_unmark: + write_lock(¤t->fs->lock); + current->fs->in_exec = 0; + write_unlock(¤t->fs->lock); + out_unlock: current->in_execve = 0; mutex_unlock(¤t->cred_exec_mutex); diff --git a/fs/ext2/acl.c b/fs/ext2/acl.c index ae8c4f8..d46e38c 100644 --- a/fs/ext2/acl.c +++ b/fs/ext2/acl.c @@ -318,7 +318,7 @@ ext2_init_acl(struct inode *inode, struct inode *dir) return PTR_ERR(acl); } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if (test_opt(inode->i_sb, POSIX_ACL) && acl) { struct posix_acl *clone; diff --git a/fs/ext3/acl.c b/fs/ext3/acl.c index b60bb24..d81ef2f 100644 --- a/fs/ext3/acl.c +++ b/fs/ext3/acl.c @@ -323,7 +323,7 @@ ext3_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) return PTR_ERR(acl); } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if (test_opt(inode->i_sb, POSIX_ACL) && acl) { struct posix_acl *clone; diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index 5853f44..3d724a9 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c @@ -42,7 +42,7 @@ const struct file_operations ext3_dir_operations = { .llseek = generic_file_llseek, .read = generic_read_dir, .readdir = ext3_readdir, /* we take BKL. needed?*/ - .ioctl = ext3_ioctl, /* BKL held */ + .unlocked_ioctl = ext3_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = ext3_compat_ioctl, #endif diff --git a/fs/ext3/file.c b/fs/ext3/file.c index 3be1e06..521f823 100644 --- a/fs/ext3/file.c +++ b/fs/ext3/file.c @@ -112,7 +112,7 @@ const struct file_operations ext3_file_operations = { .write = do_sync_write, .aio_read = generic_file_aio_read, .aio_write = ext3_file_write, - .ioctl = ext3_ioctl, + .unlocked_ioctl = ext3_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = ext3_compat_ioctl, #endif diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 4a09ff1..d3ef656 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1149,12 +1149,15 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping, struct page **pagep, void **fsdata) { struct inode *inode = mapping->host; - int ret, needed_blocks = ext3_writepage_trans_blocks(inode); + int ret; handle_t *handle; int retries = 0; struct page *page; pgoff_t index; unsigned from, to; + /* Reserve one block more for addition to orphan list in case + * we allocate blocks but write fails for some reason */ + int needed_blocks = ext3_writepage_trans_blocks(inode) + 1; index = pos >> PAGE_CACHE_SHIFT; from = pos & (PAGE_CACHE_SIZE - 1); @@ -1184,15 +1187,20 @@ retry: } write_begin_failed: if (ret) { - ext3_journal_stop(handle); - unlock_page(page); - page_cache_release(page); /* * block_write_begin may have instantiated a few blocks * outside i_size. Trim these off again. Don't need * i_size_read because we hold i_mutex. + * + * Add inode to orphan list in case we crash before truncate + * finishes. */ if (pos + len > inode->i_size) + ext3_orphan_add(handle, inode); + ext3_journal_stop(handle); + unlock_page(page); + page_cache_release(page); + if (pos + len > inode->i_size) vmtruncate(inode, inode->i_size); } if (ret == -ENOSPC && ext3_should_retry_alloc(inode->i_sb, &retries)) @@ -1211,6 +1219,18 @@ int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh) return err; } +/* For ordered writepage and write_end functions */ +static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh) +{ + /* + * Write could have mapped the buffer but it didn't copy the data in + * yet. So avoid filing such buffer into a transaction. + */ + if (buffer_mapped(bh) && buffer_uptodate(bh)) + return ext3_journal_dirty_data(handle, bh); + return 0; +} + /* For write_end() in data=journal mode */ static int write_end_fn(handle_t *handle, struct buffer_head *bh) { @@ -1221,26 +1241,20 @@ static int write_end_fn(handle_t *handle, struct buffer_head *bh) } /* - * Generic write_end handler for ordered and writeback ext3 journal modes. - * We can't use generic_write_end, because that unlocks the page and we need to - * unlock the page after ext3_journal_stop, but ext3_journal_stop must run - * after block_write_end. + * This is nasty and subtle: ext3_write_begin() could have allocated blocks + * for the whole page but later we failed to copy the data in. Update inode + * size according to what we managed to copy. The rest is going to be + * truncated in write_end function. */ -static int ext3_generic_write_end(struct file *file, - struct address_space *mapping, - loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata) +static void update_file_sizes(struct inode *inode, loff_t pos, unsigned copied) { - struct inode *inode = file->f_mapping->host; - - copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); - - if (pos+copied > inode->i_size) { - i_size_write(inode, pos+copied); + /* What matters to us is i_disksize. We don't write i_size anywhere */ + if (pos + copied > inode->i_size) + i_size_write(inode, pos + copied); + if (pos + copied > EXT3_I(inode)->i_disksize) { + EXT3_I(inode)->i_disksize = pos + copied; mark_inode_dirty(inode); } - - return copied; } /* @@ -1260,35 +1274,29 @@ static int ext3_ordered_write_end(struct file *file, unsigned from, to; int ret = 0, ret2; - from = pos & (PAGE_CACHE_SIZE - 1); - to = from + len; + copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); + from = pos & (PAGE_CACHE_SIZE - 1); + to = from + copied; ret = walk_page_buffers(handle, page_buffers(page), - from, to, NULL, ext3_journal_dirty_data); + from, to, NULL, journal_dirty_data_fn); - if (ret == 0) { - /* - * generic_write_end() will run mark_inode_dirty() if i_size - * changes. So let's piggyback the i_disksize mark_inode_dirty - * into that. - */ - loff_t new_i_size; - - new_i_size = pos + copied; - if (new_i_size > EXT3_I(inode)->i_disksize) - EXT3_I(inode)->i_disksize = new_i_size; - ret2 = ext3_generic_write_end(file, mapping, pos, len, copied, - page, fsdata); - copied = ret2; - if (ret2 < 0) - ret = ret2; - } + if (ret == 0) + update_file_sizes(inode, pos, copied); + /* + * There may be allocated blocks outside of i_size because + * we failed to copy some data. Prepare for truncate. + */ + if (pos + len > inode->i_size) + ext3_orphan_add(handle, inode); ret2 = ext3_journal_stop(handle); if (!ret) ret = ret2; unlock_page(page); page_cache_release(page); + if (pos + len > inode->i_size) + vmtruncate(inode, inode->i_size); return ret ? ret : copied; } @@ -1299,25 +1307,22 @@ static int ext3_writeback_write_end(struct file *file, { handle_t *handle = ext3_journal_current_handle(); struct inode *inode = file->f_mapping->host; - int ret = 0, ret2; - loff_t new_i_size; - - new_i_size = pos + copied; - if (new_i_size > EXT3_I(inode)->i_disksize) - EXT3_I(inode)->i_disksize = new_i_size; - - ret2 = ext3_generic_write_end(file, mapping, pos, len, copied, - page, fsdata); - copied = ret2; - if (ret2 < 0) - ret = ret2; + int ret; - ret2 = ext3_journal_stop(handle); - if (!ret) - ret = ret2; + copied = block_write_end(file, mapping, pos, len, copied, page, fsdata); + update_file_sizes(inode, pos, copied); + /* + * There may be allocated blocks outside of i_size because + * we failed to copy some data. Prepare for truncate. + */ + if (pos + len > inode->i_size) + ext3_orphan_add(handle, inode); + ret = ext3_journal_stop(handle); unlock_page(page); page_cache_release(page); + if (pos + len > inode->i_size) + vmtruncate(inode, inode->i_size); return ret ? ret : copied; } @@ -1338,15 +1343,23 @@ static int ext3_journalled_write_end(struct file *file, if (copied < len) { if (!PageUptodate(page)) copied = 0; - page_zero_new_buffers(page, from+copied, to); + page_zero_new_buffers(page, from + copied, to); + to = from + copied; } ret = walk_page_buffers(handle, page_buffers(page), from, to, &partial, write_end_fn); if (!partial) SetPageUptodate(page); - if (pos+copied > inode->i_size) - i_size_write(inode, pos+copied); + + if (pos + copied > inode->i_size) + i_size_write(inode, pos + copied); + /* + * There may be allocated blocks outside of i_size because + * we failed to copy some data. Prepare for truncate. + */ + if (pos + len > inode->i_size) + ext3_orphan_add(handle, inode); EXT3_I(inode)->i_state |= EXT3_STATE_JDATA; if (inode->i_size > EXT3_I(inode)->i_disksize) { EXT3_I(inode)->i_disksize = inode->i_size; @@ -1361,6 +1374,8 @@ static int ext3_journalled_write_end(struct file *file, unlock_page(page); page_cache_release(page); + if (pos + len > inode->i_size) + vmtruncate(inode, inode->i_size); return ret ? ret : copied; } @@ -1428,17 +1443,11 @@ static int bput_one(handle_t *handle, struct buffer_head *bh) return 0; } -static int journal_dirty_data_fn(handle_t *handle, struct buffer_head *bh) -{ - if (buffer_mapped(bh)) - return ext3_journal_dirty_data(handle, bh); - return 0; -} - static int buffer_unmapped(handle_t *handle, struct buffer_head *bh) { return !buffer_mapped(bh); } + /* * Note that we always start a transaction even if we're not journalling * data. This is to preserve ordering: any hole instantiation within diff --git a/fs/ext3/ioctl.c b/fs/ext3/ioctl.c index 5e86ce9..8897481 100644 --- a/fs/ext3/ioctl.c +++ b/fs/ext3/ioctl.c @@ -15,12 +15,11 @@ #include <linux/mount.h> #include <linux/time.h> #include <linux/compat.h> -#include <linux/smp_lock.h> #include <asm/uaccess.h> -int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, - unsigned long arg) +long ext3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { + struct inode *inode = filp->f_dentry->d_inode; struct ext3_inode_info *ei = EXT3_I(inode); unsigned int flags; unsigned short rsv_window_size; @@ -39,29 +38,25 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, unsigned int oldflags; unsigned int jflag; + if (!is_owner_or_cap(inode)) + return -EACCES; + + if (get_user(flags, (int __user *) arg)) + return -EFAULT; + err = mnt_want_write(filp->f_path.mnt); if (err) return err; - if (!is_owner_or_cap(inode)) { - err = -EACCES; - goto flags_out; - } - - if (get_user(flags, (int __user *) arg)) { - err = -EFAULT; - goto flags_out; - } - flags = ext3_mask_flags(inode->i_mode, flags); mutex_lock(&inode->i_mutex); + /* Is it quota file? Do not allow user to mess with it */ - if (IS_NOQUOTA(inode)) { - mutex_unlock(&inode->i_mutex); - err = -EPERM; + err = -EPERM; + if (IS_NOQUOTA(inode)) goto flags_out; - } + oldflags = ei->i_flags; /* The JOURNAL_DATA flag is modifiable only by root */ @@ -74,11 +69,8 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, * This test looks nicer. Thanks to Pauline Middelink */ if ((flags ^ oldflags) & (EXT3_APPEND_FL | EXT3_IMMUTABLE_FL)) { - if (!capable(CAP_LINUX_IMMUTABLE)) { - mutex_unlock(&inode->i_mutex); - err = -EPERM; + if (!capable(CAP_LINUX_IMMUTABLE)) goto flags_out; - } } /* @@ -86,17 +78,12 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, * the relevant capability. */ if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) { - if (!capable(CAP_SYS_RESOURCE)) { - mutex_unlock(&inode->i_mutex); - err = -EPERM; + if (!capable(CAP_SYS_RESOURCE)) goto flags_out; - } } - handle = ext3_journal_start(inode, 1); if (IS_ERR(handle)) { - mutex_unlock(&inode->i_mutex); err = PTR_ERR(handle); goto flags_out; } @@ -116,15 +103,13 @@ int ext3_ioctl (struct inode * inode, struct file * filp, unsigned int cmd, err = ext3_mark_iloc_dirty(handle, inode, &iloc); flags_err: ext3_journal_stop(handle); - if (err) { - mutex_unlock(&inode->i_mutex); - return err; - } + if (err) + goto flags_out; if ((jflag ^ oldflags) & (EXT3_JOURNAL_DATA_FL)) err = ext3_change_inode_journal_flag(inode, jflag); - mutex_unlock(&inode->i_mutex); flags_out: + mutex_unlock(&inode->i_mutex); mnt_drop_write(filp->f_path.mnt); return err; } @@ -140,6 +125,7 @@ flags_out: if (!is_owner_or_cap(inode)) return -EPERM; + err = mnt_want_write(filp->f_path.mnt); if (err) return err; @@ -147,6 +133,7 @@ flags_out: err = -EFAULT; goto setversion_out; } + handle = ext3_journal_start(inode, 1); if (IS_ERR(handle)) { err = PTR_ERR(handle); @@ -299,9 +286,6 @@ group_add_out: #ifdef CONFIG_COMPAT long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_path.dentry->d_inode; - int ret; - /* These are just misnamed, they actually get/put from/to user an int */ switch (cmd) { case EXT3_IOC32_GETFLAGS: @@ -341,9 +325,6 @@ long ext3_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) default: return -ENOIOCTLCMD; } - lock_kernel(); - ret = ext3_ioctl(inode, file, cmd, (unsigned long) compat_ptr(arg)); - unlock_kernel(); - return ret; + return ext3_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); } #endif diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index e2fc63c..6ddaa0a 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -161,12 +161,12 @@ static struct dx_frame *dx_probe(struct qstr *entry, struct dx_frame *frame, int *err); static void dx_release (struct dx_frame *frames); -static int dx_make_map (struct ext3_dir_entry_2 *de, int size, +static int dx_make_map(struct ext3_dir_entry_2 *de, unsigned blocksize, struct dx_hash_info *hinfo, struct dx_map_entry map[]); static void dx_sort_map(struct dx_map_entry *map, unsigned count); static struct ext3_dir_entry_2 *dx_move_dirents (char *from, char *to, struct dx_map_entry *offsets, int count); -static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); +static struct ext3_dir_entry_2 *dx_pack_dirents(char *base, unsigned blocksize); static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); static int ext3_htree_next_block(struct inode *dir, __u32 hash, struct dx_frame *frame, @@ -708,14 +708,14 @@ errout: * Create map of hash values, offsets, and sizes, stored at end of block. * Returns number of entries mapped. */ -static int dx_make_map (struct ext3_dir_entry_2 *de, int size, - struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) +static int dx_make_map(struct ext3_dir_entry_2 *de, unsigned blocksize, + struct dx_hash_info *hinfo, struct dx_map_entry *map_tail) { int count = 0; char *base = (char *) de; struct dx_hash_info h = *hinfo; - while ((char *) de < base + size) + while ((char *) de < base + blocksize) { if (de->name_len && de->inode) { ext3fs_dirhash(de->name, de->name_len, &h); @@ -1047,8 +1047,16 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str return ERR_PTR(-EIO); } inode = ext3_iget(dir->i_sb, ino); - if (IS_ERR(inode)) - return ERR_CAST(inode); + if (unlikely(IS_ERR(inode))) { + if (PTR_ERR(inode) == -ESTALE) { + ext3_error(dir->i_sb, __func__, + "deleted inode referenced: %lu", + ino); + return ERR_PTR(-EIO); + } else { + return ERR_CAST(inode); + } + } } return d_splice_alias(inode, dentry); } @@ -1120,13 +1128,14 @@ dx_move_dirents(char *from, char *to, struct dx_map_entry *map, int count) * Compact each dir entry in the range to the minimal rec_len. * Returns pointer to last entry in range. */ -static struct ext3_dir_entry_2* dx_pack_dirents(char *base, int size) +static struct ext3_dir_entry_2 *dx_pack_dirents(char *base, unsigned blocksize) { - struct ext3_dir_entry_2 *next, *to, *prev, *de = (struct ext3_dir_entry_2 *) base; + struct ext3_dir_entry_2 *next, *to, *prev; + struct ext3_dir_entry_2 *de = (struct ext3_dir_entry_2 *)base; unsigned rec_len = 0; prev = to = de; - while ((char*)de < base + size) { + while ((char *)de < base + blocksize) { next = ext3_next_entry(de); if (de->inode && de->name_len) { rec_len = EXT3_DIR_REC_LEN(de->name_len); diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c index 694ed6f..647e0d6 100644 --- a/fs/ext4/acl.c +++ b/fs/ext4/acl.c @@ -323,7 +323,7 @@ ext4_init_acl(handle_t *handle, struct inode *inode, struct inode *dir) return PTR_ERR(acl); } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if (test_opt(inode->i_sb, POSIX_ACL) && acl) { struct posix_acl *clone; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index de0004f..296785a 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -523,7 +523,9 @@ static int fat_remount(struct super_block *sb, int *flags, char *data) static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); + struct super_block *sb = dentry->d_sb; + struct msdos_sb_info *sbi = MSDOS_SB(sb); + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); /* If the count of free cluster is still unknown, counts it here. */ if (sbi->free_clusters == -1 || !sbi->free_clus_valid) { @@ -537,6 +539,8 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_blocks = sbi->max_cluster - FAT_START_ENT; buf->f_bfree = sbi->free_clusters; buf->f_bavail = sbi->free_clusters; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_namelen = sbi->options.isvfat ? 260 : 12; return 0; @@ -930,7 +934,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, opts->fs_uid = current_uid(); opts->fs_gid = current_gid(); - opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->fs_fmask = current_umask(); opts->allow_utime = -1; opts->codepage = fat_default_codepage; opts->iocharset = fat_default_iocharset; diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index e3fe991..eed4806 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -196,7 +196,7 @@ static void redirty_tail(struct inode *inode) struct inode *tail_inode; tail_inode = list_entry(sb->s_dirty.next, struct inode, i_list); - if (!time_after_eq(inode->dirtied_when, + if (time_before(inode->dirtied_when, tail_inode->dirtied_when)) inode->dirtied_when = jiffies; } @@ -220,6 +220,21 @@ static void inode_sync_complete(struct inode *inode) wake_up_bit(&inode->i_state, __I_SYNC); } +static bool inode_dirtied_after(struct inode *inode, unsigned long t) +{ + bool ret = time_after(inode->dirtied_when, t); +#ifndef CONFIG_64BIT + /* + * For inodes being constantly redirtied, dirtied_when can get stuck. + * It _appears_ to be in the future, but is actually in distant past. + * This test is necessary to prevent such wrapped-around relative times + * from permanently stopping the whole pdflush writeback. + */ + ret = ret && time_before_eq(inode->dirtied_when, jiffies); +#endif + return ret; +} + /* * Move expired dirty inodes from @delaying_queue to @dispatch_queue. */ @@ -231,7 +246,7 @@ static void move_expired_inodes(struct list_head *delaying_queue, struct inode *inode = list_entry(delaying_queue->prev, struct inode, i_list); if (older_than_this && - time_after(inode->dirtied_when, *older_than_this)) + inode_dirtied_after(inode, *older_than_this)) break; list_move(&inode->i_list, dispatch_queue); } @@ -492,8 +507,11 @@ void generic_sync_sb_inodes(struct super_block *sb, continue; /* blockdev has wrong queue */ } - /* Was this inode dirtied after sync_sb_inodes was called? */ - if (time_after(inode->dirtied_when, start)) + /* + * Was this inode dirtied after sync_sb_inodes was called? + * This keeps sync from extra jobs and livelock. + */ + if (inode_dirtied_after(inode, start)) break; /* Is another pdflush already flushing this queue? */ @@ -538,7 +556,8 @@ void generic_sync_sb_inodes(struct super_block *sb, list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { struct address_space *mapping; - if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) + if (inode->i_state & + (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) continue; mapping = inode->i_mapping; if (mapping->nrpages == 0) diff --git a/fs/fs_struct.c b/fs/fs_struct.c new file mode 100644 index 0000000..eee0590 --- /dev/null +++ b/fs/fs_struct.c @@ -0,0 +1,177 @@ +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/fs.h> +#include <linux/path.h> +#include <linux/slab.h> +#include <linux/fs_struct.h> + +/* + * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. + * It can block. + */ +void set_fs_root(struct fs_struct *fs, struct path *path) +{ + struct path old_root; + + write_lock(&fs->lock); + old_root = fs->root; + fs->root = *path; + path_get(path); + write_unlock(&fs->lock); + if (old_root.dentry) + path_put(&old_root); +} + +/* + * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. + * It can block. + */ +void set_fs_pwd(struct fs_struct *fs, struct path *path) +{ + struct path old_pwd; + + write_lock(&fs->lock); + old_pwd = fs->pwd; + fs->pwd = *path; + path_get(path); + write_unlock(&fs->lock); + + if (old_pwd.dentry) + path_put(&old_pwd); +} + +void chroot_fs_refs(struct path *old_root, struct path *new_root) +{ + struct task_struct *g, *p; + struct fs_struct *fs; + int count = 0; + + read_lock(&tasklist_lock); + do_each_thread(g, p) { + task_lock(p); + fs = p->fs; + if (fs) { + write_lock(&fs->lock); + if (fs->root.dentry == old_root->dentry + && fs->root.mnt == old_root->mnt) { + path_get(new_root); + fs->root = *new_root; + count++; + } + if (fs->pwd.dentry == old_root->dentry + && fs->pwd.mnt == old_root->mnt) { + path_get(new_root); + fs->pwd = *new_root; + count++; + } + write_unlock(&fs->lock); + } + task_unlock(p); + } while_each_thread(g, p); + read_unlock(&tasklist_lock); + while (count--) + path_put(old_root); +} + +void free_fs_struct(struct fs_struct *fs) +{ + path_put(&fs->root); + path_put(&fs->pwd); + kmem_cache_free(fs_cachep, fs); +} + +void exit_fs(struct task_struct *tsk) +{ + struct fs_struct *fs = tsk->fs; + + if (fs) { + int kill; + task_lock(tsk); + write_lock(&fs->lock); + tsk->fs = NULL; + kill = !--fs->users; + write_unlock(&fs->lock); + task_unlock(tsk); + if (kill) + free_fs_struct(fs); + } +} + +struct fs_struct *copy_fs_struct(struct fs_struct *old) +{ + struct fs_struct *fs = kmem_cache_alloc(fs_cachep, GFP_KERNEL); + /* We don't need to lock fs - think why ;-) */ + if (fs) { + fs->users = 1; + fs->in_exec = 0; + rwlock_init(&fs->lock); + fs->umask = old->umask; + read_lock(&old->lock); + fs->root = old->root; + path_get(&old->root); + fs->pwd = old->pwd; + path_get(&old->pwd); + read_unlock(&old->lock); + } + return fs; +} + +int unshare_fs_struct(void) +{ + struct fs_struct *fs = current->fs; + struct fs_struct *new_fs = copy_fs_struct(fs); + int kill; + + if (!new_fs) + return -ENOMEM; + + task_lock(current); + write_lock(&fs->lock); + kill = !--fs->users; + current->fs = new_fs; + write_unlock(&fs->lock); + task_unlock(current); + + if (kill) + free_fs_struct(fs); + + return 0; +} +EXPORT_SYMBOL_GPL(unshare_fs_struct); + +int current_umask(void) +{ + return current->fs->umask; +} +EXPORT_SYMBOL(current_umask); + +/* to be mentioned only in INIT_TASK */ +struct fs_struct init_fs = { + .users = 1, + .lock = __RW_LOCK_UNLOCKED(init_fs.lock), + .umask = 0022, +}; + +void daemonize_fs_struct(void) +{ + struct fs_struct *fs = current->fs; + + if (fs) { + int kill; + + task_lock(current); + + write_lock(&init_fs.lock); + init_fs.users++; + write_unlock(&init_fs.lock); + + write_lock(&fs->lock); + current->fs = &init_fs; + kill = !--fs->users; + write_unlock(&fs->lock); + + task_unlock(current); + if (kill) + free_fs_struct(fs); + } +} diff --git a/fs/generic_acl.c b/fs/generic_acl.c index 995d63b..e0b53aa 100644 --- a/fs/generic_acl.c +++ b/fs/generic_acl.c @@ -134,7 +134,7 @@ generic_acl_init(struct inode *inode, struct inode *dir, mode_t mode = inode->i_mode; int error; - inode->i_mode = mode & ~current->fs->umask; + inode->i_mode = mode & ~current_umask(); if (!S_ISLNK(inode->i_mode)) acl = ops->getacl(dir, ACL_TYPE_DEFAULT); if (acl) { diff --git a/fs/gfs2/acl.c b/fs/gfs2/acl.c index 43764f4..fa881bd 100644 --- a/fs/gfs2/acl.c +++ b/fs/gfs2/acl.c @@ -215,7 +215,7 @@ int gfs2_acl_create(struct gfs2_inode *dip, struct gfs2_inode *ip) if (error) return error; if (!acl) { - mode &= ~current->fs->umask; + mode &= ~current_umask(); if (mode != ip->i_inode.i_mode) error = munge_mode(ip, mode); return error; diff --git a/fs/hfs/super.c b/fs/hfs/super.c index c8b5acf..a36bb74 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c @@ -82,6 +82,7 @@ static void hfs_put_super(struct super_block *sb) static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = HFS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; @@ -90,6 +91,8 @@ static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bavail = buf->f_bfree; buf->f_files = HFS_SB(sb)->fs_ablocks; buf->f_ffree = HFS_SB(sb)->free_ablocks; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_namelen = HFS_NAMELEN; return 0; diff --git a/fs/hfsplus/options.c b/fs/hfsplus/options.c index bab7f8d..3fcbb0e 100644 --- a/fs/hfsplus/options.c +++ b/fs/hfsplus/options.c @@ -48,7 +48,7 @@ void hfsplus_fill_defaults(struct hfsplus_sb_info *opts) opts->creator = HFSPLUS_DEF_CR_TYPE; opts->type = HFSPLUS_DEF_CR_TYPE; - opts->umask = current->fs->umask; + opts->umask = current_umask(); opts->uid = current_uid(); opts->gid = current_gid(); opts->part = -1; diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index eb74531..f2a6402 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -223,6 +223,7 @@ static void hfsplus_put_super(struct super_block *sb) static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = HFSPLUS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; @@ -231,6 +232,8 @@ static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bavail = buf->f_bfree; buf->f_files = 0xFFFFFFFF; buf->f_ffree = 0xFFFFFFFF - HFSPLUS_SB(sb).next_cnid; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_namelen = HFSPLUS_MAX_STRLEN; return 0; diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index 0d049b8..fecf402 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c @@ -136,6 +136,7 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *s = dentry->d_sb; struct hpfs_sb_info *sbi = hpfs_sb(s); + u64 id = huge_encode_dev(s->s_bdev->bd_dev); lock_kernel(); /*if (sbi->sb_n_free == -1) {*/ @@ -149,6 +150,8 @@ static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bavail = sbi->sb_n_free; buf->f_files = sbi->sb_dirband_size / 4; buf->f_ffree = sbi->sb_n_free_dnodes; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_namelen = 254; unlock_kernel(); @@ -477,7 +480,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent) uid = current_uid(); gid = current_gid(); - umask = current->fs->umask; + umask = current_umask(); lowercase = 0; conv = CONV_BINARY; eas = 2; diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c index b278f7f..a5089a6 100644 --- a/fs/hppfs/hppfs.c +++ b/fs/hppfs/hppfs.c @@ -280,7 +280,12 @@ static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, "errno = %d\n", err); return err; } - count = hppfs_read_file(hppfs->host_fd, buf, count); + err = hppfs_read_file(hppfs->host_fd, buf, count); + if (err < 0) { + printk(KERN_ERR "hppfs_read: read failed: %d\n", err); + return err; + } + count = err; if (count > 0) *ppos += count; } diff --git a/fs/internal.h b/fs/internal.h index 53af885..b4dac4f 100644 --- a/fs/internal.h +++ b/fs/internal.h @@ -11,6 +11,7 @@ struct super_block; struct linux_binprm; +struct path; /* * block_dev.c @@ -43,7 +44,7 @@ extern void __init chrdev_init(void); /* * exec.c */ -extern void check_unsafe_exec(struct linux_binprm *); +extern int check_unsafe_exec(struct linux_binprm *); /* * namespace.c @@ -60,3 +61,8 @@ extern void umount_tree(struct vfsmount *, int, struct list_head *); extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); extern void __init mnt_init(void); + +/* + * fs_struct.c + */ +extern void chroot_fs_refs(struct path *, struct path *); diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 13d2edd..b4cbe96 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c @@ -923,6 +923,7 @@ out_freesbi: static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = ISOFS_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; @@ -932,6 +933,8 @@ static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf) buf->f_bavail = 0; buf->f_files = ISOFS_SB(sb)->s_ninodes; buf->f_ffree = 0; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_namelen = NAME_MAX; return 0; } diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index e79c078..737f724 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -637,6 +637,8 @@ struct journal_head *journal_get_descriptor_buffer(journal_t *journal) return NULL; bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); + if (!bh) + return NULL; lock_buffer(bh); memset(bh->b_data, 0, journal->j_blocksize); set_buffer_uptodate(bh); @@ -733,9 +735,7 @@ journal_t * journal_init_dev(struct block_device *bdev, if (!journal->j_wbuf) { printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", __func__); - kfree(journal); - journal = NULL; - goto out; + goto out_err; } journal->j_dev = bdev; journal->j_fs_dev = fs_dev; @@ -743,11 +743,19 @@ journal_t * journal_init_dev(struct block_device *bdev, journal->j_maxlen = len; bh = __getblk(journal->j_dev, start, journal->j_blocksize); - J_ASSERT(bh != NULL); + if (!bh) { + printk(KERN_ERR + "%s: Cannot get buffer for journal superblock\n", + __func__); + goto out_err; + } journal->j_sb_buffer = bh; journal->j_superblock = (journal_superblock_t *)bh->b_data; -out: + return journal; +out_err: + kfree(journal); + return NULL; } /** @@ -787,8 +795,7 @@ journal_t * journal_init_inode (struct inode *inode) if (!journal->j_wbuf) { printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", __func__); - kfree(journal); - return NULL; + goto out_err; } err = journal_bmap(journal, 0, &blocknr); @@ -796,16 +803,23 @@ journal_t * journal_init_inode (struct inode *inode) if (err) { printk(KERN_ERR "%s: Cannnot locate journal superblock\n", __func__); - kfree(journal); - return NULL; + goto out_err; } bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); - J_ASSERT(bh != NULL); + if (!bh) { + printk(KERN_ERR + "%s: Cannot get buffer for journal superblock\n", + __func__); + goto out_err; + } journal->j_sb_buffer = bh; journal->j_superblock = (journal_superblock_t *)bh->b_data; return journal; +out_err: + kfree(journal); + return NULL; } /* diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c index d987137..77ccf8c 100644 --- a/fs/jffs2/acl.c +++ b/fs/jffs2/acl.c @@ -336,7 +336,7 @@ int jffs2_init_acl_pre(struct inode *dir_i, struct inode *inode, int *i_mode) return PTR_ERR(acl); if (!acl) { - *i_mode &= ~current->fs->umask; + *i_mode &= ~current_umask(); } else { if (S_ISDIR(*i_mode)) jffs2_iset_acl(inode, &f->i_acl_default, acl); diff --git a/fs/jfs/acl.c b/fs/jfs/acl.c index a166c16..06ca1b8 100644 --- a/fs/jfs/acl.c +++ b/fs/jfs/acl.c @@ -182,7 +182,7 @@ int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir) cleanup: posix_acl_release(acl); } else - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) | inode->i_mode; diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 618865b..daad3c2 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -321,15 +321,20 @@ out: static int minix_statfs(struct dentry *dentry, struct kstatfs *buf) { - struct minix_sb_info *sbi = minix_sb(dentry->d_sb); - buf->f_type = dentry->d_sb->s_magic; - buf->f_bsize = dentry->d_sb->s_blocksize; + struct super_block *sb = dentry->d_sb; + struct minix_sb_info *sbi = minix_sb(sb); + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + buf->f_type = sb->s_magic; + buf->f_bsize = sb->s_blocksize; buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; buf->f_bfree = minix_count_free_blocks(sbi); buf->f_bavail = buf->f_bfree; buf->f_files = sbi->s_ninodes; buf->f_ffree = minix_count_free_inodes(sbi); buf->f_namelen = sbi->s_namelen; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + return 0; } @@ -82,7 +82,7 @@ static void mpage_end_io_write(struct bio *bio, int err) bio_put(bio); } -struct bio *mpage_bio_submit(int rw, struct bio *bio) +static struct bio *mpage_bio_submit(int rw, struct bio *bio) { bio->bi_end_io = mpage_end_io_read; if (rw == WRITE) @@ -90,7 +90,6 @@ struct bio *mpage_bio_submit(int rw, struct bio *bio) submit_bio(rw, bio); return NULL; } -EXPORT_SYMBOL(mpage_bio_submit); static struct bio * mpage_alloc(struct block_device *bdev, @@ -439,7 +438,14 @@ EXPORT_SYMBOL(mpage_readpage); * just allocate full-size (16-page) BIOs. */ -int __mpage_writepage(struct page *page, struct writeback_control *wbc, +struct mpage_data { + struct bio *bio; + sector_t last_block_in_bio; + get_block_t *get_block; + unsigned use_writepage; +}; + +static int __mpage_writepage(struct page *page, struct writeback_control *wbc, void *data) { struct mpage_data *mpd = data; @@ -648,7 +654,6 @@ out: mpd->bio = bio; return ret; } -EXPORT_SYMBOL(__mpage_writepage); /** * mpage_writepages - walk the list of dirty pages of the given address space & writepage() all of them @@ -32,6 +32,7 @@ #include <linux/file.h> #include <linux/fcntl.h> #include <linux/device_cgroup.h> +#include <linux/fs_struct.h> #include <asm/uaccess.h> #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) @@ -1578,7 +1579,7 @@ static int __open_namei_create(struct nameidata *nd, struct path *path, struct dentry *dir = nd->path.dentry; if (!IS_POSIXACL(dir->d_inode)) - mode &= ~current->fs->umask; + mode &= ~current_umask(); error = security_path_mknod(&nd->path, path->dentry, mode, 0); if (error) goto out_unlock; @@ -1989,7 +1990,7 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, int, mode, goto out_unlock; } if (!IS_POSIXACL(nd.path.dentry->d_inode)) - mode &= ~current->fs->umask; + mode &= ~current_umask(); error = may_mknod(mode); if (error) goto out_dput; @@ -2067,7 +2068,7 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const char __user *, pathname, int, mode) goto out_unlock; if (!IS_POSIXACL(nd.path.dentry->d_inode)) - mode &= ~current->fs->umask; + mode &= ~current_umask(); error = mnt_want_write(nd.path.mnt); if (error) goto out_dput; @@ -2897,10 +2898,3 @@ EXPORT_SYMBOL(vfs_symlink); EXPORT_SYMBOL(vfs_unlink); EXPORT_SYMBOL(dentry_unhash); EXPORT_SYMBOL(generic_readlink); - -/* to be mentioned only in INIT_TASK */ -struct fs_struct init_fs = { - .count = ATOMIC_INIT(1), - .lock = __RW_LOCK_UNLOCKED(init_fs.lock), - .umask = 0022, -}; diff --git a/fs/namespace.c b/fs/namespace.c index 0a42e0e..c6f54e4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -27,6 +27,7 @@ #include <linux/ramfs.h> #include <linux/log2.h> #include <linux/idr.h> +#include <linux/fs_struct.h> #include <asm/uaccess.h> #include <asm/unistd.h> #include "pnode.h" @@ -2093,66 +2094,6 @@ out1: } /* - * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. - * It can block. Requires the big lock held. - */ -void set_fs_root(struct fs_struct *fs, struct path *path) -{ - struct path old_root; - - write_lock(&fs->lock); - old_root = fs->root; - fs->root = *path; - path_get(path); - write_unlock(&fs->lock); - if (old_root.dentry) - path_put(&old_root); -} - -/* - * Replace the fs->{pwdmnt,pwd} with {mnt,dentry}. Put the old values. - * It can block. Requires the big lock held. - */ -void set_fs_pwd(struct fs_struct *fs, struct path *path) -{ - struct path old_pwd; - - write_lock(&fs->lock); - old_pwd = fs->pwd; - fs->pwd = *path; - path_get(path); - write_unlock(&fs->lock); - - if (old_pwd.dentry) - path_put(&old_pwd); -} - -static void chroot_fs_refs(struct path *old_root, struct path *new_root) -{ - struct task_struct *g, *p; - struct fs_struct *fs; - - read_lock(&tasklist_lock); - do_each_thread(g, p) { - task_lock(p); - fs = p->fs; - if (fs) { - atomic_inc(&fs->count); - task_unlock(p); - if (fs->root.dentry == old_root->dentry - && fs->root.mnt == old_root->mnt) - set_fs_root(fs, new_root); - if (fs->pwd.dentry == old_root->dentry - && fs->pwd.mnt == old_root->mnt) - set_fs_pwd(fs, new_root); - put_fs_struct(fs); - } else - task_unlock(p); - } while_each_thread(g, p); - read_unlock(&tasklist_lock); -} - -/* * pivot_root Semantics: * Moves the root file system of the current process to the directory put_old, * makes new_root as the new root file system of the current process, and sets diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index b82fe68..d0cc5ce 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -328,7 +328,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, data->arg.create.verifier[1] = current->pid; } - sattr->ia_mode &= ~current->fs->umask; + sattr->ia_mode &= ~current_umask(); for (;;) { status = nfs3_do_create(dir, dentry, data); @@ -528,7 +528,7 @@ nfs3_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) dprintk("NFS call mkdir %s\n", dentry->d_name.name); - sattr->ia_mode &= ~current->fs->umask; + sattr->ia_mode &= ~current_umask(); data = nfs3_alloc_createdata(); if (data == NULL) @@ -639,7 +639,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, dprintk("NFS call mknod %s %u:%u\n", dentry->d_name.name, MAJOR(rdev), MINOR(rdev)); - sattr->ia_mode &= ~current->fs->umask; + sattr->ia_mode &= ~current_umask(); data = nfs3_alloc_createdata(); if (data == NULL) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 97baccc..a4d2426 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -1501,7 +1501,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) attr.ia_mode = nd->intent.open.create_mode; attr.ia_valid = ATTR_MODE; if (!IS_POSIXACL(dir)) - attr.ia_mode &= ~current->fs->umask; + attr.ia_mode &= ~current_umask(); } else { attr.ia_valid = 0; BUG_ON(nd->intent.open.flags & O_CREAT); diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index bc3567b..7c09852 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -403,7 +403,6 @@ static int nfsd(void *vrqstp) { struct svc_rqst *rqstp = (struct svc_rqst *) vrqstp; - struct fs_struct *fsp; int err, preverr = 0; /* Lock module and set up kernel thread */ @@ -412,13 +411,11 @@ nfsd(void *vrqstp) /* At this point, the thread shares current->fs * with the init process. We need to create files with a * umask of 0 instead of init's umask. */ - fsp = copy_fs_struct(current->fs); - if (!fsp) { + if (unshare_fs_struct() < 0) { printk("Unable to start nfsd thread: out of memory\n"); goto out; } - exit_fs(current); - current->fs = fsp; + current->fs->umask = 0; /* diff --git a/fs/ocfs2/acl.c b/fs/ocfs2/acl.c index 12dfb44..fbeaec7 100644 --- a/fs/ocfs2/acl.c +++ b/fs/ocfs2/acl.c @@ -296,7 +296,7 @@ int ocfs2_init_acl(handle_t *handle, return PTR_ERR(acl); } if (!acl) - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } if ((osb->s_mount_opt & OCFS2_MOUNT_POSIX_ACL) && acl) { struct posix_acl *clone; diff --git a/fs/omfs/inode.c b/fs/omfs/inode.c index 633e9dc..379ae5f 100644 --- a/fs/omfs/inode.c +++ b/fs/omfs/inode.c @@ -262,14 +262,19 @@ static int omfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *s = dentry->d_sb; struct omfs_sb_info *sbi = OMFS_SB(s); + u64 id = huge_encode_dev(s->s_bdev->bd_dev); + buf->f_type = OMFS_MAGIC; buf->f_bsize = sbi->s_blocksize; buf->f_blocks = sbi->s_num_blocks; buf->f_files = sbi->s_num_blocks; buf->f_namelen = OMFS_NAMELEN; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); buf->f_bfree = buf->f_bavail = buf->f_ffree = omfs_count_free(s); + return 0; } @@ -421,7 +426,7 @@ static int omfs_fill_super(struct super_block *sb, void *data, int silent) sbi->s_uid = current_uid(); sbi->s_gid = current_gid(); - sbi->s_dmask = sbi->s_fmask = current->fs->umask; + sbi->s_dmask = sbi->s_fmask = current_umask(); if (!parse_options((char *) data, sbi)) goto end; @@ -29,6 +29,7 @@ #include <linux/rcupdate.h> #include <linux/audit.h> #include <linux/falloc.h> +#include <linux/fs_struct.h> int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) { diff --git a/fs/proc/base.c b/fs/proc/base.c index e0afd32..f715597 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -80,6 +80,7 @@ #include <linux/oom.h> #include <linux/elf.h> #include <linux/pid_namespace.h> +#include <linux/fs_struct.h> #include "internal.h" /* NOTE: diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 43d23948..74ea974 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -120,7 +120,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v) K(i.freeram-i.freehigh), #endif #ifndef CONFIG_MMU - K((unsigned long) atomic_read(&mmap_pages_allocated)), + K((unsigned long) atomic_long_read(&mmap_pages_allocated)), #endif K(i.totalswap), K(i.freeswap), diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 343ea12..863464d 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c @@ -2,6 +2,7 @@ #include <linux/mm.h> #include <linux/file.h> #include <linux/fdtable.h> +#include <linux/fs_struct.h> #include <linux/mount.h> #include <linux/ptrace.h> #include <linux/seq_file.h> @@ -49,7 +50,7 @@ void task_mem(struct seq_file *m, struct mm_struct *mm) else bytes += kobjsize(mm); - if (current->fs && atomic_read(¤t->fs->count) > 1) + if (current->fs && current->fs->users > 1) sbytes += kobjsize(current->fs); else bytes += kobjsize(current->fs); @@ -136,14 +137,14 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) } seq_printf(m, - "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n", + "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", vma->vm_start, vma->vm_end, flags & VM_READ ? 'r' : '-', flags & VM_WRITE ? 'w' : '-', flags & VM_EXEC ? 'x' : '-', flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p', - vma->vm_pgoff << PAGE_SHIFT, + (unsigned long long) vma->vm_pgoff << PAGE_SHIFT, MAJOR(dev), MINOR(dev), ino, &len); if (file) { diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 2aad104..fe1f0f3 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c @@ -282,6 +282,7 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock ) static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); lock_kernel(); @@ -291,6 +292,8 @@ static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bfree = qnx4_count_free_blocks(sb); buf->f_bavail = buf->f_bfree; buf->f_namelen = QNX4_NAME_MAX; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); unlock_kernel(); diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 2ca967a..607c579 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -823,7 +823,7 @@ static void add_dquot_ref(struct super_block *sb, int type) spin_lock(&inode_lock); list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { - if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) + if (inode->i_state & (I_FREEING|I_CLEAR|I_WILL_FREE|I_NEW)) continue; if (!atomic_read(&inode->i_writecount)) continue; diff --git a/fs/read_write.c b/fs/read_write.c index 400fe81..6d5d8ff 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -731,6 +731,56 @@ SYSCALL_DEFINE3(writev, unsigned long, fd, const struct iovec __user *, vec, return ret; } +SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec, + unsigned long, vlen, u32, pos_high, u32, pos_low) +{ + loff_t pos = ((loff_t)pos_high << 32) | pos_low; + struct file *file; + ssize_t ret = -EBADF; + int fput_needed; + + if (pos < 0) + return -EINVAL; + + file = fget_light(fd, &fput_needed); + if (file) { + ret = -ESPIPE; + if (file->f_mode & FMODE_PREAD) + ret = vfs_readv(file, vec, vlen, &pos); + fput_light(file, fput_needed); + } + + if (ret > 0) + add_rchar(current, ret); + inc_syscr(current); + return ret; +} + +SYSCALL_DEFINE5(pwritev, unsigned long, fd, const struct iovec __user *, vec, + unsigned long, vlen, u32, pos_high, u32, pos_low) +{ + loff_t pos = ((loff_t)pos_high << 32) | pos_low; + struct file *file; + ssize_t ret = -EBADF; + int fput_needed; + + if (pos < 0) + return -EINVAL; + + file = fget_light(fd, &fput_needed); + if (file) { + ret = -ESPIPE; + if (file->f_mode & FMODE_PWRITE) + ret = vfs_writev(file, vec, vlen, &pos); + fput_light(file, fput_needed); + } + + if (ret > 0) + add_wchar(current, ret); + inc_syscw(current); + return ret; +} + static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, size_t count, loff_t max) { diff --git a/fs/reiserfs/Kconfig b/fs/reiserfs/Kconfig index 949b8c6..513f431 100644 --- a/fs/reiserfs/Kconfig +++ b/fs/reiserfs/Kconfig @@ -1,5 +1,6 @@ config REISERFS_FS tristate "Reiserfs support" + select CRC32 help Stores not just filenames but the files themselves in a balanced tree. Uses journalling. diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 972250c6..0ae6486 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -27,6 +27,7 @@ #include <linux/mnt_namespace.h> #include <linux/mount.h> #include <linux/namei.h> +#include <linux/crc32.h> struct file_system_type reiserfs_fs_type; @@ -1904,6 +1905,10 @@ static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bsize = dentry->d_sb->s_blocksize; /* changed to accommodate gcc folks. */ buf->f_type = REISERFS_SUPER_MAGIC; + buf->f_fsid.val[0] = (u32)crc32_le(0, rs->s_uuid, sizeof(rs->s_uuid)/2); + buf->f_fsid.val[1] = (u32)crc32_le(0, rs->s_uuid + sizeof(rs->s_uuid)/2, + sizeof(rs->s_uuid)/2); + return 0; } diff --git a/fs/reiserfs/xattr_acl.c b/fs/reiserfs/xattr_acl.c index d423416..c303c42 100644 --- a/fs/reiserfs/xattr_acl.c +++ b/fs/reiserfs/xattr_acl.c @@ -428,7 +428,7 @@ reiserfs_inherit_default_acl(struct reiserfs_transaction_handle *th, } else { apply_umask: /* no ACL, apply umask */ - inode->i_mode &= ~current->fs->umask; + inode->i_mode &= ~current_umask(); } return err; diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 681ec0d..ffa6edc 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -301,6 +301,7 @@ failure: static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct squashfs_sb_info *msblk = dentry->d_sb->s_fs_info; + u64 id = huge_encode_dev(dentry->d_sb->s_bdev->bd_dev); TRACE("Entered squashfs_statfs\n"); @@ -311,6 +312,8 @@ static int squashfs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = msblk->inodes; buf->f_ffree = 0; buf->f_namelen = SQUASHFS_NAME_LEN; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); return 0; } diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 3d81bf5..da20b48 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c @@ -90,6 +90,7 @@ static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct sysv_sb_info *sbi = SYSV_SB(sb); + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); buf->f_type = sb->s_magic; buf->f_bsize = sb->s_blocksize; @@ -98,6 +99,8 @@ static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_files = sbi->s_ninodes; buf->f_ffree = sysv_count_free_inodes(sb); buf->f_namelen = SYSV_NAMELEN; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); return 0; } diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 2bb788a..e48e9a3 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -87,12 +87,12 @@ static int read_block_bitmap(struct super_block *sb, { struct buffer_head *bh = NULL; int retval = 0; - kernel_lb_addr loc; + struct kernel_lb_addr loc; loc.logicalBlockNum = bitmap->s_extPosition; loc.partitionReferenceNum = UDF_SB(sb)->s_partition; - bh = udf_tread(sb, udf_get_lb_pblock(sb, loc, block)); + bh = udf_tread(sb, udf_get_lb_pblock(sb, &loc, block)); if (!bh) retval = -EIO; @@ -140,27 +140,29 @@ static inline int load_block_bitmap(struct super_block *sb, return slot; } -static bool udf_add_free_space(struct udf_sb_info *sbi, - u16 partition, u32 cnt) +static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt) { + struct udf_sb_info *sbi = UDF_SB(sb); struct logicalVolIntegrityDesc *lvid; - if (sbi->s_lvid_bh == NULL) - return false; + if (!sbi->s_lvid_bh) + return; lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; le32_add_cpu(&lvid->freeSpaceTable[partition], cnt); - return true; + udf_updated_lvid(sb); } static void udf_bitmap_free_blocks(struct super_block *sb, struct inode *inode, struct udf_bitmap *bitmap, - kernel_lb_addr bloc, uint32_t offset, + struct kernel_lb_addr *bloc, + uint32_t offset, uint32_t count) { struct udf_sb_info *sbi = UDF_SB(sb); struct buffer_head *bh = NULL; + struct udf_part_map *partmap; unsigned long block; unsigned long block_group; unsigned long bit; @@ -169,17 +171,17 @@ static void udf_bitmap_free_blocks(struct super_block *sb, unsigned long overflow; mutex_lock(&sbi->s_alloc_mutex); - if (bloc.logicalBlockNum < 0 || - (bloc.logicalBlockNum + count) > - sbi->s_partmaps[bloc.partitionReferenceNum].s_partition_len) { + partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; + if (bloc->logicalBlockNum < 0 || + (bloc->logicalBlockNum + count) > + partmap->s_partition_len) { udf_debug("%d < %d || %d + %d > %d\n", - bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, - sbi->s_partmaps[bloc.partitionReferenceNum]. - s_partition_len); + bloc->logicalBlockNum, 0, bloc->logicalBlockNum, + count, partmap->s_partition_len); goto error_return; } - block = bloc.logicalBlockNum + offset + + block = bloc->logicalBlockNum + offset + (sizeof(struct spaceBitmapDesc) << 3); do { @@ -207,7 +209,7 @@ static void udf_bitmap_free_blocks(struct super_block *sb, } else { if (inode) vfs_dq_free_block(inode, 1); - udf_add_free_space(sbi, sbi->s_partition, 1); + udf_add_free_space(sb, sbi->s_partition, 1); } } mark_buffer_dirty(bh); @@ -218,9 +220,6 @@ static void udf_bitmap_free_blocks(struct super_block *sb, } while (overflow); error_return: - sb->s_dirt = 1; - if (sbi->s_lvid_bh) - mark_buffer_dirty(sbi->s_lvid_bh); mutex_unlock(&sbi->s_alloc_mutex); } @@ -277,9 +276,7 @@ static int udf_bitmap_prealloc_blocks(struct super_block *sb, } while (block_count > 0); out: - if (udf_add_free_space(sbi, partition, -alloc_count)) - mark_buffer_dirty(sbi->s_lvid_bh); - sb->s_dirt = 1; + udf_add_free_space(sb, partition, -alloc_count); mutex_unlock(&sbi->s_alloc_mutex); return alloc_count; } @@ -409,9 +406,7 @@ got_block: mark_buffer_dirty(bh); - if (udf_add_free_space(sbi, partition, -1)) - mark_buffer_dirty(sbi->s_lvid_bh); - sb->s_dirt = 1; + udf_add_free_space(sb, partition, -1); mutex_unlock(&sbi->s_alloc_mutex); *err = 0; return newblock; @@ -425,26 +420,28 @@ error_return: static void udf_table_free_blocks(struct super_block *sb, struct inode *inode, struct inode *table, - kernel_lb_addr bloc, uint32_t offset, + struct kernel_lb_addr *bloc, + uint32_t offset, uint32_t count) { struct udf_sb_info *sbi = UDF_SB(sb); + struct udf_part_map *partmap; uint32_t start, end; uint32_t elen; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; struct extent_position oepos, epos; int8_t etype; int i; struct udf_inode_info *iinfo; mutex_lock(&sbi->s_alloc_mutex); - if (bloc.logicalBlockNum < 0 || - (bloc.logicalBlockNum + count) > - sbi->s_partmaps[bloc.partitionReferenceNum].s_partition_len) { + partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; + if (bloc->logicalBlockNum < 0 || + (bloc->logicalBlockNum + count) > + partmap->s_partition_len) { udf_debug("%d < %d || %d + %d > %d\n", bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, - sbi->s_partmaps[bloc.partitionReferenceNum]. - s_partition_len); + partmap->s_partition_len); goto error_return; } @@ -453,11 +450,10 @@ static void udf_table_free_blocks(struct super_block *sb, could occure, but.. oh well */ if (inode) vfs_dq_free_block(inode, count); - if (udf_add_free_space(sbi, sbi->s_partition, count)) - mark_buffer_dirty(sbi->s_lvid_bh); + udf_add_free_space(sb, sbi->s_partition, count); - start = bloc.logicalBlockNum + offset; - end = bloc.logicalBlockNum + offset + count - 1; + start = bloc->logicalBlockNum + offset; + end = bloc->logicalBlockNum + offset + count - 1; epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry); elen = 0; @@ -483,7 +479,7 @@ static void udf_table_free_blocks(struct super_block *sb, start += count; count = 0; } - udf_write_aext(table, &oepos, eloc, elen, 1); + udf_write_aext(table, &oepos, &eloc, elen, 1); } else if (eloc.logicalBlockNum == (end + 1)) { if ((0x3FFFFFFF - elen) < (count << sb->s_blocksize_bits)) { @@ -502,7 +498,7 @@ static void udf_table_free_blocks(struct super_block *sb, end -= count; count = 0; } - udf_write_aext(table, &oepos, eloc, elen, 1); + udf_write_aext(table, &oepos, &eloc, elen, 1); } if (epos.bh != oepos.bh) { @@ -532,8 +528,8 @@ static void udf_table_free_blocks(struct super_block *sb, */ int adsize; - short_ad *sad = NULL; - long_ad *lad = NULL; + struct short_ad *sad = NULL; + struct long_ad *lad = NULL; struct allocExtDesc *aed; eloc.logicalBlockNum = start; @@ -541,9 +537,9 @@ static void udf_table_free_blocks(struct super_block *sb, (count << sb->s_blocksize_bits); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(short_ad); + adsize = sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(long_ad); + adsize = sizeof(struct long_ad); else { brelse(oepos.bh); brelse(epos.bh); @@ -563,7 +559,7 @@ static void udf_table_free_blocks(struct super_block *sb, elen -= sb->s_blocksize; epos.bh = udf_tread(sb, - udf_get_lb_pblock(sb, epos.block, 0)); + udf_get_lb_pblock(sb, &epos.block, 0)); if (!epos.bh) { brelse(oepos.bh); goto error_return; @@ -601,15 +597,15 @@ static void udf_table_free_blocks(struct super_block *sb, if (sbi->s_udfrev >= 0x0200) udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 3, 1, epos.block.logicalBlockNum, - sizeof(tag)); + sizeof(struct tag)); else udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, 2, 1, epos.block.logicalBlockNum, - sizeof(tag)); + sizeof(struct tag)); switch (iinfo->i_alloc_type) { case ICBTAG_FLAG_AD_SHORT: - sad = (short_ad *)sptr; + sad = (struct short_ad *)sptr; sad->extLength = cpu_to_le32( EXT_NEXT_EXTENT_ALLOCDECS | sb->s_blocksize); @@ -617,7 +613,7 @@ static void udf_table_free_blocks(struct super_block *sb, cpu_to_le32(epos.block.logicalBlockNum); break; case ICBTAG_FLAG_AD_LONG: - lad = (long_ad *)sptr; + lad = (struct long_ad *)sptr; lad->extLength = cpu_to_le32( EXT_NEXT_EXTENT_ALLOCDECS | sb->s_blocksize); @@ -635,7 +631,7 @@ static void udf_table_free_blocks(struct super_block *sb, /* It's possible that stealing the block emptied the extent */ if (elen) { - udf_write_aext(table, &epos, eloc, elen, 1); + udf_write_aext(table, &epos, &eloc, elen, 1); if (!epos.bh) { iinfo->i_lenAlloc += adsize; @@ -653,7 +649,6 @@ static void udf_table_free_blocks(struct super_block *sb, brelse(oepos.bh); error_return: - sb->s_dirt = 1; mutex_unlock(&sbi->s_alloc_mutex); return; } @@ -666,7 +661,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb, struct udf_sb_info *sbi = UDF_SB(sb); int alloc_count = 0; uint32_t elen, adsize; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; struct extent_position epos; int8_t etype = -1; struct udf_inode_info *iinfo; @@ -677,9 +672,9 @@ static int udf_table_prealloc_blocks(struct super_block *sb, iinfo = UDF_I(table); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(short_ad); + adsize = sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(long_ad); + adsize = sizeof(struct long_ad); else return 0; @@ -707,7 +702,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb, alloc_count = block_count; eloc.logicalBlockNum += alloc_count; elen -= (alloc_count << sb->s_blocksize_bits); - udf_write_aext(table, &epos, eloc, + udf_write_aext(table, &epos, &eloc, (etype << 30) | elen, 1); } else udf_delete_aext(table, epos, eloc, @@ -718,10 +713,8 @@ static int udf_table_prealloc_blocks(struct super_block *sb, brelse(epos.bh); - if (alloc_count && udf_add_free_space(sbi, partition, -alloc_count)) { - mark_buffer_dirty(sbi->s_lvid_bh); - sb->s_dirt = 1; - } + if (alloc_count) + udf_add_free_space(sb, partition, -alloc_count); mutex_unlock(&sbi->s_alloc_mutex); return alloc_count; } @@ -735,7 +728,7 @@ static int udf_table_new_block(struct super_block *sb, uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF; uint32_t newblock = 0, adsize; uint32_t elen, goal_elen = 0; - kernel_lb_addr eloc, uninitialized_var(goal_eloc); + struct kernel_lb_addr eloc, uninitialized_var(goal_eloc); struct extent_position epos, goal_epos; int8_t etype; struct udf_inode_info *iinfo = UDF_I(table); @@ -743,9 +736,9 @@ static int udf_table_new_block(struct super_block *sb, *err = -ENOSPC; if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(short_ad); + adsize = sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(long_ad); + adsize = sizeof(struct long_ad); else return newblock; @@ -814,46 +807,37 @@ static int udf_table_new_block(struct super_block *sb, } if (goal_elen) - udf_write_aext(table, &goal_epos, goal_eloc, goal_elen, 1); + udf_write_aext(table, &goal_epos, &goal_eloc, goal_elen, 1); else udf_delete_aext(table, goal_epos, goal_eloc, goal_elen); brelse(goal_epos.bh); - if (udf_add_free_space(sbi, partition, -1)) - mark_buffer_dirty(sbi->s_lvid_bh); + udf_add_free_space(sb, partition, -1); - sb->s_dirt = 1; mutex_unlock(&sbi->s_alloc_mutex); *err = 0; return newblock; } -inline void udf_free_blocks(struct super_block *sb, - struct inode *inode, - kernel_lb_addr bloc, uint32_t offset, - uint32_t count) +void udf_free_blocks(struct super_block *sb, struct inode *inode, + struct kernel_lb_addr *bloc, uint32_t offset, + uint32_t count) { - uint16_t partition = bloc.partitionReferenceNum; + uint16_t partition = bloc->partitionReferenceNum; struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) { - return udf_bitmap_free_blocks(sb, inode, - map->s_uspace.s_bitmap, - bloc, offset, count); + udf_bitmap_free_blocks(sb, inode, map->s_uspace.s_bitmap, + bloc, offset, count); } else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) { - return udf_table_free_blocks(sb, inode, - map->s_uspace.s_table, - bloc, offset, count); + udf_table_free_blocks(sb, inode, map->s_uspace.s_table, + bloc, offset, count); } else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) { - return udf_bitmap_free_blocks(sb, inode, - map->s_fspace.s_bitmap, - bloc, offset, count); + udf_bitmap_free_blocks(sb, inode, map->s_fspace.s_bitmap, + bloc, offset, count); } else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) { - return udf_table_free_blocks(sb, inode, - map->s_fspace.s_table, - bloc, offset, count); - } else { - return; + udf_table_free_blocks(sb, inode, map->s_fspace.s_table, + bloc, offset, count); } } diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 62dc270..2efd4d5 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -51,7 +51,7 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, uint8_t lfi; loff_t size = udf_ext0_offset(dir) + dir->i_size; struct buffer_head *tmp, *bha[16]; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t elen; sector_t offset; int i, num, ret = 0; @@ -80,13 +80,13 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, ret = -ENOENT; goto out; } - block = udf_get_lb_pblock(dir->i_sb, eloc, offset); + block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - epos.offset -= sizeof(short_ad); + epos.offset -= sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(long_ad); + epos.offset -= sizeof(struct long_ad); } else { offset = 0; } @@ -101,7 +101,7 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, if (i + offset > (elen >> dir->i_sb->s_blocksize_bits)) i = (elen >> dir->i_sb->s_blocksize_bits) - offset; for (num = 0; i > 0; i--) { - block = udf_get_lb_pblock(dir->i_sb, eloc, offset + i); + block = udf_get_lb_pblock(dir->i_sb, &eloc, offset + i); tmp = udf_tgetblk(dir->i_sb, block); if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) bha[num++] = tmp; @@ -161,9 +161,9 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, memcpy(fname, "..", flen); dt_type = DT_DIR; } else { - kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation); + struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation); - iblock = udf_get_lb_pblock(dir->i_sb, tloc, 0); + iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); dt_type = DT_UNKNOWN; } diff --git a/fs/udf/directory.c b/fs/udf/directory.c index 2820f8f..1d2c570 100644 --- a/fs/udf/directory.c +++ b/fs/udf/directory.c @@ -20,7 +20,7 @@ #if 0 static uint8_t *udf_filead_read(struct inode *dir, uint8_t *tmpad, - uint8_t ad_size, kernel_lb_addr fe_loc, + uint8_t ad_size, struct kernel_lb_addr fe_loc, int *pos, int *offset, struct buffer_head **bh, int *error) { @@ -75,7 +75,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, struct udf_fileident_bh *fibh, struct fileIdentDesc *cfi, struct extent_position *epos, - kernel_lb_addr *eloc, uint32_t *elen, + struct kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset) { struct fileIdentDesc *fi; @@ -111,7 +111,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, (EXT_RECORDED_ALLOCATED >> 30)) return NULL; - block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset); + block = udf_get_lb_pblock(dir->i_sb, eloc, *offset); (*offset)++; @@ -131,7 +131,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, if (i + *offset > (*elen >> blocksize_bits)) i = (*elen >> blocksize_bits)-*offset; for (num = 0; i > 0; i--) { - block = udf_get_lb_pblock(dir->i_sb, *eloc, + block = udf_get_lb_pblock(dir->i_sb, eloc, *offset + i); tmp = udf_tgetblk(dir->i_sb, block); if (tmp && !buffer_uptodate(tmp) && @@ -169,7 +169,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, (EXT_RECORDED_ALLOCATED >> 30)) return NULL; - block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset); + block = udf_get_lb_pblock(dir->i_sb, eloc, *offset); (*offset)++; @@ -249,9 +249,9 @@ struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, int *offset) } #if 0 -static extent_ad *udf_get_fileextent(void *buffer, int bufsize, int *offset) +static struct extent_ad *udf_get_fileextent(void *buffer, int bufsize, int *offset) { - extent_ad *ext; + struct extent_ad *ext; struct fileEntry *fe; uint8_t *ptr; @@ -274,54 +274,54 @@ static extent_ad *udf_get_fileextent(void *buffer, int bufsize, int *offset) if ((*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs))) ptr += *offset; - ext = (extent_ad *)ptr; + ext = (struct extent_ad *)ptr; - *offset = *offset + sizeof(extent_ad); + *offset = *offset + sizeof(struct extent_ad); return ext; } #endif -short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offset, +struct short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc) { - short_ad *sa; + struct short_ad *sa; if ((!ptr) || (!offset)) { printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n"); return NULL; } - if ((*offset + sizeof(short_ad)) > maxoffset) + if ((*offset + sizeof(struct short_ad)) > maxoffset) return NULL; else { - sa = (short_ad *)ptr; + sa = (struct short_ad *)ptr; if (sa->extLength == 0) return NULL; } if (inc) - *offset += sizeof(short_ad); + *offset += sizeof(struct short_ad); return sa; } -long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc) +struct long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc) { - long_ad *la; + struct long_ad *la; if ((!ptr) || (!offset)) { printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n"); return NULL; } - if ((*offset + sizeof(long_ad)) > maxoffset) + if ((*offset + sizeof(struct long_ad)) > maxoffset) return NULL; else { - la = (long_ad *)ptr; + la = (struct long_ad *)ptr; if (la->extLength == 0) return NULL; } if (inc) - *offset += sizeof(long_ad); + *offset += sizeof(struct long_ad); return la; } diff --git a/fs/udf/ecma_167.h b/fs/udf/ecma_167.h index a0974df..4792b77 100644 --- a/fs/udf/ecma_167.h +++ b/fs/udf/ecma_167.h @@ -38,10 +38,10 @@ #define _ECMA_167_H 1 /* Character set specification (ECMA 167r3 1/7.2.1) */ -typedef struct { +struct charspec { uint8_t charSetType; uint8_t charSetInfo[63]; -} __attribute__ ((packed)) charspec; +} __attribute__ ((packed)); /* Character Set Type (ECMA 167r3 1/7.2.1.1) */ #define CHARSPEC_TYPE_CS0 0x00 /* (1/7.2.2) */ @@ -57,7 +57,7 @@ typedef struct { typedef uint8_t dstring; /* Timestamp (ECMA 167r3 1/7.3) */ -typedef struct { +struct timestamp { __le16 typeAndTimezone; __le16 year; uint8_t month; @@ -68,7 +68,7 @@ typedef struct { uint8_t centiseconds; uint8_t hundredsOfMicroseconds; uint8_t microseconds; -} __attribute__ ((packed)) timestamp; +} __attribute__ ((packed)); /* Type and Time Zone (ECMA 167r3 1/7.3.1) */ #define TIMESTAMP_TYPE_MASK 0xF000 @@ -78,11 +78,11 @@ typedef struct { #define TIMESTAMP_TIMEZONE_MASK 0x0FFF /* Entity identifier (ECMA 167r3 1/7.4) */ -typedef struct { +struct regid { uint8_t flags; uint8_t ident[23]; uint8_t identSuffix[8]; -} __attribute__ ((packed)) regid; +} __attribute__ ((packed)); /* Flags (ECMA 167r3 1/7.4.1) */ #define ENTITYID_FLAGS_DIRTY 0x00 @@ -126,38 +126,38 @@ struct terminatingExtendedAreaDesc { /* Boot Descriptor (ECMA 167r3 2/9.4) */ struct bootDesc { - uint8_t structType; - uint8_t stdIdent[VSD_STD_ID_LEN]; - uint8_t structVersion; - uint8_t reserved1; - regid archType; - regid bootIdent; - __le32 bootExtLocation; - __le32 bootExtLength; - __le64 loadAddress; - __le64 startAddress; - timestamp descCreationDateAndTime; - __le16 flags; - uint8_t reserved2[32]; - uint8_t bootUse[1906]; + uint8_t structType; + uint8_t stdIdent[VSD_STD_ID_LEN]; + uint8_t structVersion; + uint8_t reserved1; + struct regid archType; + struct regid bootIdent; + __le32 bootExtLocation; + __le32 bootExtLength; + __le64 loadAddress; + __le64 startAddress; + struct timestamp descCreationDateAndTime; + __le16 flags; + uint8_t reserved2[32]; + uint8_t bootUse[1906]; } __attribute__ ((packed)); /* Flags (ECMA 167r3 2/9.4.12) */ #define BOOT_FLAGS_ERASE 0x01 /* Extent Descriptor (ECMA 167r3 3/7.1) */ -typedef struct { +struct extent_ad { __le32 extLength; __le32 extLocation; -} __attribute__ ((packed)) extent_ad; +} __attribute__ ((packed)); -typedef struct { +struct kernel_extent_ad { uint32_t extLength; uint32_t extLocation; -} kernel_extent_ad; +}; /* Descriptor Tag (ECMA 167r3 3/7.2) */ -typedef struct { +struct tag { __le16 tagIdent; __le16 descVersion; uint8_t tagChecksum; @@ -166,7 +166,7 @@ typedef struct { __le16 descCRC; __le16 descCRCLength; __le32 tagLocation; -} __attribute__ ((packed)) tag; +} __attribute__ ((packed)); /* Tag Identifier (ECMA 167r3 3/7.2.1) */ #define TAG_IDENT_PVD 0x0001 @@ -190,28 +190,28 @@ struct NSRDesc { /* Primary Volume Descriptor (ECMA 167r3 3/10.1) */ struct primaryVolDesc { - tag descTag; - __le32 volDescSeqNum; - __le32 primaryVolDescNum; - dstring volIdent[32]; - __le16 volSeqNum; - __le16 maxVolSeqNum; - __le16 interchangeLvl; - __le16 maxInterchangeLvl; - __le32 charSetList; - __le32 maxCharSetList; - dstring volSetIdent[128]; - charspec descCharSet; - charspec explanatoryCharSet; - extent_ad volAbstract; - extent_ad volCopyright; - regid appIdent; - timestamp recordingDateAndTime; - regid impIdent; - uint8_t impUse[64]; - __le32 predecessorVolDescSeqLocation; - __le16 flags; - uint8_t reserved[22]; + struct tag descTag; + __le32 volDescSeqNum; + __le32 primaryVolDescNum; + dstring volIdent[32]; + __le16 volSeqNum; + __le16 maxVolSeqNum; + __le16 interchangeLvl; + __le16 maxInterchangeLvl; + __le32 charSetList; + __le32 maxCharSetList; + dstring volSetIdent[128]; + struct charspec descCharSet; + struct charspec explanatoryCharSet; + struct extent_ad volAbstract; + struct extent_ad volCopyright; + struct regid appIdent; + struct timestamp recordingDateAndTime; + struct regid impIdent; + uint8_t impUse[64]; + __le32 predecessorVolDescSeqLocation; + __le16 flags; + uint8_t reserved[22]; } __attribute__ ((packed)); /* Flags (ECMA 167r3 3/10.1.21) */ @@ -219,40 +219,40 @@ struct primaryVolDesc { /* Anchor Volume Descriptor Pointer (ECMA 167r3 3/10.2) */ struct anchorVolDescPtr { - tag descTag; - extent_ad mainVolDescSeqExt; - extent_ad reserveVolDescSeqExt; - uint8_t reserved[480]; + struct tag descTag; + struct extent_ad mainVolDescSeqExt; + struct extent_ad reserveVolDescSeqExt; + uint8_t reserved[480]; } __attribute__ ((packed)); /* Volume Descriptor Pointer (ECMA 167r3 3/10.3) */ struct volDescPtr { - tag descTag; - __le32 volDescSeqNum; - extent_ad nextVolDescSeqExt; - uint8_t reserved[484]; + struct tag descTag; + __le32 volDescSeqNum; + struct extent_ad nextVolDescSeqExt; + uint8_t reserved[484]; } __attribute__ ((packed)); /* Implementation Use Volume Descriptor (ECMA 167r3 3/10.4) */ struct impUseVolDesc { - tag descTag; + struct tag descTag; __le32 volDescSeqNum; - regid impIdent; + struct regid impIdent; uint8_t impUse[460]; } __attribute__ ((packed)); /* Partition Descriptor (ECMA 167r3 3/10.5) */ struct partitionDesc { - tag descTag; + struct tag descTag; __le32 volDescSeqNum; __le16 partitionFlags; __le16 partitionNumber; - regid partitionContents; + struct regid partitionContents; uint8_t partitionContentsUse[128]; __le32 accessType; __le32 partitionStartingLocation; __le32 partitionLength; - regid impIdent; + struct regid impIdent; uint8_t impUse[128]; uint8_t reserved[156]; } __attribute__ ((packed)); @@ -278,19 +278,19 @@ struct partitionDesc { /* Logical Volume Descriptor (ECMA 167r3 3/10.6) */ struct logicalVolDesc { - tag descTag; - __le32 volDescSeqNum; - charspec descCharSet; - dstring logicalVolIdent[128]; - __le32 logicalBlockSize; - regid domainIdent; - uint8_t logicalVolContentsUse[16]; - __le32 mapTableLength; - __le32 numPartitionMaps; - regid impIdent; - uint8_t impUse[128]; - extent_ad integritySeqExt; - uint8_t partitionMaps[0]; + struct tag descTag; + __le32 volDescSeqNum; + struct charspec descCharSet; + dstring logicalVolIdent[128]; + __le32 logicalBlockSize; + struct regid domainIdent; + uint8_t logicalVolContentsUse[16]; + __le32 mapTableLength; + __le32 numPartitionMaps; + struct regid impIdent; + uint8_t impUse[128]; + struct extent_ad integritySeqExt; + uint8_t partitionMaps[0]; } __attribute__ ((packed)); /* Generic Partition Map (ECMA 167r3 3/10.7.1) */ @@ -322,30 +322,30 @@ struct genericPartitionMap2 { /* Unallocated Space Descriptor (ECMA 167r3 3/10.8) */ struct unallocSpaceDesc { - tag descTag; - __le32 volDescSeqNum; - __le32 numAllocDescs; - extent_ad allocDescs[0]; + struct tag descTag; + __le32 volDescSeqNum; + __le32 numAllocDescs; + struct extent_ad allocDescs[0]; } __attribute__ ((packed)); /* Terminating Descriptor (ECMA 167r3 3/10.9) */ struct terminatingDesc { - tag descTag; + struct tag descTag; uint8_t reserved[496]; } __attribute__ ((packed)); /* Logical Volume Integrity Descriptor (ECMA 167r3 3/10.10) */ struct logicalVolIntegrityDesc { - tag descTag; - timestamp recordingDateAndTime; - __le32 integrityType; - extent_ad nextIntegrityExt; - uint8_t logicalVolContentsUse[32]; - __le32 numOfPartitions; - __le32 lengthOfImpUse; - __le32 freeSpaceTable[0]; - __le32 sizeTable[0]; - uint8_t impUse[0]; + struct tag descTag; + struct timestamp recordingDateAndTime; + __le32 integrityType; + struct extent_ad nextIntegrityExt; + uint8_t logicalVolContentsUse[32]; + __le32 numOfPartitions; + __le32 lengthOfImpUse; + __le32 freeSpaceTable[0]; + __le32 sizeTable[0]; + uint8_t impUse[0]; } __attribute__ ((packed)); /* Integrity Type (ECMA 167r3 3/10.10.3) */ @@ -353,50 +353,50 @@ struct logicalVolIntegrityDesc { #define LVID_INTEGRITY_TYPE_CLOSE 0x00000001 /* Recorded Address (ECMA 167r3 4/7.1) */ -typedef struct { +struct lb_addr { __le32 logicalBlockNum; __le16 partitionReferenceNum; -} __attribute__ ((packed)) lb_addr; +} __attribute__ ((packed)); /* ... and its in-core analog */ -typedef struct { +struct kernel_lb_addr { uint32_t logicalBlockNum; uint16_t partitionReferenceNum; -} kernel_lb_addr; +}; /* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ -typedef struct { +struct short_ad { __le32 extLength; __le32 extPosition; -} __attribute__ ((packed)) short_ad; +} __attribute__ ((packed)); /* Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */ -typedef struct { +struct long_ad { __le32 extLength; - lb_addr extLocation; + struct lb_addr extLocation; uint8_t impUse[6]; -} __attribute__ ((packed)) long_ad; +} __attribute__ ((packed)); -typedef struct { - uint32_t extLength; - kernel_lb_addr extLocation; - uint8_t impUse[6]; -} kernel_long_ad; +struct kernel_long_ad { + uint32_t extLength; + struct kernel_lb_addr extLocation; + uint8_t impUse[6]; +}; /* Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */ -typedef struct { +struct ext_ad { __le32 extLength; __le32 recordedLength; __le32 informationLength; - lb_addr extLocation; -} __attribute__ ((packed)) ext_ad; + struct lb_addr extLocation; +} __attribute__ ((packed)); -typedef struct { - uint32_t extLength; - uint32_t recordedLength; - uint32_t informationLength; - kernel_lb_addr extLocation; -} kernel_ext_ad; +struct kernel_ext_ad { + uint32_t extLength; + uint32_t recordedLength; + uint32_t informationLength; + struct kernel_lb_addr extLocation; +}; /* Descriptor Tag (ECMA 167r3 4/7.2 - See 3/7.2) */ @@ -415,44 +415,44 @@ typedef struct { /* File Set Descriptor (ECMA 167r3 4/14.1) */ struct fileSetDesc { - tag descTag; - timestamp recordingDateAndTime; - __le16 interchangeLvl; - __le16 maxInterchangeLvl; - __le32 charSetList; - __le32 maxCharSetList; - __le32 fileSetNum; - __le32 fileSetDescNum; - charspec logicalVolIdentCharSet; - dstring logicalVolIdent[128]; - charspec fileSetCharSet; - dstring fileSetIdent[32]; - dstring copyrightFileIdent[32]; - dstring abstractFileIdent[32]; - long_ad rootDirectoryICB; - regid domainIdent; - long_ad nextExt; - long_ad streamDirectoryICB; - uint8_t reserved[32]; + struct tag descTag; + struct timestamp recordingDateAndTime; + __le16 interchangeLvl; + __le16 maxInterchangeLvl; + __le32 charSetList; + __le32 maxCharSetList; + __le32 fileSetNum; + __le32 fileSetDescNum; + struct charspec logicalVolIdentCharSet; + dstring logicalVolIdent[128]; + struct charspec fileSetCharSet; + dstring fileSetIdent[32]; + dstring copyrightFileIdent[32]; + dstring abstractFileIdent[32]; + struct long_ad rootDirectoryICB; + struct regid domainIdent; + struct long_ad nextExt; + struct long_ad streamDirectoryICB; + uint8_t reserved[32]; } __attribute__ ((packed)); /* Partition Header Descriptor (ECMA 167r3 4/14.3) */ struct partitionHeaderDesc { - short_ad unallocSpaceTable; - short_ad unallocSpaceBitmap; - short_ad partitionIntegrityTable; - short_ad freedSpaceTable; - short_ad freedSpaceBitmap; + struct short_ad unallocSpaceTable; + struct short_ad unallocSpaceBitmap; + struct short_ad partitionIntegrityTable; + struct short_ad freedSpaceTable; + struct short_ad freedSpaceBitmap; uint8_t reserved[88]; } __attribute__ ((packed)); /* File Identifier Descriptor (ECMA 167r3 4/14.4) */ struct fileIdentDesc { - tag descTag; + struct tag descTag; __le16 fileVersionNum; uint8_t fileCharacteristics; uint8_t lengthFileIdent; - long_ad icb; + struct long_ad icb; __le16 lengthOfImpUse; uint8_t impUse[0]; uint8_t fileIdent[0]; @@ -468,22 +468,22 @@ struct fileIdentDesc { /* Allocation Ext Descriptor (ECMA 167r3 4/14.5) */ struct allocExtDesc { - tag descTag; + struct tag descTag; __le32 previousAllocExtLocation; __le32 lengthAllocDescs; } __attribute__ ((packed)); /* ICB Tag (ECMA 167r3 4/14.6) */ -typedef struct { +struct icbtag { __le32 priorRecordedNumDirectEntries; __le16 strategyType; __le16 strategyParameter; __le16 numEntries; uint8_t reserved; uint8_t fileType; - lb_addr parentICBLocation; + struct lb_addr parentICBLocation; __le16 flags; -} __attribute__ ((packed)) icbtag; +} __attribute__ ((packed)); /* Strategy Type (ECMA 167r3 4/14.6.2) */ #define ICBTAG_STRATEGY_TYPE_UNDEF 0x0000 @@ -528,41 +528,41 @@ typedef struct { /* Indirect Entry (ECMA 167r3 4/14.7) */ struct indirectEntry { - tag descTag; - icbtag icbTag; - long_ad indirectICB; + struct tag descTag; + struct icbtag icbTag; + struct long_ad indirectICB; } __attribute__ ((packed)); /* Terminal Entry (ECMA 167r3 4/14.8) */ struct terminalEntry { - tag descTag; - icbtag icbTag; + struct tag descTag; + struct icbtag icbTag; } __attribute__ ((packed)); /* File Entry (ECMA 167r3 4/14.9) */ struct fileEntry { - tag descTag; - icbtag icbTag; - __le32 uid; - __le32 gid; - __le32 permissions; - __le16 fileLinkCount; - uint8_t recordFormat; - uint8_t recordDisplayAttr; - __le32 recordLength; - __le64 informationLength; - __le64 logicalBlocksRecorded; - timestamp accessTime; - timestamp modificationTime; - timestamp attrTime; - __le32 checkpoint; - long_ad extendedAttrICB; - regid impIdent; - __le64 uniqueID; - __le32 lengthExtendedAttr; - __le32 lengthAllocDescs; - uint8_t extendedAttr[0]; - uint8_t allocDescs[0]; + struct tag descTag; + struct icbtag icbTag; + __le32 uid; + __le32 gid; + __le32 permissions; + __le16 fileLinkCount; + uint8_t recordFormat; + uint8_t recordDisplayAttr; + __le32 recordLength; + __le64 informationLength; + __le64 logicalBlocksRecorded; + struct timestamp accessTime; + struct timestamp modificationTime; + struct timestamp attrTime; + __le32 checkpoint; + struct long_ad extendedAttrICB; + struct regid impIdent; + __le64 uniqueID; + __le32 lengthExtendedAttr; + __le32 lengthAllocDescs; + uint8_t extendedAttr[0]; + uint8_t allocDescs[0]; } __attribute__ ((packed)); /* Permissions (ECMA 167r3 4/14.9.5) */ @@ -604,7 +604,7 @@ struct fileEntry { /* Extended Attribute Header Descriptor (ECMA 167r3 4/14.10.1) */ struct extendedAttrHeaderDesc { - tag descTag; + struct tag descTag; __le32 impAttrLocation; __le32 appAttrLocation; } __attribute__ ((packed)); @@ -687,7 +687,7 @@ struct impUseExtAttr { uint8_t reserved[3]; __le32 attrLength; __le32 impUseLength; - regid impIdent; + struct regid impIdent; uint8_t impUse[0]; } __attribute__ ((packed)); @@ -698,7 +698,7 @@ struct appUseExtAttr { uint8_t reserved[3]; __le32 attrLength; __le32 appUseLength; - regid appIdent; + struct regid appIdent; uint8_t appUse[0]; } __attribute__ ((packed)); @@ -712,15 +712,15 @@ struct appUseExtAttr { /* Unallocated Space Entry (ECMA 167r3 4/14.11) */ struct unallocSpaceEntry { - tag descTag; - icbtag icbTag; + struct tag descTag; + struct icbtag icbTag; __le32 lengthAllocDescs; uint8_t allocDescs[0]; } __attribute__ ((packed)); /* Space Bitmap Descriptor (ECMA 167r3 4/14.12) */ struct spaceBitmapDesc { - tag descTag; + struct tag descTag; __le32 numOfBits; __le32 numOfBytes; uint8_t bitmap[0]; @@ -728,13 +728,13 @@ struct spaceBitmapDesc { /* Partition Integrity Entry (ECMA 167r3 4/14.13) */ struct partitionIntegrityEntry { - tag descTag; - icbtag icbTag; - timestamp recordingDateAndTime; - uint8_t integrityType; - uint8_t reserved[175]; - regid impIdent; - uint8_t impUse[256]; + struct tag descTag; + struct icbtag icbTag; + struct timestamp recordingDateAndTime; + uint8_t integrityType; + uint8_t reserved[175]; + struct regid impIdent; + uint8_t impUse[256]; } __attribute__ ((packed)); /* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ @@ -765,32 +765,32 @@ struct pathComponent { /* File Entry (ECMA 167r3 4/14.17) */ struct extendedFileEntry { - tag descTag; - icbtag icbTag; - __le32 uid; - __le32 gid; - __le32 permissions; - __le16 fileLinkCount; - uint8_t recordFormat; - uint8_t recordDisplayAttr; - __le32 recordLength; - __le64 informationLength; - __le64 objectSize; - __le64 logicalBlocksRecorded; - timestamp accessTime; - timestamp modificationTime; - timestamp createTime; - timestamp attrTime; - __le32 checkpoint; - __le32 reserved; - long_ad extendedAttrICB; - long_ad streamDirectoryICB; - regid impIdent; - __le64 uniqueID; - __le32 lengthExtendedAttr; - __le32 lengthAllocDescs; - uint8_t extendedAttr[0]; - uint8_t allocDescs[0]; + struct tag descTag; + struct icbtag icbTag; + __le32 uid; + __le32 gid; + __le32 permissions; + __le16 fileLinkCount; + uint8_t recordFormat; + uint8_t recordDisplayAttr; + __le32 recordLength; + __le64 informationLength; + __le64 objectSize; + __le64 logicalBlocksRecorded; + struct timestamp accessTime; + struct timestamp modificationTime; + struct timestamp createTime; + struct timestamp attrTime; + __le32 checkpoint; + __le32 reserved; + struct long_ad extendedAttrICB; + struct long_ad streamDirectoryICB; + struct regid impIdent; + __le64 uniqueID; + __le32 lengthExtendedAttr; + __le32 lengthAllocDescs; + uint8_t extendedAttr[0]; + uint8_t allocDescs[0]; } __attribute__ ((packed)); #endif /* _ECMA_167_H */ diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 47dbe56..c10fa39 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c @@ -49,12 +49,11 @@ void udf_free_inode(struct inode *inode) le32_add_cpu(&lvidiu->numDirs, -1); else le32_add_cpu(&lvidiu->numFiles, -1); - - mark_buffer_dirty(sbi->s_lvid_bh); + udf_updated_lvid(sb); } mutex_unlock(&sbi->s_alloc_mutex); - udf_free_blocks(sb, NULL, UDF_I(inode)->i_location, 0, 1); + udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1); } struct inode *udf_new_inode(struct inode *dir, int mode, int *err) @@ -122,7 +121,7 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) if (!(++uniqueID & 0x00000000FFFFFFFFUL)) uniqueID += 16; lvhd->uniqueID = cpu_to_le64(uniqueID); - mark_buffer_dirty(sbi->s_lvid_bh); + udf_updated_lvid(sb); } mutex_unlock(&sbi->s_alloc_mutex); inode->i_mode = mode; @@ -138,7 +137,7 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) iinfo->i_location.logicalBlockNum = block; iinfo->i_location.partitionReferenceNum = dinfo->i_location.partitionReferenceNum; - inode->i_ino = udf_get_lb_pblock(sb, iinfo->i_location, 0); + inode->i_ino = udf_get_lb_pblock(sb, &iinfo->i_location, 0); inode->i_blocks = 0; iinfo->i_lenEAttr = 0; iinfo->i_lenAlloc = 0; diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 30ebde4..e7533f7 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -55,15 +55,15 @@ static int udf_alloc_i_data(struct inode *inode, size_t size); static struct buffer_head *inode_getblk(struct inode *, sector_t, int *, sector_t *, int *); static int8_t udf_insert_aext(struct inode *, struct extent_position, - kernel_lb_addr, uint32_t); + struct kernel_lb_addr, uint32_t); static void udf_split_extents(struct inode *, int *, int, int, - kernel_long_ad[EXTENT_MERGE_SIZE], int *); + struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); static void udf_prealloc_extents(struct inode *, int, int, - kernel_long_ad[EXTENT_MERGE_SIZE], int *); + struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); static void udf_merge_extents(struct inode *, - kernel_long_ad[EXTENT_MERGE_SIZE], int *); + struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); static void udf_update_extents(struct inode *, - kernel_long_ad[EXTENT_MERGE_SIZE], int, int, + struct kernel_long_ad[EXTENT_MERGE_SIZE], int, int, struct extent_position *); static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); @@ -200,7 +200,7 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, { int newblock; struct buffer_head *dbh = NULL; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t elen; uint8_t alloctype; struct extent_position epos; @@ -281,7 +281,7 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, epos.bh = NULL; epos.block = iinfo->i_location; epos.offset = udf_file_entry_alloc_offset(inode); - udf_add_aext(inode, &epos, eloc, elen, 0); + udf_add_aext(inode, &epos, &eloc, elen, 0); /* UniqueID stuff */ brelse(epos.bh); @@ -359,12 +359,12 @@ static struct buffer_head *udf_getblk(struct inode *inode, long block, /* Extend the file by 'blocks' blocks, return the number of extents added */ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, - kernel_long_ad *last_ext, sector_t blocks) + struct kernel_long_ad *last_ext, sector_t blocks) { sector_t add; int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); struct super_block *sb = inode->i_sb; - kernel_lb_addr prealloc_loc = {}; + struct kernel_lb_addr prealloc_loc = {}; int prealloc_len = 0; struct udf_inode_info *iinfo; @@ -411,11 +411,11 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, } if (fake) { - udf_add_aext(inode, last_pos, last_ext->extLocation, + udf_add_aext(inode, last_pos, &last_ext->extLocation, last_ext->extLength, 1); count++; } else - udf_write_aext(inode, last_pos, last_ext->extLocation, + udf_write_aext(inode, last_pos, &last_ext->extLocation, last_ext->extLength, 1); /* Managed to do everything necessary? */ @@ -432,7 +432,7 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, /* Create enough extents to cover the whole hole */ while (blocks > add) { blocks -= add; - if (udf_add_aext(inode, last_pos, last_ext->extLocation, + if (udf_add_aext(inode, last_pos, &last_ext->extLocation, last_ext->extLength, 1) == -1) return -1; count++; @@ -440,7 +440,7 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, if (blocks) { last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | (blocks << sb->s_blocksize_bits); - if (udf_add_aext(inode, last_pos, last_ext->extLocation, + if (udf_add_aext(inode, last_pos, &last_ext->extLocation, last_ext->extLength, 1) == -1) return -1; count++; @@ -449,7 +449,7 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, out: /* Do we have some preallocated blocks saved? */ if (prealloc_len) { - if (udf_add_aext(inode, last_pos, prealloc_loc, + if (udf_add_aext(inode, last_pos, &prealloc_loc, prealloc_len, 1) == -1) return -1; last_ext->extLocation = prealloc_loc; @@ -459,9 +459,9 @@ out: /* last_pos should point to the last written extent... */ if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - last_pos->offset -= sizeof(short_ad); + last_pos->offset -= sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - last_pos->offset -= sizeof(long_ad); + last_pos->offset -= sizeof(struct long_ad); else return -1; @@ -473,11 +473,11 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, { static sector_t last_block; struct buffer_head *result = NULL; - kernel_long_ad laarr[EXTENT_MERGE_SIZE]; + struct kernel_long_ad laarr[EXTENT_MERGE_SIZE]; struct extent_position prev_epos, cur_epos, next_epos; int count = 0, startnum = 0, endnum = 0; uint32_t elen = 0, tmpelen; - kernel_lb_addr eloc, tmpeloc; + struct kernel_lb_addr eloc, tmpeloc; int c = 1; loff_t lbcount = 0, b_off = 0; uint32_t newblocknum, newblock; @@ -550,12 +550,12 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, elen = EXT_RECORDED_ALLOCATED | ((elen + inode->i_sb->s_blocksize - 1) & ~(inode->i_sb->s_blocksize - 1)); - etype = udf_write_aext(inode, &cur_epos, eloc, elen, 1); + etype = udf_write_aext(inode, &cur_epos, &eloc, elen, 1); } brelse(prev_epos.bh); brelse(cur_epos.bh); brelse(next_epos.bh); - newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset); + newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset); *phys = newblock; return NULL; } @@ -572,7 +572,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, } else { /* Create a fake extent when there's not one */ memset(&laarr[0].extLocation, 0x00, - sizeof(kernel_lb_addr)); + sizeof(struct kernel_lb_addr)); laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; /* Will udf_extend_file() create real extent from a fake one? */ @@ -602,7 +602,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | inode->i_sb->s_blocksize; memset(&laarr[c].extLocation, 0x00, - sizeof(kernel_lb_addr)); + sizeof(struct kernel_lb_addr)); count++; endnum++; } @@ -699,7 +699,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, static void udf_split_extents(struct inode *inode, int *c, int offset, int newblocknum, - kernel_long_ad laarr[EXTENT_MERGE_SIZE], + struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum) { unsigned long blocksize = inode->i_sb->s_blocksize; @@ -726,7 +726,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, if (offset) { if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { udf_free_blocks(inode->i_sb, inode, - laarr[curr].extLocation, + &laarr[curr].extLocation, 0, offset); laarr[curr].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | @@ -763,7 +763,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, } static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, - kernel_long_ad laarr[EXTENT_MERGE_SIZE], + struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum) { int start, length = 0, currlength = 0, i; @@ -817,7 +817,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, inode->i_sb->s_blocksize_bits); else { memmove(&laarr[c + 2], &laarr[c + 1], - sizeof(long_ad) * (*endnum - (c + 1))); + sizeof(struct long_ad) * (*endnum - (c + 1))); (*endnum)++; laarr[c + 1].extLocation.logicalBlockNum = next; laarr[c + 1].extLocation.partitionReferenceNum = @@ -846,7 +846,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, if (*endnum > (i + 1)) memmove(&laarr[i], &laarr[i + 1], - sizeof(long_ad) * + sizeof(struct long_ad) * (*endnum - (i + 1))); i--; (*endnum)--; @@ -859,7 +859,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, } static void udf_merge_extents(struct inode *inode, - kernel_long_ad laarr[EXTENT_MERGE_SIZE], + struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], int *endnum) { int i; @@ -867,8 +867,8 @@ static void udf_merge_extents(struct inode *inode, unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; for (i = 0; i < (*endnum - 1); i++) { - kernel_long_ad *li /*l[i]*/ = &laarr[i]; - kernel_long_ad *lip1 /*l[i plus 1]*/ = &laarr[i + 1]; + struct kernel_long_ad *li /*l[i]*/ = &laarr[i]; + struct kernel_long_ad *lip1 /*l[i plus 1]*/ = &laarr[i + 1]; if (((li->extLength >> 30) == (lip1->extLength >> 30)) && (((li->extLength >> 30) == @@ -902,7 +902,7 @@ static void udf_merge_extents(struct inode *inode, blocksize - 1) & ~(blocksize - 1)); if (*endnum > (i + 2)) memmove(&laarr[i + 1], &laarr[i + 2], - sizeof(long_ad) * + sizeof(struct long_ad) * (*endnum - (i + 2))); i--; (*endnum)--; @@ -911,7 +911,7 @@ static void udf_merge_extents(struct inode *inode, (EXT_NOT_RECORDED_ALLOCATED >> 30)) && ((lip1->extLength >> 30) == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))) { - udf_free_blocks(inode->i_sb, inode, li->extLocation, 0, + udf_free_blocks(inode->i_sb, inode, &li->extLocation, 0, ((li->extLength & UDF_EXTENT_LENGTH_MASK) + blocksize - 1) >> blocksize_bits); @@ -937,7 +937,7 @@ static void udf_merge_extents(struct inode *inode, blocksize - 1) & ~(blocksize - 1)); if (*endnum > (i + 2)) memmove(&laarr[i + 1], &laarr[i + 2], - sizeof(long_ad) * + sizeof(struct long_ad) * (*endnum - (i + 2))); i--; (*endnum)--; @@ -945,7 +945,7 @@ static void udf_merge_extents(struct inode *inode, } else if ((li->extLength >> 30) == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { udf_free_blocks(inode->i_sb, inode, - li->extLocation, 0, + &li->extLocation, 0, ((li->extLength & UDF_EXTENT_LENGTH_MASK) + blocksize - 1) >> blocksize_bits); @@ -959,12 +959,12 @@ static void udf_merge_extents(struct inode *inode, } static void udf_update_extents(struct inode *inode, - kernel_long_ad laarr[EXTENT_MERGE_SIZE], + struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], int startnum, int endnum, struct extent_position *epos) { int start = 0, i; - kernel_lb_addr tmploc; + struct kernel_lb_addr tmploc; uint32_t tmplen; if (startnum > endnum) { @@ -983,7 +983,7 @@ static void udf_update_extents(struct inode *inode, for (i = start; i < endnum; i++) { udf_next_aext(inode, epos, &tmploc, &tmplen, 0); - udf_write_aext(inode, epos, laarr[i].extLocation, + udf_write_aext(inode, epos, &laarr[i].extLocation, laarr[i].extLength, 1); } } @@ -1076,7 +1076,7 @@ static void __udf_read_inode(struct inode *inode) * i_nlink = 1 * i_op = NULL; */ - bh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 0, &ident); + bh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 0, &ident); if (!bh) { printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n", inode->i_ino); @@ -1098,24 +1098,24 @@ static void __udf_read_inode(struct inode *inode) if (fe->icbTag.strategyType == cpu_to_le16(4096)) { struct buffer_head *ibh; - ibh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 1, + ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1, &ident); if (ident == TAG_IDENT_IE && ibh) { struct buffer_head *nbh = NULL; - kernel_lb_addr loc; + struct kernel_lb_addr loc; struct indirectEntry *ie; ie = (struct indirectEntry *)ibh->b_data; loc = lelb_to_cpu(ie->indirectICB.extLocation); if (ie->indirectICB.extLength && - (nbh = udf_read_ptagged(inode->i_sb, loc, 0, + (nbh = udf_read_ptagged(inode->i_sb, &loc, 0, &ident))) { if (ident == TAG_IDENT_FE || ident == TAG_IDENT_EFE) { memcpy(&iinfo->i_location, &loc, - sizeof(kernel_lb_addr)); + sizeof(struct kernel_lb_addr)); brelse(bh); brelse(ibh); brelse(nbh); @@ -1222,8 +1222,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) inode->i_size = le64_to_cpu(fe->informationLength); iinfo->i_lenExtents = inode->i_size; - inode->i_mode = udf_convert_permissions(fe); - inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask; + if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY && + sbi->s_fmode != UDF_INVALID_MODE) + inode->i_mode = sbi->s_fmode; + else if (fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY && + sbi->s_dmode != UDF_INVALID_MODE) + inode->i_mode = sbi->s_dmode; + else + inode->i_mode = udf_convert_permissions(fe); + inode->i_mode &= ~sbi->s_umask; if (iinfo->i_efe == 0) { inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << @@ -1396,7 +1403,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) bh = udf_tread(inode->i_sb, udf_get_lb_pblock(inode->i_sb, - iinfo->i_location, 0)); + &iinfo->i_location, 0)); if (!bh) { udf_debug("bread failure\n"); return -EIO; @@ -1416,13 +1423,13 @@ static int udf_update_inode(struct inode *inode, int do_sync) iinfo->i_ext.i_data, inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)); crclen = sizeof(struct unallocSpaceEntry) + - iinfo->i_lenAlloc - sizeof(tag); + iinfo->i_lenAlloc - sizeof(struct tag); use->descTag.tagLocation = cpu_to_le32( iinfo->i_location. logicalBlockNum); use->descTag.descCRCLength = cpu_to_le16(crclen); use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use + - sizeof(tag), + sizeof(struct tag), crclen)); use->descTag.tagChecksum = udf_tag_checksum(&use->descTag); @@ -1459,23 +1466,23 @@ static int udf_update_inode(struct inode *inode, int do_sync) fe->informationLength = cpu_to_le64(inode->i_size); if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { - regid *eid; + struct regid *eid; struct deviceSpec *dsea = (struct deviceSpec *)udf_get_extendedattr(inode, 12, 1); if (!dsea) { dsea = (struct deviceSpec *) udf_add_extendedattr(inode, sizeof(struct deviceSpec) + - sizeof(regid), 12, 0x3); + sizeof(struct regid), 12, 0x3); dsea->attrType = cpu_to_le32(12); dsea->attrSubtype = 1; dsea->attrLength = cpu_to_le32( sizeof(struct deviceSpec) + - sizeof(regid)); - dsea->impUseLength = cpu_to_le32(sizeof(regid)); + sizeof(struct regid)); + dsea->impUseLength = cpu_to_le32(sizeof(struct regid)); } - eid = (regid *)dsea->impUse; - memset(eid, 0, sizeof(regid)); + eid = (struct regid *)dsea->impUse; + memset(eid, 0, sizeof(struct regid)); strcpy(eid->ident, UDF_ID_DEVELOPER); eid->identSuffix[0] = UDF_OS_CLASS_UNIX; eid->identSuffix[1] = UDF_OS_ID_LINUX; @@ -1494,7 +1501,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime); udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime); udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime); - memset(&(fe->impIdent), 0, sizeof(regid)); + memset(&(fe->impIdent), 0, sizeof(struct regid)); strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; @@ -1533,7 +1540,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime); udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime); - memset(&(efe->impIdent), 0, sizeof(regid)); + memset(&(efe->impIdent), 0, sizeof(struct regid)); strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; @@ -1584,9 +1591,9 @@ static int udf_update_inode(struct inode *inode, int do_sync) fe->descTag.tagLocation = cpu_to_le32( iinfo->i_location.logicalBlockNum); crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - - sizeof(tag); + sizeof(struct tag); fe->descTag.descCRCLength = cpu_to_le16(crclen); - fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(tag), + fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag), crclen)); fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag); @@ -1606,7 +1613,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) return err; } -struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino) +struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino) { unsigned long block = udf_get_lb_pblock(sb, ino, 0); struct inode *inode = iget_locked(sb, block); @@ -1615,7 +1622,7 @@ struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino) return NULL; if (inode->i_state & I_NEW) { - memcpy(&UDF_I(inode)->i_location, &ino, sizeof(kernel_lb_addr)); + memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr)); __udf_read_inode(inode); unlock_new_inode(inode); } @@ -1623,10 +1630,10 @@ struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino) if (is_bad_inode(inode)) goto out_iput; - if (ino.logicalBlockNum >= UDF_SB(sb)-> - s_partmaps[ino.partitionReferenceNum].s_partition_len) { + if (ino->logicalBlockNum >= UDF_SB(sb)-> + s_partmaps[ino->partitionReferenceNum].s_partition_len) { udf_debug("block=%d, partition=%d out of range\n", - ino.logicalBlockNum, ino.partitionReferenceNum); + ino->logicalBlockNum, ino->partitionReferenceNum); make_bad_inode(inode); goto out_iput; } @@ -1639,11 +1646,11 @@ struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino) } int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, - kernel_lb_addr eloc, uint32_t elen, int inc) + struct kernel_lb_addr *eloc, uint32_t elen, int inc) { int adsize; - short_ad *sad = NULL; - long_ad *lad = NULL; + struct short_ad *sad = NULL; + struct long_ad *lad = NULL; struct allocExtDesc *aed; int8_t etype; uint8_t *ptr; @@ -1657,9 +1664,9 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, ptr = epos->bh->b_data + epos->offset; if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(short_ad); + adsize = sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(long_ad); + adsize = sizeof(struct long_ad); else return -1; @@ -1667,7 +1674,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, char *sptr, *dptr; struct buffer_head *nbh; int err, loffset; - kernel_lb_addr obloc = epos->block; + struct kernel_lb_addr obloc = epos->block; epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL, obloc.partitionReferenceNum, @@ -1675,7 +1682,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, if (!epos->block.logicalBlockNum) return -1; nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb, - epos->block, + &epos->block, 0)); if (!nbh) return -1; @@ -1712,20 +1719,20 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, } if (UDF_SB(inode->i_sb)->s_udfrev >= 0x0200) udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1, - epos->block.logicalBlockNum, sizeof(tag)); + epos->block.logicalBlockNum, sizeof(struct tag)); else udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1, - epos->block.logicalBlockNum, sizeof(tag)); + epos->block.logicalBlockNum, sizeof(struct tag)); switch (iinfo->i_alloc_type) { case ICBTAG_FLAG_AD_SHORT: - sad = (short_ad *)sptr; + sad = (struct short_ad *)sptr; sad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | inode->i_sb->s_blocksize); sad->extPosition = cpu_to_le32(epos->block.logicalBlockNum); break; case ICBTAG_FLAG_AD_LONG: - lad = (long_ad *)sptr; + lad = (struct long_ad *)sptr; lad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | inode->i_sb->s_blocksize); lad->extLocation = cpu_to_lelb(epos->block); @@ -1769,12 +1776,12 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, } int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, - kernel_lb_addr eloc, uint32_t elen, int inc) + struct kernel_lb_addr *eloc, uint32_t elen, int inc) { int adsize; uint8_t *ptr; - short_ad *sad; - long_ad *lad; + struct short_ad *sad; + struct long_ad *lad; struct udf_inode_info *iinfo = UDF_I(inode); if (!epos->bh) @@ -1786,17 +1793,17 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, switch (iinfo->i_alloc_type) { case ICBTAG_FLAG_AD_SHORT: - sad = (short_ad *)ptr; + sad = (struct short_ad *)ptr; sad->extLength = cpu_to_le32(elen); - sad->extPosition = cpu_to_le32(eloc.logicalBlockNum); - adsize = sizeof(short_ad); + sad->extPosition = cpu_to_le32(eloc->logicalBlockNum); + adsize = sizeof(struct short_ad); break; case ICBTAG_FLAG_AD_LONG: - lad = (long_ad *)ptr; + lad = (struct long_ad *)ptr; lad->extLength = cpu_to_le32(elen); - lad->extLocation = cpu_to_lelb(eloc); + lad->extLocation = cpu_to_lelb(*eloc); memset(lad->impUse, 0x00, sizeof(lad->impUse)); - adsize = sizeof(long_ad); + adsize = sizeof(struct long_ad); break; default: return -1; @@ -1823,7 +1830,7 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, } int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, - kernel_lb_addr *eloc, uint32_t *elen, int inc) + struct kernel_lb_addr *eloc, uint32_t *elen, int inc) { int8_t etype; @@ -1833,7 +1840,7 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, epos->block = *eloc; epos->offset = sizeof(struct allocExtDesc); brelse(epos->bh); - block = udf_get_lb_pblock(inode->i_sb, epos->block, 0); + block = udf_get_lb_pblock(inode->i_sb, &epos->block, 0); epos->bh = udf_tread(inode->i_sb, block); if (!epos->bh) { udf_debug("reading block %d failed!\n", block); @@ -1845,13 +1852,13 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, } int8_t udf_current_aext(struct inode *inode, struct extent_position *epos, - kernel_lb_addr *eloc, uint32_t *elen, int inc) + struct kernel_lb_addr *eloc, uint32_t *elen, int inc) { int alen; int8_t etype; uint8_t *ptr; - short_ad *sad; - long_ad *lad; + struct short_ad *sad; + struct long_ad *lad; struct udf_inode_info *iinfo = UDF_I(inode); if (!epos->bh) { @@ -1900,9 +1907,9 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos, } static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, - kernel_lb_addr neloc, uint32_t nelen) + struct kernel_lb_addr neloc, uint32_t nelen) { - kernel_lb_addr oeloc; + struct kernel_lb_addr oeloc; uint32_t oelen; int8_t etype; @@ -1910,18 +1917,18 @@ static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, get_bh(epos.bh); while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) { - udf_write_aext(inode, &epos, neloc, nelen, 1); + udf_write_aext(inode, &epos, &neloc, nelen, 1); neloc = oeloc; nelen = (etype << 30) | oelen; } - udf_add_aext(inode, &epos, neloc, nelen, 1); + udf_add_aext(inode, &epos, &neloc, nelen, 1); brelse(epos.bh); return (nelen >> 30); } int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, - kernel_lb_addr eloc, uint32_t elen) + struct kernel_lb_addr eloc, uint32_t elen) { struct extent_position oepos; int adsize; @@ -1936,9 +1943,9 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, iinfo = UDF_I(inode); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(short_ad); + adsize = sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(long_ad); + adsize = sizeof(struct long_ad); else adsize = 0; @@ -1947,7 +1954,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, return -1; while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { - udf_write_aext(inode, &oepos, eloc, (etype << 30) | elen, 1); + udf_write_aext(inode, &oepos, &eloc, (etype << 30) | elen, 1); if (oepos.bh != epos.bh) { oepos.block = epos.block; brelse(oepos.bh); @@ -1956,13 +1963,13 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, oepos.offset = epos.offset - adsize; } } - memset(&eloc, 0x00, sizeof(kernel_lb_addr)); + memset(&eloc, 0x00, sizeof(struct kernel_lb_addr)); elen = 0; if (epos.bh != oepos.bh) { - udf_free_blocks(inode->i_sb, inode, epos.block, 0, 1); - udf_write_aext(inode, &oepos, eloc, elen, 1); - udf_write_aext(inode, &oepos, eloc, elen, 1); + udf_free_blocks(inode->i_sb, inode, &epos.block, 0, 1); + udf_write_aext(inode, &oepos, &eloc, elen, 1); + udf_write_aext(inode, &oepos, &eloc, elen, 1); if (!oepos.bh) { iinfo->i_lenAlloc -= (adsize * 2); mark_inode_dirty(inode); @@ -1979,7 +1986,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, mark_buffer_dirty_inode(oepos.bh, inode); } } else { - udf_write_aext(inode, &oepos, eloc, elen, 1); + udf_write_aext(inode, &oepos, &eloc, elen, 1); if (!oepos.bh) { iinfo->i_lenAlloc -= adsize; mark_inode_dirty(inode); @@ -2004,7 +2011,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, } int8_t inode_bmap(struct inode *inode, sector_t block, - struct extent_position *pos, kernel_lb_addr *eloc, + struct extent_position *pos, struct kernel_lb_addr *eloc, uint32_t *elen, sector_t *offset) { unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; @@ -2036,7 +2043,7 @@ int8_t inode_bmap(struct inode *inode, sector_t block, long udf_block_map(struct inode *inode, sector_t block) { - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t elen; sector_t offset; struct extent_position epos = {}; @@ -2046,7 +2053,7 @@ long udf_block_map(struct inode *inode, sector_t block) if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) - ret = udf_get_lb_pblock(inode->i_sb, eloc, offset); + ret = udf_get_lb_pblock(inode->i_sb, &eloc, offset); else ret = 0; diff --git a/fs/udf/misc.c b/fs/udf/misc.c index 84bf0fd..9215700 100644 --- a/fs/udf/misc.c +++ b/fs/udf/misc.c @@ -134,10 +134,10 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size, } } /* rewrite CRC + checksum of eahd */ - crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag); + crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(struct tag); eahd->descTag.descCRCLength = cpu_to_le16(crclen); eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd + - sizeof(tag), crclen)); + sizeof(struct tag), crclen)); eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag); iinfo->i_lenEAttr += size; return (struct genericFormat *)&ea[offset]; @@ -202,7 +202,7 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type, struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, uint32_t location, uint16_t *ident) { - tag *tag_p; + struct tag *tag_p; struct buffer_head *bh = NULL; /* Read the block */ @@ -216,7 +216,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, return NULL; } - tag_p = (tag *)(bh->b_data); + tag_p = (struct tag *)(bh->b_data); *ident = le16_to_cpu(tag_p->tagIdent); @@ -241,9 +241,9 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, } /* Verify the descriptor CRC */ - if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize || + if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize || le16_to_cpu(tag_p->descCRC) == crc_itu_t(0, - bh->b_data + sizeof(tag), + bh->b_data + sizeof(struct tag), le16_to_cpu(tag_p->descCRCLength))) return bh; @@ -255,27 +255,28 @@ error_out: return NULL; } -struct buffer_head *udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc, +struct buffer_head *udf_read_ptagged(struct super_block *sb, + struct kernel_lb_addr *loc, uint32_t offset, uint16_t *ident) { return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset), - loc.logicalBlockNum + offset, ident); + loc->logicalBlockNum + offset, ident); } void udf_update_tag(char *data, int length) { - tag *tptr = (tag *)data; - length -= sizeof(tag); + struct tag *tptr = (struct tag *)data; + length -= sizeof(struct tag); tptr->descCRCLength = cpu_to_le16(length); - tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(tag), length)); + tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(struct tag), length)); tptr->tagChecksum = udf_tag_checksum(tptr); } void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, uint32_t loc, int length) { - tag *tptr = (tag *)data; + struct tag *tptr = (struct tag *)data; tptr->tagIdent = cpu_to_le16(ident); tptr->descVersion = cpu_to_le16(version); tptr->tagSerialNum = cpu_to_le16(snum); @@ -283,12 +284,12 @@ void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, udf_update_tag(data, length); } -u8 udf_tag_checksum(const tag *t) +u8 udf_tag_checksum(const struct tag *t) { u8 *data = (u8 *)t; u8 checksum = 0; int i; - for (i = 0; i < sizeof(tag); ++i) + for (i = 0; i < sizeof(struct tag); ++i) if (i != 4) /* position of checksum */ checksum += data[i]; return checksum; diff --git a/fs/udf/namei.c b/fs/udf/namei.c index f84bfaa..6a29fa34 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -47,7 +47,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, struct fileIdentDesc *sfi, struct udf_fileident_bh *fibh, uint8_t *impuse, uint8_t *fileident) { - uint16_t crclen = fibh->eoffset - fibh->soffset - sizeof(tag); + uint16_t crclen = fibh->eoffset - fibh->soffset - sizeof(struct tag); uint16_t crc; int offset; uint16_t liu = le16_to_cpu(cfi->lengthOfImpUse); @@ -99,18 +99,18 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, memset(fibh->ebh->b_data, 0x00, padlen + offset); } - crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(tag), - sizeof(struct fileIdentDesc) - sizeof(tag)); + crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(struct tag), + sizeof(struct fileIdentDesc) - sizeof(struct tag)); if (fibh->sbh == fibh->ebh) { crc = crc_itu_t(crc, (uint8_t *)sfi->impUse, - crclen + sizeof(tag) - + crclen + sizeof(struct tag) - sizeof(struct fileIdentDesc)); } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) { crc = crc_itu_t(crc, fibh->ebh->b_data + sizeof(struct fileIdentDesc) + fibh->soffset, - crclen + sizeof(tag) - + crclen + sizeof(struct tag) - sizeof(struct fileIdentDesc)); } else { crc = crc_itu_t(crc, (uint8_t *)sfi->impUse, @@ -154,7 +154,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, uint8_t lfi; uint16_t liu; loff_t size; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t elen; sector_t offset; struct extent_position epos = {}; @@ -171,12 +171,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) goto out_err; - block = udf_get_lb_pblock(dir->i_sb, eloc, offset); + block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - epos.offset -= sizeof(short_ad); + epos.offset -= sizeof(struct short_ad); else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(long_ad); + epos.offset -= sizeof(struct long_ad); } else offset = 0; @@ -268,7 +268,7 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, #ifdef UDF_RECOVERY /* temporary shorthand for specifying files by inode number */ if (!strncmp(dentry->d_name.name, ".B=", 3)) { - kernel_lb_addr lb = { + struct kernel_lb_addr lb = { .logicalBlockNum = 0, .partitionReferenceNum = simple_strtoul(dentry->d_name.name + 3, @@ -283,11 +283,14 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, #endif /* UDF_RECOVERY */ if (udf_find_entry(dir, &dentry->d_name, &fibh, &cfi)) { + struct kernel_lb_addr loc; + if (fibh.sbh != fibh.ebh) brelse(fibh.ebh); brelse(fibh.sbh); - inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation)); + loc = lelb_to_cpu(cfi.icb.extLocation); + inode = udf_iget(dir->i_sb, &loc); if (!inode) { unlock_kernel(); return ERR_PTR(-EACCES); @@ -313,7 +316,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, uint8_t lfi; uint16_t liu; int block; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t elen = 0; sector_t offset; struct extent_position epos = {}; @@ -351,16 +354,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) { block = udf_get_lb_pblock(dir->i_sb, - dinfo->i_location, 0); + &dinfo->i_location, 0); fibh->soffset = fibh->eoffset = sb->s_blocksize; goto add; } - block = udf_get_lb_pblock(dir->i_sb, eloc, offset); + block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - epos.offset -= sizeof(short_ad); + epos.offset -= sizeof(struct short_ad); else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(long_ad); + epos.offset -= sizeof(struct long_ad); } else offset = 0; @@ -409,10 +412,10 @@ add: if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && elen) { elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - epos.offset -= sizeof(short_ad); + epos.offset -= sizeof(struct short_ad); else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(long_ad); - udf_write_aext(dir, &epos, eloc, elen, 1); + epos.offset -= sizeof(struct long_ad); + udf_write_aext(dir, &epos, &eloc, elen, 1); } f_pos += nfidlen; @@ -494,10 +497,10 @@ add: memset(cfi, 0, sizeof(struct fileIdentDesc)); if (UDF_SB(sb)->s_udfrev >= 0x0200) udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block, - sizeof(tag)); + sizeof(struct tag)); else udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block, - sizeof(tag)); + sizeof(struct tag)); cfi->fileVersionNum = cpu_to_le16(1); cfi->lengthFileIdent = namelen; cfi->lengthOfImpUse = cpu_to_le16(0); @@ -530,7 +533,7 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED; if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)) - memset(&(cfi->icb), 0x00, sizeof(long_ad)); + memset(&(cfi->icb), 0x00, sizeof(struct long_ad)); return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); } @@ -710,7 +713,7 @@ static int empty_dir(struct inode *dir) loff_t f_pos; loff_t size = udf_ext0_offset(dir) + dir->i_size; int block; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t elen; sector_t offset; struct extent_position epos = {}; @@ -724,12 +727,12 @@ static int empty_dir(struct inode *dir) else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) { - block = udf_get_lb_pblock(dir->i_sb, eloc, offset); + block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - epos.offset -= sizeof(short_ad); + epos.offset -= sizeof(struct short_ad); else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - epos.offset -= sizeof(long_ad); + epos.offset -= sizeof(struct long_ad); } else offset = 0; @@ -778,7 +781,7 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) struct inode *inode = dentry->d_inode; struct udf_fileident_bh fibh; struct fileIdentDesc *fi, cfi; - kernel_lb_addr tloc; + struct kernel_lb_addr tloc; retval = -ENOENT; lock_kernel(); @@ -788,7 +791,7 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) retval = -EIO; tloc = lelb_to_cpu(cfi.icb.extLocation); - if (udf_get_lb_pblock(dir->i_sb, tloc, 0) != inode->i_ino) + if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino) goto end_rmdir; retval = -ENOTEMPTY; if (!empty_dir(inode)) @@ -824,7 +827,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry) struct udf_fileident_bh fibh; struct fileIdentDesc *fi; struct fileIdentDesc cfi; - kernel_lb_addr tloc; + struct kernel_lb_addr tloc; retval = -ENOENT; lock_kernel(); @@ -834,7 +837,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry) retval = -EIO; tloc = lelb_to_cpu(cfi.icb.extLocation); - if (udf_get_lb_pblock(dir->i_sb, tloc, 0) != inode->i_ino) + if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino) goto end_unlink; if (!inode->i_nlink) { @@ -897,7 +900,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, inode->i_op = &page_symlink_inode_operations; if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t bsize; block = udf_new_block(inode->i_sb, inode, @@ -913,7 +916,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, iinfo->i_location.partitionReferenceNum; bsize = inode->i_sb->s_blocksize; iinfo->i_lenExtents = bsize; - udf_add_aext(inode, &epos, eloc, bsize, 0); + udf_add_aext(inode, &epos, &eloc, bsize, 0); brelse(epos.bh); block = udf_get_pblock(inode->i_sb, block, @@ -1108,7 +1111,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, struct fileIdentDesc ocfi, ncfi; struct buffer_head *dir_bh = NULL; int retval = -ENOENT; - kernel_lb_addr tloc; + struct kernel_lb_addr tloc; struct udf_inode_info *old_iinfo = UDF_I(old_inode); lock_kernel(); @@ -1119,7 +1122,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, brelse(ofibh.sbh); } tloc = lelb_to_cpu(ocfi.icb.extLocation); - if (!ofi || udf_get_lb_pblock(old_dir->i_sb, tloc, 0) + if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) != old_inode->i_ino) goto end_rename; @@ -1158,7 +1161,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, if (!dir_fi) goto end_rename; tloc = lelb_to_cpu(dir_fi->icb.extLocation); - if (udf_get_lb_pblock(old_inode->i_sb, tloc, 0) != + if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) != old_dir->i_ino) goto end_rename; @@ -1187,7 +1190,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, */ ncfi.fileVersionNum = ocfi.fileVersionNum; ncfi.fileCharacteristics = ocfi.fileCharacteristics; - memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad)); + memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(struct long_ad)); udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL); /* The old fid may have moved - find it again */ @@ -1242,6 +1245,7 @@ end_rename: static struct dentry *udf_get_parent(struct dentry *child) { + struct kernel_lb_addr tloc; struct inode *inode = NULL; struct qstr dotdot = {.name = "..", .len = 2}; struct fileIdentDesc cfi; @@ -1255,8 +1259,8 @@ static struct dentry *udf_get_parent(struct dentry *child) brelse(fibh.ebh); brelse(fibh.sbh); - inode = udf_iget(child->d_inode->i_sb, - lelb_to_cpu(cfi.icb.extLocation)); + tloc = lelb_to_cpu(cfi.icb.extLocation); + inode = udf_iget(child->d_inode->i_sb, &tloc); if (!inode) goto out_unlock; unlock_kernel(); @@ -1272,14 +1276,14 @@ static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block, u16 partref, __u32 generation) { struct inode *inode; - kernel_lb_addr loc; + struct kernel_lb_addr loc; if (block == 0) return ERR_PTR(-ESTALE); loc.logicalBlockNum = block; loc.partitionReferenceNum = partref; - inode = udf_iget(sb, loc); + inode = udf_iget(sb, &loc); if (inode == NULL) return ERR_PTR(-ENOMEM); @@ -1318,7 +1322,7 @@ static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, { int len = *lenp; struct inode *inode = de->d_inode; - kernel_lb_addr location = UDF_I(inode)->i_location; + struct kernel_lb_addr location = UDF_I(inode)->i_location; struct fid *fid = (struct fid *)fh; int type = FILEID_UDF_WITHOUT_PARENT; diff --git a/fs/udf/osta_udf.h b/fs/udf/osta_udf.h index 65ff479..fbff746 100644 --- a/fs/udf/osta_udf.h +++ b/fs/udf/osta_udf.h @@ -85,7 +85,7 @@ struct appIdentSuffix { /* Logical Volume Integrity Descriptor (UDF 2.50 2.2.6) */ /* Implementation Use (UDF 2.50 2.2.6.4) */ struct logicalVolIntegrityDescImpUse { - regid impIdent; + struct regid impIdent; __le32 numFiles; __le32 numDirs; __le16 minUDFReadRev; @@ -97,12 +97,12 @@ struct logicalVolIntegrityDescImpUse { /* Implementation Use Volume Descriptor (UDF 2.50 2.2.7) */ /* Implementation Use (UDF 2.50 2.2.7.2) */ struct impUseVolDescImpUse { - charspec LVICharset; + struct charspec LVICharset; dstring logicalVolIdent[128]; dstring LVInfo1[36]; dstring LVInfo2[36]; dstring LVInfo3[36]; - regid impIdent; + struct regid impIdent; uint8_t impUse[128]; } __attribute__ ((packed)); @@ -110,7 +110,7 @@ struct udfPartitionMap2 { uint8_t partitionMapType; uint8_t partitionMapLength; uint8_t reserved1[2]; - regid partIdent; + struct regid partIdent; __le16 volSeqNum; __le16 partitionNum; } __attribute__ ((packed)); @@ -120,7 +120,7 @@ struct virtualPartitionMap { uint8_t partitionMapType; uint8_t partitionMapLength; uint8_t reserved1[2]; - regid partIdent; + struct regid partIdent; __le16 volSeqNum; __le16 partitionNum; uint8_t reserved2[24]; @@ -131,7 +131,7 @@ struct sparablePartitionMap { uint8_t partitionMapType; uint8_t partitionMapLength; uint8_t reserved1[2]; - regid partIdent; + struct regid partIdent; __le16 volSeqNum; __le16 partitionNum; __le16 packetLength; @@ -146,7 +146,7 @@ struct metadataPartitionMap { uint8_t partitionMapType; uint8_t partitionMapLength; uint8_t reserved1[2]; - regid partIdent; + struct regid partIdent; __le16 volSeqNum; __le16 partitionNum; __le32 metadataFileLoc; @@ -161,7 +161,7 @@ struct metadataPartitionMap { /* Virtual Allocation Table (UDF 1.5 2.2.10) */ struct virtualAllocationTable15 { __le32 VirtualSector[0]; - regid vatIdent; + struct regid vatIdent; __le32 previousVATICBLoc; } __attribute__ ((packed)); @@ -192,8 +192,8 @@ struct sparingEntry { } __attribute__ ((packed)); struct sparingTable { - tag descTag; - regid sparingIdent; + struct tag descTag; + struct regid sparingIdent; __le16 reallocationTableLen; __le16 reserved; __le32 sequenceNum; @@ -206,7 +206,7 @@ struct sparingTable { #define ICBTAG_FILE_TYPE_MIRROR 0xFB #define ICBTAG_FILE_TYPE_BITMAP 0xFC -/* struct long_ad ICB - ADImpUse (UDF 2.50 2.2.4.3) */ +/* struct struct long_ad ICB - ADImpUse (UDF 2.50 2.2.4.3) */ struct allocDescImpUse { __le16 flags; uint8_t impUse[4]; diff --git a/fs/udf/partition.c b/fs/udf/partition.c index 96dfd20..4b540ee 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c @@ -273,7 +273,7 @@ static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block, { struct super_block *sb = inode->i_sb; struct udf_part_map *map; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t elen; sector_t ext_offset; struct extent_position epos = {}; diff --git a/fs/udf/super.c b/fs/udf/super.c index e25e701..72348cc 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c @@ -81,16 +81,13 @@ static char error_buf[1024]; /* These are the "meat" - everything else is stuffing */ static int udf_fill_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_sync_fs(struct super_block *, int); 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); -static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad); -static void udf_find_anchor(struct super_block *); -static int udf_find_fileset(struct super_block *, kernel_lb_addr *, - kernel_lb_addr *); +static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad); +static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *, + struct kernel_lb_addr *); static void udf_load_fileset(struct super_block *, struct buffer_head *, - kernel_lb_addr *); + struct kernel_lb_addr *); static void udf_open_lvid(struct super_block *); static void udf_close_lvid(struct super_block *); static unsigned int udf_count_free(struct super_block *); @@ -181,7 +178,7 @@ static const struct super_operations udf_sb_ops = { .delete_inode = udf_delete_inode, .clear_inode = udf_clear_inode, .put_super = udf_put_super, - .write_super = udf_write_super, + .sync_fs = udf_sync_fs, .statfs = udf_statfs, .remount_fs = udf_remount_fs, .show_options = udf_show_options, @@ -201,6 +198,8 @@ struct udf_options { mode_t umask; gid_t gid; uid_t uid; + mode_t fmode; + mode_t dmode; struct nls_table *nls_map; }; @@ -258,7 +257,7 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt) if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)) seq_puts(seq, ",nostrict"); - if (sb->s_blocksize != UDF_DEFAULT_BLOCKSIZE) + if (UDF_QUERY_FLAG(sb, UDF_FLAG_BLOCKSIZE_SET)) seq_printf(seq, ",bs=%lu", sb->s_blocksize); if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) seq_puts(seq, ",unhide"); @@ -282,18 +281,16 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt) seq_printf(seq, ",gid=%u", sbi->s_gid); if (sbi->s_umask != 0) seq_printf(seq, ",umask=%o", sbi->s_umask); + if (sbi->s_fmode != UDF_INVALID_MODE) + seq_printf(seq, ",mode=%o", sbi->s_fmode); + if (sbi->s_dmode != UDF_INVALID_MODE) + seq_printf(seq, ",dmode=%o", sbi->s_dmode); if (UDF_QUERY_FLAG(sb, UDF_FLAG_SESSION_SET)) seq_printf(seq, ",session=%u", sbi->s_session); if (UDF_QUERY_FLAG(sb, UDF_FLAG_LASTBLOCK_SET)) seq_printf(seq, ",lastblock=%u", sbi->s_last_block); - /* - * s_anchor[2] could be zeroed out in case there is no anchor - * in the specified block, but then the "anchor=N" option - * originally given by the user wasn't effective, so it's OK - * if we don't show it. - */ - if (sbi->s_anchor[2] != 0) - seq_printf(seq, ",anchor=%u", sbi->s_anchor[2]); + if (sbi->s_anchor != 0) + seq_printf(seq, ",anchor=%u", sbi->s_anchor); /* * volume, partition, fileset and rootdir seem to be ignored * currently @@ -317,6 +314,8 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt) * * gid= Set the default group. * umask= Set the default umask. + * mode= Set the default file permissions. + * dmode= Set the default directory permissions. * uid= Set the default user. * bs= Set the block size. * unhide Show otherwise hidden files. @@ -366,7 +365,8 @@ enum { Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock, Opt_anchor, Opt_volume, Opt_partition, Opt_fileset, Opt_rootdir, Opt_utf8, Opt_iocharset, - Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore + Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore, + Opt_fmode, Opt_dmode }; static const match_table_t tokens = { @@ -395,6 +395,8 @@ static const match_table_t tokens = { {Opt_rootdir, "rootdir=%u"}, {Opt_utf8, "utf8"}, {Opt_iocharset, "iocharset=%s"}, + {Opt_fmode, "mode=%o"}, + {Opt_dmode, "dmode=%o"}, {Opt_err, NULL} }; @@ -405,7 +407,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt, int option; uopt->novrs = 0; - uopt->blocksize = UDF_DEFAULT_BLOCKSIZE; uopt->partition = 0xFFFF; uopt->session = 0xFFFFFFFF; uopt->lastblock = 0; @@ -428,10 +429,12 @@ static int udf_parse_options(char *options, struct udf_options *uopt, switch (token) { case Opt_novrs: uopt->novrs = 1; + break; case Opt_bs: if (match_int(&args[0], &option)) return 0; uopt->blocksize = option; + uopt->flags |= (1 << UDF_FLAG_BLOCKSIZE_SET); break; case Opt_unhide: uopt->flags |= (1 << UDF_FLAG_UNHIDE); @@ -531,6 +534,16 @@ static int udf_parse_options(char *options, struct udf_options *uopt, case Opt_gforget: uopt->flags |= (1 << UDF_FLAG_GID_FORGET); break; + case Opt_fmode: + if (match_octal(args, &option)) + return 0; + uopt->fmode = option & 0777; + break; + case Opt_dmode: + if (match_octal(args, &option)) + return 0; + uopt->dmode = option & 0777; + break; default: printk(KERN_ERR "udf: bad mount option \"%s\" " "or missing value\n", p); @@ -540,17 +553,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt, return 1; } -static void udf_write_super(struct super_block *sb) -{ - lock_kernel(); - - if (!(sb->s_flags & MS_RDONLY)) - udf_open_lvid(sb); - sb->s_dirt = 0; - - unlock_kernel(); -} - static int udf_remount_fs(struct super_block *sb, int *flags, char *options) { struct udf_options uopt; @@ -560,6 +562,8 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) uopt.uid = sbi->s_uid; uopt.gid = sbi->s_gid; uopt.umask = sbi->s_umask; + uopt.fmode = sbi->s_fmode; + uopt.dmode = sbi->s_dmode; if (!udf_parse_options(options, &uopt, true)) return -EINVAL; @@ -568,6 +572,8 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) sbi->s_uid = uopt.uid; sbi->s_gid = uopt.gid; sbi->s_umask = uopt.umask; + sbi->s_fmode = uopt.fmode; + sbi->s_dmode = uopt.dmode; if (sbi->s_lvid_bh) { int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev); @@ -585,22 +591,19 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) return 0; } -static int udf_vrs(struct super_block *sb, int silent) +/* Check Volume Structure Descriptors (ECMA 167 2/9.1) */ +/* We also check any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */ +static loff_t udf_check_vsd(struct super_block *sb) { struct volStructDesc *vsd = NULL; loff_t sector = 32768; int sectorsize; struct buffer_head *bh = NULL; - int iso9660 = 0; int nsr02 = 0; int nsr03 = 0; struct udf_sb_info *sbi; - /* Block size must be a multiple of 512 */ - if (sb->s_blocksize & 511) - return 0; sbi = UDF_SB(sb); - if (sb->s_blocksize < sizeof(struct volStructDesc)) sectorsize = sizeof(struct volStructDesc); else @@ -627,7 +630,6 @@ static int udf_vrs(struct super_block *sb, int silent) break; } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, VSD_STD_ID_LEN)) { - iso9660 = sector; switch (vsd->structType) { case 0: udf_debug("ISO9660 Boot Record found\n"); @@ -679,139 +681,9 @@ static int udf_vrs(struct super_block *sb, int silent) return 0; } -/* - * Check whether there is an anchor block in the given block - */ -static int udf_check_anchor_block(struct super_block *sb, sector_t block) -{ - struct buffer_head *bh; - uint16_t ident; - - if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) && - udf_fixed_to_variable(block) >= - sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) - return 0; - - bh = udf_read_tagged(sb, block, block, &ident); - if (!bh) - return 0; - brelse(bh); - - return ident == TAG_IDENT_AVDP; -} - -/* Search for an anchor volume descriptor pointer */ -static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock) -{ - sector_t last[6]; - int i; - struct udf_sb_info *sbi = UDF_SB(sb); - - last[0] = lastblock; - last[1] = last[0] - 1; - last[2] = last[0] + 1; - last[3] = last[0] - 2; - last[4] = last[0] - 150; - last[5] = last[0] - 152; - - /* according to spec, anchor is in either: - * block 256 - * lastblock-256 - * lastblock - * however, if the disc isn't closed, it could be 512 */ - - for (i = 0; i < ARRAY_SIZE(last); i++) { - if (last[i] < 0) - continue; - if (last[i] >= sb->s_bdev->bd_inode->i_size >> - sb->s_blocksize_bits) - continue; - - if (udf_check_anchor_block(sb, last[i])) { - sbi->s_anchor[0] = last[i]; - sbi->s_anchor[1] = last[i] - 256; - return last[i]; - } - - if (last[i] < 256) - continue; - - if (udf_check_anchor_block(sb, last[i] - 256)) { - sbi->s_anchor[1] = last[i] - 256; - return last[i]; - } - } - - if (udf_check_anchor_block(sb, sbi->s_session + 256)) { - sbi->s_anchor[0] = sbi->s_session + 256; - return last[0]; - } - if (udf_check_anchor_block(sb, sbi->s_session + 512)) { - sbi->s_anchor[0] = sbi->s_session + 512; - return last[0]; - } - return 0; -} - -/* - * Find an anchor volume descriptor. The function expects sbi->s_lastblock to - * be the last block on the media. - * - * Return 1 if not found, 0 if ok - * - */ -static void udf_find_anchor(struct super_block *sb) -{ - sector_t lastblock; - struct buffer_head *bh = NULL; - uint16_t ident; - int i; - struct udf_sb_info *sbi = UDF_SB(sb); - - lastblock = udf_scan_anchors(sb, sbi->s_last_block); - if (lastblock) - goto check_anchor; - - /* No anchor found? Try VARCONV conversion of block numbers */ - UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); - /* Firstly, we try to not convert number of the last block */ - lastblock = udf_scan_anchors(sb, - udf_variable_to_fixed(sbi->s_last_block)); - if (lastblock) - goto check_anchor; - - /* Secondly, we try with converted number of the last block */ - lastblock = udf_scan_anchors(sb, sbi->s_last_block); - if (!lastblock) { - /* VARCONV didn't help. Clear it. */ - UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV); - } - -check_anchor: - /* - * Check located anchors and the anchor block supplied via - * mount options - */ - for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) { - if (!sbi->s_anchor[i]) - continue; - bh = udf_read_tagged(sb, sbi->s_anchor[i], - sbi->s_anchor[i], &ident); - if (!bh) - sbi->s_anchor[i] = 0; - else { - brelse(bh); - if (ident != TAG_IDENT_AVDP) - sbi->s_anchor[i] = 0; - } - } - - sbi->s_last_block = lastblock; -} - static int udf_find_fileset(struct super_block *sb, - kernel_lb_addr *fileset, - kernel_lb_addr *root) + struct kernel_lb_addr *fileset, + struct kernel_lb_addr *root) { struct buffer_head *bh = NULL; long lastblock; @@ -820,7 +692,7 @@ static int udf_find_fileset(struct super_block *sb, if (fileset->logicalBlockNum != 0xFFFFFFFF || fileset->partitionReferenceNum != 0xFFFF) { - bh = udf_read_ptagged(sb, *fileset, 0, &ident); + bh = udf_read_ptagged(sb, fileset, 0, &ident); if (!bh) { return 1; @@ -834,7 +706,7 @@ static int udf_find_fileset(struct super_block *sb, sbi = UDF_SB(sb); if (!bh) { /* Search backwards through the partitions */ - kernel_lb_addr newfileset; + struct kernel_lb_addr newfileset; /* --> cvg: FIXME - is it reasonable? */ return 1; @@ -850,7 +722,7 @@ static int udf_find_fileset(struct super_block *sb, newfileset.logicalBlockNum = 0; do { - bh = udf_read_ptagged(sb, newfileset, 0, + bh = udf_read_ptagged(sb, &newfileset, 0, &ident); if (!bh) { newfileset.logicalBlockNum++; @@ -902,14 +774,23 @@ static int udf_find_fileset(struct super_block *sb, static int udf_load_pvoldesc(struct super_block *sb, sector_t block) { struct primaryVolDesc *pvoldesc; - struct ustr instr; - struct ustr outstr; + struct ustr *instr, *outstr; struct buffer_head *bh; uint16_t ident; + int ret = 1; + + instr = kmalloc(sizeof(struct ustr), GFP_NOFS); + if (!instr) + return 1; + + outstr = kmalloc(sizeof(struct ustr), GFP_NOFS); + if (!outstr) + goto out1; bh = udf_read_tagged(sb, block, block, &ident); if (!bh) - return 1; + goto out2; + BUG_ON(ident != TAG_IDENT_PVD); pvoldesc = (struct primaryVolDesc *)bh->b_data; @@ -917,7 +798,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block) if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time, pvoldesc->recordingDateAndTime)) { #ifdef UDFFS_DEBUG - timestamp *ts = &pvoldesc->recordingDateAndTime; + struct timestamp *ts = &pvoldesc->recordingDateAndTime; udf_debug("recording time %04u/%02u/%02u" " %02u:%02u (%x)\n", le16_to_cpu(ts->year), ts->month, ts->day, ts->hour, @@ -925,20 +806,25 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block) #endif } - if (!udf_build_ustr(&instr, pvoldesc->volIdent, 32)) - if (udf_CS0toUTF8(&outstr, &instr)) { - strncpy(UDF_SB(sb)->s_volume_ident, outstr.u_name, - outstr.u_len > 31 ? 31 : outstr.u_len); + if (!udf_build_ustr(instr, pvoldesc->volIdent, 32)) + if (udf_CS0toUTF8(outstr, instr)) { + strncpy(UDF_SB(sb)->s_volume_ident, outstr->u_name, + outstr->u_len > 31 ? 31 : outstr->u_len); udf_debug("volIdent[] = '%s'\n", UDF_SB(sb)->s_volume_ident); } - if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128)) - if (udf_CS0toUTF8(&outstr, &instr)) - udf_debug("volSetIdent[] = '%s'\n", outstr.u_name); + if (!udf_build_ustr(instr, pvoldesc->volSetIdent, 128)) + if (udf_CS0toUTF8(outstr, instr)) + udf_debug("volSetIdent[] = '%s'\n", outstr->u_name); brelse(bh); - return 0; + ret = 0; +out2: + kfree(outstr); +out1: + kfree(instr); + return ret; } static int udf_load_metadata_files(struct super_block *sb, int partition) @@ -946,7 +832,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map; struct udf_meta_data *mdata; - kernel_lb_addr addr; + struct kernel_lb_addr addr; int fe_error = 0; map = &sbi->s_partmaps[partition]; @@ -959,7 +845,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) udf_debug("Metadata file location: block = %d part = %d\n", addr.logicalBlockNum, addr.partitionReferenceNum); - mdata->s_metadata_fe = udf_iget(sb, addr); + mdata->s_metadata_fe = udf_iget(sb, &addr); if (mdata->s_metadata_fe == NULL) { udf_warning(sb, __func__, "metadata inode efe not found, " @@ -981,7 +867,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) udf_debug("Mirror metadata file location: block = %d part = %d\n", addr.logicalBlockNum, addr.partitionReferenceNum); - mdata->s_mirror_fe = udf_iget(sb, addr); + mdata->s_mirror_fe = udf_iget(sb, &addr); if (mdata->s_mirror_fe == NULL) { if (fe_error) { @@ -1013,7 +899,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) udf_debug("Bitmap file location: block = %d part = %d\n", addr.logicalBlockNum, addr.partitionReferenceNum); - mdata->s_bitmap_fe = udf_iget(sb, addr); + mdata->s_bitmap_fe = udf_iget(sb, &addr); if (mdata->s_bitmap_fe == NULL) { if (sb->s_flags & MS_RDONLY) @@ -1037,7 +923,7 @@ error_exit: } static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, - kernel_lb_addr *root) + struct kernel_lb_addr *root) { struct fileSetDesc *fset; @@ -1119,13 +1005,13 @@ static int udf_fill_partdesc_info(struct super_block *sb, phd = (struct partitionHeaderDesc *)p->partitionContentsUse; if (phd->unallocSpaceTable.extLength) { - kernel_lb_addr loc = { + struct kernel_lb_addr loc = { .logicalBlockNum = le32_to_cpu( phd->unallocSpaceTable.extPosition), .partitionReferenceNum = p_index, }; - map->s_uspace.s_table = udf_iget(sb, loc); + map->s_uspace.s_table = udf_iget(sb, &loc); if (!map->s_uspace.s_table) { udf_debug("cannot load unallocSpaceTable (part %d)\n", p_index); @@ -1154,13 +1040,13 @@ static int udf_fill_partdesc_info(struct super_block *sb, udf_debug("partitionIntegrityTable (part %d)\n", p_index); if (phd->freedSpaceTable.extLength) { - kernel_lb_addr loc = { + struct kernel_lb_addr loc = { .logicalBlockNum = le32_to_cpu( phd->freedSpaceTable.extPosition), .partitionReferenceNum = p_index, }; - map->s_fspace.s_table = udf_iget(sb, loc); + map->s_fspace.s_table = udf_iget(sb, &loc); if (!map->s_fspace.s_table) { udf_debug("cannot load freedSpaceTable (part %d)\n", p_index); @@ -1192,7 +1078,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) { struct udf_sb_info *sbi = UDF_SB(sb); struct udf_part_map *map = &sbi->s_partmaps[p_index]; - kernel_lb_addr ino; + struct kernel_lb_addr ino; struct buffer_head *bh = NULL; struct udf_inode_info *vati; uint32_t pos; @@ -1201,7 +1087,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) /* VAT file entry is in the last recorded block */ ino.partitionReferenceNum = type1_index; ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; - sbi->s_vat_inode = udf_iget(sb, ino); + sbi->s_vat_inode = udf_iget(sb, &ino); if (!sbi->s_vat_inode) return 1; @@ -1322,7 +1208,7 @@ out_bh: } static int udf_load_logicalvol(struct super_block *sb, sector_t block, - kernel_lb_addr *fileset) + struct kernel_lb_addr *fileset) { struct logicalVolDesc *lvd; int i, j, offset; @@ -1471,7 +1357,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, } if (fileset) { - long_ad *la = (long_ad *)&(lvd->logicalVolContentsUse[0]); + struct long_ad *la = (struct long_ad *)&(lvd->logicalVolContentsUse[0]); *fileset = lelb_to_cpu(la->extLocation); udf_debug("FileSet found in LogicalVolDesc at block=%d, " @@ -1490,7 +1376,7 @@ out_bh: * udf_load_logicalvolint * */ -static void udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc) +static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc) { struct buffer_head *bh = NULL; uint16_t ident; @@ -1533,7 +1419,7 @@ static void udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc) * Written, tested, and released. */ static noinline int udf_process_sequence(struct super_block *sb, long block, - long lastblock, kernel_lb_addr *fileset) + long lastblock, struct kernel_lb_addr *fileset) { struct buffer_head *bh = NULL; struct udf_vds_record vds[VDS_POS_LENGTH]; @@ -1655,85 +1541,199 @@ static noinline int udf_process_sequence(struct super_block *sb, long block, return 0; } +static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh, + struct kernel_lb_addr *fileset) +{ + struct anchorVolDescPtr *anchor; + long main_s, main_e, reserve_s, reserve_e; + struct udf_sb_info *sbi; + + sbi = UDF_SB(sb); + anchor = (struct anchorVolDescPtr *)bh->b_data; + + /* Locate the main sequence */ + main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation); + main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength); + main_e = main_e >> sb->s_blocksize_bits; + main_e += main_s; + + /* Locate the reserve sequence */ + reserve_s = le32_to_cpu(anchor->reserveVolDescSeqExt.extLocation); + reserve_e = le32_to_cpu(anchor->reserveVolDescSeqExt.extLength); + reserve_e = reserve_e >> sb->s_blocksize_bits; + reserve_e += reserve_s; + + /* Process the main & reserve sequences */ + /* responsible for finding the PartitionDesc(s) */ + if (!udf_process_sequence(sb, main_s, main_e, fileset)) + return 1; + return !udf_process_sequence(sb, reserve_s, reserve_e, fileset); +} + /* - * udf_check_valid() + * Check whether there is an anchor block in the given block and + * load Volume Descriptor Sequence if so. */ -static int udf_check_valid(struct super_block *sb, int novrs, int silent) +static int udf_check_anchor_block(struct super_block *sb, sector_t block, + struct kernel_lb_addr *fileset) { - long block; - struct udf_sb_info *sbi = UDF_SB(sb); + struct buffer_head *bh; + uint16_t ident; + int ret; - if (novrs) { - udf_debug("Validity check skipped because of novrs option\n"); + if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) && + udf_fixed_to_variable(block) >= + sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) + return 0; + + bh = udf_read_tagged(sb, block, block, &ident); + if (!bh) + return 0; + if (ident != TAG_IDENT_AVDP) { + brelse(bh); return 0; } - /* Check that it is NSR02 compliant */ - /* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */ - block = udf_vrs(sb, silent); - if (block == -1) - udf_debug("Failed to read byte 32768. Assuming open " - "disc. Skipping validity check\n"); - if (block && !sbi->s_last_block) - sbi->s_last_block = udf_get_last_block(sb); - return !block; + ret = udf_load_sequence(sb, bh, fileset); + brelse(bh); + return ret; } -static int udf_load_sequence(struct super_block *sb, kernel_lb_addr *fileset) +/* Search for an anchor volume descriptor pointer */ +static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock, + struct kernel_lb_addr *fileset) { - struct anchorVolDescPtr *anchor; - uint16_t ident; - struct buffer_head *bh; - long main_s, main_e, reserve_s, reserve_e; + sector_t last[6]; int i; - struct udf_sb_info *sbi; - - if (!sb) - return 1; - sbi = UDF_SB(sb); + struct udf_sb_info *sbi = UDF_SB(sb); + int last_count = 0; - for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) { - if (!sbi->s_anchor[i]) + /* First try user provided anchor */ + if (sbi->s_anchor) { + if (udf_check_anchor_block(sb, sbi->s_anchor, fileset)) + return lastblock; + } + /* + * according to spec, anchor is in either: + * block 256 + * lastblock-256 + * lastblock + * however, if the disc isn't closed, it could be 512. + */ + if (udf_check_anchor_block(sb, sbi->s_session + 256, fileset)) + return lastblock; + /* + * The trouble is which block is the last one. Drives often misreport + * this so we try various possibilities. + */ + last[last_count++] = lastblock; + if (lastblock >= 1) + last[last_count++] = lastblock - 1; + last[last_count++] = lastblock + 1; + if (lastblock >= 2) + last[last_count++] = lastblock - 2; + if (lastblock >= 150) + last[last_count++] = lastblock - 150; + if (lastblock >= 152) + last[last_count++] = lastblock - 152; + + for (i = 0; i < last_count; i++) { + if (last[i] >= sb->s_bdev->bd_inode->i_size >> + sb->s_blocksize_bits) continue; - - bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i], - &ident); - if (!bh) + if (udf_check_anchor_block(sb, last[i], fileset)) + return last[i]; + if (last[i] < 256) continue; + if (udf_check_anchor_block(sb, last[i] - 256, fileset)) + return last[i]; + } - anchor = (struct anchorVolDescPtr *)bh->b_data; + /* Finally try block 512 in case media is open */ + if (udf_check_anchor_block(sb, sbi->s_session + 512, fileset)) + return last[0]; + return 0; +} - /* Locate the main sequence */ - main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation); - main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength); - main_e = main_e >> sb->s_blocksize_bits; - main_e += main_s; +/* + * Find an anchor volume descriptor and load Volume Descriptor Sequence from + * area specified by it. The function expects sbi->s_lastblock to be the last + * block on the media. + * + * Return 1 if ok, 0 if not found. + * + */ +static int udf_find_anchor(struct super_block *sb, + struct kernel_lb_addr *fileset) +{ + sector_t lastblock; + struct udf_sb_info *sbi = UDF_SB(sb); - /* Locate the reserve sequence */ - reserve_s = le32_to_cpu( - anchor->reserveVolDescSeqExt.extLocation); - reserve_e = le32_to_cpu( - anchor->reserveVolDescSeqExt.extLength); - reserve_e = reserve_e >> sb->s_blocksize_bits; - reserve_e += reserve_s; + lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset); + if (lastblock) + goto out; - brelse(bh); + /* No anchor found? Try VARCONV conversion of block numbers */ + UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); + /* Firstly, we try to not convert number of the last block */ + lastblock = udf_scan_anchors(sb, + udf_variable_to_fixed(sbi->s_last_block), + fileset); + if (lastblock) + goto out; - /* Process the main & reserve sequences */ - /* responsible for finding the PartitionDesc(s) */ - if (!(udf_process_sequence(sb, main_s, main_e, - fileset) && - udf_process_sequence(sb, reserve_s, reserve_e, - fileset))) - break; + /* Secondly, we try with converted number of the last block */ + lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset); + if (!lastblock) { + /* VARCONV didn't help. Clear it. */ + UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV); + return 0; } +out: + sbi->s_last_block = lastblock; + return 1; +} - if (i == ARRAY_SIZE(sbi->s_anchor)) { - udf_debug("No Anchor block found\n"); - return 1; +/* + * Check Volume Structure Descriptor, find Anchor block and load Volume + * Descriptor Sequence + */ +static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt, + int silent, struct kernel_lb_addr *fileset) +{ + struct udf_sb_info *sbi = UDF_SB(sb); + loff_t nsr_off; + + if (!sb_set_blocksize(sb, uopt->blocksize)) { + if (!silent) + printk(KERN_WARNING "UDF-fs: Bad block size\n"); + return 0; + } + sbi->s_last_block = uopt->lastblock; + if (!uopt->novrs) { + /* Check that it is NSR02 compliant */ + nsr_off = udf_check_vsd(sb); + if (!nsr_off) { + if (!silent) + printk(KERN_WARNING "UDF-fs: No VRS found\n"); + return 0; + } + if (nsr_off == -1) + udf_debug("Failed to read byte 32768. Assuming open " + "disc. Skipping validity check\n"); + if (!sbi->s_last_block) + sbi->s_last_block = udf_get_last_block(sb); + } else { + udf_debug("Validity check skipped because of novrs option\n"); } - udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]); - return 0; + /* Look for anchor block and load Volume Descriptor Sequence */ + sbi->s_anchor = uopt->anchor; + if (!udf_find_anchor(sb, fileset)) { + if (!silent) + printk(KERN_WARNING "UDF-fs: No anchor found\n"); + return 0; + } + return 1; } static void udf_open_lvid(struct super_block *sb) @@ -1742,9 +1742,9 @@ static void udf_open_lvid(struct super_block *sb) struct buffer_head *bh = sbi->s_lvid_bh; struct logicalVolIntegrityDesc *lvid; struct logicalVolIntegrityDescImpUse *lvidiu; + if (!bh) return; - lvid = (struct logicalVolIntegrityDesc *)bh->b_data; lvidiu = udf_sb_lvidiu(sbi); @@ -1752,14 +1752,15 @@ static void udf_open_lvid(struct super_block *sb) lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; udf_time_to_disk_stamp(&lvid->recordingDateAndTime, CURRENT_TIME); - lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN; + lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN); lvid->descTag.descCRC = cpu_to_le16( - crc_itu_t(0, (char *)lvid + sizeof(tag), + crc_itu_t(0, (char *)lvid + sizeof(struct tag), le16_to_cpu(lvid->descTag.descCRCLength))); lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); mark_buffer_dirty(bh); + sbi->s_lvid_dirty = 0; } static void udf_close_lvid(struct super_block *sb) @@ -1773,10 +1774,6 @@ static void udf_close_lvid(struct super_block *sb) return; lvid = (struct logicalVolIntegrityDesc *)bh->b_data; - - if (lvid->integrityType != LVID_INTEGRITY_TYPE_OPEN) - return; - lvidiu = udf_sb_lvidiu(sbi); lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; @@ -1790,11 +1787,12 @@ static void udf_close_lvid(struct super_block *sb) lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE); lvid->descTag.descCRC = cpu_to_le16( - crc_itu_t(0, (char *)lvid + sizeof(tag), + crc_itu_t(0, (char *)lvid + sizeof(struct tag), le16_to_cpu(lvid->descTag.descCRCLength))); lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); mark_buffer_dirty(bh); + sbi->s_lvid_dirty = 0; } static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) @@ -1846,15 +1844,18 @@ static void udf_free_partition(struct udf_part_map *map) static int udf_fill_super(struct super_block *sb, void *options, int silent) { int i; + int ret; struct inode *inode = NULL; struct udf_options uopt; - kernel_lb_addr rootdir, fileset; + struct kernel_lb_addr rootdir, fileset; struct udf_sb_info *sbi; uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); uopt.uid = -1; uopt.gid = -1; uopt.umask = 0; + uopt.fmode = UDF_INVALID_MODE; + uopt.dmode = UDF_INVALID_MODE; sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL); if (!sbi) @@ -1892,15 +1893,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) sbi->s_uid = uopt.uid; sbi->s_gid = uopt.gid; sbi->s_umask = uopt.umask; + sbi->s_fmode = uopt.fmode; + sbi->s_dmode = uopt.dmode; sbi->s_nls_map = uopt.nls_map; - /* Set the block size for all transfers */ - if (!sb_min_blocksize(sb, uopt.blocksize)) { - udf_debug("Bad block size (%d)\n", uopt.blocksize); - printk(KERN_ERR "udf: bad block size (%d)\n", uopt.blocksize); - goto error_out; - } - if (uopt.session == 0xFFFFFFFF) sbi->s_session = udf_get_last_session(sb); else @@ -1908,18 +1904,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) udf_debug("Multi-session=%d\n", sbi->s_session); - sbi->s_last_block = uopt.lastblock; - sbi->s_anchor[0] = sbi->s_anchor[1] = 0; - sbi->s_anchor[2] = uopt.anchor; - - if (udf_check_valid(sb, uopt.novrs, silent)) { - /* read volume recognition sequences */ - printk(KERN_WARNING "UDF-fs: No VRS found\n"); - goto error_out; - } - - udf_find_anchor(sb); - /* Fill in the rest of the superblock */ sb->s_op = &udf_sb_ops; sb->s_export_op = &udf_export_ops; @@ -1928,7 +1912,21 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) sb->s_magic = UDF_SUPER_MAGIC; sb->s_time_gran = 1000; - if (udf_load_sequence(sb, &fileset)) { + if (uopt.flags & (1 << UDF_FLAG_BLOCKSIZE_SET)) { + ret = udf_load_vrs(sb, &uopt, silent, &fileset); + } else { + uopt.blocksize = bdev_hardsect_size(sb->s_bdev); + ret = udf_load_vrs(sb, &uopt, silent, &fileset); + if (!ret && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) { + if (!silent) + printk(KERN_NOTICE + "UDF-fs: Rescanning with blocksize " + "%d\n", UDF_DEFAULT_BLOCKSIZE); + uopt.blocksize = UDF_DEFAULT_BLOCKSIZE; + ret = udf_load_vrs(sb, &uopt, silent, &fileset); + } + } + if (!ret) { printk(KERN_WARNING "UDF-fs: No partition found (1)\n"); goto error_out; } @@ -1978,7 +1976,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) } if (!silent) { - timestamp ts; + struct timestamp ts; udf_time_to_disk_stamp(&ts, sbi->s_record_time); udf_info("UDF: Mounting volume '%s', " "timestamp %04u/%02u/%02u %02u:%02u (%x)\n", @@ -1991,7 +1989,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) /* Assign the root inode */ /* assign inodes by physical block number */ /* perhaps it's not extensible enough, but for now ... */ - inode = udf_iget(sb, rootdir); + inode = udf_iget(sb, &rootdir); if (!inode) { printk(KERN_ERR "UDF-fs: Error in udf_iget, block=%d, " "partition=%d\n", @@ -2081,11 +2079,31 @@ static void udf_put_super(struct super_block *sb) sb->s_fs_info = NULL; } +static int udf_sync_fs(struct super_block *sb, int wait) +{ + struct udf_sb_info *sbi = UDF_SB(sb); + + mutex_lock(&sbi->s_alloc_mutex); + if (sbi->s_lvid_dirty) { + /* + * Blockdevice will be synced later so we don't have to submit + * the buffer for IO + */ + mark_buffer_dirty(sbi->s_lvid_bh); + sb->s_dirt = 0; + sbi->s_lvid_dirty = 0; + } + mutex_unlock(&sbi->s_alloc_mutex); + + return 0; +} + static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct udf_sb_info *sbi = UDF_SB(sb); struct logicalVolIntegrityDescImpUse *lvidiu; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); if (sbi->s_lvid_bh != NULL) lvidiu = udf_sb_lvidiu(sbi); @@ -2101,8 +2119,9 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) le32_to_cpu(lvidiu->numDirs)) : 0) + buf->f_bfree; buf->f_ffree = buf->f_bfree; - /* __kernel_fsid_t f_fsid */ buf->f_namelen = UDF_NAME_LEN - 2; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); return 0; } @@ -2114,7 +2133,7 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, unsigned int accum = 0; int index; int block = 0, newblock; - kernel_lb_addr loc; + struct kernel_lb_addr loc; uint32_t bytes; uint8_t *ptr; uint16_t ident; @@ -2124,7 +2143,7 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, loc.logicalBlockNum = bitmap->s_extPosition; loc.partitionReferenceNum = UDF_SB(sb)->s_partition; - bh = udf_read_ptagged(sb, loc, 0, &ident); + bh = udf_read_ptagged(sb, &loc, 0, &ident); if (!bh) { printk(KERN_ERR "udf: udf_count_free failed\n"); @@ -2147,7 +2166,7 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, bytes -= cur_bytes; if (bytes) { brelse(bh); - newblock = udf_get_lb_pblock(sb, loc, ++block); + newblock = udf_get_lb_pblock(sb, &loc, ++block); bh = udf_tread(sb, newblock); if (!bh) { udf_debug("read failed\n"); @@ -2170,7 +2189,7 @@ static unsigned int udf_count_free_table(struct super_block *sb, { unsigned int accum = 0; uint32_t elen; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; int8_t etype; struct extent_position epos; diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 65e19b4..225527c 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c @@ -28,10 +28,10 @@ #include "udf_sb.h" static void extent_trunc(struct inode *inode, struct extent_position *epos, - kernel_lb_addr eloc, int8_t etype, uint32_t elen, + struct kernel_lb_addr *eloc, int8_t etype, uint32_t elen, uint32_t nelen) { - kernel_lb_addr neloc = {}; + struct kernel_lb_addr neloc = {}; 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) >> @@ -43,12 +43,12 @@ static void extent_trunc(struct inode *inode, struct extent_position *epos, last_block); etype = (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30); } else - neloc = eloc; + neloc = *eloc; nelen = (etype << 30) | nelen; } if (elen != nelen) { - udf_write_aext(inode, epos, neloc, nelen, 0); + udf_write_aext(inode, epos, &neloc, nelen, 0); if (last_block - first_block > 0) { if (etype == (EXT_RECORDED_ALLOCATED >> 30)) mark_inode_dirty(inode); @@ -68,7 +68,7 @@ static void extent_trunc(struct inode *inode, struct extent_position *epos, void udf_truncate_tail_extent(struct inode *inode) { struct extent_position epos = {}; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t elen, nelen; uint64_t lbcount = 0; int8_t etype = -1, netype; @@ -83,9 +83,9 @@ void udf_truncate_tail_extent(struct inode *inode) return; if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(short_ad); + adsize = sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(long_ad); + adsize = sizeof(struct long_ad); else BUG(); @@ -106,7 +106,7 @@ void udf_truncate_tail_extent(struct inode *inode) (unsigned)elen); nelen = elen - (lbcount - inode->i_size); epos.offset -= adsize; - extent_trunc(inode, &epos, eloc, etype, elen, nelen); + extent_trunc(inode, &epos, &eloc, etype, elen, nelen); epos.offset += adsize; if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1) printk(KERN_ERR "udf_truncate_tail_extent(): " @@ -124,7 +124,7 @@ void udf_truncate_tail_extent(struct inode *inode) void udf_discard_prealloc(struct inode *inode) { struct extent_position epos = { NULL, 0, {0, 0} }; - kernel_lb_addr eloc; + struct kernel_lb_addr eloc; uint32_t elen; uint64_t lbcount = 0; int8_t etype = -1, netype; @@ -136,9 +136,9 @@ void udf_discard_prealloc(struct inode *inode) return; if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(short_ad); + adsize = sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(long_ad); + adsize = sizeof(struct long_ad); else adsize = 0; @@ -152,7 +152,7 @@ void udf_discard_prealloc(struct inode *inode) if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { epos.offset -= adsize; lbcount -= elen; - extent_trunc(inode, &epos, eloc, etype, elen, 0); + extent_trunc(inode, &epos, &eloc, etype, elen, 0); if (!epos.bh) { iinfo->i_lenAlloc = epos.offset - @@ -200,7 +200,7 @@ static void udf_update_alloc_ext_desc(struct inode *inode, void udf_truncate_extents(struct inode *inode) { struct extent_position epos; - kernel_lb_addr eloc, neloc = {}; + struct kernel_lb_addr eloc, neloc = {}; uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc; int8_t etype; struct super_block *sb = inode->i_sb; @@ -210,9 +210,9 @@ void udf_truncate_extents(struct inode *inode) struct udf_inode_info *iinfo = UDF_I(inode); if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) - adsize = sizeof(short_ad); + adsize = sizeof(struct short_ad); else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) - adsize = sizeof(long_ad); + adsize = sizeof(struct long_ad); else BUG(); @@ -221,7 +221,7 @@ void udf_truncate_extents(struct inode *inode) (inode->i_size & (sb->s_blocksize - 1)); if (etype != -1) { epos.offset -= adsize; - extent_trunc(inode, &epos, eloc, etype, elen, byte_offset); + extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset); epos.offset += adsize; if (byte_offset) lenalloc = epos.offset; @@ -236,12 +236,12 @@ void udf_truncate_extents(struct inode *inode) while ((etype = udf_current_aext(inode, &epos, &eloc, &elen, 0)) != -1) { if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { - udf_write_aext(inode, &epos, neloc, nelen, 0); + udf_write_aext(inode, &epos, &neloc, nelen, 0); if (indirect_ext_len) { /* We managed to free all extents in the * indirect extent - free it too */ BUG_ON(!epos.bh); - udf_free_blocks(sb, inode, epos.block, + udf_free_blocks(sb, inode, &epos.block, 0, indirect_ext_len); } else if (!epos.bh) { iinfo->i_lenAlloc = lenalloc; @@ -253,7 +253,7 @@ void udf_truncate_extents(struct inode *inode) epos.offset = sizeof(struct allocExtDesc); epos.block = eloc; epos.bh = udf_tread(sb, - udf_get_lb_pblock(sb, eloc, 0)); + udf_get_lb_pblock(sb, &eloc, 0)); if (elen) indirect_ext_len = (elen + sb->s_blocksize - 1) >> @@ -261,7 +261,7 @@ void udf_truncate_extents(struct inode *inode) else indirect_ext_len = 1; } else { - extent_trunc(inode, &epos, eloc, etype, + extent_trunc(inode, &epos, &eloc, etype, elen, 0); epos.offset += adsize; } @@ -269,7 +269,7 @@ void udf_truncate_extents(struct inode *inode) if (indirect_ext_len) { BUG_ON(!epos.bh); - udf_free_blocks(sb, inode, epos.block, 0, + udf_free_blocks(sb, inode, &epos.block, 0, indirect_ext_len); } else if (!epos.bh) { iinfo->i_lenAlloc = lenalloc; @@ -278,7 +278,7 @@ void udf_truncate_extents(struct inode *inode) udf_update_alloc_ext_desc(inode, &epos, lenalloc); } else if (inode->i_size) { if (byte_offset) { - kernel_long_ad extent; + struct kernel_long_ad extent; /* * OK, there is not extent covering inode->i_size and diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h index 4f86b1d..e58d1de 100644 --- a/fs/udf/udf_i.h +++ b/fs/udf/udf_i.h @@ -4,7 +4,7 @@ struct udf_inode_info { struct timespec i_crtime; /* Physical address of inode */ - kernel_lb_addr i_location; + struct kernel_lb_addr i_location; __u64 i_unique; __u32 i_lenEAttr; __u32 i_lenAlloc; @@ -17,8 +17,8 @@ struct udf_inode_info { unsigned i_strat4096 : 1; unsigned reserved : 26; union { - short_ad *i_sad; - long_ad *i_lad; + struct short_ad *i_sad; + struct long_ad *i_lad; __u8 *i_data; } i_ext; struct inode vfs_inode; diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 1c1c514..d113b72 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h @@ -30,6 +30,7 @@ #define UDF_FLAG_GID_SET 16 #define UDF_FLAG_SESSION_SET 17 #define UDF_FLAG_LASTBLOCK_SET 18 +#define UDF_FLAG_BLOCKSIZE_SET 19 #define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001 #define UDF_PART_FLAG_UNALLOC_TABLE 0x0002 @@ -48,6 +49,8 @@ #define UDF_SPARABLE_MAP15 0x1522U #define UDF_METADATA_MAP25 0x2511U +#define UDF_INVALID_MODE ((mode_t)-1) + #pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */ struct udf_meta_data { @@ -114,7 +117,7 @@ struct udf_sb_info { /* Sector headers */ __s32 s_session; - __u32 s_anchor[3]; + __u32 s_anchor; __u32 s_last_block; struct buffer_head *s_lvid_bh; @@ -123,6 +126,8 @@ struct udf_sb_info { mode_t s_umask; gid_t s_gid; uid_t s_uid; + mode_t s_fmode; + mode_t s_dmode; /* Root Info */ struct timespec s_record_time; @@ -143,6 +148,8 @@ struct udf_sb_info { struct inode *s_vat_inode; struct mutex s_alloc_mutex; + /* Protected by s_alloc_mutex */ + unsigned int s_lvid_dirty; }; static inline struct udf_sb_info *UDF_SB(struct super_block *sb) diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 8ec865d..cac51b7 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h @@ -62,10 +62,8 @@ static inline size_t udf_ext0_offset(struct inode *inode) return 0; } -#define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset)) - /* computes tag checksum */ -u8 udf_tag_checksum(const tag *t); +u8 udf_tag_checksum(const struct tag *t); struct dentry; struct inode; @@ -95,7 +93,7 @@ struct udf_vds_record { }; struct generic_desc { - tag descTag; + struct tag descTag; __le32 volDescSeqNum; }; @@ -108,11 +106,22 @@ struct ustr { struct extent_position { struct buffer_head *bh; uint32_t offset; - kernel_lb_addr block; + struct kernel_lb_addr block; }; /* super.c */ extern void udf_warning(struct super_block *, const char *, const char *, ...); +static inline void udf_updated_lvid(struct super_block *sb) +{ + struct buffer_head *bh = UDF_SB(sb)->s_lvid_bh; + + BUG_ON(!bh); + WARN_ON_ONCE(((struct logicalVolIntegrityDesc *) + bh->b_data)->integrityType != + cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN)); + sb->s_dirt = 1; + UDF_SB(sb)->s_lvid_dirty = 1; +} /* namei.c */ extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, @@ -124,7 +133,7 @@ extern int udf_ioctl(struct inode *, struct file *, unsigned int, unsigned long); /* inode.c */ -extern struct inode *udf_iget(struct super_block *, kernel_lb_addr); +extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); extern int udf_sync_inode(struct inode *); extern void udf_expand_file_adinicb(struct inode *, int, int *); extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); @@ -136,19 +145,19 @@ extern void udf_clear_inode(struct inode *); extern int udf_write_inode(struct inode *, int); extern long udf_block_map(struct inode *, sector_t); extern int udf_extend_file(struct inode *, struct extent_position *, - kernel_long_ad *, sector_t); + struct kernel_long_ad *, sector_t); extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, - kernel_lb_addr *, uint32_t *, sector_t *); + struct kernel_lb_addr *, uint32_t *, sector_t *); extern int8_t udf_add_aext(struct inode *, struct extent_position *, - kernel_lb_addr, uint32_t, int); + struct kernel_lb_addr *, uint32_t, int); extern int8_t udf_write_aext(struct inode *, struct extent_position *, - kernel_lb_addr, uint32_t, int); + struct kernel_lb_addr *, uint32_t, int); extern int8_t udf_delete_aext(struct inode *, struct extent_position, - kernel_lb_addr, uint32_t); + struct kernel_lb_addr, uint32_t); extern int8_t udf_next_aext(struct inode *, struct extent_position *, - kernel_lb_addr *, uint32_t *, int); + struct kernel_lb_addr *, uint32_t *, int); extern int8_t udf_current_aext(struct inode *, struct extent_position *, - kernel_lb_addr *, uint32_t *, int); + struct kernel_lb_addr *, uint32_t *, int); /* misc.c */ extern struct buffer_head *udf_tgetblk(struct super_block *, int); @@ -160,7 +169,7 @@ extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, uint32_t, uint16_t *); extern struct buffer_head *udf_read_ptagged(struct super_block *, - kernel_lb_addr, uint32_t, + struct kernel_lb_addr *, uint32_t, uint16_t *); extern void udf_update_tag(char *, int); extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int); @@ -182,6 +191,14 @@ extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t, uint32_t); extern int udf_relocate_blocks(struct super_block *, long, long *); +static inline uint32_t +udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc, + uint32_t offset) +{ + return udf_get_pblock(sb, loc->logicalBlockNum, + loc->partitionReferenceNum, offset); +} + /* unicode.c */ extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, @@ -200,7 +217,7 @@ extern void udf_truncate_extents(struct inode *); /* balloc.c */ extern void udf_free_blocks(struct super_block *, struct inode *, - kernel_lb_addr, uint32_t, uint32_t); + struct kernel_lb_addr *, uint32_t, uint32_t); extern int udf_prealloc_blocks(struct super_block *, struct inode *, uint16_t, uint32_t, uint32_t); extern int udf_new_block(struct super_block *, struct inode *, uint16_t, @@ -214,16 +231,16 @@ extern struct fileIdentDesc *udf_fileident_read(struct inode *, loff_t *, struct udf_fileident_bh *, struct fileIdentDesc *, struct extent_position *, - kernel_lb_addr *, uint32_t *, + struct kernel_lb_addr *, uint32_t *, sector_t *); extern struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, int *offset); -extern long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int); -extern short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int); +extern struct long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int); +extern struct short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int); /* udftime.c */ extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest, - timestamp src); -extern timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec src); + struct timestamp src); +extern struct timestamp *udf_time_to_disk_stamp(struct timestamp *dest, struct timespec src); #endif /* __UDF_DECL_H */ diff --git a/fs/udf/udfend.h b/fs/udf/udfend.h index 489f52f..6a9f3a9 100644 --- a/fs/udf/udfend.h +++ b/fs/udf/udfend.h @@ -4,9 +4,9 @@ #include <asm/byteorder.h> #include <linux/string.h> -static inline kernel_lb_addr lelb_to_cpu(lb_addr in) +static inline struct kernel_lb_addr lelb_to_cpu(struct lb_addr in) { - kernel_lb_addr out; + struct kernel_lb_addr out; out.logicalBlockNum = le32_to_cpu(in.logicalBlockNum); out.partitionReferenceNum = le16_to_cpu(in.partitionReferenceNum); @@ -14,9 +14,9 @@ static inline kernel_lb_addr lelb_to_cpu(lb_addr in) return out; } -static inline lb_addr cpu_to_lelb(kernel_lb_addr in) +static inline struct lb_addr cpu_to_lelb(struct kernel_lb_addr in) { - lb_addr out; + struct lb_addr out; out.logicalBlockNum = cpu_to_le32(in.logicalBlockNum); out.partitionReferenceNum = cpu_to_le16(in.partitionReferenceNum); @@ -24,9 +24,9 @@ static inline lb_addr cpu_to_lelb(kernel_lb_addr in) return out; } -static inline short_ad lesa_to_cpu(short_ad in) +static inline struct short_ad lesa_to_cpu(struct short_ad in) { - short_ad out; + struct short_ad out; out.extLength = le32_to_cpu(in.extLength); out.extPosition = le32_to_cpu(in.extPosition); @@ -34,9 +34,9 @@ static inline short_ad lesa_to_cpu(short_ad in) return out; } -static inline short_ad cpu_to_lesa(short_ad in) +static inline struct short_ad cpu_to_lesa(struct short_ad in) { - short_ad out; + struct short_ad out; out.extLength = cpu_to_le32(in.extLength); out.extPosition = cpu_to_le32(in.extPosition); @@ -44,9 +44,9 @@ static inline short_ad cpu_to_lesa(short_ad in) return out; } -static inline kernel_long_ad lela_to_cpu(long_ad in) +static inline struct kernel_long_ad lela_to_cpu(struct long_ad in) { - kernel_long_ad out; + struct kernel_long_ad out; out.extLength = le32_to_cpu(in.extLength); out.extLocation = lelb_to_cpu(in.extLocation); @@ -54,9 +54,9 @@ static inline kernel_long_ad lela_to_cpu(long_ad in) return out; } -static inline long_ad cpu_to_lela(kernel_long_ad in) +static inline struct long_ad cpu_to_lela(struct kernel_long_ad in) { - long_ad out; + struct long_ad out; out.extLength = cpu_to_le32(in.extLength); out.extLocation = cpu_to_lelb(in.extLocation); @@ -64,9 +64,9 @@ static inline long_ad cpu_to_lela(kernel_long_ad in) return out; } -static inline kernel_extent_ad leea_to_cpu(extent_ad in) +static inline struct kernel_extent_ad leea_to_cpu(struct extent_ad in) { - kernel_extent_ad out; + struct kernel_extent_ad out; out.extLength = le32_to_cpu(in.extLength); out.extLocation = le32_to_cpu(in.extLocation); diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c index 5f811655..b8c828c 100644 --- a/fs/udf/udftime.c +++ b/fs/udf/udftime.c @@ -85,7 +85,8 @@ extern struct timezone sys_tz; #define SECS_PER_HOUR (60 * 60) #define SECS_PER_DAY (SECS_PER_HOUR * 24) -struct timespec *udf_disk_stamp_to_time(struct timespec *dest, timestamp src) +struct timespec * +udf_disk_stamp_to_time(struct timespec *dest, struct timestamp src) { int yday; u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone); @@ -116,7 +117,8 @@ struct timespec *udf_disk_stamp_to_time(struct timespec *dest, timestamp src) return dest; } -timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec ts) +struct timestamp * +udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts) { long int days, rem, y; const unsigned short int *ip; diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 9fdf8c9..cefa8c8 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c @@ -254,7 +254,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, { const uint8_t *ocu; uint8_t cmp_id, ocu_len; - int i; + int i, len; ocu_len = ocu_i->u_len; @@ -279,8 +279,13 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, if (cmp_id == 16) c = (c << 8) | ocu[i++]; - utf_o->u_len += nls->uni2char(c, &utf_o->u_name[utf_o->u_len], - UDF_NAME_LEN - utf_o->u_len); + len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len], + UDF_NAME_LEN - utf_o->u_len); + /* Valid character? */ + if (len >= 0) + utf_o->u_len += len; + else + utf_o->u_name[utf_o->u_len++] = '?'; } utf_o->u_cmpID = 8; @@ -290,7 +295,8 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, int length) { - unsigned len, i, max_val; + int len; + unsigned i, max_val; uint16_t uni_char; int u_len; @@ -302,8 +308,13 @@ try_again: u_len = 0U; for (i = 0U; i < uni->u_len; i++) { len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char); - if (len <= 0) + if (!len) continue; + /* Invalid character, deal with it */ + if (len < 0) { + len = 1; + uni_char = '?'; + } if (uni_char > max_val) { max_val = 0xffffU; @@ -324,34 +335,43 @@ try_again: int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, int flen) { - struct ustr filename, unifilename; - int len; + struct ustr *filename, *unifilename; + int len = 0; - if (udf_build_ustr_exact(&unifilename, sname, flen)) + filename = kmalloc(sizeof(struct ustr), GFP_NOFS); + if (!filename) return 0; + unifilename = kmalloc(sizeof(struct ustr), GFP_NOFS); + if (!unifilename) + goto out1; + + if (udf_build_ustr_exact(unifilename, sname, flen)) + goto out2; + if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { - if (!udf_CS0toUTF8(&filename, &unifilename)) { + if (!udf_CS0toUTF8(filename, unifilename)) { udf_debug("Failed in udf_get_filename: sname = %s\n", sname); - return 0; + goto out2; } } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { - if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, &filename, - &unifilename)) { + if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, filename, + unifilename)) { udf_debug("Failed in udf_get_filename: sname = %s\n", sname); - return 0; + goto out2; } } else - return 0; - - len = udf_translate_to_linux(dname, filename.u_name, filename.u_len, - unifilename.u_name, unifilename.u_len); - if (len) - return len; - - return 0; + goto out2; + + len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, + unifilename->u_name, unifilename->u_len); +out2: + kfree(unifilename); +out1: + kfree(filename); + return len; } int udf_put_filename(struct super_block *sb, const uint8_t *sname, diff --git a/fs/ufs/super.c b/fs/ufs/super.c index e1c1fc5..6035929 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -1268,6 +1268,7 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf) struct ufs_super_block_first *usb1; struct ufs_super_block_second *usb2; struct ufs_super_block_third *usb3; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); lock_kernel(); @@ -1290,6 +1291,8 @@ static int ufs_statfs(struct dentry *dentry, struct kstatfs *buf) ? (buf->f_bfree - (((long)buf->f_blocks / 100) * uspi->s_minfree)) : 0; buf->f_files = uspi->s_ncg * uspi->s_ipg; buf->f_namelen = UFS_MAXNAMLEN; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); unlock_kernel(); diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 631d013..6075382 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c @@ -230,7 +230,7 @@ xfs_vn_mknod( } if (IS_POSIXACL(dir) && !default_acl) - mode &= ~current->fs->umask; + mode &= ~current_umask(); xfs_dentry_to_name(&name, dentry); error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL); @@ -404,7 +404,7 @@ xfs_vn_symlink( mode_t mode; mode = S_IFLNK | - (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); + (irix_symlink_mode ? 0777 & ~current_umask() : S_IRWXUGO); xfs_dentry_to_name(&name, dentry); error = xfs_symlink(XFS_I(dir), &name, symname, mode, &cip, NULL); |