Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs changes from Al Viro.
 "A lot of misc stuff.  The obvious groups:
   * Miklos' atomic_open series; kills the damn abuse of
     ->d_revalidate() by NFS, which was the major stumbling block for
     all work in that area.
   * ripping security_file_mmap() and dealing with deadlocks in the
     area; sanitizing the neighborhood of vm_mmap()/vm_munmap() in
     general.
   * ->encode_fh() switched to saner API; insane fake dentry in
     mm/cleancache.c gone.
   * assorted annotations in fs (endianness, __user)
   * parts of Artem's ->s_dirty work (jff2 and reiserfs parts)
   * ->update_time() work from Josef.
   * other bits and pieces all over the place.

  Normally it would've been in two or three pull requests, but
  signal.git stuff had eaten a lot of time during this cycle ;-/"

Fix up trivial conflicts in Documentation/filesystems/vfs.txt (the
'truncate_range' inode method was removed by the VM changes, the VFS
update adds an 'update_time()' method), and in fs/btrfs/ulist.[ch] (due
to sparse fix added twice, with other changes nearby).

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (95 commits)
  nfs: don't open in ->d_revalidate
  vfs: retry last component if opening stale dentry
  vfs: nameidata_to_filp(): don't throw away file on error
  vfs: nameidata_to_filp(): inline __dentry_open()
  vfs: do_dentry_open(): don't put filp
  vfs: split __dentry_open()
  vfs: do_last() common post lookup
  vfs: do_last(): add audit_inode before open
  vfs: do_last(): only return EISDIR for O_CREAT
  vfs: do_last(): check LOOKUP_DIRECTORY
  vfs: do_last(): make ENOENT exit RCU safe
  vfs: make follow_link check RCU safe
  vfs: do_last(): use inode variable
  vfs: do_last(): inline walk_component()
  vfs: do_last(): make exit RCU safe
  vfs: split do_lookup()
  Btrfs: move over to use ->update_time
  fs: introduce inode operation ->update_time
  reiserfs: get rid of resierfs_sync_super
  reiserfs: mark the superblock as dirty a bit later
  ...
This commit is contained in:
Linus Torvalds 2012-06-01 10:34:35 -07:00
commit 1193755ac6
148 changed files with 1497 additions and 1620 deletions

View File

@ -61,6 +61,7 @@ ata *);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
void (*update_time)(struct inode *, struct timespec *, int);
locking rules:
all may block
@ -87,6 +88,8 @@ getxattr: no
listxattr: no
removexattr: yes
fiemap: no
update_time: no
Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
victim.
cross-directory ->rename() has (per-superblock) ->s_vfs_rename_sem.

View File

@ -363,6 +363,7 @@ struct inode_operations {
ssize_t (*getxattr) (struct dentry *, const char *, void *, size_t);
ssize_t (*listxattr) (struct dentry *, char *, size_t);
int (*removexattr) (struct dentry *, const char *);
void (*update_time)(struct inode *, struct timespec *, int);
};
Again, all methods are called without any locks being held, unless
@ -471,6 +472,9 @@ otherwise noted.
removexattr: called by the VFS to remove an extended attribute from
a file. This method is called by removexattr(2) system call.
update_time: called by the VFS to update a specific time or the i_version of
an inode. If this is not defined the VFS will update the inode itself
and call mark_inode_dirty_sync.
The Address Space Object
========================

View File

@ -10,9 +10,6 @@
typedef unsigned int __kernel_ino_t;
#define __kernel_ino_t __kernel_ino_t
typedef unsigned int __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned long __kernel_sigset_t; /* at least 32 bits */
#include <asm-generic/posix_types.h>

View File

@ -22,9 +22,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -17,9 +17,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -10,9 +10,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned int __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -15,9 +15,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -10,9 +10,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -10,9 +10,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -1,9 +1,6 @@
#ifndef _ASM_IA64_POSIX_TYPES_H
#define _ASM_IA64_POSIX_TYPES_H
typedef unsigned int __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned long __kernel_sigset_t; /* at least 32 bits */
#include <asm-generic/posix_types.h>

View File

@ -604,12 +604,6 @@ pfm_unprotect_ctx_ctxsw(pfm_context_t *x, unsigned long f)
spin_unlock(&(x)->ctx_lock);
}
static inline unsigned long
pfm_get_unmapped_area(struct file *file, unsigned long addr, unsigned long len, unsigned long pgoff, unsigned long flags, unsigned long exec)
{
return get_unmapped_area(file, addr, len, pgoff, flags);
}
/* forward declaration */
static const struct dentry_operations pfmfs_dentry_operations;
@ -2333,8 +2327,8 @@ pfm_smpl_buffer_alloc(struct task_struct *task, struct file *filp, pfm_context_t
down_write(&task->mm->mmap_sem);
/* find some free area in address space, must have mmap sem held */
vma->vm_start = pfm_get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS, 0);
if (vma->vm_start == 0UL) {
vma->vm_start = get_unmapped_area(NULL, 0, size, 0, MAP_PRIVATE|MAP_ANONYMOUS);
if (IS_ERR_VALUE(vma->vm_start)) {
DPRINT(("Cannot find unmapped area for size %ld\n", size));
up_write(&task->mm->mmap_sem);
goto error;

View File

@ -171,22 +171,9 @@ asmlinkage unsigned long
ia64_mremap (unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags,
unsigned long new_addr)
{
extern unsigned long do_mremap (unsigned long addr,
unsigned long old_len,
unsigned long new_len,
unsigned long flags,
unsigned long new_addr);
down_write(&current->mm->mmap_sem);
{
addr = do_mremap(addr, old_len, new_len, flags, new_addr);
}
up_write(&current->mm->mmap_sem);
if (IS_ERR((void *) addr))
return addr;
force_successful_syscall_return();
addr = sys_mremap(addr, old_len, new_len, flags, new_addr);
if (!IS_ERR((void *) addr))
force_successful_syscall_return();
return addr;
}

View File

@ -10,9 +10,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -10,9 +10,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -17,11 +17,6 @@
* assume GCC is being used.
*/
#if (_MIPS_SZLONG == 64)
typedef unsigned int __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
#endif
typedef long __kernel_daddr_t;
#define __kernel_daddr_t __kernel_daddr_t

View File

@ -20,7 +20,7 @@ struct stat {
long st_pad1[3]; /* Reserved for network id */
ino_t st_ino;
mode_t st_mode;
nlink_t st_nlink;
__u32 st_nlink;
uid_t st_uid;
gid_t st_gid;
unsigned st_rdev;
@ -55,7 +55,7 @@ struct stat64 {
unsigned long long st_ino;
mode_t st_mode;
nlink_t st_nlink;
__u32 st_nlink;
uid_t st_uid;
gid_t st_gid;
@ -96,7 +96,7 @@ struct stat {
unsigned long st_ino;
mode_t st_mode;
nlink_t st_nlink;
__u32 st_nlink;
uid_t st_uid;
gid_t st_gid;

View File

@ -20,9 +20,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -10,9 +10,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -7,7 +7,7 @@ struct stat {
unsigned int st_dev; /* dev_t is 32 bits on parisc */
ino_t st_ino; /* 32 bits */
mode_t st_mode; /* 16 bits */
nlink_t st_nlink; /* 16 bits */
unsigned short st_nlink; /* 16 bits */
unsigned short st_reserved1; /* old st_uid */
unsigned short st_reserved2; /* old st_gid */
unsigned int st_rdev;
@ -42,7 +42,7 @@ struct hpux_stat64 {
unsigned int st_dev; /* dev_t is 32 bits on parisc */
ino_t st_ino; /* 32 bits */
mode_t st_mode; /* 16 bits */
nlink_t st_nlink; /* 16 bits */
unsigned short st_nlink; /* 16 bits */
unsigned short st_reserved1; /* old st_uid */
unsigned short st_reserved2; /* old st_gid */
unsigned int st_rdev;

View File

@ -16,9 +16,6 @@ typedef int __kernel_ssize_t;
typedef long __kernel_ptrdiff_t;
#define __kernel_size_t __kernel_size_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
#endif

View File

@ -30,11 +30,11 @@ struct stat {
unsigned long st_dev;
ino_t st_ino;
#ifdef __powerpc64__
nlink_t st_nlink;
unsigned short st_nlink;
mode_t st_mode;
#else
mode_t st_mode;
nlink_t st_nlink;
unsigned short st_nlink;
#endif
uid_t st_uid;
gid_t st_gid;

View File

@ -24,7 +24,6 @@ typedef unsigned short __kernel_old_dev_t;
typedef unsigned long __kernel_ino_t;
typedef unsigned short __kernel_mode_t;
typedef unsigned short __kernel_nlink_t;
typedef unsigned short __kernel_ipc_pid_t;
typedef unsigned short __kernel_uid_t;
typedef unsigned short __kernel_gid_t;
@ -35,7 +34,6 @@ typedef int __kernel_ptrdiff_t;
typedef unsigned int __kernel_ino_t;
typedef unsigned int __kernel_mode_t;
typedef unsigned int __kernel_nlink_t;
typedef int __kernel_ipc_pid_t;
typedef unsigned int __kernel_uid_t;
typedef unsigned int __kernel_gid_t;
@ -47,7 +45,6 @@ typedef unsigned long __kernel_sigset_t; /* at least 32 bits */
#define __kernel_ino_t __kernel_ino_t
#define __kernel_mode_t __kernel_mode_t
#define __kernel_nlink_t __kernel_nlink_t
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
#define __kernel_uid_t __kernel_uid_t
#define __kernel_gid_t __kernel_gid_t

View File

@ -3,8 +3,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
typedef unsigned short __kernel_uid_t;

View File

@ -3,8 +3,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t
typedef unsigned short __kernel_uid_t;

View File

@ -9,8 +9,6 @@
#if defined(__sparc__) && defined(__arch64__)
/* sparc 64 bit */
typedef unsigned int __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_old_uid_t;
typedef unsigned short __kernel_old_gid_t;
@ -38,9 +36,6 @@ typedef unsigned short __kernel_gid_t;
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef long __kernel_daddr_t;
#define __kernel_daddr_t __kernel_daddr_t

View File

@ -580,16 +580,9 @@ SYSCALL_DEFINE5(64_mremap, unsigned long, addr, unsigned long, old_len,
unsigned long, new_len, unsigned long, flags,
unsigned long, new_addr)
{
unsigned long ret = -EINVAL;
if (test_thread_flag(TIF_32BIT))
goto out;
down_write(&current->mm->mmap_sem);
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
up_write(&current->mm->mmap_sem);
out:
return ret;
return -EINVAL;
return sys_mremap(addr, old_len, new_len, flags, new_addr);
}
/* we come to here via sys_nis_syscall so it can setup the regs argument */

View File

@ -44,7 +44,6 @@ typedef __kernel_uid32_t __compat_gid32_t;
typedef __kernel_mode_t compat_mode_t;
typedef __kernel_dev_t compat_dev_t;
typedef __kernel_loff_t compat_loff_t;
typedef __kernel_nlink_t compat_nlink_t;
typedef __kernel_ipc_pid_t compat_ipc_pid_t;
typedef __kernel_daddr_t compat_daddr_t;
typedef __kernel_fsid_t compat_fsid_t;

View File

@ -10,9 +10,6 @@
typedef unsigned short __kernel_mode_t;
#define __kernel_mode_t __kernel_mode_t
typedef unsigned short __kernel_nlink_t;
#define __kernel_nlink_t __kernel_nlink_t
typedef unsigned short __kernel_ipc_pid_t;
#define __kernel_ipc_pid_t __kernel_ipc_pid_t

View File

@ -42,7 +42,7 @@ struct device *soc_device_to_device(struct soc_device *soc_dev)
return &soc_dev->dev;
}
static mode_t soc_attribute_mode(struct kobject *kobj,
static umode_t soc_attribute_mode(struct kobject *kobj,
struct attribute *attr,
int index)
{

View File

@ -130,11 +130,10 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
return -EINVAL;
/* This is all entirely broken */
down_write(&current->mm->mmap_sem);
old_fops = file_priv->filp->f_op;
file_priv->filp->f_op = &i810_buffer_fops;
dev_priv->mmap_buffer = buf;
buf_priv->virtual = (void *)do_mmap(file_priv->filp, 0, buf->total,
buf_priv->virtual = (void *)vm_mmap(file_priv->filp, 0, buf->total,
PROT_READ | PROT_WRITE,
MAP_SHARED, buf->bus_address);
dev_priv->mmap_buffer = NULL;
@ -145,7 +144,6 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
retcode = PTR_ERR(buf_priv->virtual);
buf_priv->virtual = NULL;
}
up_write(&current->mm->mmap_sem);
return retcode;
}

View File

@ -68,24 +68,6 @@ static gid_t v9fs_get_fsgid_for_create(struct inode *dir_inode)
return current_fsgid();
}
/**
* v9fs_dentry_from_dir_inode - helper function to get the dentry from
* dir inode.
*
*/
static struct dentry *v9fs_dentry_from_dir_inode(struct inode *inode)
{
struct dentry *dentry;
spin_lock(&inode->i_lock);
/* Directory should have only one entry. */
BUG_ON(S_ISDIR(inode->i_mode) && !list_is_singular(&inode->i_dentry));
dentry = list_entry(inode->i_dentry.next, struct dentry, d_alias);
spin_unlock(&inode->i_lock);
return dentry;
}
static int v9fs_test_inode_dotl(struct inode *inode, void *data)
{
struct v9fs_inode *v9inode = V9FS_I(inode);
@ -415,7 +397,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir,
if (dir->i_mode & S_ISGID)
omode |= S_ISGID;
dir_dentry = v9fs_dentry_from_dir_inode(dir);
dir_dentry = dentry->d_parent;
dfid = v9fs_fid_lookup(dir_dentry);
if (IS_ERR(dfid)) {
err = PTR_ERR(dfid);
@ -793,7 +775,7 @@ v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir,
dir->i_ino, old_dentry->d_name.name, dentry->d_name.name);
v9ses = v9fs_inode2v9ses(dir);
dir_dentry = v9fs_dentry_from_dir_inode(dir);
dir_dentry = dentry->d_parent;
dfid = v9fs_fid_lookup(dir_dentry);
if (IS_ERR(dfid))
return PTR_ERR(dfid);
@ -858,7 +840,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
return -EINVAL;
v9ses = v9fs_inode2v9ses(dir);
dir_dentry = v9fs_dentry_from_dir_inode(dir);
dir_dentry = dentry->d_parent;
dfid = v9fs_fid_lookup(dir_dentry);
if (IS_ERR(dfid)) {
err = PTR_ERR(dfid);

View File

@ -18,14 +18,6 @@
#define AFFS_GET_HASHENTRY(data,hashkey) be32_to_cpu(((struct dir_front *)data)->hashtable[hashkey])
#define AFFS_BLOCK(sb, bh, blk) (AFFS_HEAD(bh)->table[AFFS_SB(sb)->s_hashsize-1-(blk)])
#ifdef __LITTLE_ENDIAN
#define BO_EXBITS 0x18UL
#elif defined(__BIG_ENDIAN)
#define BO_EXBITS 0x00UL
#else
#error Endianness must be known for affs to work.
#endif
#define AFFS_HEAD(bh) ((struct affs_head *)(bh)->b_data)
#define AFFS_TAIL(sb, bh) ((struct affs_tail *)((bh)->b_data+(sb)->s_blocksize-sizeof(struct affs_tail)))
#define AFFS_ROOT_HEAD(bh) ((struct affs_root_head *)(bh)->b_data)

View File

@ -134,9 +134,9 @@ static int aio_setup_ring(struct kioctx *ctx)
info->mmap_size = nr_pages * PAGE_SIZE;
dprintk("attempting mmap of %lu bytes\n", info->mmap_size);
down_write(&ctx->mm->mmap_sem);
info->mmap_base = do_mmap(NULL, 0, info->mmap_size,
PROT_READ|PROT_WRITE, MAP_ANONYMOUS|MAP_PRIVATE,
0);
info->mmap_base = do_mmap_pgoff(NULL, 0, info->mmap_size,
PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, 0);
if (IS_ERR((void *)info->mmap_base)) {
up_write(&ctx->mm->mmap_sem);
info->mmap_size = 0;

View File

@ -176,6 +176,11 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
return -EPERM;
}
if ((ia_valid & ATTR_SIZE) && IS_I_VERSION(inode)) {
if (attr->ia_size != inode->i_size)
inode_inc_iversion(inode);
}
if ((ia_valid & ATTR_MODE)) {
umode_t amode = attr->ia_mode;
/* Flag setting protected by i_mutex */

View File

@ -329,7 +329,6 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
if (!size)
return addr;
down_write(&current->mm->mmap_sem);
/*
* total_size is the size of the ELF (interpreter) image.
* The _first_ mmap needs to know the full size, otherwise
@ -340,13 +339,12 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
*/
if (total_size) {
total_size = ELF_PAGEALIGN(total_size);
map_addr = do_mmap(filep, addr, total_size, prot, type, off);
map_addr = vm_mmap(filep, addr, total_size, prot, type, off);
if (!BAD_ADDR(map_addr))
do_munmap(current->mm, map_addr+size, total_size-size);
vm_munmap(map_addr+size, total_size-size);
} else
map_addr = do_mmap(filep, addr, size, prot, type, off);
map_addr = vm_mmap(filep, addr, size, prot, type, off);
up_write(&current->mm->mmap_sem);
return(map_addr);
}

View File

@ -562,7 +562,7 @@ static int load_flat_file(struct linux_binprm * bprm,
realdatastart = (unsigned long) -ENOMEM;
printk("Unable to allocate RAM for process data, errno %d\n",
(int)-realdatastart);
do_munmap(current->mm, textpos, text_len);
vm_munmap(textpos, text_len);
ret = realdatastart;
goto err;
}
@ -586,8 +586,8 @@ static int load_flat_file(struct linux_binprm * bprm,
}
if (IS_ERR_VALUE(result)) {
printk("Unable to read data+bss, errno %d\n", (int)-result);
do_munmap(current->mm, textpos, text_len);
do_munmap(current->mm, realdatastart, len);
vm_munmap(textpos, text_len);
vm_munmap(realdatastart, len);
ret = result;
goto err;
}
@ -654,7 +654,7 @@ static int load_flat_file(struct linux_binprm * bprm,
}
if (IS_ERR_VALUE(result)) {
printk("Unable to read code+data+bss, errno %d\n",(int)-result);
do_munmap(current->mm, textpos, text_len + data_len + extra +
vm_munmap(textpos, text_len + data_len + extra +
MAX_SHARED_LIBS * sizeof(unsigned long));
ret = result;
goto err;

View File

@ -2974,7 +2974,6 @@ int btrfs_readpage(struct file *file, struct page *page);
void btrfs_evict_inode(struct inode *inode);
int btrfs_write_inode(struct inode *inode, struct writeback_control *wbc);
int btrfs_dirty_inode(struct inode *inode);
int btrfs_update_time(struct file *file);
struct inode *btrfs_alloc_inode(struct super_block *sb);
void btrfs_destroy_inode(struct inode *inode);
int btrfs_drop_inode(struct inode *inode);

View File

@ -13,15 +13,14 @@
parent_root_objectid) / 4)
#define BTRFS_FID_SIZE_CONNECTABLE_ROOT (sizeof(struct btrfs_fid) / 4)
static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
int connectable)
static int btrfs_encode_fh(struct inode *inode, u32 *fh, int *max_len,
struct inode *parent)
{
struct btrfs_fid *fid = (struct btrfs_fid *)fh;
struct inode *inode = dentry->d_inode;
int len = *max_len;
int type;
if (connectable && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
if (parent && (len < BTRFS_FID_SIZE_CONNECTABLE)) {
*max_len = BTRFS_FID_SIZE_CONNECTABLE;
return 255;
} else if (len < BTRFS_FID_SIZE_NON_CONNECTABLE) {
@ -36,19 +35,13 @@ static int btrfs_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
fid->root_objectid = BTRFS_I(inode)->root->objectid;
fid->gen = inode->i_generation;
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
if (parent) {
u64 parent_root_id;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
fid->parent_objectid = BTRFS_I(parent)->location.objectid;
fid->parent_gen = parent->i_generation;
parent_root_id = BTRFS_I(parent)->root->objectid;
spin_unlock(&dentry->d_lock);
if (parent_root_id != fid->root_objectid) {
fid->parent_root_objectid = parent_root_id;
len = BTRFS_FID_SIZE_CONNECTABLE_ROOT;

View File

@ -1433,7 +1433,7 @@ static ssize_t btrfs_file_aio_write(struct kiocb *iocb,
goto out;
}
err = btrfs_update_time(file);
err = file_update_time(file);
if (err) {
mutex_unlock(&inode->i_mutex);
goto out;

View File

@ -77,7 +77,8 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root,
return ERR_PTR(-ENOENT);
}
inode->i_mapping->flags &= ~__GFP_FS;
mapping_set_gfp_mask(inode->i_mapping,
mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS);
return inode;
}
@ -367,7 +368,7 @@ static int io_ctl_prepare_pages(struct io_ctl *io_ctl, struct inode *inode,
static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation)
{
u64 *val;
__le64 *val;
io_ctl_map_page(io_ctl, 1);
@ -390,7 +391,7 @@ static void io_ctl_set_generation(struct io_ctl *io_ctl, u64 generation)
static int io_ctl_check_generation(struct io_ctl *io_ctl, u64 generation)
{
u64 *gen;
__le64 *gen;
/*
* Skip the crc area. If we don't check crcs then we just have a 64bit

View File

@ -4475,46 +4475,18 @@ int btrfs_dirty_inode(struct inode *inode)
* This is a copy of file_update_time. We need this so we can return error on
* ENOSPC for updating the inode in the case of file write and mmap writes.
*/
int btrfs_update_time(struct file *file)
static int btrfs_update_time(struct inode *inode, struct timespec *now,
int flags)
{
struct inode *inode = file->f_path.dentry->d_inode;
struct timespec now;
int ret;
enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0;
/* First try to exhaust all avenues to not sync */
if (IS_NOCMTIME(inode))
return 0;
now = current_fs_time(inode->i_sb);
if (!timespec_equal(&inode->i_mtime, &now))
sync_it = S_MTIME;
if (!timespec_equal(&inode->i_ctime, &now))
sync_it |= S_CTIME;
if (IS_I_VERSION(inode))
sync_it |= S_VERSION;
if (!sync_it)
return 0;
/* Finally allowed to write? Takes lock. */
if (mnt_want_write_file(file))
return 0;
/* Only change inode inside the lock region */
if (sync_it & S_VERSION)
if (flags & S_VERSION)
inode_inc_iversion(inode);
if (sync_it & S_CTIME)
inode->i_ctime = now;
if (sync_it & S_MTIME)
inode->i_mtime = now;
ret = btrfs_dirty_inode(inode);
if (!ret)
mark_inode_dirty_sync(inode);
mnt_drop_write(file->f_path.mnt);
return ret;
if (flags & S_CTIME)
inode->i_ctime = *now;
if (flags & S_MTIME)
inode->i_mtime = *now;
if (flags & S_ATIME)
inode->i_atime = *now;
return btrfs_dirty_inode(inode);
}
/*
@ -6565,7 +6537,7 @@ int btrfs_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
ret = btrfs_delalloc_reserve_space(inode, PAGE_CACHE_SIZE);
if (!ret) {
ret = btrfs_update_time(vma->vm_file);
ret = file_update_time(vma->vm_file);
reserved = 1;
}
if (ret) {
@ -7635,6 +7607,7 @@ static const struct inode_operations btrfs_file_inode_operations = {
.permission = btrfs_permission,
.fiemap = btrfs_fiemap,
.get_acl = btrfs_get_acl,
.update_time = btrfs_update_time,
};
static const struct inode_operations btrfs_special_inode_operations = {
.getattr = btrfs_getattr,
@ -7645,6 +7618,7 @@ static const struct inode_operations btrfs_special_inode_operations = {
.listxattr = btrfs_listxattr,
.removexattr = btrfs_removexattr,
.get_acl = btrfs_get_acl,
.update_time = btrfs_update_time,
};
static const struct inode_operations btrfs_symlink_inode_operations = {
.readlink = generic_readlink,
@ -7658,6 +7632,7 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
.listxattr = btrfs_listxattr,
.removexattr = btrfs_removexattr,
.get_acl = btrfs_get_acl,
.update_time = btrfs_update_time,
};
const struct dentry_operations btrfs_dentry_operations = {

View File

@ -3152,7 +3152,7 @@ SYSCALL_DEFINE2(bdflush, int, func, long, data)
/*
* Buffer-head allocation
*/
static struct kmem_cache *bh_cachep;
static struct kmem_cache *bh_cachep __read_mostly;
/*
* Once the number of bh's in the machine exceeds this level, we start

View File

@ -40,38 +40,49 @@ struct ceph_nfs_confh {
u32 parent_name_hash;
} __attribute__ ((packed));
static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
int connectable)
/*
* The presence of @parent_inode here tells us whether NFS wants a
* connectable file handle. However, we want to make a connectionable
* file handle unconditionally so that the MDS gets as much of a hint
* as possible. That means we only use @parent_dentry to indicate
* whether nfsd wants a connectable fh, and whether we should indicate
* failure from a too-small @max_len.
*/
static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,
struct inode *parent_inode)
{
int type;
struct ceph_nfs_fh *fh = (void *)rawfh;
struct ceph_nfs_confh *cfh = (void *)rawfh;
struct dentry *parent;
struct inode *inode = dentry->d_inode;
int connected_handle_length = sizeof(*cfh)/4;
int handle_length = sizeof(*fh)/4;
struct dentry *dentry = d_find_alias(inode);
struct dentry *parent;
/* don't re-export snaps */
if (ceph_snap(inode) != CEPH_NOSNAP)
return -EINVAL;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent;
if (*max_len >= connected_handle_length) {
/* if we found an alias, generate a connectable fh */
if (*max_len >= connected_handle_length && dentry) {
dout("encode_fh %p connectable\n", dentry);
cfh->ino = ceph_ino(dentry->d_inode);
spin_lock(&dentry->d_lock);
parent = dentry->d_parent;
cfh->ino = ceph_ino(inode);
cfh->parent_ino = ceph_ino(parent->d_inode);
cfh->parent_name_hash = ceph_dentry_hash(parent->d_inode,
dentry);
*max_len = connected_handle_length;
type = 2;
spin_unlock(&dentry->d_lock);
} else if (*max_len >= handle_length) {
if (connectable) {
if (parent_inode) {
/* nfsd wants connectable */
*max_len = connected_handle_length;
type = 255;
} else {
dout("encode_fh %p\n", dentry);
fh->ino = ceph_ino(dentry->d_inode);
fh->ino = ceph_ino(inode);
*max_len = handle_length;
type = 1;
}
@ -79,7 +90,6 @@ static int ceph_encode_fh(struct dentry *dentry, u32 *rawfh, int *max_len,
*max_len = handle_length;
type = 255;
}
spin_unlock(&dentry->d_lock);
return type;
}

View File

@ -871,12 +871,12 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
{
int error;
struct file *file;
int fput_needed;
struct compat_readdir_callback buf;
error = -EBADF;
file = fget(fd);
file = fget_light(fd, &fput_needed);
if (!file)
goto out;
return -EBADF;
buf.result = 0;
buf.dirent = dirent;
@ -885,8 +885,7 @@ asmlinkage long compat_sys_old_readdir(unsigned int fd,
if (buf.result)
error = buf.result;
fput(file);
out:
fput_light(file, fput_needed);
return error;
}
@ -953,16 +952,15 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
struct file * file;
struct compat_linux_dirent __user * lastdirent;
struct compat_getdents_callback buf;
int fput_needed;
int error;
error = -EFAULT;
if (!access_ok(VERIFY_WRITE, dirent, count))
goto out;
return -EFAULT;
error = -EBADF;
file = fget(fd);
file = fget_light(fd, &fput_needed);
if (!file)
goto out;
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
@ -979,8 +977,7 @@ asmlinkage long compat_sys_getdents(unsigned int fd,
else
error = count - buf.count;
}
fput(file);
out:
fput_light(file, fput_needed);
return error;
}
@ -1041,16 +1038,15 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
struct file * file;
struct linux_dirent64 __user * lastdirent;
struct compat_getdents_callback64 buf;
int fput_needed;
int error;
error = -EFAULT;
if (!access_ok(VERIFY_WRITE, dirent, count))
goto out;
return -EFAULT;
error = -EBADF;
file = fget(fd);
file = fget_light(fd, &fput_needed);
if (!file)
goto out;
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
@ -1068,8 +1064,7 @@ asmlinkage long compat_sys_getdents64(unsigned int fd,
else
error = count - buf.count;
}
fput(file);
out:
fput_light(file, fput_needed);
return error;
}
#endif /* ! __ARCH_OMIT_COMPAT_SYS_GETDENTS64 */

View File

@ -683,8 +683,6 @@ EXPORT_SYMBOL(dget_parent);
/**
* d_find_alias - grab a hashed alias of inode
* @inode: inode in question
* @want_discon: flag, used by d_splice_alias, to request
* that only a DISCONNECTED alias be returned.
*
* If inode has a hashed alias, or is a directory and has any alias,
* acquire the reference to alias and return it. Otherwise return NULL.
@ -693,10 +691,9 @@ EXPORT_SYMBOL(dget_parent);
* of a filesystem.
*
* If the inode has an IS_ROOT, DCACHE_DISCONNECTED alias, then prefer
* any other hashed alias over that one unless @want_discon is set,
* in which case only return an IS_ROOT, DCACHE_DISCONNECTED alias.
* any other hashed alias over that.
*/
static struct dentry *__d_find_alias(struct inode *inode, int want_discon)
static struct dentry *__d_find_alias(struct inode *inode)
{
struct dentry *alias, *discon_alias;
@ -708,7 +705,7 @@ static struct dentry *__d_find_alias(struct inode *inode, int want_discon)
if (IS_ROOT(alias) &&
(alias->d_flags & DCACHE_DISCONNECTED)) {
discon_alias = alias;
} else if (!want_discon) {
} else {
__dget_dlock(alias);
spin_unlock(&alias->d_lock);
return alias;
@ -739,7 +736,7 @@ struct dentry *d_find_alias(struct inode *inode)
if (!list_empty(&inode->i_dentry)) {
spin_lock(&inode->i_lock);
de = __d_find_alias(inode, 0);
de = __d_find_alias(inode);
spin_unlock(&inode->i_lock);
}
return de;
@ -1650,9 +1647,8 @@ struct dentry *d_splice_alias(struct inode *inode, struct dentry *dentry)
if (inode && S_ISDIR(inode->i_mode)) {
spin_lock(&inode->i_lock);
new = __d_find_alias(inode, 1);
new = __d_find_any_alias(inode);
if (new) {
BUG_ON(!(new->d_flags & DCACHE_DISCONNECTED));
spin_unlock(&inode->i_lock);
security_d_instantiate(new, inode);
d_move(new, dentry);
@ -2482,7 +2478,7 @@ struct dentry *d_materialise_unique(struct dentry *dentry, struct inode *inode)
struct dentry *alias;
/* Does an aliased dentry already exist? */
alias = __d_find_alias(inode, 0);
alias = __d_find_alias(inode);
if (alias) {
actual = alias;
write_seqlock(&rename_lock);
@ -2575,7 +2571,7 @@ static int prepend_path(const struct path *path,
bool slash = false;
int error = 0;
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
while (dentry != root->dentry || vfsmnt != root->mnt) {
struct dentry * parent;
@ -2606,7 +2602,7 @@ static int prepend_path(const struct path *path,
error = prepend(buffer, buflen, "/", 1);
out:
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
return error;
global_root:

View File

@ -660,11 +660,10 @@ static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
{
struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry);
char *lower_buf;
size_t lower_bufsiz = PATH_MAX;
mm_segment_t old_fs;
int rc;
lower_buf = kmalloc(lower_bufsiz, GFP_KERNEL);
lower_buf = kmalloc(PATH_MAX, GFP_KERNEL);
if (!lower_buf) {
rc = -ENOMEM;
goto out;
@ -673,58 +672,29 @@ static int ecryptfs_readlink_lower(struct dentry *dentry, char **buf,
set_fs(get_ds());
rc = lower_dentry->d_inode->i_op->readlink(lower_dentry,
(char __user *)lower_buf,
lower_bufsiz);
PATH_MAX);
set_fs(old_fs);
if (rc < 0)
goto out;
lower_bufsiz = rc;
rc = ecryptfs_decode_and_decrypt_filename(buf, bufsiz, dentry,
lower_buf, lower_bufsiz);
lower_buf, rc);
out:
kfree(lower_buf);
return rc;
}
static int
ecryptfs_readlink(struct dentry *dentry, char __user *buf, int bufsiz)
{
char *kbuf;
size_t kbufsiz, copied;
int rc;
rc = ecryptfs_readlink_lower(dentry, &kbuf, &kbufsiz);
if (rc)
goto out;
copied = min_t(size_t, bufsiz, kbufsiz);
rc = copy_to_user(buf, kbuf, copied) ? -EFAULT : copied;
kfree(kbuf);
fsstack_copy_attr_atime(dentry->d_inode,
ecryptfs_dentry_to_lower(dentry)->d_inode);
out:
return rc;
}
static void *ecryptfs_follow_link(struct dentry *dentry, struct nameidata *nd)
{
char *buf;
int len = PAGE_SIZE, rc;
mm_segment_t old_fs;
size_t len = PATH_MAX;
int rc;
/* Released in ecryptfs_put_link(); only release here on error */
buf = kmalloc(len, GFP_KERNEL);
if (!buf) {
buf = ERR_PTR(-ENOMEM);
rc = ecryptfs_readlink_lower(dentry, &buf, &len);
if (rc)
goto out;
}
old_fs = get_fs();
set_fs(get_ds());
rc = dentry->d_inode->i_op->readlink(dentry, (char __user *)buf, len);
set_fs(old_fs);
if (rc < 0) {
kfree(buf);
buf = ERR_PTR(rc);
} else
buf[rc] = '\0';
fsstack_copy_attr_atime(dentry->d_inode,
ecryptfs_dentry_to_lower(dentry)->d_inode);
buf[len] = '\0';
out:
nd_set_link(nd, buf);
return NULL;
@ -1153,7 +1123,7 @@ static int ecryptfs_removexattr(struct dentry *dentry, const char *name)
}
const struct inode_operations ecryptfs_symlink_iops = {
.readlink = ecryptfs_readlink,
.readlink = generic_readlink,
.follow_link = ecryptfs_follow_link,
.put_link = ecryptfs_put_link,
.permission = ecryptfs_permission,

View File

@ -280,10 +280,6 @@ static int __bprm_mm_init(struct linux_binprm *bprm)
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
INIT_LIST_HEAD(&vma->anon_vma_chain);
err = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1);
if (err)
goto err;
err = insert_vm_struct(mm, vma);
if (err)
goto err;

View File

@ -304,24 +304,23 @@ static int get_name(struct vfsmount *mnt, struct dentry *dentry,
/**
* export_encode_fh - default export_operations->encode_fh function
* @dentry: the dentry to encode
* @inode: the object to encode
* @fh: where to store the file handle fragment
* @max_len: maximum length to store there
* @connectable: whether to store parent information
* @parent: parent directory inode, if wanted
*
* This default encode_fh function assumes that the 32 inode number
* is suitable for locating an inode, and that the generation number
* can be used to check that it is still valid. It places them in the
* filehandle fragment where export_decode_fh expects to find them.
*/
static int export_encode_fh(struct dentry *dentry, struct fid *fid,
int *max_len, int connectable)
static int export_encode_fh(struct inode *inode, struct fid *fid,
int *max_len, struct inode *parent)
{
struct inode * inode = dentry->d_inode;
int len = *max_len;
int type = FILEID_INO32_GEN;
if (connectable && (len < 4)) {
if (parent && (len < 4)) {
*max_len = 4;
return 255;
} else if (len < 2) {
@ -332,14 +331,9 @@ static int export_encode_fh(struct dentry *dentry, struct fid *fid,
len = 2;
fid->i32.ino = inode->i_ino;
fid->i32.gen = inode->i_generation;
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
if (parent) {
fid->i32.parent_ino = parent->i_ino;
fid->i32.parent_gen = parent->i_generation;
spin_unlock(&dentry->d_lock);
len = 4;
type = FILEID_INO32_GEN_PARENT;
}
@ -352,11 +346,22 @@ int exportfs_encode_fh(struct dentry *dentry, struct fid *fid, int *max_len,
{
const struct export_operations *nop = dentry->d_sb->s_export_op;
int error;
struct dentry *p = NULL;
struct inode *inode = dentry->d_inode, *parent = NULL;
if (connectable && !S_ISDIR(inode->i_mode)) {
p = dget_parent(dentry);
/*
* note that while p might've ceased to be our parent already,
* it's still pinned by and still positive.
*/
parent = p->d_inode;
}
if (nop->encode_fh)
error = nop->encode_fh(dentry, fid->raw, max_len, connectable);
error = nop->encode_fh(inode, fid->raw, max_len, parent);
else
error = export_encode_fh(dentry, fid, max_len, connectable);
error = export_encode_fh(inode, fid, max_len, parent);
dput(p);
return error;
}

View File

@ -735,10 +735,9 @@ static struct dentry *fat_fh_to_dentry(struct super_block *sb,
}
static int
fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
fat_encode_fh(struct inode *inode, __u32 *fh, int *lenp, struct inode *parent)
{
int len = *lenp;
struct inode *inode = de->d_inode;
u32 ipos_h, ipos_m, ipos_l;
if (len < 5) {
@ -754,9 +753,9 @@ fat_encode_fh(struct dentry *de, __u32 *fh, int *lenp, int connectable)
fh[1] = inode->i_generation;
fh[2] = ipos_h;
fh[3] = ipos_m | MSDOS_I(inode)->i_logstart;
spin_lock(&de->d_lock);
fh[4] = ipos_l | MSDOS_I(de->d_parent->d_inode)->i_logstart;
spin_unlock(&de->d_lock);
fh[4] = ipos_l;
if (parent)
fh[4] |= MSDOS_I(parent)->i_logstart;
return 3;
}

View File

@ -442,28 +442,24 @@ static int check_fcntl_cmd(unsigned cmd)
SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg)
{
struct file *filp;
int fput_needed;
long err = -EBADF;
filp = fget_raw(fd);
filp = fget_raw_light(fd, &fput_needed);
if (!filp)
goto out;
if (unlikely(filp->f_mode & FMODE_PATH)) {
if (!check_fcntl_cmd(cmd)) {
fput(filp);
goto out;
}
if (!check_fcntl_cmd(cmd))
goto out1;
}
err = security_file_fcntl(filp, cmd, arg);
if (err) {
fput(filp);
return err;
}
if (!err)
err = do_fcntl(fd, cmd, arg, filp);
err = do_fcntl(fd, cmd, arg, filp);
fput(filp);
out1:
fput_light(filp, fput_needed);
out:
return err;
}
@ -473,26 +469,21 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
unsigned long, arg)
{
struct file * filp;
long err;
long err = -EBADF;
int fput_needed;
err = -EBADF;
filp = fget_raw(fd);
filp = fget_raw_light(fd, &fput_needed);
if (!filp)
goto out;
if (unlikely(filp->f_mode & FMODE_PATH)) {
if (!check_fcntl_cmd(cmd)) {
fput(filp);
goto out;
}
if (!check_fcntl_cmd(cmd))
goto out1;
}
err = security_file_fcntl(filp, cmd, arg);
if (err) {
fput(filp);
return err;
}
err = -EBADF;
if (err)
goto out1;
switch (cmd) {
case F_GETLK64:
@ -507,7 +498,8 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd,
err = do_fcntl(fd, cmd, arg, filp);
break;
}
fput(filp);
out1:
fput_light(filp, fput_needed);
out:
return err;
}

View File

@ -34,7 +34,6 @@ struct files_stat_struct files_stat = {
.max_files = NR_FILE
};
DECLARE_LGLOCK(files_lglock);
DEFINE_LGLOCK(files_lglock);
/* SLAB cache for file structures */
@ -421,9 +420,9 @@ static inline void __file_sb_list_add(struct file *file, struct super_block *sb)
*/
void file_sb_list_add(struct file *file, struct super_block *sb)
{
lg_local_lock(files_lglock);
lg_local_lock(&files_lglock);
__file_sb_list_add(file, sb);
lg_local_unlock(files_lglock);
lg_local_unlock(&files_lglock);
}
/**
@ -436,9 +435,9 @@ void file_sb_list_add(struct file *file, struct super_block *sb)
void file_sb_list_del(struct file *file)
{
if (!list_empty(&file->f_u.fu_list)) {
lg_local_lock_cpu(files_lglock, file_list_cpu(file));
lg_local_lock_cpu(&files_lglock, file_list_cpu(file));
list_del_init(&file->f_u.fu_list);
lg_local_unlock_cpu(files_lglock, file_list_cpu(file));
lg_local_unlock_cpu(&files_lglock, file_list_cpu(file));
}
}
@ -485,7 +484,7 @@ void mark_files_ro(struct super_block *sb)
struct file *f;
retry:
lg_global_lock(files_lglock);
lg_global_lock(&files_lglock);
do_file_list_for_each_entry(sb, f) {
struct vfsmount *mnt;
if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
@ -502,12 +501,12 @@ void mark_files_ro(struct super_block *sb)
file_release_write(f);
mnt = mntget(f->f_path.mnt);
/* This can sleep, so we can't hold the spinlock. */
lg_global_unlock(files_lglock);
lg_global_unlock(&files_lglock);
mnt_drop_write(mnt);
mntput(mnt);
goto retry;
} while_file_list_for_each_entry;
lg_global_unlock(files_lglock);
lg_global_unlock(&files_lglock);
}
void __init files_init(unsigned long mempages)
@ -525,6 +524,6 @@ void __init files_init(unsigned long mempages)
n = (mempages * (PAGE_SIZE / 1024)) / 10;
files_stat.max_files = max_t(unsigned long, n, NR_FILE);
files_defer_init();
lg_lock_init(files_lglock);
lg_lock_init(&files_lglock, "files_lglock");
percpu_counter_init(&nr_files, 0);
}

View File

@ -962,7 +962,9 @@ static ssize_t fuse_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
if (err)
goto out;
file_update_time(file);
err = file_update_time(file);
if (err)
goto out;
if (file->f_flags & O_DIRECT) {
written = generic_file_direct_write(iocb, iov, &nr_segs,

View File

@ -627,12 +627,10 @@ static struct dentry *fuse_get_dentry(struct super_block *sb,
return ERR_PTR(err);
}
static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
int connectable)
static int fuse_encode_fh(struct inode *inode, u32 *fh, int *max_len,
struct inode *parent)
{
struct inode *inode = dentry->d_inode;
bool encode_parent = connectable && !S_ISDIR(inode->i_mode);
int len = encode_parent ? 6 : 3;
int len = parent ? 6 : 3;
u64 nodeid;
u32 generation;
@ -648,14 +646,9 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
fh[1] = (u32)(nodeid & 0xffffffff);
fh[2] = generation;
if (encode_parent) {
struct inode *parent;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
if (parent) {
nodeid = get_fuse_inode(parent)->nodeid;
generation = parent->i_generation;
spin_unlock(&dentry->d_lock);
fh[3] = (u32)(nodeid >> 32);
fh[4] = (u32)(nodeid & 0xffffffff);
@ -663,7 +656,7 @@ static int fuse_encode_fh(struct dentry *dentry, u32 *fh, int *max_len,
}
*max_len = len;
return encode_parent ? 0x82 : 0x81;
return parent ? 0x82 : 0x81;
}
static struct dentry *fuse_fh_to_dentry(struct super_block *sb,

View File

@ -28,15 +28,14 @@
#define GFS2_LARGE_FH_SIZE 8
#define GFS2_OLD_FH_SIZE 10
static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
int connectable)
static int gfs2_encode_fh(struct inode *inode, __u32 *p, int *len,
struct inode *parent)
{
__be32 *fh = (__force __be32 *)p;
struct inode *inode = dentry->d_inode;
struct super_block *sb = inode->i_sb;
struct gfs2_inode *ip = GFS2_I(inode);
if (connectable && (*len < GFS2_LARGE_FH_SIZE)) {
if (parent && (*len < GFS2_LARGE_FH_SIZE)) {
*len = GFS2_LARGE_FH_SIZE;
return 255;
} else if (*len < GFS2_SMALL_FH_SIZE) {
@ -50,14 +49,10 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
fh[3] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
*len = GFS2_SMALL_FH_SIZE;
if (!connectable || inode == sb->s_root->d_inode)
if (!parent || inode == sb->s_root->d_inode)
return *len;
spin_lock(&dentry->d_lock);
inode = dentry->d_parent->d_inode;
ip = GFS2_I(inode);
igrab(inode);
spin_unlock(&dentry->d_lock);
ip = GFS2_I(parent);
fh[4] = cpu_to_be32(ip->i_no_formal_ino >> 32);
fh[5] = cpu_to_be32(ip->i_no_formal_ino & 0xFFFFFFFF);
@ -65,8 +60,6 @@ static int gfs2_encode_fh(struct dentry *dentry, __u32 *p, int *len,
fh[7] = cpu_to_be32(ip->i_no_addr & 0xFFFFFFFF);
*len = GFS2_LARGE_FH_SIZE;
iput(inode);
return *len;
}

View File

@ -16,9 +16,9 @@
static int chk_if_allocated(struct super_block *s, secno sec, char *msg)
{
struct quad_buffer_head qbh;
u32 *bmp;
__le32 *bmp;
if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "chk"))) goto fail;
if ((cpu_to_le32(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f)) & 1) {
if ((le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) >> (sec & 0x1f)) & 1) {
hpfs_error(s, "sector '%s' - %08x not allocated in bitmap", msg, sec);
goto fail1;
}
@ -62,7 +62,7 @@ int hpfs_chk_sectors(struct super_block *s, secno start, int len, char *msg)
static secno alloc_in_bmp(struct super_block *s, secno near, unsigned n, unsigned forward)
{
struct quad_buffer_head qbh;
unsigned *bmp;
__le32 *bmp;
unsigned bs = near & ~0x3fff;
unsigned nr = (near & 0x3fff) & ~(n - 1);
/*unsigned mnr;*/
@ -236,7 +236,7 @@ static secno alloc_in_dirband(struct super_block *s, secno near)
int hpfs_alloc_if_possible(struct super_block *s, secno sec)
{
struct quad_buffer_head qbh;
u32 *bmp;
__le32 *bmp;
if (!(bmp = hpfs_map_bitmap(s, sec >> 14, &qbh, "aip"))) goto end;
if (le32_to_cpu(bmp[(sec & 0x3fff) >> 5]) & (1 << (sec & 0x1f))) {
bmp[(sec & 0x3fff) >> 5] &= cpu_to_le32(~(1 << (sec & 0x1f)));
@ -254,7 +254,7 @@ int hpfs_alloc_if_possible(struct super_block *s, secno sec)
void hpfs_free_sectors(struct super_block *s, secno sec, unsigned n)
{
struct quad_buffer_head qbh;
u32 *bmp;
__le32 *bmp;
struct hpfs_sb_info *sbi = hpfs_sb(s);
/*printk("2 - ");*/
if (!n) return;
@ -299,7 +299,7 @@ int hpfs_check_free_dnodes(struct super_block *s, int n)
int n_bmps = (hpfs_sb(s)->sb_fs_size + 0x4000 - 1) >> 14;
int b = hpfs_sb(s)->sb_c_bitmap & 0x0fffffff;
int i, j;
u32 *bmp;
__le32 *bmp;
struct quad_buffer_head qbh;
if ((bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
for (j = 0; j < 512; j++) {
@ -351,7 +351,7 @@ void hpfs_free_dnode(struct super_block *s, dnode_secno dno)
hpfs_free_sectors(s, dno, 4);
} else {
struct quad_buffer_head qbh;
u32 *bmp;
__le32 *bmp;
unsigned ssec = (dno - hpfs_sb(s)->sb_dirband_start) / 4;
if (!(bmp = hpfs_map_dnode_bitmap(s, &qbh))) {
return;

View File

@ -20,7 +20,7 @@ secno hpfs_bplus_lookup(struct super_block *s, struct inode *inode,
int c1, c2 = 0;
go_down:
if (hpfs_sb(s)->sb_chk) if (hpfs_stop_cycles(s, a, &c1, &c2, "hpfs_bplus_lookup")) return -1;
if (btree->internal) {
if (bp_internal(btree)) {
for (i = 0; i < btree->n_used_nodes; i++)
if (le32_to_cpu(btree->u.internal[i].file_secno) > sec) {
a = le32_to_cpu(btree->u.internal[i].down);
@ -82,7 +82,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
brelse(bh);
return -1;
}
if (btree->internal) {
if (bp_internal(btree)) {
a = le32_to_cpu(btree->u.internal[n].down);
btree->u.internal[n].file_secno = cpu_to_le32(-1);
mark_buffer_dirty(bh);
@ -129,12 +129,12 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
}
if (a == node && fnod) {
anode->up = cpu_to_le32(node);
anode->btree.fnode_parent = 1;
anode->btree.flags |= BP_fnode_parent;
anode->btree.n_used_nodes = btree->n_used_nodes;
anode->btree.first_free = btree->first_free;
anode->btree.n_free_nodes = 40 - anode->btree.n_used_nodes;
memcpy(&anode->u, &btree->u, btree->n_used_nodes * 12);
btree->internal = 1;
btree->flags |= BP_internal;
btree->n_free_nodes = 11;
btree->n_used_nodes = 1;
btree->first_free = cpu_to_le16((char *)&(btree->u.internal[1]) - (char *)btree);
@ -184,7 +184,10 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
hpfs_free_sectors(s, ra, 1);
if ((anode = hpfs_map_anode(s, na, &bh))) {
anode->up = cpu_to_le32(up);
anode->btree.fnode_parent = up == node && fnod;
if (up == node && fnod)
anode->btree.flags |= BP_fnode_parent;
else
anode->btree.flags &= ~BP_fnode_parent;
mark_buffer_dirty(bh);
brelse(bh);
}
@ -198,7 +201,7 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
if ((new_anode = hpfs_alloc_anode(s, a, &na, &bh))) {
anode = new_anode;
/*anode->up = cpu_to_le32(up != -1 ? up : ra);*/
anode->btree.internal = 1;
anode->btree.flags |= BP_internal;
anode->btree.n_used_nodes = 1;
anode->btree.n_free_nodes = 59;
anode->btree.first_free = cpu_to_le16(16);
@ -215,7 +218,8 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
}
if ((anode = hpfs_map_anode(s, na, &bh))) {
anode->up = cpu_to_le32(node);
if (fnod) anode->btree.fnode_parent = 1;
if (fnod)
anode->btree.flags |= BP_fnode_parent;
mark_buffer_dirty(bh);
brelse(bh);
}
@ -234,18 +238,19 @@ secno hpfs_add_sector_to_btree(struct super_block *s, secno node, int fnod, unsi
}
ranode->up = cpu_to_le32(node);
memcpy(&ranode->btree, btree, le16_to_cpu(btree->first_free));
if (fnod) ranode->btree.fnode_parent = 1;
ranode->btree.n_free_nodes = (ranode->btree.internal ? 60 : 40) - ranode->btree.n_used_nodes;
if (ranode->btree.internal) for (n = 0; n < ranode->btree.n_used_nodes; n++) {
if (fnod)
ranode->btree.flags |= BP_fnode_parent;
ranode->btree.n_free_nodes = (bp_internal(&ranode->btree) ? 60 : 40) - ranode->btree.n_used_nodes;
if (bp_internal(&ranode->btree)) for (n = 0; n < ranode->btree.n_used_nodes; n++) {
struct anode *unode;
if ((unode = hpfs_map_anode(s, le32_to_cpu(ranode->u.internal[n].down), &bh1))) {
unode->up = cpu_to_le32(ra);
unode->btree.fnode_parent = 0;
unode->btree.flags &= ~BP_fnode_parent;
mark_buffer_dirty(bh1);
brelse(bh1);
}
}
btree->internal = 1;
btree->flags |= BP_internal;
btree->n_free_nodes = fnod ? 10 : 58;
btree->n_used_nodes = 2;
btree->first_free = cpu_to_le16((char *)&btree->u.internal[2] - (char *)btree);
@ -278,7 +283,7 @@ void hpfs_remove_btree(struct super_block *s, struct bplus_header *btree)
int d1, d2;
go_down:
d2 = 0;
while (btree1->internal) {
while (bp_internal(btree1)) {
ano = le32_to_cpu(btree1->u.internal[pos].down);
if (level) brelse(bh);
if (hpfs_sb(s)->sb_chk)
@ -412,13 +417,13 @@ void hpfs_truncate_btree(struct super_block *s, secno f, int fno, unsigned secs)
btree->n_free_nodes = 8;
btree->n_used_nodes = 0;
btree->first_free = cpu_to_le16(8);
btree->internal = 0;
btree->flags &= ~BP_internal;
mark_buffer_dirty(bh);
} else hpfs_free_sectors(s, f, 1);
brelse(bh);
return;
}
while (btree->internal) {
while (bp_internal(btree)) {
nodes = btree->n_used_nodes + btree->n_free_nodes;
for (i = 0; i < btree->n_used_nodes; i++)
if (le32_to_cpu(btree->u.internal[i].file_secno) >= secs) goto f;
@ -479,13 +484,13 @@ void hpfs_remove_fnode(struct super_block *s, fnode_secno fno)
struct extended_attribute *ea;
struct extended_attribute *ea_end;
if (!(fnode = hpfs_map_fnode(s, fno, &bh))) return;
if (!fnode->dirflag) hpfs_remove_btree(s, &fnode->btree);
if (!fnode_is_dir(fnode)) hpfs_remove_btree(s, &fnode->btree);
else hpfs_remove_dtree(s, le32_to_cpu(fnode->u.external[0].disk_secno));
ea_end = fnode_end_ea(fnode);
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
if (ea->indirect)
hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea));
hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l));
if (ea_indirect(ea))
hpfs_ea_remove(s, ea_sec(ea), ea_in_anode(ea), ea_len(ea));
hpfs_ea_ext_remove(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l));
brelse(bh);
hpfs_free_sectors(s, fno, 1);
}

View File

@ -87,7 +87,7 @@ static int hpfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
ret = -EIOERROR;
goto out;
}
if (!fno->dirflag) {
if (!fnode_is_dir(fno)) {
e = 1;
hpfs_error(inode->i_sb, "not a directory, fnode %08lx",
(unsigned long)inode->i_ino);

View File

@ -153,7 +153,7 @@ static void set_last_pointer(struct super_block *s, struct dnode *d, dnode_secno
}
de->length = cpu_to_le16(36);
de->down = 1;
*(dnode_secno *)((char *)de + 32) = cpu_to_le32(ptr);
*(__le32 *)((char *)de + 32) = cpu_to_le32(ptr);
}
}
@ -177,7 +177,7 @@ struct hpfs_dirent *hpfs_add_de(struct super_block *s, struct dnode *d,
memmove((char *)de + d_size, de, (char *)de_end - (char *)de);
memset(de, 0, d_size);
if (down_ptr) {
*(dnode_secno *)((char *)de + d_size - 4) = cpu_to_le32(down_ptr);
*(__le32 *)((char *)de + d_size - 4) = cpu_to_le32(down_ptr);
de->down = 1;
}
de->length = cpu_to_le16(d_size);
@ -656,7 +656,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
del->down = 0;
d1->first_free = cpu_to_le32(le32_to_cpu(d1->first_free) - 4);
} else if (down)
*(dnode_secno *) ((void *) del + le16_to_cpu(del->length) - 4) = cpu_to_le32(down);
*(__le32 *) ((void *) del + le16_to_cpu(del->length) - 4) = cpu_to_le32(down);
} else goto endm;
if (!(de_cp = kmalloc(le16_to_cpu(de_prev->length), GFP_NOFS))) {
printk("HPFS: out of memory for dtree balancing\n");
@ -672,7 +672,7 @@ static void delete_empty_dnode(struct inode *i, dnode_secno dno)
de_prev->down = 1;
dnode->first_free = cpu_to_le32(le32_to_cpu(dnode->first_free) + 4);
}
*(dnode_secno *) ((void *) de_prev + le16_to_cpu(de_prev->length) - 4) = cpu_to_le32(ndown);
*(__le32 *) ((void *) de_prev + le16_to_cpu(de_prev->length) - 4) = cpu_to_le32(ndown);
hpfs_mark_4buffers_dirty(&qbh);
hpfs_brelse4(&qbh);
for_all_poss(i, hpfs_pos_subst, ((loff_t)up << 4) | (p - 1), 4);
@ -1015,7 +1015,7 @@ struct hpfs_dirent *map_fnode_dirent(struct super_block *s, fnode_secno fno,
kfree(name2);
return NULL;
}
if (!upf->dirflag) {
if (!fnode_is_dir(upf)) {
brelse(bh);
hpfs_error(s, "fnode %08x has non-directory parent %08x", fno, le32_to_cpu(f->up));
kfree(name2);

View File

@ -23,15 +23,15 @@ void hpfs_ea_ext_remove(struct super_block *s, secno a, int ano, unsigned len)
return;
}
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
if (ea->indirect) {
if (ea_indirect(ea)) {
if (ea_valuelen(ea) != 8) {
hpfs_error(s, "ea->indirect set while ea->valuelen!=8, %s %08x, pos %08x",
hpfs_error(s, "ea_indirect(ea) set while ea->valuelen!=8, %s %08x, pos %08x",
ano ? "anode" : "sectors", a, pos);
return;
}
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 9, ex+4))
return;
hpfs_ea_remove(s, ea_sec(ea), ea->anode, ea_len(ea));
hpfs_ea_remove(s, ea_sec(ea), ea_in_anode(ea), ea_len(ea));
}
pos += ea->namelen + ea_valuelen(ea) + 5;
}
@ -81,7 +81,7 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
struct extended_attribute *ea_end = fnode_end_ea(fnode);
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
if (!strcmp(ea->name, key)) {
if (ea->indirect)
if (ea_indirect(ea))
goto indirect;
if (ea_valuelen(ea) >= size)
return -EINVAL;
@ -91,7 +91,7 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
}
a = le32_to_cpu(fnode->ea_secno);
len = le32_to_cpu(fnode->ea_size_l);
ano = fnode->ea_anode;
ano = fnode_in_anode(fnode);
pos = 0;
while (pos < len) {
ea = (struct extended_attribute *)ex;
@ -101,10 +101,10 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
return -EIO;
}
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return -EIO;
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))
return -EIO;
if (!strcmp(ea->name, key)) {
if (ea->indirect)
if (ea_indirect(ea))
goto indirect;
if (ea_valuelen(ea) >= size)
return -EINVAL;
@ -119,7 +119,7 @@ int hpfs_read_ea(struct super_block *s, struct fnode *fnode, char *key,
indirect:
if (ea_len(ea) >= size)
return -EINVAL;
if (hpfs_ea_read(s, ea_sec(ea), ea->anode, 0, ea_len(ea), buf))
if (hpfs_ea_read(s, ea_sec(ea), ea_in_anode(ea), 0, ea_len(ea), buf))
return -EIO;
buf[ea_len(ea)] = 0;
return 0;
@ -136,8 +136,8 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
struct extended_attribute *ea_end = fnode_end_ea(fnode);
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
if (!strcmp(ea->name, key)) {
if (ea->indirect)
return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
if (ea_indirect(ea))
return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea));
if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
printk("HPFS: out of memory for EA\n");
return NULL;
@ -148,7 +148,7 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
}
a = le32_to_cpu(fnode->ea_secno);
len = le32_to_cpu(fnode->ea_size_l);
ano = fnode->ea_anode;
ano = fnode_in_anode(fnode);
pos = 0;
while (pos < len) {
char ex[4 + 255 + 1 + 8];
@ -159,11 +159,11 @@ char *hpfs_get_ea(struct super_block *s, struct fnode *fnode, char *key, int *si
return NULL;
}
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return NULL;
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))
return NULL;
if (!strcmp(ea->name, key)) {
if (ea->indirect)
return get_indirect_ea(s, ea->anode, ea_sec(ea), *size = ea_len(ea));
if (ea_indirect(ea))
return get_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), *size = ea_len(ea));
if (!(ret = kmalloc((*size = ea_valuelen(ea)) + 1, GFP_NOFS))) {
printk("HPFS: out of memory for EA\n");
return NULL;
@ -199,9 +199,9 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
struct extended_attribute *ea_end = fnode_end_ea(fnode);
for (ea = fnode_ea(fnode); ea < ea_end; ea = next_ea(ea))
if (!strcmp(ea->name, key)) {
if (ea->indirect) {
if (ea_indirect(ea)) {
if (ea_len(ea) == size)
set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size);
} else if (ea_valuelen(ea) == size) {
memcpy(ea_data(ea), data, size);
}
@ -209,7 +209,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
}
a = le32_to_cpu(fnode->ea_secno);
len = le32_to_cpu(fnode->ea_size_l);
ano = fnode->ea_anode;
ano = fnode_in_anode(fnode);
pos = 0;
while (pos < len) {
char ex[4 + 255 + 1 + 8];
@ -220,12 +220,12 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
return;
}
if (hpfs_ea_read(s, a, ano, pos, 4, ex)) return;
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea->indirect ? 8 : 0), ex + 4))
if (hpfs_ea_read(s, a, ano, pos + 4, ea->namelen + 1 + (ea_indirect(ea) ? 8 : 0), ex + 4))
return;
if (!strcmp(ea->name, key)) {
if (ea->indirect) {
if (ea_indirect(ea)) {
if (ea_len(ea) == size)
set_indirect_ea(s, ea->anode, ea_sec(ea), data, size);
set_indirect_ea(s, ea_in_anode(ea), ea_sec(ea), data, size);
}
else {
if (ea_valuelen(ea) == size)
@ -246,7 +246,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
if (le16_to_cpu(fnode->ea_offs) < 0xc4 || le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200) {
hpfs_error(s, "fnode %08lx: ea_offs == %03x, ea_size_s == %03x",
(unsigned long)inode->i_ino,
le32_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s));
return;
}
if ((le16_to_cpu(fnode->ea_size_s) || !le32_to_cpu(fnode->ea_size_l)) &&
@ -276,7 +276,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
fnode->ea_size_l = cpu_to_le32(le16_to_cpu(fnode->ea_size_s));
fnode->ea_size_s = cpu_to_le16(0);
fnode->ea_secno = cpu_to_le32(n);
fnode->ea_anode = cpu_to_le32(0);
fnode->flags &= ~FNODE_anode;
mark_buffer_dirty(bh);
brelse(bh);
}
@ -288,9 +288,9 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
secno q = hpfs_alloc_sector(s, fno, 1, 0);
if (!q) goto bail;
fnode->ea_secno = cpu_to_le32(q);
fnode->ea_anode = 0;
fnode->flags &= ~FNODE_anode;
len++;
} else if (!fnode->ea_anode) {
} else if (!fnode_in_anode(fnode)) {
if (hpfs_alloc_if_possible(s, le32_to_cpu(fnode->ea_secno) + len)) {
len++;
} else {
@ -310,7 +310,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
anode->u.external[0].length = cpu_to_le32(len);
mark_buffer_dirty(bh);
brelse(bh);
fnode->ea_anode = 1;
fnode->flags |= FNODE_anode;
fnode->ea_secno = cpu_to_le32(a_s);*/
secno new_sec;
int i;
@ -338,7 +338,7 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
len = (pos + 511) >> 9;
}
}
if (fnode->ea_anode) {
if (fnode_in_anode(fnode)) {
if (hpfs_add_sector_to_btree(s, le32_to_cpu(fnode->ea_secno),
0, len) != -1) {
len++;
@ -351,16 +351,16 @@ void hpfs_set_ea(struct inode *inode, struct fnode *fnode, const char *key,
h[1] = strlen(key);
h[2] = size & 0xff;
h[3] = size >> 8;
if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l), 4, h)) goto bail;
if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 4, h[1] + 1, key)) goto bail;
if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode->ea_anode, le32_to_cpu(fnode->ea_size_l) + 5 + h[1], size, data)) goto bail;
if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l), 4, h)) goto bail;
if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l) + 4, h[1] + 1, key)) goto bail;
if (hpfs_ea_write(s, le32_to_cpu(fnode->ea_secno), fnode_in_anode(fnode), le32_to_cpu(fnode->ea_size_l) + 5 + h[1], size, data)) goto bail;
fnode->ea_size_l = cpu_to_le32(pos);
ret:
hpfs_i(inode)->i_ea_size += 5 + strlen(key) + size;
return;
bail:
if (le32_to_cpu(fnode->ea_secno))
if (fnode->ea_anode) hpfs_truncate_btree(s, le32_to_cpu(fnode->ea_secno), 1, (le32_to_cpu(fnode->ea_size_l) + 511) >> 9);
if (fnode_in_anode(fnode)) hpfs_truncate_btree(s, le32_to_cpu(fnode->ea_secno), 1, (le32_to_cpu(fnode->ea_size_l) + 511) >> 9);
else hpfs_free_sectors(s, le32_to_cpu(fnode->ea_secno) + ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9), len - ((le32_to_cpu(fnode->ea_size_l) + 511) >> 9));
else fnode->ea_secno = fnode->ea_size_l = cpu_to_le32(0);
}

View File

@ -51,11 +51,11 @@ struct hpfs_boot_block
u8 n_rootdir_entries[2];
u8 n_sectors_s[2];
u8 media_byte;
u16 sectors_per_fat;
u16 sectors_per_track;
u16 heads_per_cyl;
u32 n_hidden_sectors;
u32 n_sectors_l; /* size of partition */
__le16 sectors_per_fat;
__le16 sectors_per_track;
__le16 heads_per_cyl;
__le32 n_hidden_sectors;
__le32 n_sectors_l; /* size of partition */
u8 drive_number;
u8 mbz;
u8 sig_28h; /* 28h */
@ -63,7 +63,7 @@ struct hpfs_boot_block
u8 vol_label[11];
u8 sig_hpfs[8]; /* "HPFS " */
u8 pad[448];
u16 magic; /* aa55 */
__le16 magic; /* aa55 */
};
@ -75,28 +75,28 @@ struct hpfs_boot_block
struct hpfs_super_block
{
u32 magic; /* f995 e849 */
u32 magic1; /* fa53 e9c5, more magic? */
__le32 magic; /* f995 e849 */
__le32 magic1; /* fa53 e9c5, more magic? */
u8 version; /* version of a filesystem usually 2 */
u8 funcversion; /* functional version - oldest version
of filesystem that can understand
this disk */
u16 zero; /* 0 */
fnode_secno root; /* fnode of root directory */
secno n_sectors; /* size of filesystem */
u32 n_badblocks; /* number of bad blocks */
secno bitmaps; /* pointers to free space bit maps */
u32 zero1; /* 0 */
secno badblocks; /* bad block list */
u32 zero3; /* 0 */
time32_t last_chkdsk; /* date last checked, 0 if never */
time32_t last_optimize; /* date last optimized, 0 if never */
secno n_dir_band; /* number of sectors in dir band */
secno dir_band_start; /* first sector in dir band */
secno dir_band_end; /* last sector in dir band */
secno dir_band_bitmap; /* free space map, 1 dnode per bit */
__le16 zero; /* 0 */
__le32 root; /* fnode of root directory */
__le32 n_sectors; /* size of filesystem */
__le32 n_badblocks; /* number of bad blocks */
__le32 bitmaps; /* pointers to free space bit maps */
__le32 zero1; /* 0 */
__le32 badblocks; /* bad block list */
__le32 zero3; /* 0 */
__le32 last_chkdsk; /* date last checked, 0 if never */
__le32 last_optimize; /* date last optimized, 0 if never */
__le32 n_dir_band; /* number of sectors in dir band */
__le32 dir_band_start; /* first sector in dir band */
__le32 dir_band_end; /* last sector in dir band */
__le32 dir_band_bitmap; /* free space map, 1 dnode per bit */
u8 volume_name[32]; /* not used */
secno user_id_table; /* 8 preallocated sectors - user id */
__le32 user_id_table; /* 8 preallocated sectors - user id */
u32 zero6[103]; /* 0 */
};
@ -109,8 +109,8 @@ struct hpfs_super_block
struct hpfs_spare_block
{
u32 magic; /* f991 1849 */
u32 magic1; /* fa52 29c5, more magic? */
__le32 magic; /* f991 1849 */
__le32 magic1; /* fa52 29c5, more magic? */
#ifdef __LITTLE_ENDIAN
u8 dirty: 1; /* 0 clean, 1 "improperly stopped" */
@ -153,21 +153,21 @@ struct hpfs_spare_block
u8 mm_contlgulty;
u8 unused;
secno hotfix_map; /* info about remapped bad sectors */
u32 n_spares_used; /* number of hotfixes */
u32 n_spares; /* number of spares in hotfix map */
u32 n_dnode_spares_free; /* spare dnodes unused */
u32 n_dnode_spares; /* length of spare_dnodes[] list,
__le32 hotfix_map; /* info about remapped bad sectors */
__le32 n_spares_used; /* number of hotfixes */
__le32 n_spares; /* number of spares in hotfix map */
__le32 n_dnode_spares_free; /* spare dnodes unused */
__le32 n_dnode_spares; /* length of spare_dnodes[] list,
follows in this block*/
secno code_page_dir; /* code page directory block */
u32 n_code_pages; /* number of code pages */
u32 super_crc; /* on HPFS386 and LAN Server this is
__le32 code_page_dir; /* code page directory block */
__le32 n_code_pages; /* number of code pages */
__le32 super_crc; /* on HPFS386 and LAN Server this is
checksum of superblock, on normal
OS/2 unused */
u32 spare_crc; /* on HPFS386 checksum of spareblock */
u32 zero1[15]; /* unused */
dnode_secno spare_dnodes[100]; /* emergency free dnode list */
u32 zero2[1]; /* room for more? */
__le32 spare_crc; /* on HPFS386 checksum of spareblock */
__le32 zero1[15]; /* unused */
__le32 spare_dnodes[100]; /* emergency free dnode list */
__le32 zero2[1]; /* room for more? */
};
/* The bad block list is 4 sectors long. The first word must be zero,
@ -202,18 +202,18 @@ struct hpfs_spare_block
struct code_page_directory
{
u32 magic; /* 4945 21f7 */
u32 n_code_pages; /* number of pointers following */
u32 zero1[2];
__le32 magic; /* 4945 21f7 */
__le32 n_code_pages; /* number of pointers following */
__le32 zero1[2];
struct {
u16 ix; /* index */
u16 code_page_number; /* code page number */
u32 bounds; /* matches corresponding word
__le16 ix; /* index */
__le16 code_page_number; /* code page number */
__le32 bounds; /* matches corresponding word
in data block */
secno code_page_data; /* sector number of a code_page_data
__le32 code_page_data; /* sector number of a code_page_data
containing c.p. array */
u16 index; /* index in c.p. array in that sector*/
u16 unknown; /* some unknown value; usually 0;
__le16 index; /* index in c.p. array in that sector*/
__le16 unknown; /* some unknown value; usually 0;
2 in Japanese version */
} array[31]; /* unknown length */
};
@ -224,19 +224,19 @@ struct code_page_directory
struct code_page_data
{
u32 magic; /* 8945 21f7 */
u32 n_used; /* # elements used in c_p_data[] */
u32 bounds[3]; /* looks a bit like
__le32 magic; /* 8945 21f7 */
__le32 n_used; /* # elements used in c_p_data[] */
__le32 bounds[3]; /* looks a bit like
(beg1,end1), (beg2,end2)
one byte each */
u16 offs[3]; /* offsets from start of sector
__le16 offs[3]; /* offsets from start of sector
to start of c_p_data[ix] */
struct {
u16 ix; /* index */
u16 code_page_number; /* code page number */
u16 unknown; /* the same as in cp directory */
__le16 ix; /* index */
__le16 code_page_number; /* code page number */
__le16 unknown; /* the same as in cp directory */
u8 map[128]; /* upcase table for chars 80..ff */
u16 zero2;
__le16 zero2;
} code_page[3];
u8 incognita[78];
};
@ -278,8 +278,8 @@ struct code_page_data
#define DNODE_MAGIC 0x77e40aae
struct dnode {
u32 magic; /* 77e4 0aae */
u32 first_free; /* offset from start of dnode to
__le32 magic; /* 77e4 0aae */
__le32 first_free; /* offset from start of dnode to
first free dir entry */
#ifdef __LITTLE_ENDIAN
u8 root_dnode: 1; /* Is it root dnode? */
@ -293,14 +293,14 @@ struct dnode {
u8 root_dnode: 1; /* Is it root dnode? */
#endif
u8 increment_me2[3];
secno up; /* (root dnode) directory's fnode
__le32 up; /* (root dnode) directory's fnode
(nonroot) parent dnode */
dnode_secno self; /* pointer to this dnode */
__le32 self; /* pointer to this dnode */
u8 dirent[2028]; /* one or more dirents */
};
struct hpfs_dirent {
u16 length; /* offset to next dirent */
__le16 length; /* offset to next dirent */
#ifdef __LITTLE_ENDIAN
u8 first: 1; /* set on phony ^A^A (".") entry */
@ -346,12 +346,12 @@ struct hpfs_dirent {
u8 read_only: 1; /* dos attrib */
#endif
fnode_secno fnode; /* fnode giving allocation info */
time32_t write_date; /* mtime */
u32 file_size; /* file length, bytes */
time32_t read_date; /* atime */
time32_t creation_date; /* ctime */
u32 ea_size; /* total EA length, bytes */
__le32 fnode; /* fnode giving allocation info */
__le32 write_date; /* mtime */
__le32 file_size; /* file length, bytes */
__le32 read_date; /* atime */
__le32 creation_date; /* ctime */
__le32 ea_size; /* total EA length, bytes */
u8 no_of_acls; /* number of ACL's (low 3 bits) */
u8 ix; /* code page index (of filename), see
struct code_page_data */
@ -375,50 +375,36 @@ struct hpfs_dirent {
struct bplus_leaf_node
{
u32 file_secno; /* first file sector in extent */
u32 length; /* length, sectors */
secno disk_secno; /* first corresponding disk sector */
__le32 file_secno; /* first file sector in extent */
__le32 length; /* length, sectors */
__le32 disk_secno; /* first corresponding disk sector */
};
struct bplus_internal_node
{
u32 file_secno; /* subtree maps sectors < this */
anode_secno down; /* pointer to subtree */
__le32 file_secno; /* subtree maps sectors < this */
__le32 down; /* pointer to subtree */
};
enum {
BP_hbff = 1,
BP_fnode_parent = 0x20,
BP_binary_search = 0x40,
BP_internal = 0x80
};
struct bplus_header
{
#ifdef __LITTLE_ENDIAN
u8 hbff: 1; /* high bit of first free entry offset */
u8 flag1234: 4;
u8 fnode_parent: 1; /* ? we're pointed to by an fnode,
u8 flags; /* bit 0 - high bit of first free entry offset
bit 5 - we're pointed to by an fnode,
the data btree or some ea or the
main ea bootage pointer ea_secno */
/* also can get set in fnodes, which
may be a chkdsk glitch or may mean
this bit is irrelevant in fnodes,
or this interpretation is all wet */
u8 binary_search: 1; /* suggest binary search (unused) */
u8 internal: 1; /* 1 -> (internal) tree of anodes
0 -> (leaf) list of extents */
#else
u8 internal: 1; /* 1 -> (internal) tree of anodes
0 -> (leaf) list of extents */
u8 binary_search: 1; /* suggest binary search (unused) */
u8 fnode_parent: 1; /* ? we're pointed to by an fnode,
the data btree or some ea or the
main ea bootage pointer ea_secno */
/* also can get set in fnodes, which
may be a chkdsk glitch or may mean
this bit is irrelevant in fnodes,
or this interpretation is all wet */
u8 flag1234: 4;
u8 hbff: 1; /* high bit of first free entry offset */
#endif
main ea bootage pointer ea_secno
bit 6 - suggest binary search (unused)
bit 7 - 1 -> (internal) tree of anodes
0 -> (leaf) list of extents */
u8 fill[3];
u8 n_free_nodes; /* free nodes in following array */
u8 n_used_nodes; /* used nodes in following array */
u16 first_free; /* offset from start of header to
__le16 first_free; /* offset from start of header to
first free node in array */
union {
struct bplus_internal_node internal[0]; /* (internal) 2-word entries giving
@ -428,6 +414,16 @@ struct bplus_header
} u;
};
static inline bool bp_internal(struct bplus_header *bp)
{
return bp->flags & BP_internal;
}
static inline bool bp_fnode_parent(struct bplus_header *bp)
{
return bp->flags & BP_fnode_parent;
}
/* fnode: root of allocation b+ tree, and EA's */
/* Every file and every directory has one fnode, pointed to by the directory
@ -436,62 +432,56 @@ struct bplus_header
#define FNODE_MAGIC 0xf7e40aae
enum {FNODE_anode = cpu_to_le16(2), FNODE_dir = cpu_to_le16(256)};
struct fnode
{
u32 magic; /* f7e4 0aae */
u32 zero1[2]; /* read history */
__le32 magic; /* f7e4 0aae */
__le32 zero1[2]; /* read history */
u8 len, name[15]; /* true length, truncated name */
fnode_secno up; /* pointer to file's directory fnode */
secno acl_size_l;
secno acl_secno;
u16 acl_size_s;
__le32 up; /* pointer to file's directory fnode */
__le32 acl_size_l;
__le32 acl_secno;
__le16 acl_size_s;
u8 acl_anode;
u8 zero2; /* history bit count */
u32 ea_size_l; /* length of disk-resident ea's */
secno ea_secno; /* first sector of disk-resident ea's*/
u16 ea_size_s; /* length of fnode-resident ea's */
__le32 ea_size_l; /* length of disk-resident ea's */
__le32 ea_secno; /* first sector of disk-resident ea's*/
__le16 ea_size_s; /* length of fnode-resident ea's */
#ifdef __LITTLE_ENDIAN
u8 flag0: 1;
u8 ea_anode: 1; /* 1 -> ea_secno is an anode */
u8 flag234567: 6;
#else
u8 flag234567: 6;
u8 ea_anode: 1; /* 1 -> ea_secno is an anode */
u8 flag0: 1;
#endif
#ifdef __LITTLE_ENDIAN
u8 dirflag: 1; /* 1 -> directory. first & only extent
__le16 flags; /* bit 1 set -> ea_secno is an anode */
/* bit 8 set -> directory. first & only extent
points to dnode. */
u8 flag9012345: 7;
#else
u8 flag9012345: 7;
u8 dirflag: 1; /* 1 -> directory. first & only extent
points to dnode. */
#endif
struct bplus_header btree; /* b+ tree, 8 extents or 12 subtrees */
union {
struct bplus_leaf_node external[8];
struct bplus_internal_node internal[12];
} u;
u32 file_size; /* file length, bytes */
u32 n_needea; /* number of EA's with NEEDEA set */
__le32 file_size; /* file length, bytes */
__le32 n_needea; /* number of EA's with NEEDEA set */
u8 user_id[16]; /* unused */
u16 ea_offs; /* offset from start of fnode
__le16 ea_offs; /* offset from start of fnode
to first fnode-resident ea */
u8 dasd_limit_treshhold;
u8 dasd_limit_delta;
u32 dasd_limit;
u32 dasd_usage;
__le32 dasd_limit;
__le32 dasd_usage;
u8 ea[316]; /* zero or more EA's, packed together
with no alignment padding.
(Do not use this name, get here
via fnode + ea_offs. I think.) */
};
static inline bool fnode_in_anode(struct fnode *p)
{
return (p->flags & FNODE_anode) != 0;
}
static inline bool fnode_is_dir(struct fnode *p)
{
return (p->flags & FNODE_dir) != 0;
}
/* anode: 99.44% pure allocation tree */
@ -499,9 +489,9 @@ struct fnode
struct anode
{
u32 magic; /* 37e4 0aae */
anode_secno self; /* pointer to this anode */
secno up; /* parent anode or fnode */
__le32 magic; /* 37e4 0aae */
__le32 self; /* pointer to this anode */
__le32 up; /* parent anode or fnode */
struct bplus_header btree; /* b+tree, 40 extents or 60 subtrees */
union {
@ -509,7 +499,7 @@ struct anode
struct bplus_internal_node internal[60];
} u;
u32 fill[3]; /* unused */
__le32 fill[3]; /* unused */
};
@ -528,32 +518,23 @@ struct anode
run, or in multiple runs. Flags in the fnode tell whether the EA list
is immediate, in a single run, or in multiple runs. */
enum {EA_indirect = 1, EA_anode = 2, EA_needea = 128 };
struct extended_attribute
{
#ifdef __LITTLE_ENDIAN
u8 indirect: 1; /* 1 -> value gives sector number
u8 flags; /* bit 0 set -> value gives sector number
where real value starts */
u8 anode: 1; /* 1 -> sector is an anode
/* bit 1 set -> sector is an anode
that points to fragmented value */
u8 flag23456: 5;
u8 needea: 1; /* required ea */
#else
u8 needea: 1; /* required ea */
u8 flag23456: 5;
u8 anode: 1; /* 1 -> sector is an anode
that points to fragmented value */
u8 indirect: 1; /* 1 -> value gives sector number
where real value starts */
#endif
/* bit 7 set -> required ea */
u8 namelen; /* length of name, bytes */
u8 valuelen_lo; /* length of value, bytes */
u8 valuelen_hi; /* length of value, bytes */
u8 name[0];
u8 name[];
/*
u8 name[namelen]; ascii attrib name
u8 nul; terminating '\0', not counted
u8 value[valuelen]; value, arbitrary
if this.indirect, valuelen is 8 and the value is
if this.flags & 1, valuelen is 8 and the value is
u32 length; real length of value, bytes
secno secno; sector address where it starts
if this.anode, the above sector number is the root of an anode tree
@ -561,6 +542,16 @@ struct extended_attribute
*/
};
static inline bool ea_indirect(struct extended_attribute *ea)
{
return ea->flags & EA_indirect;
}
static inline bool ea_in_anode(struct extended_attribute *ea)
{
return ea->flags & EA_anode;
}
/*
Local Variables:
comment-column: 40

View File

@ -75,7 +75,7 @@ struct hpfs_sb_info {
unsigned char *sb_cp_table; /* code page tables: */
/* 128 bytes uppercasing table & */
/* 128 bytes lowercasing table */
unsigned *sb_bmp_dir; /* main bitmap directory */
__le32 *sb_bmp_dir; /* main bitmap directory */
unsigned sb_c_bitmap; /* current bitmap */
unsigned sb_max_fwd_alloc; /* max forwad allocation */
int sb_timeshift;
@ -93,7 +93,7 @@ struct quad_buffer_head {
static inline dnode_secno de_down_pointer (struct hpfs_dirent *de)
{
CHKCOND(de->down,("HPFS: de_down_pointer: !de->down\n"));
return le32_to_cpu(*(dnode_secno *) ((void *) de + le16_to_cpu(de->length) - 4));
return le32_to_cpu(*(__le32 *) ((void *) de + le16_to_cpu(de->length) - 4));
}
/* The first dir entry in a dnode */
@ -141,12 +141,12 @@ static inline struct extended_attribute *next_ea(struct extended_attribute *ea)
static inline secno ea_sec(struct extended_attribute *ea)
{
return le32_to_cpu(get_unaligned((secno *)((char *)ea + 9 + ea->namelen)));
return le32_to_cpu(get_unaligned((__le32 *)((char *)ea + 9 + ea->namelen)));
}
static inline secno ea_len(struct extended_attribute *ea)
{
return le32_to_cpu(get_unaligned((secno *)((char *)ea + 5 + ea->namelen)));
return le32_to_cpu(get_unaligned((__le32 *)((char *)ea + 5 + ea->namelen)));
}
static inline char *ea_data(struct extended_attribute *ea)
@ -171,7 +171,7 @@ static inline void copy_de(struct hpfs_dirent *dst, struct hpfs_dirent *src)
dst->not_8x3 = n;
}
static inline unsigned tstbits(u32 *bmp, unsigned b, unsigned n)
static inline unsigned tstbits(__le32 *bmp, unsigned b, unsigned n)
{
int i;
if ((b >= 0x4000) || (b + n - 1 >= 0x4000)) return n;
@ -268,10 +268,10 @@ void hpfs_evict_inode(struct inode *);
/* map.c */
unsigned *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *);
unsigned *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *);
__le32 *hpfs_map_dnode_bitmap(struct super_block *, struct quad_buffer_head *);
__le32 *hpfs_map_bitmap(struct super_block *, unsigned, struct quad_buffer_head *, char *);
unsigned char *hpfs_load_code_page(struct super_block *, secno);
secno *hpfs_load_bitmap_directory(struct super_block *, secno bmp);
__le32 *hpfs_load_bitmap_directory(struct super_block *, secno bmp);
struct fnode *hpfs_map_fnode(struct super_block *s, ino_t, struct buffer_head **);
struct anode *hpfs_map_anode(struct super_block *s, anode_secno, struct buffer_head **);
struct dnode *hpfs_map_dnode(struct super_block *s, dnode_secno, struct quad_buffer_head *);

View File

@ -110,7 +110,7 @@ void hpfs_read_inode(struct inode *i)
}
}
}
if (fnode->dirflag) {
if (fnode_is_dir(fnode)) {
int n_dnodes, n_subdirs;
i->i_mode |= S_IFDIR;
i->i_op = &hpfs_dir_iops;

View File

@ -8,12 +8,12 @@
#include "hpfs_fn.h"
unsigned *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh)
__le32 *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh)
{
return hpfs_map_4sectors(s, hpfs_sb(s)->sb_dmap, qbh, 0);
}
unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
__le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block,
struct quad_buffer_head *qbh, char *id)
{
secno sec;
@ -89,18 +89,18 @@ unsigned char *hpfs_load_code_page(struct super_block *s, secno cps)
return cp_table;
}
secno *hpfs_load_bitmap_directory(struct super_block *s, secno bmp)
__le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp)
{
struct buffer_head *bh;
int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21;
int i;
secno *b;
__le32 *b;
if (!(b = kmalloc(n * 512, GFP_KERNEL))) {
printk("HPFS: can't allocate memory for bitmap directory\n");
return NULL;
}
for (i=0;i<n;i++) {
secno *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1);
__le32 *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1);
if (!d) {
kfree(b);
return NULL;
@ -130,16 +130,16 @@ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_hea
(unsigned long)ino);
goto bail;
}
if (!fnode->dirflag) {
if (!fnode_is_dir(fnode)) {
if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes !=
(fnode->btree.internal ? 12 : 8)) {
(bp_internal(&fnode->btree) ? 12 : 8)) {
hpfs_error(s,
"bad number of nodes in fnode %08lx",
(unsigned long)ino);
goto bail;
}
if (le16_to_cpu(fnode->btree.first_free) !=
8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) {
8 + fnode->btree.n_used_nodes * (bp_internal(&fnode->btree) ? 8 : 12)) {
hpfs_error(s,
"bad first_free pointer in fnode %08lx",
(unsigned long)ino);
@ -187,12 +187,12 @@ struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buff
goto bail;
}
if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes !=
(anode->btree.internal ? 60 : 40)) {
(bp_internal(&anode->btree) ? 60 : 40)) {
hpfs_error(s, "bad number of nodes in anode %08x", ano);
goto bail;
}
if (le16_to_cpu(anode->btree.first_free) !=
8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) {
8 + anode->btree.n_used_nodes * (bp_internal(&anode->btree) ? 8 : 12)) {
hpfs_error(s, "bad first_free pointer in anode %08x", ano);
goto bail;
}

View File

@ -70,7 +70,7 @@ static int hpfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
fnode->len = len;
memcpy(fnode->name, name, len > 15 ? 15 : len);
fnode->up = cpu_to_le32(dir->i_ino);
fnode->dirflag = 1;
fnode->flags |= FNODE_dir;
fnode->btree.n_free_nodes = 7;
fnode->btree.n_used_nodes = 1;
fnode->btree.first_free = cpu_to_le16(0x14);

View File

@ -572,7 +572,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
mark_buffer_dirty(bh2);
}
if (le32_to_cpu(spareblock->hotfixes_used) || le32_to_cpu(spareblock->n_spares_used)) {
if (spareblock->hotfixes_used || spareblock->n_spares_used) {
if (errs >= 2) {
printk("HPFS: Hotfixes not supported here, try chkdsk\n");
mark_dirty(s, 0);
@ -645,7 +645,7 @@ static int hpfs_fill_super(struct super_block *s, void *options, int silent)
root->i_mtime.tv_nsec = 0;
root->i_ctime.tv_sec = local_to_gmt(s, le32_to_cpu(de->creation_date));
root->i_ctime.tv_nsec = 0;
hpfs_i(root)->i_ea_size = le16_to_cpu(de->ea_size);
hpfs_i(root)->i_ea_size = le32_to_cpu(de->ea_size);
hpfs_i(root)->i_parent_dir = root->i_ino;
if (root->i_size == -1)
root->i_size = 2048;

View File

@ -1487,10 +1487,30 @@ static int relatime_need_update(struct vfsmount *mnt, struct inode *inode,
return 0;
}
/*
* This does the actual work of updating an inodes time or version. Must have
* had called mnt_want_write() before calling this.
*/
static int update_time(struct inode *inode, struct timespec *time, int flags)
{
if (inode->i_op->update_time)
return inode->i_op->update_time(inode, time, flags);
if (flags & S_ATIME)
inode->i_atime = *time;
if (flags & S_VERSION)
inode_inc_iversion(inode);
if (flags & S_CTIME)
inode->i_ctime = *time;
if (flags & S_MTIME)
inode->i_mtime = *time;
mark_inode_dirty_sync(inode);
return 0;
}
/**
* touch_atime - update the access time
* @mnt: mount the inode is accessed on
* @dentry: dentry accessed
* @path: the &struct path to update
*
* Update the accessed time on an inode and mark it for writeback.
* This function automatically handles read only file systems and media,
@ -1525,12 +1545,83 @@ void touch_atime(struct path *path)
if (mnt_want_write(mnt))
return;
inode->i_atime = now;
mark_inode_dirty_sync(inode);
/*
* File systems can error out when updating inodes if they need to
* allocate new space to modify an inode (such is the case for
* Btrfs), but since we touch atime while walking down the path we
* really don't care if we failed to update the atime of the file,
* so just ignore the return value.
*/
update_time(inode, &now, S_ATIME);
mnt_drop_write(mnt);
}
EXPORT_SYMBOL(touch_atime);
/*
* The logic we want is
*
* if suid or (sgid and xgrp)
* remove privs
*/
int should_remove_suid(struct dentry *dentry)
{
umode_t mode = dentry->d_inode->i_mode;
int kill = 0;
/* suid always must be killed */
if (unlikely(mode & S_ISUID))
kill = ATTR_KILL_SUID;
/*
* sgid without any exec bits is just a mandatory locking mark; leave
* it alone. If some exec bits are set, it's a real sgid; kill it.
*/
if (unlikely((mode & S_ISGID) && (mode & S_IXGRP)))
kill |= ATTR_KILL_SGID;
if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode)))
return kill;
return 0;
}
EXPORT_SYMBOL(should_remove_suid);
static int __remove_suid(struct dentry *dentry, int kill)
{
struct iattr newattrs;
newattrs.ia_valid = ATTR_FORCE | kill;
return notify_change(dentry, &newattrs);
}
int file_remove_suid(struct file *file)
{
struct dentry *dentry = file->f_path.dentry;
struct inode *inode = dentry->d_inode;
int killsuid;
int killpriv;
int error = 0;
/* Fast path for nothing security related */
if (IS_NOSEC(inode))
return 0;
killsuid = should_remove_suid(dentry);
killpriv = security_inode_need_killpriv(dentry);
if (killpriv < 0)
return killpriv;
if (killpriv)
error = security_inode_killpriv(dentry);
if (!error && killsuid)
error = __remove_suid(dentry, killsuid);
if (!error && (inode->i_sb->s_flags & MS_NOSEC))
inode->i_flags |= S_NOSEC;
return error;
}
EXPORT_SYMBOL(file_remove_suid);
/**
* file_update_time - update mtime and ctime time
* @file: file accessed
@ -1540,18 +1631,20 @@ EXPORT_SYMBOL(touch_atime);
* usage in the file write path of filesystems, and filesystems may
* choose to explicitly ignore update via this function with the
* S_NOCMTIME inode flag, e.g. for network filesystem where these
* timestamps are handled by the server.
* timestamps are handled by the server. This can return an error for
* file systems who need to allocate space in order to update an inode.
*/
void file_update_time(struct file *file)
int file_update_time(struct file *file)
{
struct inode *inode = file->f_path.dentry->d_inode;
struct timespec now;
enum { S_MTIME = 1, S_CTIME = 2, S_VERSION = 4 } sync_it = 0;
int sync_it = 0;
int ret;
/* First try to exhaust all avenues to not sync */
if (IS_NOCMTIME(inode))
return;
return 0;
now = current_fs_time(inode->i_sb);
if (!timespec_equal(&inode->i_mtime, &now))
@ -1564,21 +1657,16 @@ void file_update_time(struct file *file)
sync_it |= S_VERSION;
if (!sync_it)
return;
return 0;
/* Finally allowed to write? Takes lock. */
if (mnt_want_write_file(file))
return;
return 0;
/* Only change inode inside the lock region */
if (sync_it & S_VERSION)
inode_inc_iversion(inode);
if (sync_it & S_CTIME)
inode->i_ctime = now;
if (sync_it & S_MTIME)
inode->i_mtime = now;
mark_inode_dirty_sync(inode);
ret = update_time(inode, &now, sync_it);
mnt_drop_write_file(file);
return ret;
}
EXPORT_SYMBOL(file_update_time);

View File

@ -56,7 +56,7 @@ extern int sb_prepare_remount_readonly(struct super_block *);
extern void __init mnt_init(void);
DECLARE_BRLOCK(vfsmount_lock);
extern struct lglock vfsmount_lock;
/*
@ -100,6 +100,7 @@ extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
extern long do_handle_open(int mountdirfd,
struct file_handle __user *ufh, int open_flag);
extern int open_check_o_direct(struct file *f);
/*
* inode.c

View File

@ -107,12 +107,11 @@ static struct dentry *isofs_export_get_parent(struct dentry *child)
}
static int
isofs_export_encode_fh(struct dentry *dentry,
isofs_export_encode_fh(struct inode *inode,
__u32 *fh32,
int *max_len,
int connectable)
struct inode *parent)
{
struct inode * inode = dentry->d_inode;
struct iso_inode_info * ei = ISOFS_I(inode);
int len = *max_len;
int type = 1;
@ -124,7 +123,7 @@ isofs_export_encode_fh(struct dentry *dentry,
* offset of the inode and the upper 16 bits of fh32[1] to
* hold the offset of the parent.
*/
if (connectable && (len < 5)) {
if (parent && (len < 5)) {
*max_len = 5;
return 255;
} else if (len < 3) {
@ -136,16 +135,12 @@ isofs_export_encode_fh(struct dentry *dentry,
fh32[0] = ei->i_iget5_block;
fh16[2] = (__u16)ei->i_iget5_offset; /* fh16 [sic] */
fh32[2] = inode->i_generation;
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
if (parent) {
struct iso_inode_info *eparent;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
eparent = ISOFS_I(parent);
fh32[3] = eparent->i_iget5_block;
fh16[3] = (__u16)eparent->i_iget5_offset; /* fh16 [sic] */
fh32[4] = parent->i_generation;
spin_unlock(&dentry->d_lock);
len = 5;
type = 2;
}

View File

@ -126,6 +126,10 @@ struct jffs2_sb_info {
struct jffs2_inodirty *wbuf_inodes;
struct rw_semaphore wbuf_sem; /* Protects the write buffer */
struct delayed_work wbuf_dwork; /* write-buffer write-out work */
int wbuf_queued; /* non-zero delayed work is queued */
spinlock_t wbuf_dwork_lock; /* protects wbuf_dwork and and wbuf_queued */
unsigned char *oobbuf;
int oobavail; /* How many bytes are available for JFFS2 in OOB */
#endif

View File

@ -95,6 +95,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f)
#define jffs2_ubivol(c) (0)
#define jffs2_ubivol_setup(c) (0)
#define jffs2_ubivol_cleanup(c) do {} while (0)
#define jffs2_dirty_trigger(c) do {} while (0)
#else /* NAND and/or ECC'd NOR support present */
@ -135,14 +136,10 @@ void jffs2_ubivol_cleanup(struct jffs2_sb_info *c);
#define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && ! (c->mtd->flags & MTD_BIT_WRITEABLE))
int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c);
void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c);
void jffs2_dirty_trigger(struct jffs2_sb_info *c);
#endif /* WRITEBUFFER */
static inline void jffs2_dirty_trigger(struct jffs2_sb_info *c)
{
OFNI_BS_2SFFJ(c)->s_dirt = 1;
}
/* background.c */
int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);

View File

@ -63,21 +63,6 @@ static void jffs2_i_init_once(void *foo)
inode_init_once(&f->vfs_inode);
}
static void jffs2_write_super(struct super_block *sb)
{
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
lock_super(sb);
sb->s_dirt = 0;
if (!(sb->s_flags & MS_RDONLY)) {
jffs2_dbg(1, "%s()\n", __func__);
jffs2_flush_wbuf_gc(c, 0);
}
unlock_super(sb);
}
static const char *jffs2_compr_name(unsigned int compr)
{
switch (compr) {
@ -113,8 +98,6 @@ static int jffs2_sync_fs(struct super_block *sb, int wait)
{
struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
jffs2_write_super(sb);
mutex_lock(&c->alloc_sem);
jffs2_flush_wbuf_pad(c);
mutex_unlock(&c->alloc_sem);
@ -251,7 +234,6 @@ static const struct super_operations jffs2_super_operations =
.alloc_inode = jffs2_alloc_inode,
.destroy_inode =jffs2_destroy_inode,
.put_super = jffs2_put_super,
.write_super = jffs2_write_super,
.statfs = jffs2_statfs,
.remount_fs = jffs2_remount_fs,
.evict_inode = jffs2_evict_inode,
@ -319,9 +301,6 @@ static void jffs2_put_super (struct super_block *sb)
jffs2_dbg(2, "%s()\n", __func__);
if (sb->s_dirt)
jffs2_write_super(sb);
mutex_lock(&c->alloc_sem);
jffs2_flush_wbuf_pad(c);
mutex_unlock(&c->alloc_sem);

View File

@ -20,6 +20,7 @@
#include <linux/mtd/nand.h>
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/writeback.h>
#include "nodelist.h"
@ -85,7 +86,7 @@ static void jffs2_wbuf_dirties_inode(struct jffs2_sb_info *c, uint32_t ino)
{
struct jffs2_inodirty *new;
/* Mark the superblock dirty so that kupdated will flush... */
/* Schedule delayed write-buffer write-out */
jffs2_dirty_trigger(c);
if (jffs2_wbuf_pending_for_ino(c, ino))
@ -1148,6 +1149,47 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *
return 1;
}
static struct jffs2_sb_info *work_to_sb(struct work_struct *work)
{
struct delayed_work *dwork;
dwork = container_of(work, struct delayed_work, work);
return container_of(dwork, struct jffs2_sb_info, wbuf_dwork);
}
static void delayed_wbuf_sync(struct work_struct *work)
{
struct jffs2_sb_info *c = work_to_sb(work);
struct super_block *sb = OFNI_BS_2SFFJ(c);
spin_lock(&c->wbuf_dwork_lock);
c->wbuf_queued = 0;
spin_unlock(&c->wbuf_dwork_lock);
if (!(sb->s_flags & MS_RDONLY)) {
jffs2_dbg(1, "%s()\n", __func__);
jffs2_flush_wbuf_gc(c, 0);
}
}
void jffs2_dirty_trigger(struct jffs2_sb_info *c)
{
struct super_block *sb = OFNI_BS_2SFFJ(c);
unsigned long delay;
if (sb->s_flags & MS_RDONLY)
return;
spin_lock(&c->wbuf_dwork_lock);
if (!c->wbuf_queued) {
jffs2_dbg(1, "%s()\n", __func__);
delay = msecs_to_jiffies(dirty_writeback_interval * 10);
queue_delayed_work(system_long_wq, &c->wbuf_dwork, delay);
c->wbuf_queued = 1;
}
spin_unlock(&c->wbuf_dwork_lock);
}
int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
{
struct nand_ecclayout *oinfo = c->mtd->ecclayout;
@ -1169,6 +1211,8 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
/* Initialise write buffer */
init_rwsem(&c->wbuf_sem);
spin_lock_init(&c->wbuf_dwork_lock);
INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync);
c->wbuf_pagesize = c->mtd->writesize;
c->wbuf_ofs = 0xFFFFFFFF;
@ -1207,8 +1251,8 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
/* Initialize write buffer */
init_rwsem(&c->wbuf_sem);
spin_lock_init(&c->wbuf_dwork_lock);
INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync);
c->wbuf_pagesize = c->mtd->erasesize;
/* Find a suitable c->sector_size
@ -1267,6 +1311,9 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) {
/* Initialize write buffer */
init_rwsem(&c->wbuf_sem);
spin_lock_init(&c->wbuf_dwork_lock);
INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync);
c->wbuf_pagesize = c->mtd->writesize;
c->wbuf_ofs = 0xFFFFFFFF;
@ -1299,6 +1346,8 @@ int jffs2_ubivol_setup(struct jffs2_sb_info *c) {
return 0;
init_rwsem(&c->wbuf_sem);
spin_lock_init(&c->wbuf_dwork_lock);
INIT_DELAYED_WORK(&c->wbuf_dwork, delayed_wbuf_sync);
c->wbuf_pagesize = c->mtd->writesize;
c->wbuf_ofs = 0xFFFFFFFF;

View File

@ -1636,12 +1636,13 @@ EXPORT_SYMBOL(flock_lock_file_wait);
SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
{
struct file *filp;
int fput_needed;
struct file_lock *lock;
int can_sleep, unlock;
int error;
error = -EBADF;
filp = fget(fd);
filp = fget_light(fd, &fput_needed);
if (!filp)
goto out;
@ -1674,7 +1675,7 @@ SYSCALL_DEFINE2(flock, unsigned int, fd, unsigned int, cmd)
locks_free_lock(lock);
out_putf:
fput(filp);
fput_light(filp, fput_needed);
out:
return error;
}

View File

@ -449,7 +449,7 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
mntget(nd->path.mnt);
rcu_read_unlock();
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
nd->flags &= ~LOOKUP_RCU;
return 0;
@ -507,14 +507,14 @@ static int complete_walk(struct nameidata *nd)
if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) {
spin_unlock(&dentry->d_lock);
rcu_read_unlock();
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
return -ECHILD;
}
BUG_ON(nd->inode != dentry->d_inode);
spin_unlock(&dentry->d_lock);
mntget(nd->path.mnt);
rcu_read_unlock();
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
}
if (likely(!(nd->flags & LOOKUP_JUMPED)))
@ -681,15 +681,15 @@ int follow_up(struct path *path)
struct mount *parent;
struct dentry *mountpoint;
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
parent = mnt->mnt_parent;
if (&parent->mnt == path->mnt) {
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
return 0;
}
mntget(&parent->mnt);
mountpoint = dget(mnt->mnt_mountpoint);
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
dput(path->dentry);
path->dentry = mountpoint;
mntput(path->mnt);
@ -947,7 +947,7 @@ static int follow_dotdot_rcu(struct nameidata *nd)
if (!(nd->flags & LOOKUP_ROOT))
nd->root.mnt = NULL;
rcu_read_unlock();
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
return -ECHILD;
}
@ -1125,8 +1125,8 @@ static struct dentry *__lookup_hash(struct qstr *name,
* small and for now I'd prefer to have fast path as straight as possible.
* It _is_ time-critical.
*/
static int do_lookup(struct nameidata *nd, struct qstr *name,
struct path *path, struct inode **inode)
static int lookup_fast(struct nameidata *nd, struct qstr *name,
struct path *path, struct inode **inode)
{
struct vfsmount *mnt = nd->path.mnt;
struct dentry *dentry, *parent = nd->path.dentry;
@ -1208,7 +1208,7 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
goto need_lookup;
}
}
done:
path->mnt = mnt;
path->dentry = dentry;
err = follow_managed(path, nd->flags);
@ -1222,6 +1222,17 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
return 0;
need_lookup:
return 1;
}
/* Fast lookup failed, do it the slow way */
static int lookup_slow(struct nameidata *nd, struct qstr *name,
struct path *path)
{
struct dentry *dentry, *parent;
int err;
parent = nd->path.dentry;
BUG_ON(nd->inode != parent->d_inode);
mutex_lock(&parent->d_inode->i_mutex);
@ -1229,7 +1240,16 @@ static int do_lookup(struct nameidata *nd, struct qstr *name,
mutex_unlock(&parent->d_inode->i_mutex);
if (IS_ERR(dentry))
return PTR_ERR(dentry);
goto done;
path->mnt = nd->path.mnt;
path->dentry = dentry;
err = follow_managed(path, nd->flags);
if (unlikely(err < 0)) {
path_put_conditional(path, nd);
return err;
}
if (err)
nd->flags |= LOOKUP_JUMPED;
return 0;
}
static inline int may_lookup(struct nameidata *nd)
@ -1265,7 +1285,7 @@ static void terminate_walk(struct nameidata *nd)
if (!(nd->flags & LOOKUP_ROOT))
nd->root.mnt = NULL;
rcu_read_unlock();
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
}
}
@ -1301,21 +1321,26 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
*/
if (unlikely(type != LAST_NORM))
return handle_dots(nd, type);
err = do_lookup(nd, name, path, &inode);
err = lookup_fast(nd, name, path, &inode);
if (unlikely(err)) {
terminate_walk(nd);
return err;
}
if (!inode) {
path_to_nameidata(path, nd);
terminate_walk(nd);
return -ENOENT;
if (err < 0)
goto out_err;
err = lookup_slow(nd, name, path);
if (err < 0)
goto out_err;
inode = path->dentry->d_inode;
}
err = -ENOENT;
if (!inode)
goto out_path_put;
if (should_follow_link(inode, follow)) {
if (nd->flags & LOOKUP_RCU) {
if (unlikely(unlazy_walk(nd, path->dentry))) {
terminate_walk(nd);
return -ECHILD;
err = -ECHILD;
goto out_err;
}
}
BUG_ON(inode != path->dentry->d_inode);
@ -1324,6 +1349,12 @@ static inline int walk_component(struct nameidata *nd, struct path *path,
path_to_nameidata(path, nd);
nd->inode = inode;
return 0;
out_path_put:
path_to_nameidata(path, nd);
out_err:
terminate_walk(nd);
return err;
}
/*
@ -1620,7 +1651,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
nd->path = nd->root;
nd->inode = inode;
if (flags & LOOKUP_RCU) {
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
rcu_read_lock();
nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
} else {
@ -1633,7 +1664,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
if (*name=='/') {
if (flags & LOOKUP_RCU) {
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
rcu_read_lock();
set_root_rcu(nd);
} else {
@ -1646,7 +1677,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
struct fs_struct *fs = current->fs;
unsigned seq;
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
rcu_read_lock();
do {
@ -1682,7 +1713,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
if (fput_needed)
*fp = file;
nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
rcu_read_lock();
} else {
path_get(&file->f_path);
@ -2169,6 +2200,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
int want_write = 0;
int acc_mode = op->acc_mode;
struct file *filp;
struct inode *inode;
int symlink_ok = 0;
struct path save_parent = { .dentry = NULL, .mnt = NULL };
bool retried = false;
int error;
nd->flags &= ~LOOKUP_PARENT;
@ -2200,30 +2235,23 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
}
if (!(open_flag & O_CREAT)) {
int symlink_ok = 0;
if (nd->last.name[nd->last.len])
nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
symlink_ok = 1;
/* we _can_ be in RCU mode here */
error = walk_component(nd, path, &nd->last, LAST_NORM,
!symlink_ok);
if (error < 0)
return ERR_PTR(error);
if (error) /* symlink */
return NULL;
/* sayonara */
error = complete_walk(nd);
if (error)
return ERR_PTR(error);
error = -ENOTDIR;
if (nd->flags & LOOKUP_DIRECTORY) {
if (!nd->inode->i_op->lookup)
error = lookup_fast(nd, &nd->last, path, &inode);
if (unlikely(error)) {
if (error < 0)
goto exit;
error = lookup_slow(nd, &nd->last, path);
if (error < 0)
goto exit;
inode = path->dentry->d_inode;
}
audit_inode(pathname, nd->path.dentry);
goto ok;
goto finish_lookup;
}
/* create side of things */
@ -2241,6 +2269,7 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (nd->last.name[nd->last.len])
goto exit;
retry_lookup:
mutex_lock(&dir->d_inode->i_mutex);
dentry = lookup_hash(nd);
@ -2302,22 +2331,49 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (error)
nd->flags |= LOOKUP_JUMPED;
BUG_ON(nd->flags & LOOKUP_RCU);
inode = path->dentry->d_inode;
finish_lookup:
/* we _can_ be in RCU mode here */
error = -ENOENT;
if (!path->dentry->d_inode)
goto exit_dput;
if (!inode) {
path_to_nameidata(path, nd);
goto exit;
}
if (path->dentry->d_inode->i_op->follow_link)
if (should_follow_link(inode, !symlink_ok)) {
if (nd->flags & LOOKUP_RCU) {
if (unlikely(unlazy_walk(nd, path->dentry))) {
error = -ECHILD;
goto exit;
}
}
BUG_ON(inode != path->dentry->d_inode);
return NULL;
}
path_to_nameidata(path, nd);
nd->inode = path->dentry->d_inode;
if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
path_to_nameidata(path, nd);
} else {
save_parent.dentry = nd->path.dentry;
save_parent.mnt = mntget(path->mnt);
nd->path.dentry = path->dentry;
}
nd->inode = inode;
/* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
error = complete_walk(nd);
if (error)
if (error) {
path_put(&save_parent);
return ERR_PTR(error);
}
error = -EISDIR;
if (S_ISDIR(nd->inode->i_mode))
if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
goto exit;
error = -ENOTDIR;
if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
goto exit;
audit_inode(pathname, nd->path.dentry);
ok:
if (!S_ISREG(nd->inode->i_mode))
will_truncate = 0;
@ -2333,6 +2389,20 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
if (error)
goto exit;
filp = nameidata_to_filp(nd);
if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) {
BUG_ON(save_parent.dentry != dir);
path_put(&nd->path);
nd->path = save_parent;
nd->inode = dir->d_inode;
save_parent.mnt = NULL;
save_parent.dentry = NULL;
if (want_write) {
mnt_drop_write(nd->path.mnt);
want_write = 0;
}
retried = true;
goto retry_lookup;
}
if (!IS_ERR(filp)) {
error = ima_file_check(filp, op->acc_mode);
if (error) {
@ -2352,7 +2422,8 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
out:
if (want_write)
mnt_drop_write(nd->path.mnt);
path_put(&nd->path);
path_put(&save_parent);
terminate_walk(nd);
return filp;
exit_mutex_unlock:
@ -2415,6 +2486,12 @@ static struct file *path_openat(int dfd, const char *pathname,
if (base)
fput(base);
release_open_intent(nd);
if (filp == ERR_PTR(-EOPENSTALE)) {
if (flags & LOOKUP_RCU)
filp = ERR_PTR(-ECHILD);
else
filp = ERR_PTR(-ESTALE);
}
return filp;
out_filp:

View File

@ -397,7 +397,7 @@ static int mnt_make_readonly(struct mount *mnt)
{
int ret = 0;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
/*
* After storing MNT_WRITE_HOLD, we'll read the counters. This store
@ -431,15 +431,15 @@ static int mnt_make_readonly(struct mount *mnt)
*/
smp_wmb();
mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
return ret;
}
static void __mnt_unmake_readonly(struct mount *mnt)
{
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
mnt->mnt.mnt_flags &= ~MNT_READONLY;
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
}
int sb_prepare_remount_readonly(struct super_block *sb)
@ -451,7 +451,7 @@ int sb_prepare_remount_readonly(struct super_block *sb)
if (atomic_long_read(&sb->s_remove_count))
return -EBUSY;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
list_for_each_entry(mnt, &sb->s_mounts, mnt_instance) {
if (!(mnt->mnt.mnt_flags & MNT_READONLY)) {
mnt->mnt.mnt_flags |= MNT_WRITE_HOLD;
@ -473,7 +473,7 @@ int sb_prepare_remount_readonly(struct super_block *sb)
if (mnt->mnt.mnt_flags & MNT_WRITE_HOLD)
mnt->mnt.mnt_flags &= ~MNT_WRITE_HOLD;
}
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
return err;
}
@ -522,14 +522,14 @@ struct vfsmount *lookup_mnt(struct path *path)
{
struct mount *child_mnt;
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
child_mnt = __lookup_mnt(path->mnt, path->dentry, 1);
if (child_mnt) {
mnt_add_count(child_mnt, 1);
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
return &child_mnt->mnt;
} else {
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
return NULL;
}
}
@ -714,9 +714,9 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
mnt->mnt.mnt_sb = root->d_sb;
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
list_add_tail(&mnt->mnt_instance, &root->d_sb->s_mounts);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
return &mnt->mnt;
}
EXPORT_SYMBOL_GPL(vfs_kern_mount);
@ -745,9 +745,9 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
mnt->mnt.mnt_root = dget(root);
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
if (flag & CL_SLAVE) {
list_add(&mnt->mnt_slave, &old->mnt_slave_list);
@ -803,35 +803,36 @@ static void mntput_no_expire(struct mount *mnt)
{
put_again:
#ifdef CONFIG_SMP
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
if (likely(atomic_read(&mnt->mnt_longterm))) {
mnt_add_count(mnt, -1);
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
return;
}
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
mnt_add_count(mnt, -1);
if (mnt_get_count(mnt)) {
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
return;
}
#else
mnt_add_count(mnt, -1);
if (likely(mnt_get_count(mnt)))
return;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
#endif
if (unlikely(mnt->mnt_pinned)) {
mnt_add_count(mnt, mnt->mnt_pinned + 1);
mnt->mnt_pinned = 0;
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
acct_auto_close_mnt(&mnt->mnt);
goto put_again;
}
list_del(&mnt->mnt_instance);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
mntfree(mnt);
}
@ -857,21 +858,21 @@ EXPORT_SYMBOL(mntget);
void mnt_pin(struct vfsmount *mnt)
{
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
real_mount(mnt)->mnt_pinned++;
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
}
EXPORT_SYMBOL(mnt_pin);
void mnt_unpin(struct vfsmount *m)
{
struct mount *mnt = real_mount(m);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
if (mnt->mnt_pinned) {
mnt_add_count(mnt, 1);
mnt->mnt_pinned--;
}
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
}
EXPORT_SYMBOL(mnt_unpin);
@ -988,12 +989,12 @@ int may_umount_tree(struct vfsmount *m)
BUG_ON(!m);
/* write lock needed for mnt_get_count */
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
for (p = mnt; p; p = next_mnt(p, mnt)) {
actual_refs += mnt_get_count(p);
minimum_refs += 2;
}
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
if (actual_refs > minimum_refs)
return 0;
@ -1020,10 +1021,10 @@ int may_umount(struct vfsmount *mnt)
{
int ret = 1;
down_read(&namespace_sem);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
if (propagate_mount_busy(real_mount(mnt), 2))
ret = 0;
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
up_read(&namespace_sem);
return ret;
}
@ -1040,13 +1041,13 @@ void release_mounts(struct list_head *head)
struct dentry *dentry;
struct mount *m;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
dentry = mnt->mnt_mountpoint;
m = mnt->mnt_parent;
mnt->mnt_mountpoint = mnt->mnt.mnt_root;
mnt->mnt_parent = mnt;
m->mnt_ghosts--;
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
dput(dentry);
mntput(&m->mnt);
}
@ -1073,8 +1074,9 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)
list_del_init(&p->mnt_expire);
list_del_init(&p->mnt_list);
__touch_mnt_namespace(p->mnt_ns);
if (p->mnt_ns)
__mnt_make_shortterm(p);
p->mnt_ns = NULL;
__mnt_make_shortterm(p);
list_del_init(&p->mnt_child);
if (mnt_has_parent(p)) {
p->mnt_parent->mnt_ghosts++;
@ -1112,12 +1114,12 @@ static int do_umount(struct mount *mnt, int flags)
* probably don't strictly need the lock here if we examined
* all race cases, but it's a slowpath.
*/
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
if (mnt_get_count(mnt) != 2) {
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
return -EBUSY;
}
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
if (!xchg(&mnt->mnt_expiry_mark, 1))
return -EAGAIN;
@ -1159,7 +1161,7 @@ static int do_umount(struct mount *mnt, int flags)
}
down_write(&namespace_sem);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
event++;
if (!(flags & MNT_DETACH))
@ -1171,7 +1173,7 @@ static int do_umount(struct mount *mnt, int flags)
umount_tree(mnt, 1, &umount_list);
retval = 0;
}
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
up_write(&namespace_sem);
release_mounts(&umount_list);
return retval;
@ -1286,19 +1288,19 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
q = clone_mnt(p, p->mnt.mnt_root, flag);
if (!q)
goto Enomem;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
list_add_tail(&q->mnt_list, &res->mnt_list);
attach_mnt(q, &path);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
}
}
return res;
Enomem:
if (res) {
LIST_HEAD(umount_list);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
umount_tree(res, 0, &umount_list);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
release_mounts(&umount_list);
}
return NULL;
@ -1318,9 +1320,9 @@ void drop_collected_mounts(struct vfsmount *mnt)
{
LIST_HEAD(umount_list);
down_write(&namespace_sem);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
umount_tree(real_mount(mnt), 0, &umount_list);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
up_write(&namespace_sem);
release_mounts(&umount_list);
}
@ -1448,7 +1450,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
if (err)
goto out_cleanup_ids;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
if (IS_MNT_SHARED(dest_mnt)) {
for (p = source_mnt; p; p = next_mnt(p, source_mnt))
@ -1467,7 +1469,7 @@ static int attach_recursive_mnt(struct mount *source_mnt,
list_del_init(&child->mnt_hash);
commit_tree(child);
}
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
return 0;
@ -1565,10 +1567,10 @@ static int do_change_type(struct path *path, int flag)
goto out_unlock;
}
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL))
change_mnt_propagation(m, type);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
out_unlock:
up_write(&namespace_sem);
@ -1617,9 +1619,9 @@ static int do_loopback(struct path *path, char *old_name,
err = graft_tree(mnt, path);
if (err) {
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
umount_tree(mnt, 0, &umount_list);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
}
out2:
unlock_mount(path);
@ -1677,16 +1679,16 @@ static int do_remount(struct path *path, int flags, int mnt_flags,
else
err = do_remount_sb(sb, flags, data, 0);
if (!err) {
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
mnt_flags |= mnt->mnt.mnt_flags & MNT_PROPAGATION_MASK;
mnt->mnt.mnt_flags = mnt_flags;
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
}
up_write(&sb->s_umount);
if (!err) {
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
touch_mnt_namespace(mnt->mnt_ns);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
}
return err;
}
@ -1893,9 +1895,9 @@ int finish_automount(struct vfsmount *m, struct path *path)
/* remove m from any expiration list it may be on */
if (!list_empty(&mnt->mnt_expire)) {
down_write(&namespace_sem);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
list_del_init(&mnt->mnt_expire);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
up_write(&namespace_sem);
}
mntput(m);
@ -1911,11 +1913,11 @@ int finish_automount(struct vfsmount *m, struct path *path)
void mnt_set_expiry(struct vfsmount *mnt, struct list_head *expiry_list)
{
down_write(&namespace_sem);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
list_add_tail(&real_mount(mnt)->mnt_expire, expiry_list);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
up_write(&namespace_sem);
}
EXPORT_SYMBOL(mnt_set_expiry);
@ -1935,7 +1937,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
return;
down_write(&namespace_sem);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
/* extract from the expiration list every vfsmount that matches the
* following criteria:
@ -1954,7 +1956,7 @@ void mark_mounts_for_expiry(struct list_head *mounts)
touch_mnt_namespace(mnt->mnt_ns);
umount_tree(mnt, 1, &umounts);
}
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
up_write(&namespace_sem);
release_mounts(&umounts);
@ -2218,9 +2220,9 @@ void mnt_make_shortterm(struct vfsmount *m)
struct mount *mnt = real_mount(m);
if (atomic_add_unless(&mnt->mnt_longterm, -1, 1))
return;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
atomic_dec(&mnt->mnt_longterm);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
#endif
}
@ -2250,9 +2252,9 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
return ERR_PTR(-ENOMEM);
}
new_ns->root = new;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
list_add_tail(&new_ns->list, &new->mnt_list);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
/*
* Second pass: switch the tsk->fs->* elements and mark new vfsmounts
@ -2416,9 +2418,9 @@ bool is_path_reachable(struct mount *mnt, struct dentry *dentry,
int path_is_under(struct path *path1, struct path *path2)
{
int res;
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
res = is_path_reachable(real_mount(path1->mnt), path1->dentry, path2);
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
return res;
}
EXPORT_SYMBOL(path_is_under);
@ -2505,7 +2507,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
/* make sure we can reach put_old from new_root */
if (!is_path_reachable(real_mount(old.mnt), old.dentry, &new))
goto out4;
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
detach_mnt(new_mnt, &parent_path);
detach_mnt(root_mnt, &root_parent);
/* mount old root on put_old */
@ -2513,7 +2515,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
/* mount new_root on / */
attach_mnt(new_mnt, &root_parent);
touch_mnt_namespace(current->nsproxy->mnt_ns);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
chroot_fs_refs(&root, &new);
error = 0;
out4:
@ -2576,7 +2578,7 @@ void __init mnt_init(void)
for (u = 0; u < HASH_SIZE; u++)
INIT_LIST_HEAD(&mount_hashtable[u]);
br_lock_init(vfsmount_lock);
br_lock_init(&vfsmount_lock);
err = sysfs_init();
if (err)
@ -2596,9 +2598,9 @@ void put_mnt_ns(struct mnt_namespace *ns)
if (!atomic_dec_and_test(&ns->count))
return;
down_write(&namespace_sem);
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
umount_tree(ns->root, 0, &umount_list);
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
up_write(&namespace_sem);
release_mounts(&umount_list);
kfree(ns);

View File

@ -221,6 +221,10 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
already_written = 0;
errno = file_update_time(file);
if (errno)
goto outrel;
bouncebuffer = vmalloc(bufsize);
if (!bouncebuffer) {
errno = -EIO; /* -ENOMEM */
@ -252,8 +256,6 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t *
}
vfree(bouncebuffer);
file_update_time(file);
*ppos = pos;
if (pos > i_size_read(inode)) {

View File

@ -23,17 +23,17 @@ struct ncp_mount_data_kernel {
unsigned long flags; /* NCP_MOUNT_* flags */
unsigned int int_flags; /* internal flags */
#define NCP_IMOUNT_LOGGEDIN_POSSIBLE 0x0001
__kernel_uid32_t mounted_uid; /* Who may umount() this filesystem? */
uid_t mounted_uid; /* Who may umount() this filesystem? */
struct pid *wdog_pid; /* Who cares for our watchdog packets? */
unsigned int ncp_fd; /* The socket to the ncp port */
unsigned int time_out; /* How long should I wait after
sending a NCP request? */
unsigned int retry_count; /* And how often should I retry? */
unsigned char mounted_vol[NCP_VOLNAME_LEN + 1];
__kernel_uid32_t uid;
__kernel_gid32_t gid;
__kernel_mode_t file_mode;
__kernel_mode_t dir_mode;
uid_t uid;
gid_t gid;
umode_t file_mode;
umode_t dir_mode;
int info_fd;
};

View File

@ -1354,10 +1354,10 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
}
#ifdef CONFIG_NFS_V4
static int nfs_open_revalidate(struct dentry *, struct nameidata *);
static int nfs4_lookup_revalidate(struct dentry *, struct nameidata *);
const struct dentry_operations nfs4_dentry_operations = {
.d_revalidate = nfs_open_revalidate,
.d_revalidate = nfs4_lookup_revalidate,
.d_delete = nfs_dentry_delete,
.d_iput = nfs_dentry_iput,
.d_automount = nfs_d_automount,
@ -1519,13 +1519,11 @@ static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry
return nfs_lookup(dir, dentry, nd);
}
static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
{
struct dentry *parent = NULL;
struct inode *inode;
struct inode *dir;
struct nfs_open_context *ctx;
struct iattr attr;
int openflags, ret = 0;
if (nd->flags & LOOKUP_RCU)
@ -1554,57 +1552,13 @@ static int nfs_open_revalidate(struct dentry *dentry, struct nameidata *nd)
/* We cannot do exclusive creation on a positive dentry */
if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
goto no_open_dput;
/* We can't create new files here */
openflags &= ~(O_CREAT|O_EXCL);
ctx = create_nfs_open_context(dentry, openflags);
ret = PTR_ERR(ctx);
if (IS_ERR(ctx))
goto out;
/* Let f_op->open() actually open (and revalidate) the file */
ret = 1;
attr.ia_valid = ATTR_OPEN;
if (openflags & O_TRUNC) {
attr.ia_valid |= ATTR_SIZE;
attr.ia_size = 0;
nfs_wb_all(inode);
}
/*
* Note: we're not holding inode->i_mutex and so may be racing with
* operations that change the directory. We therefore save the
* change attribute *before* we do the RPC call.
*/
inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
if (IS_ERR(inode)) {
ret = PTR_ERR(inode);
switch (ret) {
case -EPERM:
case -EACCES:
case -EDQUOT:
case -ENOSPC:
case -EROFS:
goto out_put_ctx;
default:
goto out_drop;
}
}
iput(inode);
if (inode != dentry->d_inode)
goto out_drop;
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
ret = nfs_intent_set_file(nd, ctx);
if (ret >= 0)
ret = 1;
out:
dput(parent);
return ret;
out_drop:
d_drop(dentry);
ret = 0;
out_put_ctx:
put_nfs_open_context(ctx);
goto out;
no_open_dput:
dput(parent);

View File

@ -879,12 +879,81 @@ const struct file_operations nfs_file_operations = {
static int
nfs4_file_open(struct inode *inode, struct file *filp)
{
struct nfs_open_context *ctx;
struct dentry *dentry = filp->f_path.dentry;
struct dentry *parent = NULL;
struct inode *dir;
unsigned openflags = filp->f_flags;
struct iattr attr;
int err;
BUG_ON(inode != dentry->d_inode);
/*
* NFSv4 opens are handled in d_lookup and d_revalidate. If we get to
* this point, then something is very wrong
* If no cached dentry exists or if it's negative, NFSv4 handled the
* opens in ->lookup() or ->create().
*
* We only get this far for a cached positive dentry. We skipped
* revalidation, so handle it here by dropping the dentry and returning
* -EOPENSTALE. The VFS will retry the lookup/create/open.
*/
dprintk("NFS: %s called! inode=%p filp=%p\n", __func__, inode, filp);
return -ENOTDIR;
dprintk("NFS: open file(%s/%s)\n",
dentry->d_parent->d_name.name,
dentry->d_name.name);
if ((openflags & O_ACCMODE) == 3)
openflags--;
/* We can't create new files here */
openflags &= ~(O_CREAT|O_EXCL);
parent = dget_parent(dentry);
dir = parent->d_inode;
ctx = alloc_nfs_open_context(filp->f_path.dentry, filp->f_mode);
err = PTR_ERR(ctx);
if (IS_ERR(ctx))
goto out;
attr.ia_valid = ATTR_OPEN;
if (openflags & O_TRUNC) {
attr.ia_valid |= ATTR_SIZE;
attr.ia_size = 0;
nfs_wb_all(inode);
}
inode = NFS_PROTO(dir)->open_context(dir, ctx, openflags, &attr);
if (IS_ERR(inode)) {
err = PTR_ERR(inode);
switch (err) {
case -EPERM:
case -EACCES:
case -EDQUOT:
case -ENOSPC:
case -EROFS:
goto out_put_ctx;
default:
goto out_drop;
}
}
iput(inode);
if (inode != dentry->d_inode)
goto out_drop;
nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
nfs_file_set_open_context(filp, ctx);
err = 0;
out_put_ctx:
put_nfs_open_context(ctx);
out:
dput(parent);
return err;
out_drop:
d_drop(dentry);
err = -EOPENSTALE;
goto out_put_ctx;
}
const struct file_operations nfs4_file_operations = {

View File

@ -508,31 +508,29 @@ static struct dentry *nilfs_fh_to_parent(struct super_block *sb, struct fid *fh,
return nilfs_get_dentry(sb, fid->cno, fid->parent_ino, fid->parent_gen);
}
static int nilfs_encode_fh(struct dentry *dentry, __u32 *fh, int *lenp,
int connectable)
static int nilfs_encode_fh(struct inode *inode, __u32 *fh, int *lenp,
struct inode *parent)
{
struct nilfs_fid *fid = (struct nilfs_fid *)fh;
struct inode *inode = dentry->d_inode;
struct nilfs_root *root = NILFS_I(inode)->i_root;
int type;
if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE ||
(connectable && *lenp < NILFS_FID_SIZE_CONNECTABLE))
if (parent && *lenp < NILFS_FID_SIZE_CONNECTABLE) {
*lenp = NILFS_FID_SIZE_CONNECTABLE;
return 255;
}
if (*lenp < NILFS_FID_SIZE_NON_CONNECTABLE) {
*lenp = NILFS_FID_SIZE_NON_CONNECTABLE;
return 255;
}
fid->cno = root->cno;
fid->ino = inode->i_ino;
fid->gen = inode->i_generation;
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
if (parent) {
fid->parent_ino = parent->i_ino;
fid->parent_gen = parent->i_generation;
spin_unlock(&dentry->d_lock);
type = FILEID_NILFS_WITH_PARENT;
*lenp = NILFS_FID_SIZE_CONNECTABLE;
} else {

View File

@ -123,7 +123,7 @@ int __fsnotify_parent(struct path *path, struct dentry *dentry, __u32 mask)
}
EXPORT_SYMBOL_GPL(__fsnotify_parent);
static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
static int send_to_group(struct inode *to_tell,
struct fsnotify_mark *inode_mark,
struct fsnotify_mark *vfsmount_mark,
__u32 mask, void *data,
@ -168,10 +168,10 @@ static int send_to_group(struct inode *to_tell, struct vfsmount *mnt,
vfsmount_test_mask &= ~inode_mark->ignored_mask;
}
pr_debug("%s: group=%p to_tell=%p mnt=%p mask=%x inode_mark=%p"
pr_debug("%s: group=%p to_tell=%p mask=%x inode_mark=%p"
" inode_test_mask=%x vfsmount_mark=%p vfsmount_test_mask=%x"
" data=%p data_is=%d cookie=%d event=%p\n",
__func__, group, to_tell, mnt, mask, inode_mark,
__func__, group, to_tell, mask, inode_mark,
inode_test_mask, vfsmount_mark, vfsmount_test_mask, data,
data_is, cookie, *event);
@ -258,16 +258,16 @@ int fsnotify(struct inode *to_tell, __u32 mask, void *data, int data_is,
if (inode_group > vfsmount_group) {
/* handle inode */
ret = send_to_group(to_tell, NULL, inode_mark, NULL, mask, data,
ret = send_to_group(to_tell, inode_mark, NULL, mask, data,
data_is, cookie, file_name, &event);
/* we didn't use the vfsmount_mark */
vfsmount_group = NULL;
} else if (vfsmount_group > inode_group) {
ret = send_to_group(to_tell, &mnt->mnt, NULL, vfsmount_mark, mask, data,
ret = send_to_group(to_tell, NULL, vfsmount_mark, mask, data,
data_is, cookie, file_name, &event);
inode_group = NULL;
} else {
ret = send_to_group(to_tell, &mnt->mnt, inode_mark, vfsmount_mark,
ret = send_to_group(to_tell, inode_mark, vfsmount_mark,
mask, data, data_is, cookie, file_name,
&event);
}

View File

@ -2096,7 +2096,9 @@ static ssize_t ntfs_file_aio_write_nolock(struct kiocb *iocb,
err = file_remove_suid(file);
if (err)
goto out;
file_update_time(file);
err = file_update_time(file);
if (err)
goto out;
written = ntfs_file_buffered_write(iocb, iov, nr_segs, pos, ppos,
count);
out:

View File

@ -422,45 +422,46 @@ int ocfs2_block_check_validate(void *data, size_t blocksize,
struct ocfs2_blockcheck_stats *stats)
{
int rc = 0;
struct ocfs2_block_check check;
u32 bc_crc32e;
u16 bc_ecc;
u32 crc, ecc;
ocfs2_blockcheck_inc_check(stats);
check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
check.bc_ecc = le16_to_cpu(bc->bc_ecc);
bc_crc32e = le32_to_cpu(bc->bc_crc32e);
bc_ecc = le16_to_cpu(bc->bc_ecc);
memset(bc, 0, sizeof(struct ocfs2_block_check));
/* Fast path - if the crc32 validates, we're good to go */
crc = crc32_le(~0, data, blocksize);
if (crc == check.bc_crc32e)
if (crc == bc_crc32e)
goto out;
ocfs2_blockcheck_inc_failure(stats);
mlog(ML_ERROR,
"CRC32 failed: stored: 0x%x, computed 0x%x. Applying ECC.\n",
(unsigned int)check.bc_crc32e, (unsigned int)crc);
(unsigned int)bc_crc32e, (unsigned int)crc);
/* Ok, try ECC fixups */
ecc = ocfs2_hamming_encode_block(data, blocksize);
ocfs2_hamming_fix_block(data, blocksize, ecc ^ check.bc_ecc);
ocfs2_hamming_fix_block(data, blocksize, ecc ^ bc_ecc);
/* And check the crc32 again */
crc = crc32_le(~0, data, blocksize);
if (crc == check.bc_crc32e) {
if (crc == bc_crc32e) {
ocfs2_blockcheck_inc_recover(stats);
goto out;
}
mlog(ML_ERROR, "Fixed CRC32 failed: stored: 0x%x, computed 0x%x\n",
(unsigned int)check.bc_crc32e, (unsigned int)crc);
(unsigned int)bc_crc32e, (unsigned int)crc);
rc = -EIO;
out:
bc->bc_crc32e = cpu_to_le32(check.bc_crc32e);
bc->bc_ecc = cpu_to_le16(check.bc_ecc);
bc->bc_crc32e = cpu_to_le32(bc_crc32e);
bc->bc_ecc = cpu_to_le16(bc_ecc);
return rc;
}
@ -528,7 +529,8 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
struct ocfs2_blockcheck_stats *stats)
{
int i, rc = 0;
struct ocfs2_block_check check;
u32 bc_crc32e;
u16 bc_ecc;
u32 crc, ecc, fix;
BUG_ON(nr < 0);
@ -538,21 +540,21 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
ocfs2_blockcheck_inc_check(stats);
check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
check.bc_ecc = le16_to_cpu(bc->bc_ecc);
bc_crc32e = le32_to_cpu(bc->bc_crc32e);
bc_ecc = le16_to_cpu(bc->bc_ecc);
memset(bc, 0, sizeof(struct ocfs2_block_check));
/* Fast path - if the crc32 validates, we're good to go */
for (i = 0, crc = ~0; i < nr; i++)
crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
if (crc == check.bc_crc32e)
if (crc == bc_crc32e)
goto out;
ocfs2_blockcheck_inc_failure(stats);
mlog(ML_ERROR,
"CRC32 failed: stored: %u, computed %u. Applying ECC.\n",
(unsigned int)check.bc_crc32e, (unsigned int)crc);
(unsigned int)bc_crc32e, (unsigned int)crc);
/* Ok, try ECC fixups */
for (i = 0, ecc = 0; i < nr; i++) {
@ -565,7 +567,7 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
bhs[i]->b_size * 8,
bhs[i]->b_size * 8 * i);
}
fix = ecc ^ check.bc_ecc;
fix = ecc ^ bc_ecc;
for (i = 0; i < nr; i++) {
/*
* Try the fix against each buffer. It will only affect
@ -578,19 +580,19 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
/* And check the crc32 again */
for (i = 0, crc = ~0; i < nr; i++)
crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
if (crc == check.bc_crc32e) {
if (crc == bc_crc32e) {
ocfs2_blockcheck_inc_recover(stats);
goto out;
}
mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
(unsigned int)check.bc_crc32e, (unsigned int)crc);
(unsigned int)bc_crc32e, (unsigned int)crc);
rc = -EIO;
out:
bc->bc_crc32e = cpu_to_le32(check.bc_crc32e);
bc->bc_ecc = cpu_to_le16(check.bc_ecc);
bc->bc_crc32e = cpu_to_le32(bc_crc32e);
bc->bc_ecc = cpu_to_le16(bc_ecc);
return rc;
}

View File

@ -293,7 +293,7 @@ int dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data,
struct dlm_proxy_ast *past = (struct dlm_proxy_ast *) msg->buf;
char *name;
struct list_head *iter, *head=NULL;
u64 cookie;
__be64 cookie;
u32 flags;
u8 node;

View File

@ -679,7 +679,7 @@ struct dlm_query_join_packet {
};
union dlm_query_join_response {
u32 intval;
__be32 intval;
struct dlm_query_join_packet packet;
};
@ -755,8 +755,8 @@ struct dlm_query_region {
struct dlm_node_info {
u8 ni_nodenum;
u8 pad1;
u16 ni_ipv4_port;
u32 ni_ipv4_address;
__be16 ni_ipv4_port;
__be32 ni_ipv4_address;
};
struct dlm_query_nodeinfo {

View File

@ -818,7 +818,7 @@ static void dlm_query_join_packet_to_wire(struct dlm_query_join_packet *packet,
union dlm_query_join_response response;
response.packet = *packet;
*wire = cpu_to_be32(response.intval);
*wire = be32_to_cpu(response.intval);
}
static void dlm_query_join_wire_to_packet(u32 wire,

View File

@ -177,21 +177,23 @@ static struct dentry *ocfs2_get_parent(struct dentry *child)
return parent;
}
static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
int connectable)
static int ocfs2_encode_fh(struct inode *inode, u32 *fh_in, int *max_len,
struct inode *parent)
{
struct inode *inode = dentry->d_inode;
int len = *max_len;
int type = 1;
u64 blkno;
u32 generation;
__le32 *fh = (__force __le32 *) fh_in;
#ifdef TRACE_HOOKS_ARE_NOT_BRAINDEAD_IN_YOUR_OPINION
#error "You go ahead and fix that mess, then. Somehow"
trace_ocfs2_encode_fh_begin(dentry, dentry->d_name.len,
dentry->d_name.name,
fh, len, connectable);
#endif
if (connectable && (len < 6)) {
if (parent && (len < 6)) {
*max_len = 6;
type = 255;
goto bail;
@ -211,12 +213,7 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
fh[1] = cpu_to_le32((u32)(blkno & 0xffffffff));
fh[2] = cpu_to_le32(generation);
if (connectable && !S_ISDIR(inode->i_mode)) {
struct inode *parent;
spin_lock(&dentry->d_lock);
parent = dentry->d_parent->d_inode;
if (parent) {
blkno = OCFS2_I(parent)->ip_blkno;
generation = parent->i_generation;
@ -224,8 +221,6 @@ static int ocfs2_encode_fh(struct dentry *dentry, u32 *fh_in, int *max_len,
fh[4] = cpu_to_le32((u32)(blkno & 0xffffffff));
fh[5] = cpu_to_le32(generation);
spin_unlock(&dentry->d_lock);
len = 6;
type = 2;

View File

@ -273,11 +273,13 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
inode->i_gid = le32_to_cpu(fe->i_gid);
/* Fast symlinks will have i_size but no allocated clusters. */
if (S_ISLNK(inode->i_mode) && !fe->i_clusters)
if (S_ISLNK(inode->i_mode) && !fe->i_clusters) {
inode->i_blocks = 0;
else
inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops;
} else {
inode->i_blocks = ocfs2_inode_sector_count(inode);
inode->i_mapping->a_ops = &ocfs2_aops;
inode->i_mapping->a_ops = &ocfs2_aops;
}
inode->i_atime.tv_sec = le64_to_cpu(fe->i_atime);
inode->i_atime.tv_nsec = le32_to_cpu(fe->i_atime_nsec);
inode->i_mtime.tv_sec = le64_to_cpu(fe->i_mtime);
@ -331,10 +333,7 @@ void ocfs2_populate_inode(struct inode *inode, struct ocfs2_dinode *fe,
OCFS2_I(inode)->ip_dir_lock_gen = 1;
break;
case S_IFLNK:
if (ocfs2_inode_is_fast_symlink(inode))
inode->i_op = &ocfs2_fast_symlink_inode_operations;
else
inode->i_op = &ocfs2_symlink_inode_operations;
inode->i_op = &ocfs2_symlink_inode_operations;
i_size_write(inode, le64_to_cpu(fe->i_size));
break;
default:

View File

@ -864,7 +864,7 @@ int ocfs2_info_handle(struct inode *inode, struct ocfs2_info *info,
if (status)
break;
reqp = (struct ocfs2_info_request *)(unsigned long)req_addr;
reqp = (struct ocfs2_info_request __user *)(unsigned long)req_addr;
if (!reqp) {
status = -EINVAL;
goto bail;
@ -888,9 +888,11 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
struct ocfs2_space_resv sr;
struct ocfs2_new_group_input input;
struct reflink_arguments args;
const char *old_path, *new_path;
const char __user *old_path;
const char __user *new_path;
bool preserve;
struct ocfs2_info info;
void __user *argp = (void __user *)arg;
switch (cmd) {
case OCFS2_IOC_GETFLAGS:
@ -937,17 +939,15 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
return ocfs2_group_add(inode, &input);
case OCFS2_IOC_REFLINK:
if (copy_from_user(&args, (struct reflink_arguments *)arg,
sizeof(args)))
if (copy_from_user(&args, argp, sizeof(args)))
return -EFAULT;
old_path = (const char *)(unsigned long)args.old_path;
new_path = (const char *)(unsigned long)args.new_path;
old_path = (const char __user *)(unsigned long)args.old_path;
new_path = (const char __user *)(unsigned long)args.new_path;
preserve = (args.preserve != 0);
return ocfs2_reflink_ioctl(inode, old_path, new_path, preserve);
case OCFS2_IOC_INFO:
if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
sizeof(struct ocfs2_info)))
if (copy_from_user(&info, argp, sizeof(struct ocfs2_info)))
return -EFAULT;
return ocfs2_info_handle(inode, &info, 0);
@ -960,22 +960,20 @@ long ocfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
if (copy_from_user(&range, (struct fstrim_range *)arg,
sizeof(range)))
if (copy_from_user(&range, argp, sizeof(range)))
return -EFAULT;
ret = ocfs2_trim_fs(sb, &range);
if (ret < 0)
return ret;
if (copy_to_user((struct fstrim_range *)arg, &range,
sizeof(range)))
if (copy_to_user(argp, &range, sizeof(range)))
return -EFAULT;
return 0;
}
case OCFS2_IOC_MOVE_EXT:
return ocfs2_ioctl_move_extents(filp, (void __user *)arg);
return ocfs2_ioctl_move_extents(filp, argp);
default:
return -ENOTTY;
}
@ -988,6 +986,7 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
struct reflink_arguments args;
struct inode *inode = file->f_path.dentry->d_inode;
struct ocfs2_info info;
void __user *argp = (void __user *)arg;
switch (cmd) {
case OCFS2_IOC32_GETFLAGS:
@ -1006,16 +1005,14 @@ long ocfs2_compat_ioctl(struct file *file, unsigned cmd, unsigned long arg)
case FITRIM:
break;
case OCFS2_IOC_REFLINK:
if (copy_from_user(&args, (struct reflink_arguments *)arg,
sizeof(args)))
if (copy_from_user(&args, argp, sizeof(args)))
return -EFAULT;
preserve = (args.preserve != 0);
return ocfs2_reflink_ioctl(inode, compat_ptr(args.old_path),
compat_ptr(args.new_path), preserve);
case OCFS2_IOC_INFO:
if (copy_from_user(&info, (struct ocfs2_info __user *)arg,
sizeof(struct ocfs2_info)))
if (copy_from_user(&info, argp, sizeof(struct ocfs2_info)))
return -EFAULT;
return ocfs2_info_handle(inode, &info, 1);

View File

@ -1082,8 +1082,7 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp)
context->file = filp;
if (argp) {
if (copy_from_user(&range, (struct ocfs2_move_extents *)argp,
sizeof(range))) {
if (copy_from_user(&range, argp, sizeof(range))) {
status = -EFAULT;
goto out;
}
@ -1138,8 +1137,7 @@ int ocfs2_ioctl_move_extents(struct file *filp, void __user *argp)
* length and new_offset even if failure happens somewhere.
*/
if (argp) {
if (copy_to_user((struct ocfs2_move_extents *)argp, &range,
sizeof(range)))
if (copy_to_user(argp, &range, sizeof(range)))
status = -EFAULT;
}

View File

@ -1724,15 +1724,16 @@ static int ocfs2_symlink(struct inode *dir,
fe = (struct ocfs2_dinode *) new_fe_bh->b_data;
inode->i_rdev = 0;
newsize = l - 1;
inode->i_op = &ocfs2_symlink_inode_operations;
if (l > ocfs2_fast_symlink_chars(sb)) {
u32 offset = 0;
inode->i_op = &ocfs2_symlink_inode_operations;
status = dquot_alloc_space_nodirty(inode,
ocfs2_clusters_to_bytes(osb->sb, 1));
if (status)
goto bail;
did_quota = 1;
inode->i_mapping->a_ops = &ocfs2_aops;
status = ocfs2_add_inode_data(osb, inode, &offset, 1, 0,
new_fe_bh,
handle, data_ac, NULL,
@ -1750,7 +1751,7 @@ static int ocfs2_symlink(struct inode *dir,
i_size_write(inode, newsize);
inode->i_blocks = ocfs2_inode_sector_count(inode);
} else {
inode->i_op = &ocfs2_fast_symlink_inode_operations;
inode->i_mapping->a_ops = &ocfs2_fast_symlink_aops;
memcpy((char *) fe->id2.i_symlink, symname, l);
i_size_write(inode, newsize);
inode->i_blocks = 0;

View File

@ -54,101 +54,40 @@
#include "buffer_head_io.h"
static char *ocfs2_fast_symlink_getlink(struct inode *inode,
struct buffer_head **bh)
static int ocfs2_fast_symlink_readpage(struct file *unused, struct page *page)
{
int status;
char *link = NULL;
struct inode *inode = page->mapping->host;
struct buffer_head *bh;
int status = ocfs2_read_inode_block(inode, &bh);
struct ocfs2_dinode *fe;
const char *link;
void *kaddr;
size_t len;
status = ocfs2_read_inode_block(inode, bh);
if (status < 0) {
mlog_errno(status);
link = ERR_PTR(status);
goto bail;
return status;
}
fe = (struct ocfs2_dinode *) (*bh)->b_data;
fe = (struct ocfs2_dinode *) bh->b_data;
link = (char *) fe->id2.i_symlink;
bail:
return link;
}
static int ocfs2_readlink(struct dentry *dentry,
char __user *buffer,
int buflen)
{
int ret;
char *link;
struct buffer_head *bh = NULL;
struct inode *inode = dentry->d_inode;
link = ocfs2_fast_symlink_getlink(inode, &bh);
if (IS_ERR(link)) {
ret = PTR_ERR(link);
goto out;
}
/*
* Without vfsmount we can't update atime now,
* but we will update atime here ultimately.
*/
ret = vfs_readlink(dentry, buffer, buflen, link);
/* will be less than a page size */
len = strnlen(link, ocfs2_fast_symlink_chars(inode->i_sb));
kaddr = kmap_atomic(page);
memcpy(kaddr, link, len + 1);
kunmap_atomic(kaddr);
SetPageUptodate(page);
unlock_page(page);
brelse(bh);
out:
if (ret < 0)
mlog_errno(ret);
return ret;
return 0;
}
static void *ocfs2_fast_follow_link(struct dentry *dentry,
struct nameidata *nd)
{
int status = 0;
int len;
char *target, *link = ERR_PTR(-ENOMEM);
struct inode *inode = dentry->d_inode;
struct buffer_head *bh = NULL;
BUG_ON(!ocfs2_inode_is_fast_symlink(inode));
target = ocfs2_fast_symlink_getlink(inode, &bh);
if (IS_ERR(target)) {
status = PTR_ERR(target);
mlog_errno(status);
goto bail;
}
/* Fast symlinks can't be large */
len = strnlen(target, ocfs2_fast_symlink_chars(inode->i_sb));
link = kzalloc(len + 1, GFP_NOFS);
if (!link) {
status = -ENOMEM;
mlog_errno(status);
goto bail;
}
memcpy(link, target, len);
bail:
nd_set_link(nd, status ? ERR_PTR(status) : link);
brelse(bh);
if (status)
mlog_errno(status);
return NULL;
}
static void ocfs2_fast_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie)
{
char *link = nd_get_link(nd);
if (!IS_ERR(link))
kfree(link);
}
const struct address_space_operations ocfs2_fast_symlink_aops = {
.readpage = ocfs2_fast_symlink_readpage,
};
const struct inode_operations ocfs2_symlink_inode_operations = {
.readlink = page_readlink,
.readlink = generic_readlink,
.follow_link = page_follow_link_light,
.put_link = page_put_link,
.getattr = ocfs2_getattr,
@ -159,15 +98,3 @@ const struct inode_operations ocfs2_symlink_inode_operations = {
.removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap,
};
const struct inode_operations ocfs2_fast_symlink_inode_operations = {
.readlink = ocfs2_readlink,
.follow_link = ocfs2_fast_follow_link,
.put_link = ocfs2_fast_put_link,
.getattr = ocfs2_getattr,
.setattr = ocfs2_setattr,
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = ocfs2_listxattr,
.removexattr = generic_removexattr,
.fiemap = ocfs2_fiemap,
};

View File

@ -27,7 +27,7 @@
#define OCFS2_SYMLINK_H
extern const struct inode_operations ocfs2_symlink_inode_operations;
extern const struct inode_operations ocfs2_fast_symlink_inode_operations;
extern const struct address_space_operations ocfs2_fast_symlink_aops;
/*
* Test whether an inode is a fast symlink.

View File

@ -654,10 +654,23 @@ static inline int __get_file_write_access(struct inode *inode,
return error;
}
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
int open_check_o_direct(struct file *f)
{
/* NB: we're sure to have correct a_ops only after f_op->open */
if (f->f_flags & O_DIRECT) {
if (!f->f_mapping->a_ops ||
((!f->f_mapping->a_ops->direct_IO) &&
(!f->f_mapping->a_ops->get_xip_mem))) {
return -EINVAL;
}
}
return 0;
}
static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
{
static const struct file_operations empty_fops = {};
struct inode *inode;
@ -713,16 +726,6 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
/* NB: we're sure to have correct a_ops only after f_op->open */
if (f->f_flags & O_DIRECT) {
if (!f->f_mapping->a_ops ||
((!f->f_mapping->a_ops->direct_IO) &&
(!f->f_mapping->a_ops->get_xip_mem))) {
fput(f);
f = ERR_PTR(-EINVAL);
}
}
return f;
cleanup_all:
@ -744,12 +747,29 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
f->f_path.dentry = NULL;
f->f_path.mnt = NULL;
cleanup_file:
put_filp(f);
dput(dentry);
mntput(mnt);
return ERR_PTR(error);
}
static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
struct file *f,
int (*open)(struct inode *, struct file *),
const struct cred *cred)
{
struct file *res = do_dentry_open(dentry, mnt, f, open, cred);
if (!IS_ERR(res)) {
int error = open_check_o_direct(f);
if (error) {
fput(res);
res = ERR_PTR(error);
}
} else {
put_filp(f);
}
return res;
}
/**
* lookup_instantiate_filp - instantiates the open intent filp
* @nd: pointer to nameidata
@ -804,13 +824,31 @@ struct file *nameidata_to_filp(struct nameidata *nd)
/* Pick up the filp from the open intent */
filp = nd->intent.open.file;
nd->intent.open.file = NULL;
/* Has the filesystem initialised the file for us? */
if (filp->f_path.dentry == NULL) {
if (filp->f_path.dentry != NULL) {
nd->intent.open.file = NULL;
} else {
struct file *res;
path_get(&nd->path);
filp = __dentry_open(nd->path.dentry, nd->path.mnt, filp,
NULL, cred);
res = do_dentry_open(nd->path.dentry, nd->path.mnt,
filp, NULL, cred);
if (!IS_ERR(res)) {
int error;
nd->intent.open.file = NULL;
BUG_ON(res != filp);
error = open_check_o_direct(filp);
if (error) {
fput(filp);
filp = ERR_PTR(error);
}
} else {
/* Allow nd->intent.open.file to be recycled */
filp = res;
}
}
return filp;
}

View File

@ -654,8 +654,11 @@ pipe_write(struct kiocb *iocb, const struct iovec *_iov,
wake_up_interruptible_sync_poll(&pipe->wait, POLLIN | POLLRDNORM);
kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN);
}
if (ret > 0)
file_update_time(filp);
if (ret > 0) {
int err = file_update_time(filp);
if (err)
ret = err;
}
return ret;
}

View File

@ -257,12 +257,12 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
prev_src_mnt = child;
}
out:
br_write_lock(vfsmount_lock);
br_write_lock(&vfsmount_lock);
while (!list_empty(&tmp_list)) {
child = list_first_entry(&tmp_list, struct mount, mnt_hash);
umount_tree(child, 0, &umount_list);
}
br_write_unlock(vfsmount_lock);
br_write_unlock(&vfsmount_lock);
release_mounts(&umount_list);
return ret;
}

View File

@ -23,12 +23,12 @@ static unsigned mounts_poll(struct file *file, poll_table *wait)
poll_wait(file, &p->ns->poll, wait);
br_read_lock(vfsmount_lock);
br_read_lock(&vfsmount_lock);
if (p->m.poll_event != ns->event) {
p->m.poll_event = ns->event;
res |= POLLERR | POLLPRI;
}
br_read_unlock(vfsmount_lock);
br_read_unlock(&vfsmount_lock);
return res;
}

View File

@ -108,11 +108,11 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
int error;
struct file * file;
struct readdir_callback buf;
int fput_needed;
error = -EBADF;
file = fget(fd);
file = fget_light(fd, &fput_needed);
if (!file)
goto out;
return -EBADF;
buf.result = 0;
buf.dirent = dirent;
@ -121,8 +121,7 @@ SYSCALL_DEFINE3(old_readdir, unsigned int, fd,
if (buf.result)
error = buf.result;
fput(file);
out:
fput_light(file, fput_needed);
return error;
}
@ -195,16 +194,15 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
struct file * file;
struct linux_dirent __user * lastdirent;
struct getdents_callback buf;
int fput_needed;
int error;
error = -EFAULT;
if (!access_ok(VERIFY_WRITE, dirent, count))
goto out;
return -EFAULT;
error = -EBADF;
file = fget(fd);
file = fget_light(fd, &fput_needed);
if (!file)
goto out;
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
@ -221,8 +219,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, fd,
else
error = count - buf.count;
}
fput(file);
out:
fput_light(file, fput_needed);
return error;
}
@ -278,16 +275,15 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
struct file * file;
struct linux_dirent64 __user * lastdirent;
struct getdents_callback64 buf;
int fput_needed;
int error;
error = -EFAULT;
if (!access_ok(VERIFY_WRITE, dirent, count))
goto out;
return -EFAULT;
error = -EBADF;
file = fget(fd);
file = fget_light(fd, &fput_needed);
if (!file)
goto out;
return -EBADF;
buf.current_dir = dirent;
buf.previous = NULL;
@ -305,7 +301,6 @@ SYSCALL_DEFINE3(getdents64, unsigned int, fd,
else
error = count - buf.count;
}
fput(file);
out:
fput_light(file, fput_needed);
return error;
}

View File

@ -1592,13 +1592,12 @@ struct dentry *reiserfs_fh_to_parent(struct super_block *sb, struct fid *fid,
(fh_type == 6) ? fid->raw[5] : 0);
}
int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
int need_parent)
int reiserfs_encode_fh(struct inode *inode, __u32 * data, int *lenp,
struct inode *parent)
{
struct inode *inode = dentry->d_inode;
int maxlen = *lenp;
if (need_parent && (maxlen < 5)) {
if (parent && (maxlen < 5)) {
*lenp = 5;
return 255;
} else if (maxlen < 3) {
@ -1610,20 +1609,15 @@ int reiserfs_encode_fh(struct dentry *dentry, __u32 * data, int *lenp,
data[1] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id);
data[2] = inode->i_generation;
*lenp = 3;
/* no room for directory info? return what we've stored so far */
if (maxlen < 5 || !need_parent)
return 3;
spin_lock(&dentry->d_lock);
inode = dentry->d_parent->d_inode;
data[3] = inode->i_ino;
data[4] = le32_to_cpu(INODE_PKEY(inode)->k_dir_id);
*lenp = 5;
if (maxlen >= 6) {
data[5] = inode->i_generation;
*lenp = 6;
if (parent) {
data[3] = parent->i_ino;
data[4] = le32_to_cpu(INODE_PKEY(parent)->k_dir_id);
*lenp = 5;
if (maxlen >= 6) {
data[5] = parent->i_generation;
*lenp = 6;
}
}
spin_unlock(&dentry->d_lock);
return *lenp;
}

View File

@ -1923,6 +1923,8 @@ static int do_journal_release(struct reiserfs_transaction_handle *th,
* the workqueue job (flush_async_commit) needs this lock
*/
reiserfs_write_unlock(sb);
cancel_delayed_work_sync(&REISERFS_SB(sb)->old_work);
flush_workqueue(commit_wq);
if (!reiserfs_mounted_fs_count) {
@ -3231,8 +3233,6 @@ int journal_mark_dirty(struct reiserfs_transaction_handle *th,
th->t_trans_id, journal->j_trans_id);
}
sb->s_dirt = 1;
prepared = test_clear_buffer_journal_prepared(bh);
clear_buffer_journal_restore_dirty(bh);
/* already in this transaction, we are done */
@ -3316,6 +3316,7 @@ int journal_mark_dirty(struct reiserfs_transaction_handle *th,
journal->j_first = cn;
journal->j_last = cn;
}
reiserfs_schedule_old_flush(sb);
return 0;
}
@ -3492,7 +3493,7 @@ static void flush_async_commits(struct work_struct *work)
** flushes any old transactions to disk
** ends the current transaction if it is too old
*/
int reiserfs_flush_old_commits(struct super_block *sb)
void reiserfs_flush_old_commits(struct super_block *sb)
{
time_t now;
struct reiserfs_transaction_handle th;
@ -3502,9 +3503,8 @@ int reiserfs_flush_old_commits(struct super_block *sb)
/* safety check so we don't flush while we are replaying the log during
* mount
*/
if (list_empty(&journal->j_journal_list)) {
return 0;
}
if (list_empty(&journal->j_journal_list))
return;
/* check the current transaction. If there are no writers, and it is
* too old, finish it, and force the commit blocks to disk
@ -3526,7 +3526,6 @@ int reiserfs_flush_old_commits(struct super_block *sb)
do_journal_end(&th, sb, 1, COMMIT_NOW | WAIT);
}
}
return sb->s_dirt;
}
/*
@ -3955,7 +3954,7 @@ static int do_journal_end(struct reiserfs_transaction_handle *th,
** it tells us if we should continue with the journal_end, or just return
*/
if (!check_journal_end(th, sb, nblocks, flags)) {
sb->s_dirt = 1;
reiserfs_schedule_old_flush(sb);
wake_queued_writers(sb);
reiserfs_async_progress_wait(sb);
goto out;

Some files were not shown because too many files have changed in this diff Show More