mirror of https://gitee.com/openkylin/linux.git
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:
commit
1193755ac6
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
========================
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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(¤t->mm->mmap_sem);
|
||||
{
|
||||
addr = do_mremap(addr, old_len, new_len, flags, new_addr);
|
||||
}
|
||||
up_write(¤t->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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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(¤t->mm->mmap_sem);
|
||||
ret = do_mremap(addr, old_len, new_len, flags, new_addr);
|
||||
up_write(¤t->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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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(¤t->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(¤t->mm->mmap_sem);
|
||||
|
||||
return retcode;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
6
fs/aio.c
6
fs/aio.c
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -329,7 +329,6 @@ static unsigned long elf_map(struct file *filep, unsigned long addr,
|
|||
if (!size)
|
||||
return addr;
|
||||
|
||||
down_write(¤t->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(¤t->mm->mmap_sem);
|
||||
return(map_addr);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
33
fs/compat.c
33
fs/compat.c
|
@ -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 */
|
||||
|
|
20
fs/dcache.c
20
fs/dcache.c
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
42
fs/fcntl.c
42
fs/fcntl.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
60
fs/hpfs/ea.c
60
fs/hpfs/ea.c
|
@ -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);
|
||||
}
|
||||
|
|
289
fs/hpfs/hpfs.h
289
fs/hpfs/hpfs.h
|
@ -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
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
124
fs/inode.c
124
fs/inode.c
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
179
fs/namei.c
179
fs/namei.c
|
@ -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:
|
||||
|
|
142
fs/namespace.c
142
fs/namespace.c
|
@ -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);
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
56
fs/nfs/dir.c
56
fs/nfs/dir.c
|
@ -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);
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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.
|
||||
|
|
76
fs/open.c
76
fs/open.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
33
fs/readdir.c
33
fs/readdir.c
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue